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

module Test.Cardano.Ledger.Binary.Golden (
  decodeEnc,
  expectDecoderSuccessAnn,
  expectDecoderSuccessAnnWith,
  expectDecoderFailureAnn,
  expectDecoderResultOn,
) where

import Cardano.Ledger.Binary (
  Annotator,
  DecCBOR (..),
  DecoderError,
  ToCBOR (..),
  Version,
  decodeFullAnnotator,
  toLazyByteString,
 )
import qualified Cardano.Ledger.Binary as Binary
import Data.TreeDiff (ToExpr (..))
import Data.Typeable (Proxy (..))
import GHC.Stack (HasCallStack)
import Test.Cardano.Ledger.Binary.Plain.Golden (Enc)
import Test.Cardano.Ledger.Binary.RoundTrip (embedTripAnnExpectation)
import Test.Hspec (Expectation, expectationFailure, shouldBe)

decodeEnc :: forall a. DecCBOR (Annotator a) => Version -> Enc -> Either DecoderError a
decodeEnc :: forall a.
DecCBOR (Annotator a) =>
Version -> Enc -> Either DecoderError a
decodeEnc Version
version Enc
enc = forall a.
Version
-> Text
-> (forall s. Decoder s (Annotator a))
-> ByteString
-> Either DecoderError a
decodeFullAnnotator @a Version
version (Proxy (Annotator a) -> Text
forall a. DecCBOR a => Proxy a -> Text
Binary.label (Proxy (Annotator a) -> Text) -> Proxy (Annotator a) -> Text
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @(Annotator a)) Decoder s (Annotator a)
forall s. Decoder s (Annotator a)
forall a s. DecCBOR a => Decoder s a
decCBOR ByteString
bytes
  where
    bytes :: ByteString
bytes = Encoding -> ByteString
toLazyByteString (Encoding -> ByteString) -> Encoding -> ByteString
forall a b. (a -> b) -> a -> b
$ Enc -> Encoding
forall a. ToCBOR a => a -> Encoding
toCBOR Enc
enc

expectDecoderSuccessAnnWith ::
  forall a.
  ( DecCBOR (Annotator a)
  , HasCallStack
  , Show a
  , Eq a
  ) =>
  (a -> a -> Bool) ->
  Version ->
  Enc ->
  a ->
  Expectation
expectDecoderSuccessAnnWith :: forall a.
(DecCBOR (Annotator a), HasCallStack, Show a, Eq a) =>
(a -> a -> Bool) -> Version -> Enc -> a -> Expectation
expectDecoderSuccessAnnWith a -> a -> Bool
equals Version
version Enc
enc a
expected =
  case forall a.
DecCBOR (Annotator a) =>
Version -> Enc -> Either DecoderError a
decodeEnc @a Version
version Enc
enc of
    Left DecoderError
err -> HasCallStack => String -> Expectation
String -> Expectation
expectationFailure (String -> Expectation) -> String -> Expectation
forall a b. (a -> b) -> a -> b
$ String
"Unexpected decoder failure: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> DecoderError -> String
forall a. Show a => a -> String
show DecoderError
err
    Right a
x | a
x a -> a -> Bool
`equals` a
expected -> () -> Expectation
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Right a
result -> a
result a -> a -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`shouldBe` a
expected

expectDecoderSuccessAnn ::
  ( DecCBOR (Annotator a)
  , Eq a
  , HasCallStack
  , Show a
  ) =>
  Version -> Enc -> a -> Expectation
expectDecoderSuccessAnn :: forall a.
(DecCBOR (Annotator a), Eq a, HasCallStack, Show a) =>
Version -> Enc -> a -> Expectation
expectDecoderSuccessAnn = (a -> a -> Bool) -> Version -> Enc -> a -> Expectation
forall a.
(DecCBOR (Annotator a), HasCallStack, Show a, Eq a) =>
(a -> a -> Bool) -> Version -> Enc -> a -> Expectation
expectDecoderSuccessAnnWith a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)

expectDecoderFailureAnn ::
  forall a.
  (ToExpr a, DecCBOR (Annotator a), HasCallStack) =>
  Version ->
  Enc ->
  DecoderError ->
  Expectation
expectDecoderFailureAnn :: forall a.
(ToExpr a, DecCBOR (Annotator a), HasCallStack) =>
Version -> Enc -> DecoderError -> Expectation
expectDecoderFailureAnn Version
version Enc
enc DecoderError
expectedErr =
  case forall a.
DecCBOR (Annotator a) =>
Version -> Enc -> Either DecoderError a
decodeEnc @a Version
version Enc
enc of
    Left DecoderError
err -> DecoderError
err DecoderError -> DecoderError -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`shouldBe` DecoderError
expectedErr
    Right a
x ->
      HasCallStack => String -> Expectation
String -> Expectation
expectationFailure (String -> Expectation) -> String -> Expectation
forall a b. (a -> b) -> a -> b
$
        String
"Expected a failure, but decoder succeeded:\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Expr -> String
forall a. Show a => a -> String
show (a -> Expr
forall a. ToExpr a => a -> Expr
toExpr a
x)

expectDecoderResultOn ::
  forall a b.
  ( DecCBOR (Annotator a)
  , Eq b
  , HasCallStack
  , Show b
  ) =>
  Version -> Enc -> a -> (a -> b) -> Expectation
expectDecoderResultOn :: forall a b.
(DecCBOR (Annotator a), Eq b, HasCallStack, Show b) =>
Version -> Enc -> a -> (a -> b) -> Expectation
expectDecoderResultOn Version
version Enc
enc a
expected a -> b
f =
  Version
-> Version -> (a -> Enc -> Expectation) -> Enc -> Expectation
forall a b.
(ToCBOR a, DecCBOR (Annotator b), HasCallStack) =>
Version -> Version -> (b -> a -> Expectation) -> a -> Expectation
embedTripAnnExpectation
    Version
version
    Version
version
    (\a
x Enc
_ -> a -> b
f a
x b -> b -> Expectation
forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`shouldBe` a -> b
f a
expected)
    Enc
enc