Skip to content

Commit f162f1c

Browse files
committed
Add CDDL testing to golden and roundtrip tests
1 parent 21ab8a5 commit f162f1c

File tree

4 files changed

+177
-53
lines changed

4 files changed

+177
-53
lines changed

ouroboros-consensus/ouroboros-consensus.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ library unstable-consensus-testlib
408408
Test.Util.SOP
409409
Test.Util.SanityCheck
410410
Test.Util.Schedule
411+
Test.Util.Serialisation.CDDL
411412
Test.Util.Serialisation.Examples
412413
Test.Util.Serialisation.Golden
413414
Test.Util.Serialisation.Roundtrip
@@ -459,6 +460,7 @@ library unstable-consensus-testlib
459460
ouroboros-network-api,
460461
ouroboros-network-mock,
461462
pretty-simple,
463+
process,
462464
quickcheck-instances,
463465
quickcheck-state-machine:no-vendored-treediff ^>=0.10,
464466
quiet,
@@ -477,6 +479,7 @@ library unstable-consensus-testlib
477479
tasty-quickcheck >=0.11,
478480
tasty-rerun,
479481
template-haskell,
482+
temporary,
480483
text,
481484
time,
482485
transformers-base,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
3+
module Test.Util.Serialisation.CDDL (cddlTestCase, cddlTest, CDDLsForNodeToNode (..)) where
4+
5+
import qualified Data.ByteString as BS
6+
import qualified Data.Text as T
7+
import System.Exit
8+
import System.IO
9+
import System.IO.Temp
10+
import System.Process
11+
import Test.Tasty
12+
import Test.Tasty.HUnit
13+
14+
-- | A Tasty test case running the @cuddle@
15+
cddlTestCase :: IO BS.ByteString -> FilePath -> T.Text -> TestTree
16+
cddlTestCase cborM cddl rule =
17+
testCase "CDDL compliance" $
18+
cddlTest cborM cddl rule >>= \case
19+
Left err -> assertFailure err
20+
Right _ -> pure ()
21+
22+
-- | Test the CDDL conformance of the given bytestring
23+
cddlTest ::
24+
IO BS.ByteString ->
25+
String ->
26+
T.Text ->
27+
IO (Either String ())
28+
cddlTest cborM cddl rule =
29+
withTempFile "." "testcase.cbor" $ \fp h -> do
30+
bs <- cborM
31+
BS.hPutStr h bs
32+
hClose h
33+
(code, _out, err) <-
34+
readProcessWithExitCode "cuddle" ["validate-cbor", "-c", fp, "-r", T.unpack rule, cddl] mempty
35+
case code of
36+
ExitFailure _ -> do
37+
BS.writeFile "failing.cbor" bs
38+
pure (Left err)
39+
ExitSuccess -> pure (Right ())
40+
41+
-- | A collection of CDDL spec and the relevant rule to use
42+
data CDDLsForNodeToNode = CDDLsForNodeToNode
43+
{ blockCDDL :: (FilePath, T.Text)
44+
, headerCDDL :: (FilePath, T.Text)
45+
}

ouroboros-consensus/src/unstable-consensus-testlib/Test/Util/Serialisation/Golden.hs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import qualified Data.ByteString.UTF8 as BS.UTF8
4747
import Data.List (nub)
4848
import qualified Data.Map.Strict as Map
4949
import Data.Proxy (Proxy (..))
50+
import qualified Data.Text as T
5051
import Data.TreeDiff
5152
import GHC.Stack (HasCallStack)
5253
import Ouroboros.Consensus.Block (CodecConfig)
@@ -78,6 +79,7 @@ import System.FilePath (takeDirectory, (</>))
7879
import Test.Cardano.Binary.TreeDiff (CBORBytes (..))
7980
import Test.Tasty
8081
import Test.Tasty.Golden.Advanced (goldenTest)
82+
import Test.Util.Serialisation.CDDL
8183
import Test.Util.Serialisation.Examples (Examples (..), Labelled)
8284
import Test.Util.Serialisation.SomeResult (SomeResult (..))
8385

