Skip to content

Commit e86bae4

Browse files
committed
WIP Unit tests for hook implementations
1 parent e095e9c commit e86bae4

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{-# LANGUAGE QuasiQuotes #-}
2+
3+
{- |
4+
Copyright : (c) Runtime Verification, 2024
5+
License : BSD-3-Clause
6+
-}
7+
module Test.Booster.Builtin (
8+
test_builtins,
9+
) where
10+
11+
import Control.Monad.Trans.Except
12+
import Data.Either (isLeft)
13+
import Data.Map qualified as Map
14+
import Data.Maybe (fromMaybe)
15+
import Data.Text qualified as Text
16+
17+
import Hedgehog
18+
import Hedgehog.Gen qualified as Gen
19+
import Hedgehog.Range qualified as Range
20+
import Test.Tasty (TestTree, testGroup)
21+
import Test.Tasty.HUnit hiding (assert)
22+
import Test.Tasty.Hedgehog
23+
24+
import Booster.Builtin qualified as Builtin (hooks)
25+
import Booster.Builtin.BOOL qualified as Builtin
26+
import Booster.Builtin.INT qualified as Builtin
27+
import Booster.Pattern.Base
28+
import Booster.Syntax.Json.Internalise (trm)
29+
import Booster.Syntax.ParsedKore.Internalise (symb)
30+
import Test.Booster.Fixture as Fixture
31+
32+
test_builtins :: [TestTree]
33+
test_builtins =
34+
[ testIntHooks
35+
, testListSizeHooks
36+
]
37+
38+
testIntHooks :: TestTree
39+
testIntHooks =
40+
testGroup
41+
"Integer hooks"
42+
[ testIntHook2 "INT.add" (+) Builtin.intTerm
43+
, testIntHook2 "INT.mul" (*) Builtin.intTerm
44+
, testIntHook2 "INT.sub" (-) Builtin.intTerm
45+
, -- comparisons
46+
testIntHook2 "INT.gt" (>) Builtin.boolTerm
47+
, testIntHook2 "INT.ge" (>=) Builtin.boolTerm
48+
, testIntHook2 "INT.lt" (<) Builtin.boolTerm
49+
, testIntHook2 "INT.le" (<=) Builtin.boolTerm
50+
, testIntHook2 "INT.eq" (==) Builtin.boolTerm
51+
, testIntHook2 "INT.ne" (/=) Builtin.boolTerm
52+
]
53+
where
54+
-- testIntHook2 :: ByteString -> (Int -> Int -> a) -> (a -> Term) -> TestTree
55+
testIntHook2 name op result =
56+
testProperty ("Hook " <> show name) . property $ do
57+
let f =
58+
fromMaybe
59+
(error $ "Hook " <> show name <> " missing")
60+
(Map.lookup name Builtin.hooks)
61+
runHook h args = either (error . Text.unpack) id . runExcept $ h args
62+
a <- fmap fromIntegral $ forAll $ Gen.int64 Range.linearBounded
63+
b <- fmap fromIntegral $ forAll $ Gen.int64 Range.linearBounded
64+
let dv_a = Builtin.intTerm a
65+
dv_b = Builtin.intTerm b
66+
-- regular computation
67+
Just (result $ op a b) === runHook f [dv_a, dv_b]
68+
-- Nothing for unevaluated arguments
69+
let fct = [symb| symbol f{}(SortInt) : SortInt [function{}()] |]
70+
Nothing === runHook f [app fct [dv_a], dv_b]
71+
Nothing === runHook f [dv_a, app fct [dv_b]]
72+
Nothing === runHook f [app fct [dv_a], app fct [dv_b]]
73+
-- arity error on wrong argument count
74+
let assertException = assert . isLeft . runExcept
75+
assertException $ f []
76+
assertException $ f [dv_a]
77+
assertException $ f [dv_a, dv_a, dv_a]
78+
79+
testListSizeHooks :: TestTree
80+
testListSizeHooks =
81+
testGroup
82+
"LIST.size hooks"
83+
[ testProperty "LIST.size on concrete lists works" . property $ do
84+
l <- forAll $ Gen.int (Range.constant 0 12)
85+
let aList =
86+
KList Fixture.testKListDef (replicate l [trm| \dv{SomeSort{}}("thing")|]) Nothing
87+
hook <- maybe failure pure $ Map.lookup "LIST.size" Builtin.hooks
88+
result <- evalEither $ runExcept $ hook [aList]
89+
Just (Builtin.intTerm (fromIntegral l)) === result
90+
, testProperty "LIST.size on symbolic lists has no result" . property $ do
91+
l <- forAll $ Gen.int (Range.constant 1 5)
92+
let aList =
93+
KList Fixture.testKListDef [] $
94+
Just ([trm| INIT:SortList|], replicate l [trm| \dv{SomeSort{}}("thing")|])
95+
hook <- maybe failure pure $ Map.lookup "LIST.size" Builtin.hooks
96+
result <- evalEither $ runExcept $ hook [aList]
97+
Nothing === result
98+
, testCase "LIST.size arity is checked" $ do
99+
hook <- maybe (error "LIST.size hook not found") pure $ Map.lookup "LIST.size" Builtin.hooks
100+
let assertException = assertBool "Unexpected success" . isLeft . runExcept
101+
assertException $ hook []
102+
assertException $ hook $ replicate 2 [trm| X:SortList{} |]
103+
]

0 commit comments

Comments
 (0)