-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathGeneratorSpec.hs
More file actions
97 lines (89 loc) · 3.91 KB
/
GeneratorSpec.hs
File metadata and controls
97 lines (89 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
module Test.Codec.CBOR.Cuddle.CDDL.GeneratorSpec (spec) where
import Codec.CBOR.Cuddle.CBOR.Gen (GenPhase, generateFromName)
import Codec.CBOR.Cuddle.CBOR.Validator (validateCBOR)
import Codec.CBOR.Cuddle.CDDL (Name)
import Codec.CBOR.Cuddle.CDDL.CTree (CTreeRoot (..))
import Codec.CBOR.Cuddle.CDDL.Resolve (MonoReferenced, MonoSimple, fullResolveCDDL)
import Codec.CBOR.Cuddle.Huddle (Huddle, toCDDL)
import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..), mapCDDLDropExt)
import Codec.CBOR.Pretty (prettyHexEnc)
import Codec.CBOR.Read (deserialiseFromBytes)
import Codec.CBOR.Term (Term (..), decodeTerm, encodeTerm)
import Codec.CBOR.Write (toStrictByteString)
import Data.ByteString.Lazy qualified as LBS
import Data.Text.Lazy qualified as TL
import Test.AntiGen (runAntiGen, zapAntiGen)
import Test.Codec.CBOR.Cuddle.CDDL.Examples.Huddle (
bytesExample,
customGenExample,
opCertExample,
optionalMapExample,
rangeListExample,
rangeMapExample,
refTermExample,
sizeBytesExample,
sizeTextExample,
)
import Test.Codec.CBOR.Cuddle.CDDL.Validator (expectInvalid)
import Test.Hspec (HasCallStack, Spec, describe, runIO, shouldBe, shouldSatisfy)
import Test.Hspec.Core.Spec (SpecM)
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck (Gen, Property, Testable (..), counterexample)
import Text.Pretty.Simple (pShow)
generateCDDL :: CTreeRoot GenPhase -> Gen Term
generateCDDL cddl = runAntiGen $ generateFromName cddl "root"
tryResolveHuddle :: HasCallStack => Huddle -> SpecM () (CTreeRoot MonoReferenced)
tryResolveHuddle huddle = do
case fullResolveCDDL . mapCDDLDropExt $ toCDDL huddle of
Right x -> pure x
Left err -> runIO . fail $ "Failed to resolve CDDL:\n" <> show err
expectZapInvalidates :: CTreeRoot MonoReferenced -> Name -> Property
expectZapInvalidates cddl name = property $ do
value <- zapAntiGen 1 $ generateFromName (mapIndex cddl) name
let
bs = toStrictByteString $ encodeTerm value
validationRes = validateCBOR bs name $ mapIndex cddl
failMsg = case deserialiseFromBytes decodeTerm (LBS.fromStrict bs) of
Right (_, t) -> prettyHexEnc (encodeTerm t)
Left _ -> mempty
pure . counterexample failMsg $ expectInvalid validationRes
zapInvalidatesHuddle :: String -> Huddle -> Spec
zapInvalidatesHuddle n huddle = do
cddl <- tryResolveHuddle huddle
prop n . counterexample (TL.unpack . pShow $ mapIndex @_ @_ @MonoSimple cddl) $
expectZapInvalidates cddl "root"
spec :: Spec
spec = do
describe "Negative generator" $ do
describe "Zapped value fails to validate" $ do
zapInvalidatesHuddle "customGen" customGenExample
zapInvalidatesHuddle "refTerm" refTermExample
zapInvalidatesHuddle "opCert" opCertExample
zapInvalidatesHuddle "sizeText" sizeTextExample
zapInvalidatesHuddle "sizeBytes" sizeBytesExample
zapInvalidatesHuddle "rangeList" rangeListExample
zapInvalidatesHuddle "rangeMap" rangeMapExample
zapInvalidatesHuddle "optionalMapExample" optionalMapExample
describe "Custom generators" $ do
describe "Huddle" $ do
customGenExampleCddl <- tryResolveHuddle customGenExample
prop "If a term has a custom generator then it is used" $ do
res <- generateCDDL $ mapIndex customGenExampleCddl
pure $
res `shouldSatisfy` \case
TInt i -> i > 3 && i < 7
_ -> False
refTermExampleCddl <- tryResolveHuddle refTermExample
prop "Custom generator works when called via reference" $ do
res <- generateCDDL $ mapIndex refTermExampleCddl
pure $
res `shouldSatisfy` \case
TList [TInt 0, TInt i] -> i > 3 && i < 7
_ -> False
bytesExampleCddl <- tryResolveHuddle bytesExample
prop "Bytes are generated correctly" $ do
res <- generateCDDL $ mapIndex bytesExampleCddl
pure $ res `shouldBe` TBytes "\x01\x02\x03\xff"