stgi-1: test/Testsuite/Test/Marshal.hs
{-# LANGUAGE NumDecimals #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Test.Marshal (tests) where
import qualified Data.List.NonEmpty as NE
import Data.Proxy
import Data.Text (Text)
import qualified Data.Text as T
import Stg.Language.Prettyprint
import Stg.Machine
import Stg.Marshal
import Stg.Parser.QuasiQuoter
import Test.Orphans ()
import Test.Tasty
import Test.Tasty.QuickCheck
tests :: TestTree
tests = testGroup "Marshalling"
[ boolRoundtrip
, integerRoundtrip
, unitRoundtrip
, listRoundtrip
, nestedListRoundtrip
, maybeRoundtrip
, nestedMaybeRoundtrip
, eitherRoundtrip
, testGroup "Tuples"
[tuple2Roundtrip
, tuple3Roundtrip
, tuple4Roundtrip
, tuple5Roundtrip ]
, crazyRoundtrip
]
-- | Specifies a test that is based on the reduction of a closure.
data RoundtripSpec a = RoundtripSpec
{ testName :: Text
, testType :: Proxy a
-- ^ Pin down the type of @a@
, maxSteps :: Integer
}
defSpec :: RoundtripSpec a
defSpec = RoundtripSpec
{ testName = "Default test spec"
, testType = Proxy
, maxSteps = 10e3}
roundTripTest
:: forall a. (Arbitrary a, ToStg a, FromStg a, Show a, Eq a)
=> RoundtripSpec a
-> TestTree
roundTripTest spec = testProperty (T.unpack (testName spec)) test
where
test :: (Arbitrary a, ToStg a, FromStg a, Show a, Eq a) => a -> Property
test payload = counterexample (T.unpack (prettyprint finalState))
(expected === Right payload)
where
source = mconcat
[ toStg "payload" payload
, [stg|
main = \ => case forceUntyped payload of _ -> Done;
forceUntyped = \value -> case value of
Unit -> Done;
Nothing -> Done;
Just x -> forceUntyped x;
True -> Done;
False -> Done;
Int# _ -> Done;
Left l -> forceUntyped l;
Right r -> forceUntyped r;
Pair x y -> case forceUntyped x of
_ -> forceUntyped y;
Triple x y z -> case forceUntyped x of
_ -> case forceUntyped y of
_ -> forceUntyped z;
Nil -> Done;
Cons x xs -> case forceUntyped x of
_ -> forceUntyped xs;
_ -> Error
|]]
prog = initialState "main" source
states = evalsUntil
(RunForMaxSteps (maxSteps spec))
(HaltIf (const False))
(PerformGc (const Nothing))
prog
finalState = garbageCollect triStateTracing (NE.last states)
expected = fromStg finalState "payload"
boolRoundtrip :: TestTree
boolRoundtrip = roundTripTest defSpec
{ testName = "Bool"
, testType = Proxy :: Proxy Bool }
integerRoundtrip :: TestTree
integerRoundtrip = roundTripTest defSpec
{ testName = "Integer"
, testType = Proxy :: Proxy Integer }
unitRoundtrip :: TestTree
unitRoundtrip = roundTripTest defSpec
{ testName = "Unit"
, testType = Proxy :: Proxy () }
listRoundtrip :: TestTree
listRoundtrip = roundTripTest defSpec
{ testName = "List"
, testType = Proxy :: Proxy [Integer] }
nestedListRoundtrip :: TestTree
nestedListRoundtrip = roundTripTest defSpec
{ testName = "Nested list"
, testType = Proxy :: Proxy [[Integer]] }
maybeRoundtrip :: TestTree
maybeRoundtrip = roundTripTest defSpec
{ testName = "Maybe"
, testType = Proxy :: Proxy (Maybe Integer) }
nestedMaybeRoundtrip :: TestTree
nestedMaybeRoundtrip = roundTripTest defSpec
{ testName = "Maybe"
, testType = Proxy :: Proxy (Maybe (Maybe Integer)) }
eitherRoundtrip :: TestTree
eitherRoundtrip = roundTripTest defSpec
{ testName = "Maybe"
, testType = Proxy :: Proxy (Either Integer Bool) }
tuple2Roundtrip :: TestTree
tuple2Roundtrip = roundTripTest defSpec
{ testName = "2-tuple"
, testType = Proxy :: Proxy (Integer, Integer) }
tuple3Roundtrip :: TestTree
tuple3Roundtrip = roundTripTest defSpec
{ testName = "3-tuple"
, testType = Proxy :: Proxy (Integer, Integer, Integer) }
tuple4Roundtrip :: TestTree
tuple4Roundtrip = roundTripTest defSpec
{ testName = "4-tuple"
, testType = Proxy :: Proxy (Integer, Integer, Integer, Integer) }
tuple5Roundtrip :: TestTree
tuple5Roundtrip = roundTripTest defSpec
{ testName = "5-tuple"
, testType = Proxy :: Proxy (Integer, Integer, Integer, Integer, Integer) }
crazyRoundtrip :: TestTree
crazyRoundtrip = roundTripTest defSpec
{ testName = "Crazy giant type"
, testType = Proxy :: Proxy [Either ([[[Integer]]], [Maybe ()]) (Maybe [([Bool], Integer, [Bool])])]
, maxSteps = 10e5 }