module Signet.Unstable.Type.SignaturesTest where

import qualified Control.Monad.Catch as Exception
import qualified Crypto.Error as Error
import qualified Crypto.Hash as Hash
import qualified Crypto.PubKey.Ed25519 as Ed25519
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Char8 as Ascii
import qualified Heck as Test
import qualified Signet.Unstable.Exception.InvalidAsymmetricSignature as InvalidAsymmetricSignature
import qualified Signet.Unstable.Exception.InvalidSignature as InvalidSignature
import qualified Signet.Unstable.Exception.InvalidSymmetricSignature as InvalidSymmetricSignature
import qualified Signet.Unstable.Exception.UnknownSignature as UnknownSignature
import qualified Signet.Unstable.Extra.Either as Either
import qualified Signet.Unstable.Type.AsymmetricSignature as AsymmetricSignature
import qualified Signet.Unstable.Type.Signature as Signature
import qualified Signet.Unstable.Type.Signatures as Signatures
import qualified Signet.Unstable.Type.SymmetricSignature as SymmetricSignature

spec :: (Exception.MonadThrow io, Monad tree) => Test.Test io tree -> tree ()
spec :: forall (io :: * -> *) (tree :: * -> *).
(MonadThrow io, Monad tree) =>
Test io tree -> tree ()
spec Test io tree
test = Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"Signet.Unstable.Type.Signatures" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"parse" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"succeeds with no signatures" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      Test io tree
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
ByteString.empty) (([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
forall a b. b -> Either a b
Right ([], [Signature] -> Signatures
Signatures.MkSignatures []))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"succeeds with one signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let signature :: Signature
signature = SymmetricSignature -> Signature
Signature.Symmetric (SymmetricSignature -> Signature)
-> (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256
-> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> Signature) -> Digest SHA256 -> Signature
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="
      Test io tree
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
byteString) (([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
forall a b. b -> Either a b
Right ([], [Signature] -> Signatures
Signatures.MkSignatures [Signature
signature]))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"succeeds with many signatures" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let symmetricSignature :: SymmetricSignature
symmetricSignature = Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256 -> SymmetricSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      asymmetricSignature <- Either CryptoError AsymmetricSignature -> io AsymmetricSignature
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either CryptoError AsymmetricSignature -> io AsymmetricSignature)
-> (ByteString -> Either CryptoError AsymmetricSignature)
-> ByteString
-> io AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> AsymmetricSignature)
-> Either CryptoError Signature
-> Either CryptoError AsymmetricSignature
forall a b.
(a -> b) -> Either CryptoError a -> Either CryptoError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Signature -> AsymmetricSignature
AsymmetricSignature.MkAsymmetricSignature (Either CryptoError Signature
 -> Either CryptoError AsymmetricSignature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> Either CryptoError AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoFailable Signature -> Either CryptoError Signature
forall a. CryptoFailable a -> Either CryptoError a
Error.eitherCryptoError (CryptoFailable Signature -> Either CryptoError Signature)
-> (ByteString -> CryptoFailable Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> CryptoFailable Signature
forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed25519.signature (ByteString -> io AsymmetricSignature)
-> ByteString -> io AsymmetricSignature
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789-abcdefghijklmnopqrstuvqxyz"
      let byteString = String -> ByteString
Ascii.pack String
"v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= v1a,QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVotMDEyMzQ1Njc4OS1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2cXh5eg=="
      let signatures =
            [Signature] -> Signatures
Signatures.MkSignatures
              [ SymmetricSignature -> Signature
Signature.Symmetric SymmetricSignature
symmetricSignature,
                AsymmetricSignature -> Signature
Signature.Asymmetric AsymmetricSignature
asymmetricSignature
              ]
      Test.assertEq test (Signatures.parse byteString) (Right ([], signatures))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"fails with an invalid symmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let x :: ByteString
x = String -> ByteString
Ascii.pack String
"invalid"
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"v1," ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
x
      Test io tree
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
byteString) (InvalidSignature
-> Either InvalidSignature ([UnknownSignature], Signatures)
forall a b. a -> Either a b
Left (InvalidSymmetricSignature -> InvalidSignature
InvalidSignature.InvalidSymmetricSignature (InvalidSymmetricSignature -> InvalidSignature)
-> InvalidSymmetricSignature -> InvalidSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidSymmetricSignature
InvalidSymmetricSignature.MkInvalidSymmetricSignature ByteString
x))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"fails with an invalid asymmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let x :: ByteString
x = String -> ByteString
Ascii.pack String
"invalid"
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"v1a," ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
x
      Test io tree
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
byteString) (InvalidSignature
-> Either InvalidSignature ([UnknownSignature], Signatures)
forall a b. a -> Either a b
Left (InvalidAsymmetricSignature -> InvalidSignature
InvalidSignature.InvalidAsymmetricSignature (InvalidAsymmetricSignature -> InvalidSignature)
-> InvalidAsymmetricSignature -> InvalidSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidAsymmetricSignature
InvalidAsymmetricSignature.MkInvalidAsymmetricSignature ByteString
x))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"succeeds with an unknown signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let byteString :: ByteString
byteString = String -> ByteString
Ascii.pack String
"unknown"
      Test io tree
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
byteString) (([UnknownSignature], Signatures)
-> Either InvalidSignature ([UnknownSignature], Signatures)
forall a b. b -> Either a b
Right ([ByteString -> UnknownSignature
UnknownSignature.MkUnknownSignature ByteString
byteString], [Signature] -> Signatures
Signatures.MkSignatures []))

  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"render" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"renders no signatures" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let signatures :: Signatures
