module Signet.Unstable.Type.MessageTest where

import qualified Data.ByteString.Char8 as Ascii
import qualified Signet.Unstable.Exception.InvalidMessage as InvalidMessage
import qualified Signet.Unstable.Exception.InvalidTimestamp as InvalidTimestamp
import qualified Signet.Unstable.Extra.Either as Either
import qualified Signet.Unstable.Extra.Tasty as Tasty
import qualified Signet.Unstable.Type.Id as Id
import qualified Signet.Unstable.Type.Message as Message
import qualified Signet.Unstable.Type.Payload as Payload
import qualified Signet.Unstable.Type.Timestamp as Timestamp
import Test.Tasty.HUnit ((@?=))

spec :: Tasty.Spec
spec :: Spec
spec = TestName -> Spec -> Spec
Tasty.describe TestName
"Signet.Unstable.Type.Message" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
  TestName -> Spec -> Spec
Tasty.describe TestName
"parse" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    TestName -> Assertion -> Spec
Tasty.it TestName
"fails with invalid timestamp" (Assertion -> Spec) -> Assertion -> Spec
forall a b. (a -> b) -> a -> b
$ do
      let timestamp :: ByteString
timestamp = TestName -> ByteString
Ascii.pack TestName
"invalid"
      let byteString :: ByteString
byteString = TestName -> ByteString
Ascii.pack TestName
"i." ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
timestamp ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> TestName -> ByteString
Ascii.pack TestName
".p"
      let result :: Either InvalidMessage Message
result = ByteString -> Either InvalidMessage Message
Message.parse ByteString
byteString
      Either InvalidMessage Message
result Either InvalidMessage Message
-> Either InvalidMessage Message -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= InvalidMessage -> Either InvalidMessage Message
forall a b. a -> Either a b
Left (InvalidTimestamp -> InvalidMessage
InvalidMessage.InvalidTimestamp (InvalidTimestamp -> InvalidMessage)
-> InvalidTimestamp -> InvalidMessage
forall a b. (a -> b) -> a -> b
$ ByteString -> InvalidTimestamp
InvalidTimestamp.MkInvalidTimestamp ByteString
timestamp)

    TestName -> Assertion -> Spec
Tasty.it TestName
"succeeds with valid input" (Assertion -> Spec) -> Assertion -> Spec
forall a b. (a -> b) -> a -> b
$ do
      let result :: Either InvalidMessage Message
result = ByteString -> Either InvalidMessage Message
Message.parse (ByteString -> Either InvalidMessage Message)
-> ByteString -> Either InvalidMessage Message
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i.0.p"
      Id
id_ <- Either InvalidId Id -> IO Id
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidId Id -> IO Id)
-> (ByteString -> Either InvalidId Id) -> ByteString -> IO Id
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidId Id
Id.parse (ByteString -> IO Id) -> ByteString -> IO Id
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i"
      Timestamp
timestamp <- Either InvalidTimestamp Timestamp -> IO Timestamp
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidTimestamp Timestamp -> IO Timestamp)
-> (ByteString -> Either InvalidTimestamp Timestamp)
-> ByteString
-> IO Timestamp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidTimestamp Timestamp
Timestamp.parse (ByteString -> IO Timestamp) -> ByteString -> IO Timestamp
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"0"
      let payload :: Payload
payload = ByteString -> Payload
Payload.MkPayload (ByteString -> Payload) -> ByteString -> Payload
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"p"
      Either InvalidMessage Message
result
        Either InvalidMessage Message
-> Either InvalidMessage Message -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Message -> Either InvalidMessage Message
forall a b. b -> Either a b
Right
          Message.MkMessage
            { id_ :: Id
Message.id_ = Id
id_,
              timestamp :: Timestamp
Message.timestamp = Timestamp
timestamp,
              payload :: Payload
Message.payload = Payload
payload
            }

  TestName -> Spec -> Spec
Tasty.describe TestName
"render" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    TestName -> Assertion -> Spec
Tasty.it TestName
"returns the correct ByteString representation" (Assertion -> Spec) -> Assertion -> Spec
forall a b. (a -> b) -> a -> b
$ do
      Id
id_ <- Either InvalidId Id -> IO Id
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidId Id -> IO Id)
-> (ByteString -> Either InvalidId Id) -> ByteString -> IO Id
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidId Id
Id.parse (ByteString -> IO Id) -> ByteString -> IO Id
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i"
      Timestamp
timestamp <- Either InvalidTimestamp Timestamp -> IO Timestamp
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidTimestamp Timestamp -> IO Timestamp)
-> (ByteString -> Either InvalidTimestamp Timestamp)
-> ByteString
-> IO Timestamp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidTimestamp Timestamp
Timestamp.parse (ByteString -> IO Timestamp) -> ByteString -> IO Timestamp
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"0"
      let payload :: Payload
payload = ByteString -> Payload
Payload.MkPayload (ByteString -> Payload) -> ByteString -> Payload
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"p"
      let message :: Message
message =
            Message.MkMessage
              { id_ :: Id
Message.id_ = Id
id_,
                timestamp :: Timestamp
Message.timestamp = Timestamp
timestamp,
                payload :: Payload
Message.payload = Payload
payload
              }
      Message -> ByteString
Message.render Message
message ByteString -> ByteString -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= TestName -> ByteString
Ascii.pack TestName
"i.0.p"