Commit a0c7e701 authored by Valentin Reis's avatar Valentin Reis

Merge branch 'experiment-commands' into 'master'

Experiment commands

See merge request argo/argotest!14
parents a2b60e73 014360e9
Pipeline #4864 passed with stage
in 11 seconds
...@@ -112,34 +112,6 @@ There are a few things one has to be aware of using this workflow: ...@@ -112,34 +112,6 @@ There are a few things one has to be aware of using this workflow:
minutes by default. Use a local checkout if you need to modify some of these minutes by default. Use a local checkout if you need to modify some of these
sources on the fly. sources on the fly.
### Example CI setup
``` {.yml}
integration.test:
stage: test
script:
- nix-shell -E '{ argotest ? (builtins.fetchGit {
url = https://xgitlab.cels.anl.gov/argo/argotest.git;
ref="master";})
}:
(import argotest { containers-src = ./. ; }).test' \
--run 'argotk.hs TestHello'
artifacts:
paths:
- argotest/_output/cmd_err.log
- argotest/_output/cmd_out.log
- argotest/_output/daemon_out.log
- argotest/_output/daemon_out.log
- argotest/_output/nrm.log
- argotest/_output/time.log
expire_in: 1 week
except:
- /^wip\/.*/
- /^WIP\/.*/
tags:
- integration
```
### Hacking ### Hacking
- edit `.README.md` in place of README.md. - edit `.README.md` in place of README.md.
......
...@@ -3,3 +3,10 @@ _output ...@@ -3,3 +3,10 @@ _output
result result
.shake .shake
*.log *.log
*/build
*/new-build
*/dist
*/new-dist
*/result
_output
*/_output
...@@ -12,6 +12,6 @@ library ...@@ -12,6 +12,6 @@ library
exposed-Modules: Argo.Stack exposed-Modules: Argo.Stack
Argo.Utils Argo.Utils
Argo.Args Argo.Args
build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text, optparse-applicative, extra, foldl, conduit,conduit-extra, bytestring, stm build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text, optparse-applicative, extra, foldl, conduit,conduit-extra, bytestring, stm, pretty-show
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
{-# LANGUAGE {-# LANGUAGE OverloadedStrings, ApplicativeDo, GeneralizedNewtypeDeriving, RecordWildCards #-}
OverloadedStrings,
ApplicativeDo,
RecordWildCards #-}
module Argo.Args where module Argo.Args where
import Options.Applicative as OA import Options.Applicative as OA
import Options.Applicative.Types
import Options.Applicative.Builder ( option )
import Data.Default import Data.Default
import Data.Text as T import Data.Text as T
hiding ( empty ) hiding ( empty )
import Turtle import Turtle hiding ( option )
import Prelude hiding ( FilePath ) import Prelude hiding ( FilePath )
import System.Process hiding ( shell )
data OutputFiles = OutputFiles FilePath FilePath data OutputFiles = OutputFiles FilePath FilePath
data StackArgs = StackArgs data StackArgs = StackArgs
{ app :: Text { verbosity :: Verbosity
, args :: [Text] , app :: AppName
, containerName :: Text , args :: AppArgs
, workingDirectory :: FilePath , containerName :: ContainerName
, manifestDir :: FilePath , workingDirectory :: WorkingDirectory
, manifestName :: FilePath , manifestDir :: ManifestDir
, cmd_run_out :: FilePath , manifestName :: ManifestName
, cmd_run_err :: FilePath , daemon :: ProcessBehavior
, cmd_listen_out :: FilePath , cmdrun :: ProcessBehavior
, cmd_listen_err :: FilePath , cmdlisten :: ProcessBehavior
, daemon_out :: FilePath , cmdlistenprogress :: ProcessBehavior
, daemon_err :: FilePath , cmdlistenpower :: ProcessBehavior
, nrm_log :: FilePath
, messageDaemonOut :: Maybe Text
, messageDaemonErr :: Maybe Text
, messageCmdRunOut :: Maybe Text
, messageCmdRunErr :: Maybe Text
, messageCmdListenOut :: Maybe Text
, messageCmdListenErr :: Maybe Text
} }
data Verbosity = Normal | Verbose deriving (Show,Read,Eq)
newtype AppArgs = AppArgs [Text] deriving (Show, Read)
newtype WorkingDirectory = WorkingDirectory FilePath deriving (IsString, Show)
newtype AppName = AppName Text deriving (IsString, Show, Read)
newtype ContainerName = ContainerName Text deriving (IsString, Show, Read)
newtype ManifestDir = ManifestDir FilePath deriving (IsString, Show)
newtype ManifestName = ManifestName FilePath deriving (IsString, Show)
newtype StdOutLog = StdOutLog Text deriving (Show, Read)
newtype StdErrLog = StdErrLog Text deriving (Show, Read)
newtype TestText = TestText Text deriving (Show, Read)
data ProcessBehavior =
SucceedTestOnMessage TestText StdOutLog StdErrLog
| JustRun StdOutLog StdErrLog
| DontRun deriving (Show,Read)
behavior :: ReadM ProcessBehavior
behavior = read <$> readerAsk
behaviorOption :: Mod OptionFields ProcessBehavior -> Parser ProcessBehavior
behaviorOption = option behavior
instance Default StackArgs where instance Default StackArgs where
def = StackArgs def = StackArgs
{ app = "echo" { verbosity = Verbose
, args = ["foobar"] , app = AppName "ls"
, containerName = "testContainer" , args = AppArgs []
, workingDirectory = "_output" , containerName = ContainerName "testContainer"
, manifestDir = "manifests" , workingDirectory = WorkingDirectory "_output"
, manifestName = "basic.json" , manifestDir = ManifestDir "manifests"
, cmd_run_out = "cmd_run_out.log" , manifestName = ManifestName "basic.json"
, cmd_run_err = "cmd_run_err.log" , daemon = DontRun
, cmd_listen_out = "cmd_listen_out.log" , cmdrun = DontRun
, cmd_listen_err = "cmd_listen_err.log" , cmdlisten = DontRun
, daemon_out = "daemon_out.log" , cmdlistenprogress = DontRun
, daemon_err = "daemon_err.log" , cmdlistenpower = DontRun
, nrm_log = "nrm.log"
, messageDaemonOut = Nothing
, messageDaemonErr = Nothing
, messageCmdRunOut = Nothing
, messageCmdRunErr = Nothing
, messageCmdListenOut = Nothing
, messageCmdListenErr = Nothing
} }
parseExtendStackArgs :: StackArgs -> Parser StackArgs parseExtendStackArgs :: StackArgs -> Parser StackArgs
parseExtendStackArgs StackArgs {..} = do parseExtendStackArgs StackArgs {..} = do
verbosity <- flag
Normal
Verbose
(long "verbose" <> short 'v' <> help "Enable verbose mode")
app <- strOption app <- strOption
( long "application" ( long "application"
<> metavar "APP" <> metavar "APP"
...@@ -97,113 +109,39 @@ parseExtendStackArgs StackArgs {..} = do ...@@ -97,113 +109,39 @@ parseExtendStackArgs StackArgs {..} = do
<> showDefault <> showDefault
<> value manifestName <> value manifestName
) )
cmd_run_out <- strOption daemon <- behaviorOption
( long "cmd_run_out" ( long "daemon"
<> metavar "FILENAME" <> metavar "BEHAVIOR"
<> help "Output file (relative to --output_dir), \"cmd run\" stdout" <> help "`daemon` behavior"
<> showDefault
<> value cmd_run_out
)
cmd_run_err <- strOption
( long "cmd_run_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd run\" stderr"
<> showDefault
<> value cmd_run_err
)
cmd_listen_out <- strOption
( long "cmd_listen_out"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd listen\" stdout"
<> showDefault
<> value cmd_listen_out
)
cmd_listen_err <- strOption
( long "cmd_listen_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd listen\" stderr"
<> showDefault
<> value cmd_listen_err
)
daemon_out <- strOption
( long "daemon_out"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon stdout"
<> showDefault
<> value daemon_out
)
daemon_err <- strOption
( long "daemon_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon stderr"
<> showDefault
<> value daemon_err
)
nrm_log <- strOption
( long "nrm_log"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon log"
<> showDefault
<> value nrm_log
)
messageDaemonOut <- optional $ strOption
( long "message_daemon_stdout"
<> metavar "STRING"
<> help
"The appearance of this character string in the daemon stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault
<> maybe mempty value messageDaemonOut
)
messageDaemonErr <- optional $ strOption
( long "message_daemon_stderr"
<> metavar "STRING"
<> help
"The appearance of this character string in the daemon stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageDaemonErr <> value daemon
) )
messageCmdRunOut <- optional $ strOption cmdrun <- behaviorOption
( long "message_cmd_run_stdout" ( long "cmd_run"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd run` behavior"
"The appearance of this character string in the cmd run stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdRunOut <> value cmdrun
) )
messageCmdRunErr <- optional $ strOption cmdlisten <- behaviorOption
( long "message_cmd_run_stderr" ( long "cmd_listen"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen` behavior"
"The appearance of this character string in the cmd run stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdRunErr <> value cmdlisten
) )
messageCmdListenOut <- optional $ strOption cmdlistenprogress <- behaviorOption
( long "message_cmd_listen_stdout" ( long "cmd_listen_progress"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen --filter progress` behavior"
"The appearance of this character string in the cmd listen stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdListenOut <> value cmdlistenprogress
) )
messageCmdListenErr <- optional $ strOption cmdlistenpower <- behaviorOption
( long "message_cmd_listen_stderr" ( long "cmd_listen_power"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen --filter power` behavior"
"The appearance of this character string in the cmd listen stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdListenErr <> value cmdlistenpower
) )
pure StackArgs {..} pure StackArgs {..}
{-# LANGUAGE {-# LANGUAGE
TupleSections,
ScopedTypeVariables, ScopedTypeVariables,
LambdaCase, LambdaCase,
RecordWildCards, RecordWildCards,
...@@ -43,43 +44,17 @@ import Data.ByteString.Char8 as C8 ...@@ -43,43 +44,17 @@ import Data.ByteString.Char8 as C8
import Control.Exception.Base import Control.Exception.Base
import Data.Maybe import Data.Maybe
import Control.Foldl as Fold import Control.Foldl as Fold
import Text.Show.Pretty
cleanLeftovers :: WorkingDirectory -> Shell ()
{-cleanLeftoverProcesses :: Shell ()-} cleanLeftovers (WorkingDirectory wd) = do
{-cleanLeftoverProcesses = do-} printInfo "Cleaning working(output) directory.\n"
{-printInfo "Cleaning leftover processes.\n"-} cleanLog wd
{-daemon <- myWhich "daemon"-} printInfo "Cleaning sockets.\n"
{-verboseShell (format ("pkill " % fp) daemon) empty-}
{-cmd <- myWhich "cmd"-}
{-void $ verboseShell (format ("pkill " % fp) cmd) empty-}
{-daemon_wrapped <- myWhichMaybe ".daemon-wrapped"-}
{-E.whenJust daemon_wrapped-}
{-(\x -> void $ verboseShell "pkill .daemon-wrapped" empty)-}
{-cmd_wrapped <- myWhichMaybe ".cmd-wrapped"-}
{-void $ E.whenJust cmd_wrapped-}
{-(\x -> void $ verboseShell "pkill .cmd-wrapped" empty)-}
cleanLeftovers :: StackArgs -> Shell ()
cleanLeftovers StackArgs {..} = do
{-cleanLeftoverProcesses-}
printInfo "Cleaning leftover files.\n"
CM.mapM_
cleanLog
[ workingDirectory </> daemon_out
, workingDirectory </> daemon_err
, workingDirectory </> cmd_run_out
, workingDirectory </> cmd_run_err
, workingDirectory </> cmd_listen_out
, workingDirectory </> cmd_listen_err
, workingDirectory </> nrm_log
, workingDirectory </> ".argo_nodeos_config_exit_message"
, workingDirectory </> "argo_nodeos_config"
]
printInfo "Cleaning leftover sockets.\n"
CM.mapM_ cleanSocket ["/tmp/nrm-downstream-in", "/tmp/nrm-upstream-in"] CM.mapM_ cleanSocket ["/tmp/nrm-downstream-in", "/tmp/nrm-upstream-in"]
checkFsAttributes :: StackArgs -> Shell () checkFsAttributes :: FilePath -> Shell ()
checkFsAttributes StackArgs {..} = do checkFsAttributes workingDirectory = do
let x = case toText workingDirectory of let x = case toText workingDirectory of
Left x -> x Left x -> x
Right x -> x Right x -> x
...@@ -89,11 +64,9 @@ checkFsAttributes StackArgs {..} = do ...@@ -89,11 +64,9 @@ checkFsAttributes StackArgs {..} = do
("The output directory, " % fp % ", must not mounted with \"nosuid\"") ("The output directory, " % fp % ", must not mounted with \"nosuid\"")
workingDirectory workingDirectory
prepareDaemon :: StackArgs -> Shell Instrumentation prepareDaemon
prepareDaemon sa@StackArgs {..} = do :: StdOutLog -> StdErrLog -> Maybe TestText -> Shell Instrumentation
mktree workingDirectory prepareDaemon (StdOutLog out) (StdErrLog err) test = do
checkFsAttributes sa
cd workingDirectory
myWhich "daemon" myWhich "daemon"
confPath <- myWhich "argo_nodeos_config" confPath <- myWhich "argo_nodeos_config"
let confPath' = "./argo_nodeos_config" let confPath' = "./argo_nodeos_config"
...@@ -109,13 +82,10 @@ prepareDaemon sa@StackArgs {..} = do ...@@ -109,13 +82,10 @@ prepareDaemon sa@StackArgs {..} = do
ExitFailure n -> die ("Setting suid bit failed with exit code " <> repr n) ExitFailure n -> die ("Setting suid bit failed with exit code " <> repr n)
cleanContainers confPath' 1 2 cleanContainers confPath' 1 2
export "ARGO_NODEOS_CONFIG" (format fp confPath') export "ARGO_NODEOS_CONFIG" (format fp confPath')
return $ Instrumentation return $ Instrumentation (P.proc "daemon" [])
{ process = P.proc "daemon" ["--nrm_log", encodeString nrm_log] (StdOutLog out)
, stdOutFile = daemon_out (StdErrLog err)
, stdErrFile = daemon_err test
, messageOut = messageDaemonOut
, messageErr = messageDaemonErr
}
where where
nodeOsFailure (ExitFailure n, _, _) = do nodeOsFailure (ExitFailure n, _, _) = do
printError ("argo_nodeos_config failed with exit code :" <> repr n <> "\n") printError ("argo_nodeos_config failed with exit code :" <> repr n <> "\n")
...@@ -164,97 +134,104 @@ prepareDaemon sa@StackArgs {..} = do ...@@ -164,97 +134,104 @@ prepareDaemon sa@StackArgs {..} = do
else else
printInfo printInfo
"argo_nodeos_config successfully cleaned the container \ "argo_nodeos_config successfully cleaned the container \
\config." \config.\n"
prepareCmdRun :: StackArgs -> Instrumentation cmdRunI
prepareCmdRun StackArgs {..} = Instrumentation :: AppName
{ process = P.proc "cmd" -> AppArgs
$ [ "run" -> ContainerName
, "-u" -> ManifestDir
, T.unpack containerName -> ManifestName
, encodeString $ manifestDir </> manifestName -> ProcessBehavior
, T.unpack app -> Maybe (StackI, Instrumentation)
] cmdRunI (AppName app) (AppArgs args) (ContainerName cn) (ManifestDir md) (ManifestName mn) pb
= Just (Run, )
<*> processBehaviorToI
( P.proc "cmd"
$ ["run", "-u", T.unpack cn, encodeString $ md </> mn, T.unpack app]
++ fmap T.unpack args ++ fmap T.unpack args
, stdOutFile = cmd_run_out )
, stdErrFile = cmd_run_err pb
, messageOut = messageCmdRunOut
, messageErr = messageCmdRunErr cmdListenI
} :: ContainerName -> ProcessBehavior -> Maybe (StackI, Instrumentation)
cmdListenI (ContainerName cn) pb =
Just (Listen, )
<*> processBehaviorToI (P.proc "cmd" ["listen", "-u", T.unpack cn]) pb
cmdListenProgressI
:: ContainerName -> ProcessBehavior -> Maybe (StackI, Instrumentation)
cmdListenProgressI (ContainerName cn) pb =
Just (Progress, )
<*> processBehaviorToI
(P.proc "cmd" ["listen", "-u", T.unpack cn, "--filter", "progress"])
pb
cmdListenPowerI
:: ContainerName -> ProcessBehavior -> Maybe (StackI, Instrumentation)
cmdListenPowerI (ContainerName cn) pb =
Just (Power, )
<*> processBehaviorToI
(P.proc "cmd" ["listen", "-u", T.unpack cn, "--filter", "power"])
pb
data StackOutput =
FoundMessage
| Died StackI ExitCode
data StackI = Daemon | Run | Listen | Progress | Power deriving (Show)
runStack :: StackArgs -> Shell StackOutput
runStack a@StackArgs {..} = do
CM.mapM_ cleanSocket ["/tmp/nrm-downstream-in", "/tmp/nrm-upstream-in"]
let (WorkingDirectory wd) = workingDirectory
Turtle.shell (format ("rm -rf " % fp) wd) Turtle.empty
mktree wd
checkFsAttributes wd
cd wd
iDaemon <- case daemon of
DontRun -> return Nothing
JustRun out err ->
(\x -> Just (Daemon, x)) <$> prepareDaemon out err Nothing
SucceedTestOnMessage t out err ->
(\x -> Just (Daemon, x)) <$> prepareDaemon out err (Just t)
let milist =
[ iDaemon
, cmdRunI app args containerName manifestDir manifestName cmdrun
, cmdListenI containerName cmdlisten
, cmdListenProgressI containerName cmdlistenprogress
, cmdListenPowerI containerName cmdlistenpower
]
ilist = catMaybes milist
prepareCmdListen :: StackArgs -> Instrumentation if verbosity == Verbose
prepareCmdListen StackArgs {..} = Instrumentation then do
{ process = P.proc "cmd" ["listen", "-u", T.unpack containerName] printInfo "Starting the following processes:\n"
, stdOutFile = cmd_listen_out liftIO $ pPrint ilist
, stdErrFile = cmd_listen_err else liftIO $ pPrint (fmap fst ilist)
, messageOut = messageCmdListenOut
, messageErr = messageCmdListenErr
}
data StackOutput = FoundMessage | DaemonDied | CmdDied asyncs <- liftIO $ mapM tupleToAsync ilist
liftIO $ kbInstallHandler $ CM.mapM_ cancel asyncs
runSimpleStack :: StackArgs -> Shell StackOutput when (verbosity == Verbose) $ printInfo "Processes started.\n"
runSimpleStack a@StackArgs {..} = do
cleanLeftovers a
iDaemon <- prepareDaemon a
let iRun = prepareCmdRun a
printInfo "Running the daemon.."
liftIO $ withAsync (runI iDaemon) $ \daemon -> do
kbInstallHandler $ cancel daemon
sh $ printInfo "Daemon running.\n"
sh $ printInfo "Running 'cmd run'.."
withAsync (runI iRun) $ \cmd -> do
sh $ printInfo "'cmd run' running.\n"
kbInstallHandler $ cancel daemon >> cancel cmd
waitEitherCancel daemon cmd >>= \case
Left (Left PatternMatched) -> return FoundMessage
Left (Right _ ) -> return DaemonDied
Right (Left PatternMatched) -> return FoundMessage
Right (Right _ ) -> return CmdDied
data ListenAsyncConclusion a = out <- liftIO $ waitAnyCancel asyncs
Daemon a
| Listen a
| Run a
data ListenStackOutput = printInfo
LSFoundMessage ( "Processes cancelled due to termination of: "
| LSMessageNotFound <> repr (fst $ snd out)
| LSDaemonDied ExitCode <> " with exit information: "
| LSRunDied ExitCode <> repr (snd $ snd out)
| LSListenDied ExitCode <> "\n"
)
runListenStack :: StackArgs -> Shell ListenStackOutput return $ case snd out of
runListenStack a@StackArgs {..} = do (_ , Left PatternMatched) -> FoundMessage
cleanLeftovers a (stacki, Right (e, _, _) ) -> Died stacki e
iDaemon <- prepareDaemon a
let iRun = prepareCmdRun a
let iListen = prepareCmdListen a
printInfo "Running the daemon.."
liftIO $ withAsync (runI iDaemon) $ \daemon -> do
kbInstallHandler $ cancel daemon
sh $ printInfo "Daemon running.\n"
sh $ printInfo "Running 'cmd run'.."
withAsync (runI iRun) $ \run -> do
sh $ printInfo "'cmd run' running.\n"
kbInstallHandler $ cancel daemon >> cancel run
sh $ printInfo "Running 'cmd listen'.."
withAsync (runI iListen) $ \listen -> do
sh $ printInfo "'cmd listen' running.\n"
kbInstallHandler $ cancel daemon >> cancel run >> cancel listen
waitStackCancel daemon run listen >>= \case
Daemon (Left PatternMatched) -> return LSFoundMessage
Daemon (Right (e, _, _) ) -> return $ LSDaemonDied e
Run (Left PatternMatched) -> return LSFoundMessage
Run (Right (e, _, _) ) -> return $ LSRunDied e
Listen (Left PatternMatched) -> return LSFoundMessage
Listen (Right (e, _, _) ) -> return $ LSListenDied e
where where
waitStackCancel daemon run listen = tupleToAsync
waitStack daemon run listen :: (StackI, Instrumentation)
`finally` (cancel daemon >> cancel run >> cancel listen) -> IO (Async (StackI, Either PatternMatched (ExitCode, (), ())))
waitStack daemon run listen = tupleToAsync (stacki, instrum) = async $ (stacki, ) <$> runI instrum
atomically
$ (Daemon <$> waitSTM daemon)
`orElse` (Run <$> waitSTM run)
`orElse` (Listen <$> waitSTM listen)
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
module Argo.Utils where module Argo.Utils where
import Argo.Args
import Turtle import Turtle
import Prelude hiding ( FilePath ) import Prelude hiding ( FilePath )
import System.Console.ANSI import System.Console.ANSI
...@@ -37,7 +38,7 @@ printCommand = printf ("Running: " % s % "\n") ...@@ -37,7 +38,7 @@ printCommand = printf ("Running: " % s % "\n")
printWarning = colorShell Yellow . printf ("Warning: " % s) printWarning = colorShell Yellow . printf ("Warning: " % s)
printError = colorShell Red . printf ("Error: " % s) printError = colorShell Red . printf ("Error: " % s)
printSuccess = colorShell Green . printf ("Success: " % s) printSuccess = colorShell Green . printf ("Success: " % s)
printTest = colorShell Green . printf ("RUNNING TEST: " % s%"\n") printTest = colorShell Green . printf ("RUNNING TEST: " % s % "\n")
dieRed str = dieRed str =
colorShell Red (printf ("Failure: " % s) str) >> exit (ExitFailure 1) colorShell Red (printf ("Failure: " % s) str) >> exit (ExitFailure 1)
...@@ -60,7 +61,7 @@ sudoRemoveFile printer desc filePath = do ...@@ -60,7 +61,7 @@ sudoRemoveFile printer desc filePath = do
go useSudo = do go useSudo = do
printer $ format ("found stale " % s % " at " % fp % ".. ") desc filePath printer $ format ("found stale " % s % " at " % fp % ".. ") desc filePath
shell shell
(format ((if useSudo then "sudo " else "") % "rm -f " % fp) filePath) (format ((if useSudo then "sudo " else "") % "rm -rf " % fp) filePath)
Turtle.empty Turtle.empty
>>= \case >>= \case
ExitSuccess -> colorShell Green $ printf " Successfully removed.\n" ExitSuccess -> colorShell Green $ printf " Successfully removed.\n"
...@@ -82,35 +83,35 @@ verboseShell' command input = ...@@ -82,35 +83,35 @@ verboseShell' command input =
printCommand command >> shellStrictWithErr command input printCommand command >> shellStrictWithErr command input
cleanSocket = sudoRemoveFile printError "socket" cleanSocket = sudoRemoveFile printError "socket"
cleanLog = sudoRemoveFile printWarning "log file" cleanLog = sudoRemoveFile printWarning "log folder"
kbInstallHandler :: IO () -> IO Handler kbInstallHandler :: IO () -> IO Handler
kbInstallHandler h = installHandler keyboardSignal (Catch h) Nothing kbInstallHandler h = installHandler keyboardSignal (Catch h) Nothing
data PatternMatched = PatternMatched deriving (Show, Typeable) data PatternMatched = PatternMatched deriving (Show, Typeable)
instance Exception PatternMatched instance Exception PatternMatched
data Instrumentation = Instrumentation data Instrumentation = Instrumentation
{ process :: CreateProcess CreateProcess
, stdOutFile :: FilePath StdOutLog
, stdErrFile :: FilePath StdErrLog
, messageOut :: Maybe Text (Maybe TestText)
, messageErr :: Maybe Text } deriving (Show) deriving (Show)
runI :: Instrumentation -> IO (Either PatternMatched (ExitCode, (), ())) runI :: Instrumentation -> IO (Either PatternMatched (ExitCode, (), ()))
runI Instrumentation {..} = try (reroutedDaemon process) runI (Instrumentation cp outlog@(StdOutLog out) errlog@(StdErrLog err) t) = try
(reroutedDaemon cp)
where where
reroutedDaemon process = reroutedDaemon process =
withSinkFile (encodeString stdOutFile) $ \outSink -> withSinkFile (T.unpack out)
withSinkFile (encodeString stdErrFile) $ \outSink ->
$ \errSink -> sourceProcessWithStreams withSinkFile (T.unpack err) $ \errSink -> sourceProcessWithStreams
process process
mempty mempty
(makeMatcher messageOut .| outSink) (makeMatcher t .| outSink)
(