automaton-1.4: test/Automaton.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Automaton where
-- base
import Control.Applicative (Alternative (..))
import Control.Arrow
import Control.Monad (guard)
import Data.Functor.Identity (runIdentity)
import Data.List (uncons)
import Data.Maybe (maybeToList)
-- transformers
import Control.Monad.State.Strict (StateT (..))
-- selective
import Control.Selective ((<*?))
-- tasty
import Test.Tasty (testGroup)
-- tasty-quickcheck
import Test.Tasty.QuickCheck
-- tasty-hunit
import Test.Tasty.HUnit (testCase, (@?=))
-- automaton
import Automaton.Except
import Automaton.Trans.Accum
import Data.Automaton
import Data.Automaton.Final
import Data.Automaton.Trans.Maybe
tests =
testGroup
"Automaton"
[ testGroup
"Alternative"
[ testGroup
"<|>"
[ testProperty "has same semantics as final" $
\(input :: [(Maybe Int, Maybe Int)]) ->
embed ((arr fst >>> inMaybe) <|> (arr snd >>> inMaybe)) input
=== embed (fromFinal $ (arr fst >>> toFinal inMaybe) <|> (arr snd >>> toFinal inMaybe)) input
]
, testGroup
"some"
[ testCase "Maybe" $ embed (some $ arrM id) [Nothing] @?= (Nothing :: Maybe [[()]])
, testCase "Parser" $ runParser (embed (some $ constM aChar) [(), ()]) "hi" @?= [(["h", "i"], "")]
]
, testGroup
"many"
[ testCase "Maybe" $ embed (many $ arrM id) [Nothing] @?= (Just [[]] :: Maybe [[()]])
, testCase "Parser" $ runParser (many (char 'h')) "hi" @?= [("h", "i"), ("", "hi")]
]
]
, testGroup
"parallely"
[ testCase "Outputs separate sums" $ runIdentity (embed (parallely sumN) [[], [], [1, 2], [10, 20], [100], [], [1000, 200]]) @?= [[], [], [1, 2], [11, 22], [111], [], [1111, 222]]
]
, testGroup
"Selective"
[ testCase "selects second Automaton conditionally" $
runIdentity (embed (right sumN <*? arr (const (* 2))) [Right 1, Right 2, Left 10, Right 3, Left 20]) @?= [1, 3, 20, 6, 40]
]
, testCase "count" $ runIdentity (embed count [(), (), ()]) @?= [1, 2, 3]
, testCase "delay" $ runIdentity (embed (count >>> delay 0) [(), (), ()]) @?= [0, 1, 2]
, testCase "sumS" $ runIdentity (embed (arr (const (1 :: Float)) >>> sumS) [(), (), ()]) @?= [1, 2, 3]
, testCase "sumN" $ runIdentity (embed (arr (const (1 :: Integer)) >>> sumN) [(), (), ()]) @?= [1, 2, 3]
, testCase "lastS" $ runIdentity (embed (lastS 0) [Nothing, Just 10]) @?= [0, 10]
, Automaton.Except.tests
, Automaton.Trans.Accum.tests
]
inMaybe :: Automaton Maybe (Maybe a) a
inMaybe = hoistS (runIdentity . runMaybeT) inMaybeT
-- * Parser helper type to test many & some
newtype Parser a = Parser {getParser :: StateT String [] a}
deriving (Functor, Applicative, Monad, Alternative)
runParser :: Parser a -> String -> [(a, String)]
runParser = runStateT . getParser
aChar :: Parser Char
aChar = Parser $ StateT $ maybeToList . uncons
char :: Char -> Parser Char
char c = do
c' <- aChar
guard $ c == c'
return c