swarm-0.4: test/unit/TestBoolExpr.hs
{-# LANGUAGE OverloadedStrings #-}
-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Boolean expression unit tests
module TestBoolExpr where
import Data.BoolExpr qualified as BE
import Data.BoolExpr.Simplify qualified as Simplify
import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Set qualified as Set
import Swarm.Game.Scenario.Objective.Logic
import Swarm.Game.Scenario.Objective.WinCheck qualified as WC
import Test.Tasty
import Test.Tasty.HUnit
testBoolExpr :: TestTree
testBoolExpr =
testGroup
"Boolean evaluation"
[ testGroup
"Expression simplification"
[ testGroup
"Return true if the expression can be simplified to False"
[ testGroup
"Effect of constant literals"
[ testCase
"False input via single literal"
$ expectTrue BE.BFalse
, testCase
"True input via composed literals"
$ expectFalse BE.BTrue
, testCase
"False input via composed literals"
$ expectTrue
$ BE.BOr BE.BFalse BE.BFalse
, testCase
"True input via composed literals"
$ expectFalse
$ BE.BOr BE.BFalse BE.BTrue
, testCase
"Constant OR'd with False"
$ expectFalse
$ BE.BOr BE.BFalse (BE.BConst (BE.Positive "foo"))
, testCase
"Constant OR'd with True"
$ expectFalse
$ BE.BOr (BE.BConst (BE.Positive "foo")) BE.BTrue
, testCase
"Constant AND'd with False"
$ expectTrue
$ BE.BAnd BE.BFalse (BE.BConst (BE.Positive "foo"))
, testCase
"Constant AND'd with True"
$ expectFalse
$ BE.BAnd (BE.BConst (BE.Positive "foo")) BE.BTrue
, testCase
"Nested Constants AND'd with False within OR"
$ expectTrue
$ BE.BOr
(BE.BAnd BE.BFalse (BE.BConst (BE.Positive "foo")))
(BE.BAnd (BE.BConst (BE.Positive "bar")) BE.BFalse)
, testCase
"Deeply nested Constants AND'd with False within OR with multiple negations"
$ expectTrue
$ BE.BOr
(BE.BAnd (BE.BNot BE.BTrue) (BE.BNot (BE.BNot (BE.BNot (BE.BConst (BE.Positive "foo"))))))
(BE.BAnd (BE.BConst (BE.Positive "bar")) (BE.BNot (BE.BNot BE.BFalse)))
]
, testGroup
"Effect of contradicting named constants"
[ testCase
"via NOT operator"
$ expectTrue
$ BE.BAnd (BE.BNot (BE.BConst (BE.Positive "foo"))) (BE.BConst (BE.Positive "foo"))
, testCase
"via signedness"
$ expectTrue
$ BE.BAnd (BE.BConst (BE.Positive "foo")) (BE.BConst (BE.Negative "foo"))
]
]
]
, testGroup
"Prerequisite expressions"
[ testCase
"A negated goal is completed"
. assertBool "Should have returned true"
$ WC.isUnwinnablePrereq (Set.singleton "b") demoPrereqs
, testCase
"A non-negated goal is completed"
. assertBool "Should have returned false"
. not
$ WC.isUnwinnablePrereq (Set.singleton "c") demoPrereqs
]
]
where
expectTrue, expectFalse :: BE.BoolExpr String -> Assertion
expectTrue = assertBool "Should have returned true" . Simplify.cannotBeTrue
expectFalse = assertBool "Should have returned false" . not . Simplify.cannotBeTrue
demoPrereqs :: Prerequisite ObjectiveLabel
demoPrereqs =
And $
Id "a"
:| [Not (Id "b"), Id "c"]