Skip to content

Commit 0ee80cc

Browse files
committed
copilot-theorem: Add a test case for struct updates. Refs #524.
This adds a basic test case that ensures that applying a struct update followed by accessing the updated field is equivalent to accessing the field and then updating it.
1 parent 634b928 commit 0ee80cc

File tree

1 file changed

+59
-4
lines changed
  • copilot-theorem/tests/Test/Copilot/Theorem

1 file changed

+59
-4
lines changed

copilot-theorem/tests/Test/Copilot/Theorem/What4.hs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE DataKinds #-}
12
-- The following warning is disabled due to a necessary instance of SatResult
23
-- defined in this module.
34
{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -6,17 +7,22 @@ module Test.Copilot.Theorem.What4 where
67

78
-- External imports
89
import Data.Int (Int8)
10+
import Data.Word (Word32)
911
import Test.Framework (Test, testGroup)
1012
import Test.Framework.Providers.QuickCheck2 (testProperty)
11-
import Test.QuickCheck (Property, arbitrary, forAll)
13+
import Test.QuickCheck (Arbitrary (arbitrary), Property,
14+
arbitrary, forAll)
1215
import Test.QuickCheck.Monadic (monadicIO, run)
1316

1417
-- External imports: Copilot
15-
import Copilot.Core.Expr (Expr (Const, Op2))
16-
import Copilot.Core.Operators (Op2 (..))
18+
import Copilot.Core.Expr (Expr (Const, Op1, Op2))
19+
import Copilot.Core.Operators (Op1 (..), Op2 (..))
1720
import Copilot.Core.Spec (Spec (..))
1821
import qualified Copilot.Core.Spec as Copilot
19-
import Copilot.Core.Type (Typed (typeOf))
22+
import Copilot.Core.Type (Field (..),
23+
Struct (toValues, typeName),
24+
Type (Struct), Typed (typeOf),
25+
Value (..))
2026

2127
-- Internal imports: Modules being tested
2228
import Copilot.Theorem.What4 (SatResult (..), Solver (..), prove)
@@ -30,6 +36,7 @@ tests =
3036
[ testProperty "Prove via Z3 that true is valid" testProveZ3True
3137
, testProperty "Prove via Z3 that false is invalid" testProveZ3False
3238
, testProperty "Prove via Z3 that x == x is valid" testProveZ3EqConst
39+
, testProperty "Prove via Z3 that a struct update is valid" testProveZ3StructUpdate
3340
]
3441

3542
-- * Individual tests
@@ -77,6 +84,54 @@ testProveZ3EqConst = forAll arbitrary $ \x ->
7784
spec x = propSpec propName $
7885
Op2 (Eq typeOf) (Const typeOf x) (Const typeOf x)
7986

87+
-- | Test that Z3 is able to prove the following expresion valid:
88+
-- @
89+
-- for all (s :: MyStruct),
90+
-- ((s ## testField =$ (+1)) # testField) == ((s # testField) + 1)
91+
-- @
92+
testProveZ3StructUpdate :: Property
93+
testProveZ3StructUpdate = forAll arbitrary $ \x ->
94+
monadicIO $ run $ checkResult Z3 propName (spec x) Valid
95+
where
96+
propName :: String
97+
propName = "prop"
98+
99+
spec :: TestStruct -> Spec
100+
spec s = propSpec propName $
101+
Op2
102+
(Eq typeOf)
103+
(getField
104+
(Op2
105+
(UpdateField typeOf typeOf testField)
106+
sExpr
107+
(add1 (getField sExpr))))
108+
(add1 (getField sExpr))
109+
where
110+
sExpr :: Expr TestStruct
111+
sExpr = Const typeOf s
112+
113+
getField :: Expr TestStruct -> Expr Word32
114+
getField = Op1 (GetField typeOf typeOf testField)
115+
116+
add1 :: Expr Word32 -> Expr Word32
117+
add1 x = Op2 (Add typeOf) x (Const typeOf 1)
118+
119+
-- | A simple data type with a 'Struct' instance and a 'Field'. This is only
120+
-- used as part of 'testProveZ3StructUpdate'.
121+
newtype TestStruct = TestStruct { testField :: Field "testField" Word32 }
122+
123+
instance Arbitrary TestStruct where
124+
arbitrary = do
125+
w32 <- arbitrary
126+
return (TestStruct (Field w32))
127+
128+
instance Struct TestStruct where
129+
typeName _ = "testStruct"
130+
toValues s = [Value typeOf (testField s)]
131+
132+
instance Typed TestStruct where
133+
typeOf = Struct (TestStruct (Field 0))
134+
80135
-- | Check that the solver's satisfiability result for the given property in
81136
-- the given spec matches the expectation.
82137
checkResult :: Solver -> String -> Spec -> SatResult -> IO Bool

0 commit comments

Comments
 (0)