{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.Cardano.Protocol.Binary.CddlSpec (spec) where

import Cardano.Ledger.Allegra (AllegraEra)
import Cardano.Ledger.Alonzo (AlonzoEra)
import Cardano.Ledger.Binary.Group (CBORGroup)
import Cardano.Ledger.Core
import Cardano.Ledger.Mary (MaryEra)
import Cardano.Ledger.Shelley (ShelleyEra)
import Cardano.Protocol.Crypto (StandardCrypto)
import Cardano.Protocol.TPraos.BHeader (BHBody, BHeader)
import Cardano.Protocol.TPraos.OCert (OCert)
import Codec.CBOR.Cuddle.Huddle (Huddle)
import qualified Data.ByteString.Lazy as BSL
import Test.Cardano.Ledger.Allegra.Binary.Cddl (readAllegraCddlFiles)
import Test.Cardano.Ledger.Allegra.CDDL (allegraCDDL)
import Test.Cardano.Ledger.Alonzo.Binary.Cddl (readAlonzoCddlFiles)
import Test.Cardano.Ledger.Alonzo.CDDL (alonzoCDDL)
import Test.Cardano.Ledger.Binary.Cddl (beforeAllCddlFile, cddlRoundTripCborSpec)
import Test.Cardano.Ledger.Binary.Cuddle
import Test.Cardano.Ledger.Common
import Test.Cardano.Ledger.Mary.Binary.Cddl (readMaryCddlFiles)
import Test.Cardano.Ledger.Mary.CDDL (maryCDDL)
import Test.Cardano.Ledger.Shelley.Binary.Cddl (readShelleyCddlFiles)
import Test.Cardano.Ledger.Shelley.CDDL (shelleyCDDL)
import Test.Cardano.Protocol.Binary.Cddl (
  cddlBlockSpec,
  huddleBlockSpec,
 )

spec :: Spec
spec :: Spec
spec =
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"CDDL" forall a b. (a -> b) -> a -> b
$ do
    let n :: Int
n = Int
3
    forall era.
(Era era, AtMostEra AlonzoEra era) =>
IO [ByteString] -> Huddle -> Int -> Spec
specForEra @ShelleyEra IO [ByteString]
readShelleyCddlFiles Huddle
shelleyCDDL Int
n
    forall era.
(Era era, AtMostEra AlonzoEra era) =>
IO [ByteString] -> Huddle -> Int -> Spec
specForEra @AllegraEra IO [ByteString]
readAllegraCddlFiles Huddle
allegraCDDL Int
n
    forall era.
(Era era, AtMostEra AlonzoEra era) =>
IO [ByteString] -> Huddle -> Int -> Spec
specForEra @MaryEra IO [ByteString]
readMaryCddlFiles Huddle
maryCDDL Int
n
    forall era.
(Era era, AtMostEra AlonzoEra era) =>
IO [ByteString] -> Huddle -> Int -> Spec
specForEra @AlonzoEra IO [ByteString]
readAlonzoCddlFiles Huddle
alonzoCDDL Int
n

specForEra ::
  forall era.
  (Era era, AtMostEra AlonzoEra era) =>
  IO [BSL.ByteString] ->
  Huddle ->
  Int ->
  Spec
specForEra :: forall era.
(Era era, AtMostEra AlonzoEra era) =>
IO [ByteString] -> Huddle -> Int -> Spec
specForEra IO [ByteString]
readCddlFiles Huddle
cddlFiles Int
n = do
  forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall era. Era era => String
eraName @era) forall a b. (a -> b) -> a -> b
$ do
    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"Ruby-based" forall a b. (a -> b) -> a -> b
$
      HasCallStack => Int -> IO [ByteString] -> SpecWith CddlData -> Spec
beforeAllCddlFile Int
n IO [ByteString]
readCddlFiles forall a b. (a -> b) -> a -> b
$ do
        forall era c (bh :: * -> *) (bhbody :: * -> *).
(Era era, Eq (bh c), Show (bh c), DecCBOR (bh c), EncCBOR (bh c),
 DecCBOR (Annotator (bh c)), Eq (bhbody c), Show (bhbody c),
 DecCBOR (bhbody c), EncCBOR (bhbody c)) =>
SpecWith CddlData
cddlBlockSpec @era @StandardCrypto @BHeader @BHBody
        forall a.
(HasCallStack, Eq a, Show a, EncCBOR a, DecCBOR a) =>
Version -> Text -> SpecWith CddlData
cddlRoundTripCborSpec @(CBORGroup (OCert StandardCrypto))
          (forall era. Era era => Version
eraProtVerLow @era)
          Text
"[ operational_cert ]"

    forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"Huddle" forall a b. (a -> b) -> a -> b
$
      Huddle -> Int -> SpecWith CuddleData -> Spec
specWithHuddle Huddle
cddlFiles Int
100 forall a b. (a -> b) -> a -> b
$ do
        forall era c (bh :: * -> *) (bhbody :: * -> *).
(Era era, Eq (bh c), Show (bh c), DecCBOR (bh c), EncCBOR (bh c),
 DecCBOR (Annotator (bh c)), Eq (bhbody c), Show (bhbody c),
 DecCBOR (bhbody c), EncCBOR (bhbody c)) =>
SpecWith CuddleData
huddleBlockSpec @era @StandardCrypto @BHeader @BHBody
        forall a. HasCallStack => String -> SpecWith a -> SpecWith a
xdescribe String
"Cannot generate a CBOR term corresponding to a group with cuddle" forall a b. (a -> b) -> a -> b
$
          forall a.
(HasCallStack, Eq a, Show a, EncCBOR a, DecCBOR a) =>
Version -> Text -> SpecWith CuddleData
huddleRoundTripCborSpec @(CBORGroup (OCert StandardCrypto))
            (forall era. Era era => Version
eraProtVerLow @era)
            Text
"[ operational_cert ]"
  where
    _atMostAlonzo :: ()
_atMostAlonzo = forall eraName era. AtMostEra eraName era => ()
atMostEra @AlonzoEra @era