module Hydra.LoggingSpec where

import Hydra.Prelude
import Test.Hydra.Prelude

import Data.Aeson (object, (.=))
import Data.Aeson.Lens (key)
import Hydra.JSONSchema (prop_specIsComplete, prop_validateJSONSchema)
import Hydra.Ledger.Cardano (Tx)
import Hydra.Logging (Envelope (..), Verbosity (Verbose), traceWith, withTracer)
import Hydra.Logging.Messages (HydraLog)
import System.IO.Silently (capture_)

spec :: Spec
spec :: Spec
spec = do
  [Char] -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
[Char] -> a -> SpecWith (Arg a)
it [Char]
"dumps logs to stdout in JSON with timestamp" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
    [Char]
captured <- IO () -> IO [Char]
forall a. IO a -> IO [Char]
capture_ (IO () -> IO [Char]) -> IO () -> IO [Char]
forall a b. (a -> b) -> a -> b
$ do
      Verbosity -> (Tracer IO Value -> IO ()) -> IO ()
forall (m :: * -> *) msg a.
(MonadIO m, MonadFork m, MonadTime m, ToJSON msg) =>
Verbosity -> (Tracer m msg -> IO a) -> IO a
withTracer (Text -> Verbosity
Verbose Text
"test") ((Tracer IO Value -> IO ()) -> IO ())
-> (Tracer IO Value -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Tracer IO Value
tracer -> do
        Tracer IO Value -> Value -> IO ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer IO Value
tracer ([Pair] -> Value
object [Key
"foo" Key -> Int -> Pair
forall v. ToJSON v => Key -> v -> Pair
forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.= (Int
42 :: Int)])

    -- This test is flakey in CI. Suspected race condition.
    IO () -> IO ()
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ DiffTime -> IO ()
forall (m :: * -> *). MonadDelay m => DiffTime -> m ()
threadDelay DiffTime
2

    [Char]
captured [Char] -> [Char] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => [a] -> [a] -> IO ()
`shouldContain` [Char]
"{\"foo\":42}"

  [Char] -> Property -> Spec
forall prop.
(HasCallStack, Testable prop) =>
[Char] -> prop -> Spec
prop [Char]
"Validates logs.yaml schema" (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
    forall a.
(HasCallStack, ToJSON a, Arbitrary a, Show a) =>
[Char] -> SchemaSelector -> Property
prop_validateJSONSchema @(Envelope (HydraLog Tx ())) [Char]
"logs.json" (Value -> f Value) -> Value -> f Value
forall a. a -> a
SchemaSelector
id

  [Char] -> Property -> Spec
forall prop.
(HasCallStack, Testable prop) =>
[Char] -> prop -> Spec
prop [Char]
"Schema covers all defined log entries" (Property -> Spec) -> Property -> Spec
forall a b. (a -> b) -> a -> b
$
    forall a.
(Arbitrary a, Show a) =>
[Char] -> SchemaSelector -> Property
prop_specIsComplete @(HydraLog Tx ()) [Char]
"logs.json" (Key -> SchemaSelector
forall t. AsValue t => Key -> Traversal' t Value
key Key
"properties" ((Value -> f Value) -> Value -> f Value)
-> ((Value -> f Value) -> Value -> f Value)
-> (Value -> f Value)
-> Value
-> f Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> SchemaSelector
forall t. AsValue t => Key -> Traversal' t Value
key Key
"message")