serokell-util-0.9.0: test/Test/Serokell/Util/VerifySpec.hs
module Test.Serokell.Util.VerifySpec
( spec
) where
import Universum
import Test.Hspec (Expectation, Spec, describe, it, shouldBe)
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck (Property, (===), (==>))
import Test.QuickCheck.Instances ()
import Data.List.NonEmpty (fromList)
import Serokell.Arbitrary ()
import qualified Serokell.Util.Verify as V
spec :: Spec
spec =
describe "Verify" $ do
describe "isVerSuccess" $
prop description_isVerSuccess isVerSuccessWorks
describe "isVerSuccess" $
prop description_isVerFailure isVerFailureWorks
describe "Monoid VerificationRes" $
prop description_verificationResIsMonoid verificationResIsMonoid
describe "verifyGeneric" $ do
it "verifyGeneric of an empty string always succeeds"
(V.verifyGeneric [] `shouldBe` V.VerSuccess)
prop description_verifyGeneric verifyGenericWorks
prop description_verifyGenericMessageOrder verifyGenericMessageOrder
where
description_isVerSuccess =
"A successful verification should yield True, and an unsuccessful one should\
\ yield False"
description_isVerFailure =
"An unsuccessful verification should yield True, and an unsuccessful one should\
\ yield False"
description_verificationResIsMonoid =
"The set of verification results with the concatenation operation defined in the\
\ Serokell.Util.Verify module forms a monoid"
description_verifyGeneric =
"A list of predicates with a single failure yields a failed verification, and a\
\ list of predicates with no failures yields a successful verification"
description_verifyGenericMessageOrder =
"Error messages in a predicate list are taken from left to right"
isVerSuccessWorks :: V.VerificationRes -> Expectation
isVerSuccessWorks v = case v of
V.VerSuccess -> V.isVerSuccess v `shouldBe` True
V.VerFailure _ -> V.isVerSuccess v `shouldBe` False
-- | The property
-- `isVerFailure = not . isVerSuccess`
-- should hold for all v in VerificationRes
isVerFailureWorks :: V.VerificationRes -> Property
isVerFailureWorks v = (not . V.isVerSuccess $ v) === V.isVerFailure v
verificationResIsMonoid
:: V.VerificationRes
-> V.VerificationRes
-> V.VerificationRes
-> Bool
verificationResIsMonoid v1 v2 v3 =
let isAssociative =
let assoc1 = (v1 <> v2) <> v3
assoc2 = v1 <> (v2 <> v3)
in assoc1 == assoc2
hasIdentity =
let id1 = mempty <> v1
id2 = v1 <> mempty
in (v1 == id1) && (v1 == id2)
in isAssociative && hasIdentity
-- | The function `verifyGeneric` must have the following properties
-- (any (not . fst) l :: [(Bool, a)]) iff (isVerFailure . verifyGeneric) l
-- (all (identity . fst) l :: [(Bool, a)]) iff (isVerSuccess . verifyGeneric) l
verifyGenericWorks :: [(Bool, Text)] -> Bool
verifyGenericWorks l =
let someFailure = any (not . fst) l
allSuccess = not someFailure
in (someFailure == (V.isVerFailure . V.verifyGeneric $ l)) &&
(allSuccess == (V.isVerSuccess . V.verifyGeneric $ l))
-- | This property checks that the error messages in a list of predicates are collected
-- from left to right.
verifyGenericMessageOrder :: [(Bool, Text)] -> Property
verifyGenericMessageOrder l =
let someFailure = any (not . fst) l
msgList = foldr (\(b, err) accList ->
if not b then err : accList
else accList) [] l
in someFailure ==>
((V.VerFailure $ fromList msgList) == V.verifyGeneric l)