cuddle-1.1.0.0: test/Test/Codec/CBOR/Cuddle/CDDL/Pretty.hs
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Test.Codec.CBOR.Cuddle.CDDL.Pretty (
spec,
) where
import Codec.CBOR.Cuddle.CDDL (
Assign (..),
CDDL,
Group (..),
GroupEntry (..),
GroupEntryVariant (..),
GrpChoice (..),
Name (..),
Rule (..),
Type0 (..),
Type1 (..),
Type2 (..),
TypeOrGroup (..),
ValueVariant (..),
value,
)
import Codec.CBOR.Cuddle.Huddle (HuddleItem (..), a, bstr, (<+), (=:=), (=:~))
import Codec.CBOR.Cuddle.Huddle qualified as H
import Codec.CBOR.Cuddle.IndexMappable (IndexMappable (..))
import Codec.CBOR.Cuddle.Pretty (PrettyStage, XRule (..))
import Data.Default.Class (Default (..))
import Data.List.NonEmpty (NonEmpty (..))
import Data.Text qualified as T
import Data.TreeDiff (ToExpr (..), prettyExpr)
import Prettyprinter (Pretty (..), defaultLayoutOptions, layoutPretty)
import Prettyprinter.Render.String (renderString)
import Test.Codec.CBOR.Cuddle.CDDL.Gen ()
import Test.HUnit (assertEqual)
import Test.Hspec (Expectation, Spec, describe, it, shouldBe, xit)
import Test.Hspec.QuickCheck (xprop)
import Test.QuickCheck (counterexample)
import Prelude hiding ((/))
prettyPrintsTo :: (Pretty a, ToExpr a) => a -> String -> Expectation
prettyPrintsTo x s = assertEqual (show . prettyExpr $ toExpr x) s rendered
where
rendered = renderString (layoutPretty defaultLayoutOptions (pretty x))
t2Name :: Type2 PrettyStage
t2Name = T2Name (Name "a") mempty
t1Name :: Type1 PrettyStage
t1Name = Type1 t2Name Nothing mempty
mkType0 :: Type2 PrettyStage -> Type0 PrettyStage
mkType0 t2 = Type0 $ Type1 t2 Nothing mempty :| []
spec :: Spec
spec = describe "Pretty printer" $ do
unitSpec
qcSpec
qcSpec :: Spec
qcSpec = describe "QuickCheck" $ do
xprop "CDDL prettyprinter leaves no trailing spaces" $ \(cddl :: CDDL PrettyStage) -> do
let
prettyStr = T.pack . renderString . layoutPretty defaultLayoutOptions $ pretty cddl
stripLines = T.unlines . fmap T.stripEnd . T.lines
counterexample (show . prettyExpr $ toExpr cddl) $
prettyStr `shouldBe` stripLines prettyStr
drep :: Rule PrettyStage
drep =
Rule
"drep"
Nothing
AssignEq
( TOGType
( Type0
( Type1
( T2Array
( Group
( GrpChoice
[ GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Value . value $ VUInt 0) Nothing mempty :| []))
mempty
, GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Name "addr_keyhash" Nothing) Nothing mempty :| []))
mempty
]
mempty
:| [ GrpChoice
[ GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Value . value $ VUInt 1) Nothing mempty :| []))
mempty
, GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Name "script_hash" Nothing) Nothing mempty :| []))
mempty
]
mempty
, GrpChoice
[ GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Value . value $ VUInt 2) Nothing mempty :| []))
mempty
]
mempty
, GrpChoice
[ GroupEntry
Nothing
(GEType Nothing (Type0 $ Type1 (T2Value . value $ VUInt 3) Nothing mempty :| []))
mempty
]
mempty
]
)
)
)
Nothing
mempty
:| []
)
)
)
def
unitSpec :: Spec
unitSpec = describe "HUnit" $ do
describe "CDDL" $ do
describe "Name" $ do
it "names" $ Name "a" `prettyPrintsTo` "a"
describe "Type0" $ do
it "name" $ Type0 @PrettyStage (t1Name :| []) `prettyPrintsTo` "a"
describe "Type1" $ do
it "name" $ t1Name `prettyPrintsTo` "a"
describe "Type2" $ do
it "T2Name" $ t2Name `prettyPrintsTo` "a"
describe "T2Array" $ do
let groupEntryName = GroupEntry Nothing (GERef (Name "a") Nothing) ""
it "one element" $
T2Array (Group (GrpChoice [groupEntryName] mempty :| [])) `prettyPrintsTo` "[a]"
it "two elements" $
T2Array
( Group
( GrpChoice
[ GroupEntry Nothing (GEType Nothing (mkType0 . T2Value . value $ VUInt 1)) ""
, groupEntryName
]
mempty
:| []
)
)
`prettyPrintsTo` "[1, a]"
it "two elements with comments" $
T2Array
( Group
( GrpChoice
[ GroupEntry Nothing (GEType Nothing (mkType0 . T2Value . value $ VUInt 1)) "one"
, GroupEntry Nothing (GEType Nothing (mkType0 . T2Value . value $ VUInt 2)) "two"
]
mempty
:| []
)
)
`prettyPrintsTo` "[ 1 ; one\n, 2 ; two\n]"
it "two elements with multiline comments" $
T2Array
( Group
( GrpChoice
[ GroupEntry
Nothing
(GEType Nothing (mkType0 . T2Value . value $ VUInt 1))
"first\nmultiline comment"
, GroupEntry
Nothing
(GEType Nothing (mkType0 . T2Value . value $ VUInt 2))
"second\nmultiline comment"
]
mempty
:| []
)
)
`prettyPrintsTo` "[ 1 ; first\n ; multiline comment\n, 2 ; second\n ; multiline comment\n]"
describe "Rule" $ do
it "simple assignment" $
Rule @PrettyStage
(Name "a")
Nothing
AssignEq
(TOGType (Type0 (Type1 (T2Name (Name "b") mempty) Nothing mempty :| [])))
def
`prettyPrintsTo` "a = b"
it "simple assignment with comment" $
Rule @PrettyStage
(Name "a")
Nothing
AssignEq
(TOGType (Type0 (Type1 (T2Name (Name "b") mempty) Nothing mempty :| [])))
(PrettyXRule "comment")
`prettyPrintsTo` "; comment\na = b"
xit "drep" $
drep
`prettyPrintsTo` "drep = [0, addr_keyhash // 1, script_hash // 2 // 3]"
describe "Huddle" $ do
let
huddlePrettyPrintsTo rs str =
mapIndex @_ @_ @PrettyStage (H.toCDDLNoRoot $ H.collectFrom rs) `prettyPrintsTo` str
describe "Rule" $ do
-- TODO get rid of trailing newline
it "simple assignment" $
[HIRule $ "a" =:= H.bool True]
`huddlePrettyPrintsTo` "a = true\n"
it "simple assignment with comment" $
[HIRule $ H.comment "comment" $ "a" =:= H.bool True]
`huddlePrettyPrintsTo` "; comment\na = true\n"
it "comment and reference" $
let
b = H.comment "this is rule 'b'" $ "b" =:= H.text "bee"
in
[ HIRule $ H.comment "comment" $ "a" =:= b
]
`huddlePrettyPrintsTo` "; comment\na = b\n\n; this is rule 'b'\nb = \"bee\"\n"
it "bstr expects hex, not bytes" $
[ HIRule $ "a" =:= bstr "010200ff"
]
`huddlePrettyPrintsTo` "a = h'010200ff'\n"
describe "Generic rule" $ do
it "comment and generic reference" $
let
b :: H.IsType0 a => a -> H.GRuleCall
b = H.binding $ \x -> H.comment "bar" $ "b" =:= H.arr [0 <+ a x]
in
[ HIRule . H.comment "foo" $ "a" =:= b (H.bool True)
]
`huddlePrettyPrintsTo` "; foo\na = b<true>\n\n; bar\nb<a0> = [* a0]\n"
describe "GroupDef" $ do
it "simple pair" $
[HIGroup $ "a" =:~ [a $ H.bool True, a $ H.int 3]]
`huddlePrettyPrintsTo` "a = (true, 3)\n"
it "simple pair with comment" $
[HIGroup $ H.comment "comment" $ "a" =:~ [a $ H.bool True, a $ H.int 3]]
`huddlePrettyPrintsTo` "; comment\na = (true, 3)\n"
it "comment and reference" $
let
b = H.comment "bar" $ "b" =:~ [a $ H.int 2, a $ H.text "bee"]
in
[ HIGroup . H.comment "foo" $ "a" =:~ [a $ H.bool True, a b]
]
`huddlePrettyPrintsTo` "; foo\na = (true, b)\n\n; bar\nb = (2, \"bee\")\n"