@@ -96,14 +98,27 @@ goldenTestCBOR ::
9698
(a -> Encoding) ->
9799
-- | Path to the file containing the golden output
98100
FilePath ->
101+
-- | Path to the CDDL file that defines this CBOR, and the rule name
102+
Maybe (FilePath, T.Text) ->
99103
TestTree
100-
goldenTestCBOR testName example enc goldenFile =
101-
goldenTest
102-
testName
103-
(Strict.readFile goldenFile)
104-
(either exceptionToByteString id <$> try (evaluate actualValue))
105-
diff
106-
updateGoldenFile
104+
goldenTestCBOR testName example enc goldenFile mCddlPath =
105+
testGroup testName $
106+
[ goldenTest
107+
"Golden == actual"
108+
(Strict.readFile goldenFile)
109+
(either exceptionToByteString id <$> try (evaluate actualValue))
110+
diff
111+
updateGoldenFile
112+
]
113+
++ ( case mCddlPath of
114+
Nothing -> []
115+
Just (cddlPath, rule) ->
116+
[ cddlTestCase
117+
(Strict.readFile goldenFile)
118+
cddlPath
119+
rule
120+
]
121+
)
107122
where
108123
-- Copied from tasty-golden because it isn't exported
109124
updateGoldenFile :: Strict.ByteString -> IO ()
@@ -185,18 +200,19 @@ goldenTests ::
185200
(a -> Encoding) ->
186201
-- | Folder containing the golden files
187202
FilePath ->
203+
Maybe (FilePath, T.Text) ->
188204
TestTree
189-
goldenTests testName examples enc goldenFolder
205+
goldenTests testName examples enc goldenFolder mCDDL
190206
| nub labels /= labels =
191207
error $ "Examples with the same label for " <> testName
192208
| [(Nothing, example)] <- examples =
193209
-- If there's just a single unlabelled example, no need for grouping,
194210
-- which makes the output more verbose.
195-
goldenTestCBOR testName example enc (goldenFolder </> testName)
211+
goldenTestCBOR testName example enc (goldenFolder </> testName) mCDDL
196212
| otherwise =
197213
testGroup
198214
testName
199-
[ goldenTestCBOR testName' example enc (goldenFolder </> testName')
215+
[ goldenTestCBOR testName' example enc (goldenFolder </> testName') mCDDL
200216
| (mbLabel, example) <- examples
201217
, let testName' = case mbLabel of
202218
Nothing -> testName
@@ -212,18 +228,19 @@ goldenTests' ::
212228
Labelled (a, a -> Encoding) ->
213229
-- | Folder containing the golden files
214230
FilePath ->
231+
Maybe (FilePath, T.Text) ->
215232
TestTree
216-
goldenTests' testName examples goldenFolder
233+
goldenTests' testName examples goldenFolder mCDDL
217234
| nub labels /= labels =
218235
error $ "Examples with the same label for " <> testName
219236
| [(Nothing, (example, exampleEncoder))] <- examples =
220237
-- If there's just a single unlabelled example, no need for grouping,
221238
-- which makes the output more verbose.
222-
goldenTestCBOR testName example exampleEncoder (goldenFolder </> testName)
239+
goldenTestCBOR testName example exampleEncoder (goldenFolder </> testName) mCDDL
223240
| otherwise =
224241
testGroup
225242
testName
226-
[ goldenTestCBOR testName' example exampleEncoder (goldenFolder </> testName')
243+
[ goldenTestCBOR testName' example exampleEncoder (goldenFolder </> testName') mCDDL
227244
| (mbLabel, (example, exampleEncoder)) <- examples
228245
, let testName' = case mbLabel of
229246
Nothing -> testName
@@ -272,13 +289,14 @@ goldenTest_all ::
272289
-- | Path relative to the root of the repository that contains the golden
273290
-- files
274291
FilePath ->
292+
Maybe CDDLsForNodeToNode ->
275293
Examples blk ->
276294
TestTree
277-
goldenTest_all codecConfig goldenDir examples =
295+
goldenTest_all codecConfig goldenDir mCDDLs examples =
278296
testGroup
279297
"Golden tests"
280298
[ goldenTest_SerialiseDisk codecConfig goldenDir examples
281-
, goldenTest_SerialiseNodeToNode codecConfig goldenDir examples
299+
, goldenTest_SerialiseNodeToNode codecConfig goldenDir mCDDLs examples
282300
, goldenTest_SerialiseNodeToClient codecConfig goldenDir examples
283301
]
284302

@@ -312,6 +330,7 @@ goldenTest_SerialiseDisk codecConfig goldenDir Examples{..} =
312330
exampleValues
313331
enc
314332
(goldenDir </> "disk")
333+
Nothing
315334

316335
testLedgerTables :: TestTree
317336
testLedgerTables =
@@ -323,6 +342,7 @@ goldenTest_SerialiseDisk codecConfig goldenDir Examples{..} =
323342
exampleLedgerState
324343
)
325344
(goldenDir </> "disk")
345+
Nothing
326346

327347
encodeExt = encodeDiskExtLedgerState codecConfig
328348

@@ -337,9 +357,10 @@ goldenTest_SerialiseNodeToNode ::
337357
) =>
338358
CodecConfig blk ->
339359
FilePath ->
360+
Maybe CDDLsForNodeToNode ->
340361
Examples blk ->
341362
TestTree
342-
goldenTest_SerialiseNodeToNode codecConfig goldenDir Examples{..} =
363+
goldenTest_SerialiseNodeToNode codecConfig goldenDir mCDDLs Examples{..} =
343364
testGroup
344365
"SerialiseNodeToNode"
345366
[ testVersion version
@@ -350,15 +371,15 @@ goldenTest_SerialiseNodeToNode codecConfig goldenDir Examples{..} =
350371
testVersion version =
351372
testGroup
352373
(toGoldenDirectory version)
353-
[ test "Block" exampleBlock
354-
, test "Header" exampleHeader
355-
, test "SerialisedBlock" exampleSerialisedBlock
356-
, test "SerialisedHeader" exampleSerialisedHeader
357-
, test "GenTx" exampleGenTx
358-
, test "GenTxId" exampleGenTxId
374+
[ test "Block" exampleBlock $ fmap blockCDDL mCDDLs
375+
, test "Header" exampleHeader $ fmap headerCDDL mCDDLs
376+
, test "SerialisedBlock" exampleSerialisedBlock Nothing
377+
, test "SerialisedHeader" exampleSerialisedHeader Nothing
378+
, test "GenTx" exampleGenTx Nothing
379+
, test "GenTxId" exampleGenTxId Nothing
359380
]
360381
where
361-
test :: SerialiseNodeToNode blk a => TestName -> Labelled a -> TestTree
382+
test :: SerialiseNodeToNode blk a => TestName -> Labelled a -> Maybe (FilePath, T.Text) -> TestTree
362383
test testName exampleValues =
363384
goldenTests
364385
testName
@@ -416,6 +437,7 @@ goldenTest_SerialiseNodeToClient codecConfig goldenDir Examples{..} =
416437
exampleValues
417438
enc
418439
(goldenDir </> toGoldenDirectory versions)
440+
Nothing
419441

420442
{-------------------------------------------------------------------------------
421443
FlatTerm

0 commit comments

Comments
 (0)