{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeApplications #-}
module Hedgehog.Extras.Test.File
( createDirectoryIfMissing
, createDirectoryIfMissing_
, createSubdirectoryIfMissing
, createSubdirectoryIfMissing_
, copyFile
, renameFile
, createFileLink
, listDirectory
, appendFile
, writeFile
, openFile
, readFile
, lbsWriteFile
, lbsReadFile
, textWriteFile
, textReadFile
, copyRewriteJsonFile
, readJsonFile
, readJsonFileOk
, rewriteJsonFile
, rewriteLbsJson
, copyRewriteYamlFile
, readYamlFile
, readYamlFileOk
, rewriteYamlFile
, rewriteLbsYaml
, cat
, assertIsJsonFile
, assertIsYamlFile
, assertFileExists
, assertFilesExist
, assertFileMissing
, assertFilesMissing
, assertFileOccurences
, assertFileLines
, assertEndsWithSingleNewline
, appendFileTimeDelta
) where
import Control.Applicative (Applicative (..))
import Control.Monad
import Control.Monad.IO.Class
import Data.Aeson (Value)
import Data.Bool
import Data.Either
import Data.Foldable (for_)
import Data.Function
import Data.Functor
import Data.Int
import Data.Maybe
import Data.Semigroup
import Data.String (String)
import Data.Text (Text)
import Data.Time.Clock (UTCTime)
import GHC.Stack (HasCallStack)
import Hedgehog (MonadTest)
import Hedgehog.Extras.Stock.Monad
import Hedgehog.Extras.Stock.OS
import System.FilePath ((</>))
import System.IO (FilePath, Handle, IOMode)
import Text.Show
import qualified Data.Aeson as J
import qualified Data.ByteString.Lazy as LBS
import qualified Data.List as L
import qualified Data.Text.IO as T
import qualified Data.Time.Clock as DTC
import qualified Data.Yaml as Y
import qualified GHC.Stack as GHC
import qualified Hedgehog as H
import qualified Hedgehog.Extras.Test.Base as H
import qualified System.Directory as IO
import qualified System.IO as IO
createDirectoryIfMissing :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m FilePath
createDirectoryIfMissing :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
createDirectoryIfMissing FilePath
directory = (HasCallStack => m FilePath) -> m FilePath
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m FilePath) -> m FilePath)
-> (HasCallStack => m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ do
FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Creating directory if missing: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
directory
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
IO.createDirectoryIfMissing Bool
True FilePath
directory
FilePath -> m FilePath
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
directory
createDirectoryIfMissing_ :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
createDirectoryIfMissing_ :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
createDirectoryIfMissing_ FilePath
directory = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$
m FilePath -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m FilePath -> m ()) -> m FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m FilePath
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
createDirectoryIfMissing FilePath
directory
createSubdirectoryIfMissing :: ()
=> HasCallStack
=> MonadTest m
=> MonadIO m
=> FilePath
-> FilePath
-> m FilePath
createSubdirectoryIfMissing :: forall (m :: * -> *).
(HasCallStack, MonadTest m, MonadIO m) =>
FilePath -> FilePath -> m FilePath
createSubdirectoryIfMissing FilePath
parent FilePath
subdirectory = (HasCallStack => m FilePath) -> m FilePath
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m FilePath) -> m FilePath)
-> (HasCallStack => m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ do
FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Creating subdirectory if missing: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
subdirectory
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
IO.createDirectoryIfMissing Bool
True (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
parent FilePath -> FilePath -> FilePath
</> FilePath
subdirectory
FilePath -> m FilePath
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FilePath
subdirectory
createSubdirectoryIfMissing_ :: ()
=> HasCallStack
=> MonadTest m
=> MonadIO m
=> FilePath
-> FilePath
-> m ()
createSubdirectoryIfMissing_ :: forall (m :: * -> *).
(HasCallStack, MonadTest m, MonadIO m) =>
FilePath -> FilePath -> m ()
createSubdirectoryIfMissing_ FilePath
parent FilePath
subdirectory = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$
m FilePath -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m FilePath -> m ()) -> m FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> m FilePath
forall (m :: * -> *).
(HasCallStack, MonadTest m, MonadIO m) =>
FilePath -> FilePath -> m FilePath
createSubdirectoryIfMissing FilePath
parent FilePath
subdirectory
copyFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> FilePath -> m ()
copyFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
copyFile FilePath
src FilePath
dst = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Copying from " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
src FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" to " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
dst
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.copyFile FilePath
src FilePath
dst
renameFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> FilePath -> m ()
renameFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
renameFile FilePath
src FilePath
dst = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Renaming from " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
src FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" to " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
dst
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.renameFile FilePath
src FilePath
dst
createFileLink :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> FilePath -> m ()
createFileLink :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
createFileLink FilePath
src FilePath
dst = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Creating link from " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
dst FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" to " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
src
if Bool
isWin32
then IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.copyFile FilePath
src FilePath
dst
else IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.createFileLink FilePath
src FilePath
dst
listDirectory :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m [FilePath]
listDirectory :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m [FilePath]
listDirectory FilePath
p = (HasCallStack => m [FilePath]) -> m [FilePath]
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m [FilePath]) -> m [FilePath])
-> (HasCallStack => m [FilePath]) -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Listing directory: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
p
IO [FilePath] -> m [FilePath]
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO [FilePath] -> m [FilePath]) -> IO [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO [FilePath]
IO.listDirectory FilePath
p
appendFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> String -> m ()
appendFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
appendFile FilePath
filePath FilePath
contents = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Writing file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.appendFile FilePath
filePath FilePath
contents
writeFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> String -> m ()
writeFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
writeFile FilePath
filePath FilePath
contents = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Writing file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
IO.writeFile FilePath
filePath FilePath
contents
openFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> IOMode -> m Handle
openFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> IOMode -> m Handle
openFile FilePath
filePath IOMode
mode = (HasCallStack => m Handle) -> m Handle
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m Handle) -> m Handle)
-> (HasCallStack => m Handle) -> m Handle
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Opening file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO Handle -> m Handle
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO Handle -> m Handle) -> IO Handle -> m Handle
forall a b. (a -> b) -> a -> b
$ FilePath -> IOMode -> IO Handle
IO.openFile FilePath
filePath IOMode
mode
readFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m String
readFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
readFile FilePath
filePath = (HasCallStack => m FilePath) -> m FilePath
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m FilePath) -> m FilePath)
-> (HasCallStack => m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Reading file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO FilePath -> m FilePath
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO FilePath -> m FilePath) -> IO FilePath -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
IO.readFile FilePath
filePath
lbsWriteFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> LBS.ByteString -> m ()
lbsWriteFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> ByteString -> m ()
lbsWriteFile FilePath
filePath ByteString
contents = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Writing file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> ByteString -> IO ()
LBS.writeFile FilePath
filePath ByteString
contents
lbsReadFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m LBS.ByteString
lbsReadFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ByteString
lbsReadFile FilePath
filePath = (HasCallStack => m ByteString) -> m ByteString
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ByteString) -> m ByteString)
-> (HasCallStack => m ByteString) -> m ByteString
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Reading file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO ByteString -> m ByteString
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ByteString
LBS.readFile FilePath
filePath
textWriteFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> Text -> m ()
textWriteFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> Text -> m ()
textWriteFile FilePath
filePath Text
contents = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Writing file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO () -> m ()
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> Text -> IO ()
T.writeFile FilePath
filePath Text
contents
textReadFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m Text
textReadFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m Text
textReadFile FilePath
filePath = (HasCallStack => m Text) -> m Text
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m Text) -> m Text)
-> (HasCallStack => m Text) -> m Text
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Reading file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO Text -> m Text
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Text
T.readFile FilePath
filePath
readJsonFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m (Either String Value)
readJsonFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either FilePath Value)
readJsonFile FilePath
filePath = (HasCallStack => m (Either FilePath Value))
-> m (Either FilePath Value)
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m (Either FilePath Value))
-> m (Either FilePath Value))
-> (HasCallStack => m (Either FilePath Value))
-> m (Either FilePath Value)
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Reading JSON file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO (Either FilePath Value) -> m (Either FilePath Value)
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO (Either FilePath Value) -> m (Either FilePath Value))
-> IO (Either FilePath Value) -> m (Either FilePath Value)
forall a b. (a -> b) -> a -> b
$ forall a. FromJSON a => ByteString -> Either FilePath a
J.eitherDecode @Value (ByteString -> Either FilePath Value)
-> IO ByteString -> IO (Either FilePath Value)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO ByteString
LBS.readFile FilePath
filePath
readJsonFileOk :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m Value
readJsonFileOk :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m Value
readJsonFileOk FilePath
filePath = (HasCallStack => m Value) -> m Value
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m Value) -> m Value)
-> (HasCallStack => m Value) -> m Value
forall a b. (a -> b) -> a -> b
$
m (Either FilePath Value) -> m Value
forall (m :: * -> *) e a.
(MonadTest m, Show e, HasCallStack) =>
m (Either e a) -> m a
H.leftFailM (m (Either FilePath Value) -> m Value)
-> m (Either FilePath Value) -> m Value
forall a b. (a -> b) -> a -> b
$ FilePath -> m (Either FilePath Value)
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either FilePath Value)
readJsonFile FilePath
filePath
rewriteLbsJson :: (MonadTest m, HasCallStack) => (Value -> Value) -> LBS.ByteString -> m LBS.ByteString
rewriteLbsJson :: forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsJson Value -> Value
f ByteString
lbs = (HasCallStack => m ByteString) -> m ByteString
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ByteString) -> m ByteString)
-> (HasCallStack => m ByteString) -> m ByteString
forall a b. (a -> b) -> a -> b
$ do
case ByteString -> Either FilePath Value
forall a. FromJSON a => ByteString -> Either FilePath a
J.eitherDecode ByteString
lbs of
Right Value
iv -> ByteString -> m ByteString
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode (Value -> Value
f Value
iv))
Left FilePath
msg -> CallStack -> FilePath -> m ByteString
forall (m :: * -> *) a. MonadTest m => CallStack -> FilePath -> m a
H.failMessage CallStack
HasCallStack => CallStack
GHC.callStack FilePath
msg
rewriteJsonFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> (Value -> Value) -> m ()
rewriteJsonFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> (Value -> Value) -> m ()
rewriteJsonFile FilePath
filePath Value -> Value
f = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Rewriting JSON file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
FilePath -> m ByteString
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ByteString
lbsReadFile FilePath
filePath m ByteString -> (ByteString -> m ByteString) -> m ByteString
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Value) -> ByteString -> m ByteString
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsJson Value -> Value
f m ByteString -> (ByteString -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FilePath -> ByteString -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> ByteString -> m ()
lbsWriteFile FilePath
filePath
copyRewriteJsonFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> FilePath -> (Value -> Value) -> m ()
copyRewriteJsonFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> (Value -> Value) -> m ()
copyRewriteJsonFile FilePath
src FilePath
dst Value -> Value
f = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Rewriting JSON from file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
src FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" to file " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
dst
FilePath -> m ByteString
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ByteString
lbsReadFile FilePath
src m ByteString -> (ByteString -> m ByteString) -> m ByteString
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Value) -> ByteString -> m ByteString
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsJson Value -> Value
f m ByteString -> (ByteString -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FilePath -> ByteString -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> ByteString -> m ()
lbsWriteFile FilePath
dst
readYamlFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m (Either Y.ParseException Value)
readYamlFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either ParseException Value)
readYamlFile FilePath
filePath = (HasCallStack => m (Either ParseException Value))
-> m (Either ParseException Value)
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m (Either ParseException Value))
-> m (Either ParseException Value))
-> (HasCallStack => m (Either ParseException Value))
-> m (Either ParseException Value)
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Reading YAML file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
IO (Either ParseException Value) -> m (Either ParseException Value)
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO (Either ParseException Value)
-> m (Either ParseException Value))
-> IO (Either ParseException Value)
-> m (Either ParseException Value)
forall a b. (a -> b) -> a -> b
$ forall a. FromJSON a => ByteString -> Either ParseException a
Y.decodeEither' @Value (ByteString -> Either ParseException Value)
-> (ByteString -> ByteString)
-> ByteString
-> Either ParseException Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
LBS.toStrict (ByteString -> Either ParseException Value)
-> IO ByteString -> IO (Either ParseException Value)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO ByteString
LBS.readFile FilePath
filePath
readYamlFileOk :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m Value
readYamlFileOk :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m Value
readYamlFileOk FilePath
filePath = (HasCallStack => m Value) -> m Value
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m Value) -> m Value)
-> (HasCallStack => m Value) -> m Value
forall a b. (a -> b) -> a -> b
$
m (Either ParseException Value) -> m Value
forall (m :: * -> *) e a.
(MonadTest m, Show e, HasCallStack) =>
m (Either e a) -> m a
H.leftFailM (m (Either ParseException Value) -> m Value)
-> m (Either ParseException Value) -> m Value
forall a b. (a -> b) -> a -> b
$ FilePath -> m (Either ParseException Value)
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either ParseException Value)
readYamlFile FilePath
filePath
rewriteLbsYaml :: (MonadTest m, HasCallStack) => (Value -> Value) -> LBS.ByteString -> m LBS.ByteString
rewriteLbsYaml :: forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsYaml Value -> Value
f ByteString
lbs = (HasCallStack => m ByteString) -> m ByteString
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ByteString) -> m ByteString)
-> (HasCallStack => m ByteString) -> m ByteString
forall a b. (a -> b) -> a -> b
$ do
case ByteString -> Either ParseException Value
forall a. FromJSON a => ByteString -> Either ParseException a
Y.decodeEither' (ByteString -> ByteString
LBS.toStrict ByteString
lbs) of
Right Value
iv -> ByteString -> m ByteString
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode (Value -> Value
f Value
iv))
Left ParseException
msg -> CallStack -> FilePath -> m ByteString
forall (m :: * -> *) a. MonadTest m => CallStack -> FilePath -> m a
H.failMessage CallStack
HasCallStack => CallStack
GHC.callStack (ParseException -> FilePath
forall a. Show a => a -> FilePath
show ParseException
msg)
rewriteYamlFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> (Value -> Value) -> m ()
rewriteYamlFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> (Value -> Value) -> m ()
rewriteYamlFile FilePath
filePath Value -> Value
f = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Rewriting YAML file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath
FilePath -> m ByteString
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ByteString
lbsReadFile FilePath
filePath m ByteString -> (ByteString -> m ByteString) -> m ByteString
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Value) -> ByteString -> m ByteString
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsYaml Value -> Value
f m ByteString -> (ByteString -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FilePath -> ByteString -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> ByteString -> m ()
lbsWriteFile FilePath
filePath
copyRewriteYamlFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> FilePath -> (Value -> Value) -> m ()
copyRewriteYamlFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> (Value -> Value) -> m ()
copyRewriteYamlFile FilePath
src FilePath
dst Value -> Value
f = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Rewriting YAML from file: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
src FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" to file " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
dst
FilePath -> m ByteString
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ByteString
lbsReadFile FilePath
src m ByteString -> (ByteString -> m ByteString) -> m ByteString
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Value) -> ByteString -> m ByteString
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
(Value -> Value) -> ByteString -> m ByteString
rewriteLbsYaml Value -> Value
f m ByteString -> (ByteString -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FilePath -> ByteString -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> ByteString -> m ()
lbsWriteFile FilePath
dst
cat :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
cat :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
cat FilePath
filePath = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
!FilePath
contents <- m FilePath -> m FilePath
forall (m :: * -> *) a. (Monad m, NFData a) => m a -> m a
forceM (m FilePath -> m FilePath) -> m FilePath -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> m FilePath
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
readFile FilePath
filePath
m () -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m () -> m ()) -> (FilePath -> m ()) -> FilePath -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, HasCallStack) =>
FilePath -> m ()
H.annotate (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
L.unlines
[ FilePath
"━━━━ File: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
filePath FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" ━━━━"
, FilePath
contents
]
() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
assertIsJsonFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
assertIsJsonFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertIsJsonFile FilePath
fp = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
Either FilePath Value
jsonResult <- FilePath -> m (Either FilePath Value)
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either FilePath Value)
readJsonFile FilePath
fp
case Either FilePath Value
jsonResult of
Right Value
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Left FilePath
msg -> CallStack -> FilePath -> m ()
forall (m :: * -> *) a. MonadTest m => CallStack -> FilePath -> m a
H.failMessage CallStack
HasCallStack => CallStack
GHC.callStack FilePath
msg
assertIsYamlFile :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
assertIsYamlFile :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertIsYamlFile FilePath
fp = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
Either FilePath Value
result <- FilePath -> m (Either FilePath Value)
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m (Either FilePath Value)
readJsonFile FilePath
fp
case Either FilePath Value
result of
Right Value
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Left FilePath
msg -> CallStack -> FilePath -> m ()
forall (m :: * -> *) a. MonadTest m => CallStack -> FilePath -> m a
H.failMessage CallStack
HasCallStack => CallStack
GHC.callStack FilePath
msg
assertFileExists :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
assertFileExists :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertFileExists FilePath
file = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
Bool
exists <- IO Bool -> m Bool
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
IO.doesFileExist FilePath
file
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ CallStack -> Maybe Diff -> FilePath -> m ()
forall (m :: * -> *) a.
MonadTest m =>
CallStack -> Maybe Diff -> FilePath -> m a
H.failWithCustom CallStack
HasCallStack => CallStack
GHC.callStack Maybe Diff
forall a. Maybe a
Nothing (FilePath
file FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" has not been successfully created.")
assertFilesExist :: (MonadTest m, MonadIO m, HasCallStack) => [FilePath] -> m ()
assertFilesExist :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
[FilePath] -> m ()
assertFilesExist [FilePath]
files = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ [FilePath] -> (FilePath -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [FilePath]
files FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertFileExists
assertFileMissing :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
assertFileMissing :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertFileMissing FilePath
file = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
Bool
exists <- IO Bool -> m Bool
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack) =>
IO a -> m a
H.evalIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
IO.doesFileExist FilePath
file
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
exists (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ CallStack -> Maybe Diff -> FilePath -> m ()
forall (m :: * -> *) a.
MonadTest m =>
CallStack -> Maybe Diff -> FilePath -> m a
H.failWithCustom CallStack
HasCallStack => CallStack
GHC.callStack Maybe Diff
forall a. Maybe a
Nothing (FilePath
file FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" should not have been created.")
assertFilesMissing :: (MonadTest m, MonadIO m, HasCallStack) => [FilePath] -> m ()
assertFilesMissing :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
[FilePath] -> m ()
assertFilesMissing [FilePath]
files = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ [FilePath] -> (FilePath -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [FilePath]
files FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertFileMissing
assertFileOccurences :: (MonadTest m, MonadIO m, HasCallStack) => Int -> String -> FilePath -> m ()
assertFileOccurences :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
Int -> FilePath -> FilePath -> m ()
assertFileOccurences Int
n FilePath
s FilePath
fp = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath
contents <- FilePath -> m FilePath
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
readFile FilePath
fp
[FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
L.length ((FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
L.filter (FilePath
s FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`L.isInfixOf`) (FilePath -> [FilePath]
L.lines FilePath
contents)) Int -> Int -> m ()
forall (m :: * -> *) a.
(MonadTest m, Eq a, Show a, HasCallStack) =>
a -> a -> m ()
H.=== Int
n
assertFileLines :: (MonadTest m, MonadIO m, HasCallStack) => (Int -> Bool) -> FilePath -> m ()
assertFileLines :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
(Int -> Bool) -> FilePath -> m ()
assertFileLines Int -> Bool
p FilePath
fp = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath
contents <- FilePath -> m FilePath
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
readFile FilePath
fp
let lines :: [FilePath]
lines = FilePath -> [FilePath]
L.lines FilePath
contents
let len :: Int
len = case [FilePath] -> [FilePath]
forall a. [a] -> [a]
L.reverse [FilePath]
lines of
FilePath
"":[FilePath]
xs -> [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
L.length [FilePath]
xs
[FilePath]
xs -> [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
L.length [FilePath]
xs
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int -> Bool
p Int
len) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
CallStack -> Maybe Diff -> FilePath -> m ()
forall (m :: * -> *) a.
MonadTest m =>
CallStack -> Maybe Diff -> FilePath -> m a
H.failWithCustom CallStack
HasCallStack => CallStack
GHC.callStack Maybe Diff
forall a. Maybe a
Nothing (FilePath
fp FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" has an unexpected number of lines")
assertEndsWithSingleNewline :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> m ()
assertEndsWithSingleNewline :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m ()
assertEndsWithSingleNewline FilePath
fp = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
FilePath
contents <- FilePath -> m FilePath
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> m FilePath
readFile FilePath
fp
case FilePath -> FilePath
forall a. [a] -> [a]
L.reverse FilePath
contents of
Char
'\n':Char
'\n':FilePath
_ -> CallStack -> Maybe Diff -> FilePath -> m ()
forall (m :: * -> *) a.
MonadTest m =>
CallStack -> Maybe Diff -> FilePath -> m a
H.failWithCustom CallStack
HasCallStack => CallStack
GHC.callStack Maybe Diff
forall a. Maybe a
Nothing (FilePath
fp FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" ends with too many newlines.")
Char
'\n':FilePath
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
FilePath
_ -> CallStack -> Maybe Diff -> FilePath -> m ()
forall (m :: * -> *) a.
MonadTest m =>
CallStack -> Maybe Diff -> FilePath -> m a
H.failWithCustom CallStack
HasCallStack => CallStack
GHC.callStack Maybe Diff
forall a. Maybe a
Nothing (FilePath
fp FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
" must end with newline.")
appendFileTimeDelta :: (MonadTest m, MonadIO m, HasCallStack) => FilePath -> UTCTime -> m ()
appendFileTimeDelta :: forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> UTCTime -> m ()
appendFileTimeDelta FilePath
filePath UTCTime
offsetTime = (HasCallStack => m ()) -> m ()
forall a. HasCallStack => (HasCallStack => a) -> a
GHC.withFrozenCallStack ((HasCallStack => m ()) -> m ()) -> (HasCallStack => m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ do
UTCTime
baseTime <- IO UTCTime -> m UTCTime
forall (m :: * -> *) a.
(MonadTest m, MonadIO m, HasCallStack, Show a) =>
IO a -> m a
H.noteShowIO IO UTCTime
DTC.getCurrentTime
let delay :: NominalDiffTime
delay = UTCTime -> UTCTime -> NominalDiffTime
DTC.diffUTCTime UTCTime
baseTime UTCTime
offsetTime
FilePath -> FilePath -> m ()
forall (m :: * -> *).
(MonadTest m, MonadIO m, HasCallStack) =>
FilePath -> FilePath -> m ()
appendFile FilePath
filePath (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> FilePath
show @DTC.NominalDiffTime NominalDiffTime
delay FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"\n"