module HaskellWorks.Polysemy.Hedgehog.Golden
( diffVsGoldenFile,
diffFileVsGoldenFile,
diffJsonVsGoldenFile,
diffYamlVsGoldenFile,
) where
import Control.Applicative
import Control.Monad
import qualified Data.Aeson as J
import Data.Algorithm.Diff (PolyDiff (Both),
getGroupedDiff)
import Data.Algorithm.DiffOutput (ppDiff)
import Data.Bool
import Data.Eq
import Data.Function
import Data.Maybe
import Data.Monoid
import Data.String
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import GHC.Stack (callStack)
import HaskellWorks.Polysemy.Hedgehog.Assert
import HaskellWorks.Polysemy.Hedgehog.Jot
import System.FilePath (takeDirectory)
import qualified Control.Concurrent.QSem as IO
import qualified Data.ByteString.Lazy as LBS
import qualified Data.List as List
import Data.Yaml as Y
import qualified HaskellWorks.Polysemy.Control.Concurrent.QSem as PIO
import HaskellWorks.Polysemy.Data.ByteString as PBS
import HaskellWorks.Polysemy.Prelude
import HaskellWorks.Polysemy.System.Directory as PIO
import HaskellWorks.Polysemy.System.IO as PIO
import Polysemy
import Polysemy.Error
import Polysemy.Log
import Polysemy.Resource
import qualified System.Environment as IO
import qualified System.IO.Unsafe as IO
sem :: IO.QSem
sem :: QSem
sem = IO QSem -> QSem
forall a. IO a -> a
IO.unsafePerformIO (IO QSem -> QSem) -> IO QSem -> QSem
forall a b. (a -> b) -> a -> b
$ Int -> IO QSem
IO.newQSem Int
1
{-# NOINLINE sem #-}
mGoldenFileLogFile :: Maybe FilePath
mGoldenFileLogFile :: Maybe String
mGoldenFileLogFile = IO (Maybe String) -> Maybe String
forall a. IO a -> a
IO.unsafePerformIO (IO (Maybe String) -> Maybe String)
-> IO (Maybe String) -> Maybe String
forall a b. (a -> b) -> a -> b
$
String -> IO (Maybe String)
IO.lookupEnv String
"GOLDEN_FILE_LOG_FILE"
createGoldenFiles :: Bool
createGoldenFiles :: Bool
createGoldenFiles = IO Bool -> Bool
forall a. IO a -> a
IO.unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
Maybe String
value <- String -> IO (Maybe String)
IO.lookupEnv String
"CREATE_GOLDEN_FILES"
Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Maybe String
value Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> Maybe String
forall a. a -> Maybe a
Just String
"1"
recreateGoldenFiles :: Bool
recreateGoldenFiles :: Bool
recreateGoldenFiles = IO Bool -> Bool
forall a. IO a -> a
IO.unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$ do
Maybe String
value <- String -> IO (Maybe String)
IO.lookupEnv String
"RECREATE_GOLDEN_FILES"
Bool -> IO Bool
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Maybe String
value Maybe String -> Maybe String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> Maybe String
forall a. a -> Maybe a
Just String
"1"
writeGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member (Error IOException) r
=> Member Log r
=> FilePath
-> String
-> Sem r ()
writeGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> String -> Sem r ()
writeGoldenFile String
goldenFile String
actualContent = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
String -> Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, ToString a) =>
a -> Sem r ()
jot_ (String -> Sem r ()) -> String -> Sem r ()
forall a b. (a -> b) -> a -> b
$ String
"Creating golden file " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
goldenFile
Bool -> String -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
Bool -> String -> Sem r ()
PIO.createDirectoryIfMissing Bool
True (String -> String
takeDirectory String
goldenFile)
String -> String -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> String -> Sem r ()
PIO.writeFile String
goldenFile String
actualContent
writeByteStringGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member (Error IOException) r
=> Member Log r
=> FilePath
-> ByteString
-> Sem r ()
writeByteStringGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> ByteString -> Sem r ()
writeByteStringGoldenFile String
goldenFile ByteString
bs = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
String -> Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, ToString a) =>
a -> Sem r ()
jot_ (String -> Sem r ()) -> String -> Sem r ()
forall a b. (a -> b) -> a -> b
$ String
"Creating golden file " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
goldenFile
Bool -> String -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
Bool -> String -> Sem r ()
PIO.createDirectoryIfMissing Bool
True (String -> String
takeDirectory String
goldenFile)
String -> ByteString -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> ByteString -> Sem r ()
PBS.writeFile String
goldenFile ByteString
bs
reportGoldenFileMissing :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member (Error IOException) r
=> Member Log r
=> FilePath
-> Sem r ()
reportGoldenFileMissing :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> Sem r ()
reportGoldenFileMissing String
goldenFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
String -> Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, ToString a) =>
a -> Sem r ()
jot_ (String -> Sem r ()) -> String -> Sem r ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Golden file " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
goldenFile String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" does not exist."
, String
"To create it, run with CREATE_GOLDEN_FILES=1."
, String
"To recreate it, run with RECREATE_GOLDEN_FILES=1."
]
Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack) =>
Sem r a
failure
checkAgainstGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member (Error IOException) r
=> Member Log r
=> FilePath
-> [String]
-> Sem r ()
checkAgainstGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> [String] -> Sem r ()
checkAgainstGoldenFile String
goldenFile [String]
actualLines = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
[String]
referenceLines <- String -> [String]
List.lines (String -> [String]) -> Sem r String -> Sem r [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Sem r String
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> Sem r String
PIO.readFile String
goldenFile
let difference :: [Diff [String]]
difference = [String] -> [String] -> [Diff [String]]
forall a. Eq a => [a] -> [a] -> [Diff [a]]
getGroupedDiff [String]
actualLines [String]
referenceLines
case [Diff [String]]
difference of
[] -> () -> Sem r ()
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
[Both{}] -> () -> Sem r ()
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
[Diff [String]]
_ -> do
String -> Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, ToString a) =>
a -> Sem r ()
jot_ (String -> Sem r ()) -> String -> Sem r ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
[ String
"Golden test failed against golden file: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
goldenFile
, String
"To recreate golden file, run with RECREATE_GOLDEN_FILES=1."
]
CallStack -> String -> Sem r ()
forall a (r :: EffectRow).
(Member Hedgehog r, HasCallStack) =>
CallStack -> String -> Sem r a
failMessage CallStack
HasCallStack => CallStack
callStack (String -> Sem r ()) -> String -> Sem r ()
forall a b. (a -> b) -> a -> b
$ [Diff [String]] -> String
ppDiff [Diff [String]]
difference
diffVsGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member Resource r
=> Member Log r
=> String
-> FilePath
-> Sem r ()
diffVsGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r) =>
String -> String -> Sem r ()
diffVsGoldenFile String
actualContent String
goldenFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
Maybe String -> (String -> Sem r ()) -> Sem r ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe String
mGoldenFileLogFile ((String -> Sem r ()) -> Sem r ())
-> (String -> Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ \String
logFile ->
QSem -> Sem r () -> Sem r ()
forall a (r :: EffectRow) (m :: * -> *).
(MonadIO m, Member (Embed m) r, Member Resource r) =>
QSem -> Sem r a -> Sem r a
PIO.bracketQSem QSem
sem (Sem r () -> Sem r ()) -> Sem r () -> Sem r ()
forall a b. (a -> b) -> a -> b
$
String -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> String -> Sem r ()
PIO.appendFile String
logFile (String
goldenFile String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n")
Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
Bool
fileExists <- String -> Sem (Error IOException : r) Bool
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> Sem r Bool
PIO.doesFileExist String
goldenFile
Sem (Error IOException : r) Bool
-> (Sem (Error IOException : r) Bool -> Sem r Bool) -> Sem r Bool
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
if
| Bool
recreateGoldenFiles -> String -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> String -> Sem r ()
writeGoldenFile String
goldenFile String
actualContent Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
fileExists -> String -> [String] -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> [String] -> Sem r ()
checkAgainstGoldenFile String
goldenFile [String]
actualLines Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
createGoldenFiles -> String -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> String -> Sem r ()
writeGoldenFile String
goldenFile String
actualContent Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
otherwise -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> Sem r ()
reportGoldenFileMissing String
goldenFile Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
where
actualLines :: [String]
actualLines = String -> [String]
List.lines String
actualContent
diffByteStringVsGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member Resource r
=> Member Log r
=> ByteString
-> FilePath
-> Sem r ()
diffByteStringVsGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r) =>
ByteString -> String -> Sem r ()
diffByteStringVsGoldenFile ByteString
bs String
goldenFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
Maybe String -> (String -> Sem r ()) -> Sem r ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe String
mGoldenFileLogFile ((String -> Sem r ()) -> Sem r ())
-> (String -> Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ \String
logFile ->
QSem -> Sem r () -> Sem r ()
forall a (r :: EffectRow) (m :: * -> *).
(MonadIO m, Member (Embed m) r, Member Resource r) =>
QSem -> Sem r a -> Sem r a
PIO.bracketQSem QSem
sem (Sem r () -> Sem r ()) -> Sem r () -> Sem r ()
forall a b. (a -> b) -> a -> b
$
String -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> String -> Sem r ()
PIO.appendFile String
logFile (String
goldenFile String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"\n")
Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
Bool
fileExists <- String -> Sem (Error IOException : r) Bool
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> Sem r Bool
PIO.doesFileExist String
goldenFile
Sem (Error IOException : r) Bool
-> (Sem (Error IOException : r) Bool -> Sem r Bool) -> Sem r Bool
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
if
| Bool
recreateGoldenFiles -> String -> ByteString -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> ByteString -> Sem r ()
writeByteStringGoldenFile String
goldenFile ByteString
bs Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
fileExists -> String -> [String] -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> [String] -> Sem r ()
checkAgainstGoldenFile String
goldenFile [String]
actualLines Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
createGoldenFiles -> String -> ByteString -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> ByteString -> Sem r ()
writeByteStringGoldenFile String
goldenFile ByteString
bs Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
| Bool
otherwise -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member (Error IOException) r, Member Log r) =>
String -> Sem r ()
reportGoldenFileMissing String
goldenFile Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
where
actualLines :: [String]
actualLines = String -> [String]
List.lines (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
T.decodeUtf8 ByteString
bs
diffJsonVsGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member Resource r
=> Member Log r
=> ToJSON a
=> a
-> FilePath
-> Sem r ()
diffJsonVsGoldenFile :: forall (r :: EffectRow) a.
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r, ToJSON a) =>
a -> String -> Sem r ()
diffJsonVsGoldenFile a
a String
goldenFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$
ByteString -> String -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r) =>
ByteString -> String -> Sem r ()
diffByteStringVsGoldenFile (ByteString -> ByteString
LBS.toStrict (a -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode a
a)) String
goldenFile
diffYamlVsGoldenFile :: ()
=> HasCallStack
=> Member Hedgehog r
=> Member (Embed IO) r
=> Member Resource r
=> Member Log r
=> ToJSON a
=> a
-> FilePath
-> Sem r ()
diffYamlVsGoldenFile :: forall (r :: EffectRow) a.
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r, ToJSON a) =>
a -> String -> Sem r ()
diffYamlVsGoldenFile a
a String
goldenFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$
ByteString -> String -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r) =>
ByteString -> String -> Sem r ()
diffByteStringVsGoldenFile (a -> ByteString
forall a. ToJSON a => a -> ByteString
Y.encode a
a) String
goldenFile
diffFileVsGoldenFile :: ()
=> HasCallStack
=> Member (Embed IO) r
=> Member Hedgehog r
=> Member Log r
=> Member Resource r
=> FilePath
-> FilePath
-> Sem r ()
diffFileVsGoldenFile :: forall (r :: EffectRow).
(HasCallStack, Member (Embed IO) r, Member Hedgehog r,
Member Log r, Member Resource r) =>
String -> String -> Sem r ()
diffFileVsGoldenFile String
actualFile String
referenceFile = (HasCallStack => Sem r ()) -> Sem r ()
forall a. HasCallStack => (HasCallStack => a) -> a
withFrozenCallStack ((HasCallStack => Sem r ()) -> Sem r ())
-> (HasCallStack => Sem r ()) -> Sem r ()
forall a b. (a -> b) -> a -> b
$ do
String
contents <- String -> Sem (Error IOException : r) String
forall (r :: EffectRow).
(HasCallStack, Member (Error IOException) r, Member (Embed IO) r,
Member Log r) =>
String -> Sem r String
PIO.readFile String
actualFile
Sem (Error IOException : r) String
-> (Sem (Error IOException : r) String -> Sem r String)
-> Sem r String
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException
String -> String -> Sem (Error IOException : r) ()
forall (r :: EffectRow).
(HasCallStack, Member Hedgehog r, Member (Embed IO) r,
Member Resource r, Member Log r) =>
String -> String -> Sem r ()
diffVsGoldenFile String
contents String
referenceFile
Sem (Error IOException : r) ()
-> (Sem (Error IOException : r) () -> Sem r ()) -> Sem r ()
forall a b. a -> (a -> b) -> b
& forall e a (r :: EffectRow).
(Member Hedgehog r, HasCallStack, Show e) =>
Sem (Error e : r) a -> Sem r a
trapFail @IOException