module Test.Ouroboros.Storage.LedgerDB.Serialisation (tests) where

import Codec.CBOR.FlatTerm
  ( FlatTerm
  , TermToken (..)
  , fromFlatTerm
  , toFlatTerm
  )
import Codec.Serialise (decode, encode)
import Ouroboros.Consensus.Storage.LedgerDB.Snapshots
import Test.Tasty
import Test.Tasty.HUnit
import Test.Util.Orphans.Arbitrary ()

tests :: TestTree
tests :: TestTree
tests =
  String -> [TestTree] -> TestTree
testGroup
    String
"Serialisation"
    [ String -> Assertion -> TestTree
testCase String
"encode" Assertion
test_encode_ledger
    , String -> Assertion -> TestTree
testCase String
"decode" Assertion
test_decode_ledger
    ]

{-------------------------------------------------------------------------------
  Serialisation
-------------------------------------------------------------------------------}

-- | The LedgerDB is parametric in the ledger @l@. We use @Int@ for simplicity.
example_ledger :: Int
example_ledger :: Int
example_ledger = Int
100

golden_ledger :: FlatTerm
golden_ledger :: [TermToken]
golden_ledger =
  [ Word -> TermToken
TkListLen Word
2
  , -- VersionNumber
    Int -> TermToken
TkInt Int
2
  , -- ledger: Int
    Int -> TermToken
TkInt Int
100
  ]

test_encode_ledger :: Assertion
test_encode_ledger :: Assertion
test_encode_ledger =
  Encoding -> [TermToken]
toFlatTerm (Int -> Encoding
enc Int
example_ledger) [TermToken] -> [TermToken] -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= [TermToken]
golden_ledger
 where
  enc :: Int -> Encoding
enc = (Int -> Encoding) -> Int -> Encoding
forall l. (l -> Encoding) -> l -> Encoding
encodeL Int -> Encoding
forall a. Serialise a => a -> Encoding
encode

test_decode_ledger :: Assertion
test_decode_ledger :: Assertion
test_decode_ledger =
  (forall s. Decoder s Int) -> [TermToken] -> Either String Int
forall a. (forall s. Decoder s a) -> [TermToken] -> Either String a
fromFlatTerm Decoder s Int
forall s. Decoder s Int
dec [TermToken]
golden_ledger Either String Int -> Either String Int -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Int -> Either String Int
forall a b. b -> Either a b
Right Int
example_ledger
 where
  dec :: Decoder s Int
dec = (forall s. Decoder s Int) -> forall s. Decoder s Int
forall l. (forall s. Decoder s l) -> forall s. Decoder s l
decodeL Decoder s Int
forall s. Decoder s Int
forall a s. Serialise a => Decoder s a
decode