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

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

import Cardano.Ledger.Allegra (AllegraEra)
import Cardano.Ledger.Alonzo (AlonzoEra)
import Cardano.Ledger.Binary (Annotator, DecCBOR, ToCBOR)
import Cardano.Ledger.Block
import Cardano.Ledger.Core
import Cardano.Ledger.Mary (MaryEra)
import Cardano.Ledger.Shelley (ShelleyEra)
import Cardano.Protocol.Crypto
import Cardano.Protocol.TPraos.BlockHeader (BHeader)
import Data.Proxy
import Data.Typeable (typeRep)
import qualified Test.Cardano.Base.QuickCheck as BaseQC
import Test.Cardano.Ledger.Allegra.Arbitrary ()
import Test.Cardano.Ledger.Alonzo.Arbitrary ()
import Test.Cardano.Ledger.Binary (decoderEquivalenceProp)
import Test.Cardano.Ledger.Common
import Test.Cardano.Ledger.Mary.Arbitrary ()
import Test.Cardano.Protocol.Binary.Annotator ()
import Test.Cardano.Protocol.TPraos.Arbitrary ()

spec :: Spec
spec :: Spec
spec = do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"DecCBOR instances equivalence" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    forall era.
(EraBlockBody era, Arbitrary (Tx TopTx era),
 Arbitrary (BlockBody era),
 ToCBOR (Block (BHeader StandardCrypto) era),
 DecCBOR (Annotator (Block (BHeader StandardCrypto) era))) =>
Spec
blockEraSpec @ShelleyEra
    forall era.
(EraBlockBody era, Arbitrary (Tx TopTx era),
 Arbitrary (BlockBody era),
 ToCBOR (Block (BHeader StandardCrypto) era),
 DecCBOR (Annotator (Block (BHeader StandardCrypto) era))) =>
Spec
blockEraSpec @AllegraEra
    forall era.
(EraBlockBody era, Arbitrary (Tx TopTx era),
 Arbitrary (BlockBody era),
 ToCBOR (Block (BHeader StandardCrypto) era),
 DecCBOR (Annotator (Block (BHeader StandardCrypto) era))) =>
Spec
blockEraSpec @MaryEra
    forall era.
(EraBlockBody era, Arbitrary (Tx TopTx era),
 Arbitrary (BlockBody era),
 ToCBOR (Block (BHeader StandardCrypto) era),
 DecCBOR (Annotator (Block (BHeader StandardCrypto) era))) =>
Spec
blockEraSpec @AlonzoEra

blockEraSpec ::
  forall era.
  ( EraBlockBody era
  , Arbitrary (Tx TopTx era)
  , Arbitrary (BlockBody era)
  , ToCBOR (Block (BHeader StandardCrypto) era)
  , DecCBOR (Annotator (Block (BHeader StandardCrypto) era))
  ) =>
  Spec
blockEraSpec :: forall era.
(EraBlockBody era, Arbitrary (Tx TopTx era),
 Arbitrary (BlockBody era),
 ToCBOR (Block (BHeader StandardCrypto) era),
 DecCBOR (Annotator (Block (BHeader StandardCrypto) era))) =>
Spec
blockEraSpec =
  String -> Property -> Spec
forall prop.
(HasCallStack, Testable prop) =>
String -> prop -> Spec
prop (TypeRep -> String
forall a. Show a => a -> String
show (Proxy (Block (BHeader StandardCrypto) era) -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy (Block (BHeader StandardCrypto) era) -> TypeRep)
-> Proxy (Block (BHeader StandardCrypto) era) -> TypeRep
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(Block (BHeader StandardCrypto) era))) (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
    Int -> (Block (BHeader StandardCrypto) era -> Property) -> Property
forall prop. Testable prop => Int -> prop -> Property
BaseQC.withNumTests Int
3 ((Block (BHeader StandardCrypto) era -> Property) -> Property)
-> (Block (BHeader StandardCrypto) era -> Property) -> Property
forall a b. (a -> b) -> a -> b
$
      forall t.
(Eq t, ToCBOR t, DecCBOR (Annotator t), Show t) =>
Version -> Version -> t -> Property
decoderEquivalenceProp @(Block (BHeader StandardCrypto) era)
        (forall era. Era era => Version
eraProtVerLow @era)
        (forall era. Era era => Version
eraProtVerHigh @era)