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

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

import Cardano.Ledger.Allegra (AllegraEra)
import Cardano.Ledger.Allegra.HuddleSpec (allegraCDDL)
import Cardano.Ledger.Alonzo (AlonzoEra)
import Cardano.Ledger.Alonzo.HuddleSpec (alonzoCDDL)
import Cardano.Ledger.Binary.Group (CBORGroup)
import Cardano.Ledger.Core
import Cardano.Ledger.Mary (MaryEra)
import Cardano.Ledger.Mary.HuddleSpec (maryCDDL)
import Cardano.Ledger.Shelley (ShelleyEra)
import Cardano.Ledger.Shelley.HuddleSpec (shelleyCDDL)
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 Test.Cardano.Ledger.Binary.Cuddle
import Test.Cardano.Ledger.Common
import Test.Cardano.Protocol.Binary.Annotator ()
import Test.Cardano.Protocol.Binary.Cddl (huddleBlockSpec)

spec :: Spec
spec :: Spec
spec =
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"CDDL" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    forall era. (Era era, AtMostEra "Alonzo" era) => Huddle -> Spec
specForEra @ShelleyEra Huddle
shelleyCDDL
    forall era. (Era era, AtMostEra "Alonzo" era) => Huddle -> Spec
specForEra @AllegraEra Huddle
allegraCDDL
    forall era. (Era era, AtMostEra "Alonzo" era) => Huddle -> Spec
specForEra @MaryEra Huddle
maryCDDL
    forall era. (Era era, AtMostEra "Alonzo" era) => Huddle -> Spec
specForEra @AlonzoEra Huddle
alonzoCDDL

specForEra ::
  forall era.
  (Era era, AtMostEra "Alonzo" era) =>
  Huddle ->
  Spec
specForEra :: forall era. (Era era, AtMostEra "Alonzo" era) => Huddle -> Spec
specForEra Huddle
cddlFiles = do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe (forall era. Era era => String
eraName @era) (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"Huddle" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$
      Huddle -> SpecWith HuddleEnv -> Spec
specWithHuddle Huddle
cddlFiles (SpecWith HuddleEnv -> Spec)
-> (SpecWith HuddleEnv -> SpecWith HuddleEnv)
-> SpecWith HuddleEnv
-> Spec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SpecWith HuddleEnv -> SpecWith HuddleEnv
noTwiddle (SpecWith HuddleEnv -> Spec) -> SpecWith HuddleEnv -> Spec
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 HuddleEnv
huddleBlockSpec @era @StandardCrypto @BHeader @BHBody
        String -> SpecWith HuddleEnv -> SpecWith HuddleEnv
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
xdescribe String
"Cannot generate a CBOR term corresponding to a group with cuddle" (SpecWith HuddleEnv -> SpecWith HuddleEnv)
-> SpecWith HuddleEnv -> SpecWith HuddleEnv
forall a b. (a -> b) -> a -> b
$
          forall a.
(HasCallStack, Eq a, Show a, EncCBOR a, DecCBOR a) =>
Version -> Text -> SpecWith HuddleEnv
huddleRoundTripCborSpec @(CBORGroup (OCert StandardCrypto))
            (forall era. Era era => Version
eraProtVerLow @era)
            Text
"[ operational_cert ]"
  where
    _atMostAlonzo :: ()
_atMostAlonzo = forall (eraName :: Symbol) era. AtMostEra eraName era => ()
atMostEra @"Alonzo" @era