covenant-1.0.0: test/primops/Main.hs
module Main (main) where
import Covenant.Prim
( typeOneArgFunc,
typeThreeArgFunc,
typeTwoArgFunc,
)
import Covenant.Type
( AbstractTy (BoundAt),
CompT,
Renamed (Unifiable),
arity,
renameCompT,
runRenameM,
)
import Data.Functor.Classes (liftEq)
import Data.Kind (Type)
import Test.QuickCheck
( Arbitrary (arbitrary),
Property,
counterexample,
forAll,
property,
(===),
)
import Test.Tasty (defaultMain, testGroup)
import Test.Tasty.QuickCheck (testProperty)
main :: IO ()
main =
defaultMain . testGroup "Primops" $
[ -- Since there are so few primops, we don't increase the test count
-- beyond the default 100, as it would just be redundant.
testGroup
"Arity"
[ testProperty "One-argument primops take one argument" prop1Arg,
testProperty "Two-argument primops take two arguments" prop2Args,
testProperty "Three-argument primops take three arguments" prop3Args
-- testProperty "Six-argument primops take six arguments" prop6Args
],
testGroup
"Renaming"
[ testProperty "One-argument primops rename correctly" prop1Rename,
testProperty "Two-argument primops rename correctly" prop2Rename,
testProperty "Three-argument primops rename correctly" prop3Rename
-- testProperty "Six-argument primops rename correctly" prop6Rename
]
]
-- Test cases and properties
prop1Arg :: Property
prop1Arg = mkArgProp typeOneArgFunc 1
prop1Rename :: Property
prop1Rename = mkRenameProp typeOneArgFunc
prop2Args :: Property
prop2Args = mkArgProp typeTwoArgFunc 2
prop2Rename :: Property
prop2Rename = mkRenameProp typeTwoArgFunc
prop3Args :: Property
prop3Args = mkArgProp typeThreeArgFunc 3
prop3Rename :: Property
prop3Rename = mkRenameProp typeThreeArgFunc
{-
prop6Args :: Property
prop6Args = mkArgProp typeSixArgFunc 6
prop6Rename :: Property
prop6Rename = mkRenameProp typeSixArgFunc
-}
-- Helpers
mkArgProp ::
forall (a :: Type).
(Show a, Arbitrary a) =>
(a -> CompT AbstractTy) ->
Int ->
Property
mkArgProp typingFun targetArity = forAll arbitrary $ \f ->
let t = typingFun f
in arity t === targetArity
mkRenameProp ::
forall (a :: Type).
(Show a, Arbitrary a) =>
(a -> CompT AbstractTy) ->
Property
mkRenameProp typingFun = forAll arbitrary $ \f ->
let t = typingFun f
result = runRenameM . renameCompT $ t
in case result of
Left err -> counterexample (show err) False
Right renamed -> property $ liftEq eqRenamedVar t renamed
-- In our context, the _only_ variables we have are unifiable. If we see
-- anything else, we know we've messed up somewhere. Furthermore, the indexes
-- should 'line up'.
eqRenamedVar :: AbstractTy -> Renamed -> Bool
eqRenamedVar (BoundAt _ ix) = \case
Unifiable ix' -> ix == ix'
_ -> False