signatures = [Signature] -> Signatures
Signatures.MkSignatures []
      Test io tree -> ByteString -> ByteString -> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (Signatures -> ByteString
Signatures.render Signatures
signatures) ByteString
ByteString.empty

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"renders one signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let signatures :: Signatures
signatures = [Signature] -> Signatures
Signatures.MkSignatures ([Signature] -> Signatures)
-> (Digest SHA256 -> [Signature]) -> Digest SHA256 -> Signatures
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Signature -> [Signature]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Signature -> [Signature])
-> (Digest SHA256 -> Signature) -> Digest SHA256 -> [Signature]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymmetricSignature -> Signature
Signature.Symmetric (SymmetricSignature -> Signature)
-> (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256
-> Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> Signatures) -> Digest SHA256 -> Signatures
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      Test io tree -> ByteString -> ByteString -> io ()
forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
Test.assertEq Test io tree
test (Signatures -> ByteString
Signatures.render Signatures
signatures) (String -> ByteString
Ascii.pack String
"v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"renders many signatures" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let symmetricSignature :: SymmetricSignature
symmetricSignature = Digest SHA256 -> SymmetricSignature
SymmetricSignature.MkSymmetricSignature (Digest SHA256 -> SymmetricSignature)
-> Digest SHA256 -> SymmetricSignature
forall a b. (a -> b) -> a -> b
$ ByteString -> Digest SHA256
forall ba a.
(ByteArrayAccess ba, HashAlgorithm a) =>
ba -> Digest a
Hash.hash ByteString
ByteString.empty
      asymmetricSignature <- Either CryptoError AsymmetricSignature -> io AsymmetricSignature
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either CryptoError AsymmetricSignature -> io AsymmetricSignature)
-> (ByteString -> Either CryptoError AsymmetricSignature)
-> ByteString
-> io AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Signature -> AsymmetricSignature)
-> Either CryptoError Signature
-> Either CryptoError AsymmetricSignature
forall a b.
(a -> b) -> Either CryptoError a -> Either CryptoError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Signature -> AsymmetricSignature
AsymmetricSignature.MkAsymmetricSignature (Either CryptoError Signature
 -> Either CryptoError AsymmetricSignature)
-> (ByteString -> Either CryptoError Signature)
-> ByteString
-> Either CryptoError AsymmetricSignature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CryptoFailable Signature -> Either CryptoError Signature
forall a. CryptoFailable a -> Either CryptoError a
Error.eitherCryptoError (CryptoFailable Signature -> Either CryptoError Signature)
-> (ByteString -> CryptoFailable Signature)
-> ByteString
-> Either CryptoError Signature
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> CryptoFailable Signature
forall ba. ByteArrayAccess ba => ba -> CryptoFailable Signature
Ed25519.signature (ByteString -> io AsymmetricSignature)
-> ByteString -> io AsymmetricSignature
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789-abcdefghijklmnopqrstuvqxyz"
      let signatures =
            [Signature] -> Signatures
Signatures.MkSignatures
              [ SymmetricSignature -> Signature
Signature.Symmetric SymmetricSignature
symmetricSignature,
                AsymmetricSignature -> Signature
Signature.Asymmetric AsymmetricSignature
asymmetricSignature
              ]
      Test.assertEq test (Signatures.render signatures) (Ascii.pack "v1,47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= v1a,QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVotMDEyMzQ1Njc4OS1hYmNkZWZnaGlqa2xtbm9wcXJzdHV2cXh5eg==")