Commit 7e7c66e4 authored by Valentin Reis's avatar Valentin Reis
Browse files

Added daemon log file parsing to the perf-wrapper test. This waits for

"payload" to appear in the daemon stdouts and exits with success.
parent 772f8098
Pipeline #4716 passed with stage
in 30 seconds
...@@ -11,6 +11,6 @@ cabal-version: >=1.10 ...@@ -11,6 +11,6 @@ cabal-version: >=1.10
library library
exposed-Modules: Argo.Stack exposed-Modules: Argo.Stack
Argo.Utils Argo.Utils
build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text, optparse-applicative
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
{-# LANGUAGE ScopedTypeVariables, LambdaCase , RecordWildCards , OverloadedStrings , {-# LANGUAGE ScopedTypeVariables,
DataKinds , FlexibleInstances , TypeOperators #-} LambdaCase,
RecordWildCards,
OverloadedStrings,
DataKinds,
FlexibleInstances,
TypeOperators,
ApplicativeDo #-}
module Argo.Stack where module Argo.Stack where
...@@ -19,24 +25,23 @@ import Data.Text.IO as Text ...@@ -19,24 +25,23 @@ import Data.Text.IO as Text
import Argo.Utils import Argo.Utils
import System.Process as P import System.Process as P
hiding ( shell ) hiding ( shell )
import Options.Applicative as OA
data StackArgs = StackArgs data StackArgs = StackArgs
{ dargs :: [Text] --"Daemon arguments. Properly quote this." { app :: Text
, app :: Text --"Target application call, sh+path valid" , workingDirectory :: FilePath
, workingDirectory :: FilePath --"Working directory." , manifestDir :: FilePath
, manifestDir :: FilePath --"Manifest lookup directory" , manifestName :: FilePath
, manifestName :: FilePath --"Manifest file name" , cmd_out :: FilePath
, cmd_out :: FilePath --"Output file, application stdout" , cmd_err :: FilePath
, cmd_err :: FilePath --"Output file, application stderr" , daemon_out :: FilePath
, daemon_out :: FilePath --"Output file, daemon stdout" , daemon_err :: FilePath
, daemon_err :: FilePath --"Output file, daemon stderr" , nrm_log :: FilePath
, nrm_log :: FilePath --"Output file, daemon log" , time_file :: FilePath }
, time_file :: FilePath } --"Output file, application runtime"
instance Default StackArgs where instance Default StackArgs where
def = StackArgs def = StackArgs
{ dargs = [] { app = "echo foobar"
, app = "echo \"HelloWorld\""
, workingDirectory = "_output" , workingDirectory = "_output"
, manifestDir = "manifests" , manifestDir = "manifests"
, manifestName = "basic.json" , manifestName = "basic.json"
...@@ -48,35 +53,106 @@ instance Default StackArgs where ...@@ -48,35 +53,106 @@ instance Default StackArgs where
, time_file = "time.log" , time_file = "time.log"
} }
cleanLeftovers parseExtendStackArgs :: StackArgs -> Parser StackArgs
:: FilePath parseExtendStackArgs StackArgs {..} = do
-> FilePath app <- strOption
-> FilePath ( long "application"
-> FilePath <> metavar "FILE"
-> FilePath <> help "Target application call, sh+path valid"
-> FilePath <> showDefault
-> FilePath <> value app
-> Shell () )
cleanLeftovers wd daemon_out daemon_err cmd_out cmd_err time_file nrm_log = do workingDirectory <- strOption
( long "output"
<> metavar "FILE"
<> help "Working directory."
<> showDefault
<> value workingDirectory
)
manifestDir <- strOption
( long "manifest_directory"
<> metavar "FILE"
<> help "Manifest lookup directory"
<> showDefault
<> value manifestDir
)
manifestName <- strOption
( long "manifest_name"
<> metavar "FILE"
<> help "Manifest basename"
<> showDefault
<> value manifestName
)
cmd_out <- strOption
( long "cmd_out"
<> metavar "FILE"
<> help "Output file, application stdout"
<> showDefault
<> value cmd_out
)
cmd_err <- strOption
( long "cmd_err"
<> metavar "FILE"
<> help "Output file, application stderr"
<> showDefault
<> value cmd_err
)
daemon_out <- strOption
( long "daemon_out"
<> metavar "FILE"
<> help "Output file, daemon stdout"
<> showDefault
<> value daemon_out
)
daemon_err <- strOption
( long "daemon_err"
<> metavar "FILE"
<> help "Output file, daemon stderr"
<> showDefault
<> value daemon_err
)
nrm_log <- strOption
( long "nrm_log"
<> metavar "FILE"
<> help "Output file, daemon log"
<> showDefault
<> value nrm_log
)
time_file <- strOption
( long "time_file"
<> metavar "FILE"
<> help "Output file, application runtime"
<> showDefault
<> value time_file
)
pure StackArgs {..}
cleanLeftovers :: StackArgs -> Shell ()
cleanLeftovers StackArgs {..} = do
printInfo "Cleaning leftovers..\n" printInfo "Cleaning leftovers..\n"
mapM_ mapM_
cleanLog cleanLog
[ wd </> daemon_out [ workingDirectory </> daemon_out
, wd </> daemon_err , workingDirectory </> daemon_err
, wd </> cmd_out , workingDirectory </> cmd_out
, wd </> cmd_err , workingDirectory </> cmd_err
, wd </> time_file , workingDirectory </> time_file
, wd </> nrm_log , workingDirectory </> nrm_log
, wd </> ".argo_nodeos_config_exit_message" , workingDirectory </> ".argo_nodeos_config_exit_message"
, wd </> "argo_nodeos_config" , workingDirectory </> "argo_nodeos_config"
] ]
mapM_ cleanSocket ["/tmp/nrm-downstream-in", "/tmp/nrm-upstream-in"] mapM_ cleanSocket ["/tmp/nrm-downstream-in", "/tmp/nrm-upstream-in"]
prepareDaemonShell prepareDaemonShell :: StackArgs -> Shell (IO ())
:: FilePath -> [Text] -> FilePath -> FilePath -> FilePath -> Shell (IO ()) prepareDaemonShell = prepareDaemonShellWithStoppingCriterion id
prepareDaemonShell wd dargs daemon_out daemon_err nrm_log = do
mktree wd prepareDaemonShellWithStoppingCriterion
cd wd :: (Shell (Either Line Line) -> Shell (Either Line Line))
-> StackArgs
-> Shell (IO ())
prepareDaemonShellWithStoppingCriterion waitCondition StackArgs {..} = do
mktree workingDirectory
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"
...@@ -116,17 +192,17 @@ prepareDaemonShell wd dargs daemon_out daemon_err nrm_log = do ...@@ -116,17 +192,17 @@ prepareDaemonShell wd dargs daemon_out daemon_err nrm_log = do
daemon_out daemon_out
daemon_err daemon_err
export "ARGO_NODEOS_CONFIG" (format fp confPath') export "ARGO_NODEOS_CONFIG" (format fp confPath')
return $ twoWayPrint daemon_out daemon_err $ inprocWithErr return $ twoWayPrint daemon_out daemon_err $ waitCondition $ inprocWithErr
"daemon" "daemon"
(dargs ++ ["--nrm_log", Text.pack $ encodeString nrm_log]) ["--nrm_log", Text.pack $ encodeString nrm_log]
empty empty
-- | See at the bottom of this file for discussion of this function. (1) -- | See at the bottom of this file for discussion of this function. (1)
cmdShell :: FilePath -> Text -> FilePath -> FilePath -> Shell () cmdShell :: StackArgs -> Shell ()
cmdShell manifest app cmd_out cmd_err = cmdShell StackArgs {..} =
shell shell
(format ("cmd run -u toto " % fp % " " % s % " > " % fp % " 2>" % fp) (format ("cmd run -u toto " % fp % " " % s % " > " % fp % " 2>" % fp)
manifest (manifestDir </> manifestName)
app app
cmd_out cmd_out
cmd_err cmd_err
...@@ -152,29 +228,22 @@ twoWayPrint outPath errPath s = sh $ do ...@@ -152,29 +228,22 @@ twoWayPrint outPath errPath s = sh $ do
Right err -> liftIO $ Text.hPutStrLn handleErr (lineToText err) Right err -> liftIO $ Text.hPutStrLn handleErr (lineToText err)
runSimpleStack :: StackArgs -> IO () runSimpleStack :: StackArgs -> IO ()
runSimpleStack a@StackArgs {..} = sh $ do runSimpleStack = runSimpleStackWithCriterion id
cleanLeftovers workingDirectory
daemon_out runSimpleStackWithCriterion
daemon_err :: (Shell (Either Line Line) -> Shell (Either Line Line))
cmd_out -> StackArgs
cmd_err -> IO ()
time_file runSimpleStackWithCriterion stoppingCriterion a@StackArgs {..} = sh $ do
nrm_log cleanLeftovers a
daemonShell <- prepareDaemonShell workingDirectory daemonShell <- prepareDaemonShellWithStoppingCriterion stoppingCriterion a
dargs
daemon_out
daemon_err
nrm_log
liftIO $ withAsync daemonShell $ \daemon -> do liftIO $ withAsync daemonShell $ \daemon -> do
kbInstallHandler $ cancel daemon kbInstallHandler $ cancel daemon
withAsync withAsync (time $ sh $ cmdShell a) $ \cmd -> do
(time $ sh $ cmdShell (manifestDir </> manifestName) app cmd_out cmd_err kbInstallHandler $ cancel daemon >> cancel cmd
) waitEitherCancel daemon cmd >>= \case
$ \cmd -> do Left _ -> die "Daemon died."
kbInstallHandler $ cancel daemon >> cancel cmd Right (_, t) -> writeTextFile time_file (repr t)
waitEitherCancel daemon cmd >>= \case
Left _ -> die "Daemon died."
Right (_, t) -> writeTextFile time_file (repr t)
-- | (1) -- | (1)
-- --
......
...@@ -16,7 +16,7 @@ executable argotk ...@@ -16,7 +16,7 @@ executable argotk
main-is: argotk.hs main-is: argotk.hs
-- other-modules: -- other-modules:
-- other-extensions: -- other-extensions:
build-depends: base >=4.10 && <4.11, shake, FindBin build-depends: base, shake
--hs-source-dirs: src --hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
GHC-Options: -Wall GHC-Options: -Wall
#! /usr/bin/env runhaskell #! /usr/bin/env runhaskell
{-# LANGUAGE {-# LANGUAGE
OverloadedStrings OverloadedStrings,
, RecordWildCards #-} LambdaCase,
RecordWildCards #-}
import Argo.Stack import Argo.Stack
import Argo.Utils import Argo.Utils
...@@ -16,6 +17,9 @@ import System.Console.ANSI.Types ( Color ) ...@@ -16,6 +17,9 @@ import System.Console.ANSI.Types ( Color )
import Options.Applicative import Options.Applicative
import System.Posix.Signals import System.Posix.Signals
import Control.Monad import Control.Monad
import Data.Either
helloWorldText = "HelloWorldFromApp"
opts :: StackArgs -> Parser (IO ()) opts :: StackArgs -> Parser (IO ())
opts sa = hsubparser opts sa = hsubparser
...@@ -24,26 +28,24 @@ opts sa = hsubparser ...@@ -24,26 +28,24 @@ opts sa = hsubparser
<> command <> command
"daemon" "daemon"
(info (info
(pure $ runDaemon sa) (runDaemon <$> parseExtendStackArgs sa)
(progDesc (progDesc
"Set up and launch the daemon in synchronous mode, \ "Set up and launch the daemon in synchronous mode, \
\with properly cleaned sockets, logfiles." \with properly cleaned sockets, logfiles."
) )
) )
<> command <> command
"application" "stack"
(info (info
(runApp sa <$> strArgument (runSimpleStack <$> parseExtendStackArgs sa)
( metavar "COMMAND"
<> help "Application to run inside the container"
)
)
(progDesc "Setup stack and run an arbitrary command in a container.") (progDesc "Setup stack and run an arbitrary command in a container.")
) )
<> command <> command
"helloworld" "helloworld"
(info (info
(pure $ runHelloWorld sa) (runCheckCmdOutput "helloworld" <$> parseExtendStackArgs
(sa { app = format ("echo " % s) "helloworld" })
)
(progDesc (progDesc
"Test 1: Setup stack and check that a hello world app sends \ "Test 1: Setup stack and check that a hello world app sends \
\message back to cmd." \message back to cmd."
...@@ -52,47 +54,61 @@ opts sa = hsubparser ...@@ -52,47 +54,61 @@ opts sa = hsubparser
<> command <> command
"perfwrapper" "perfwrapper"
(info (info
(pure $ runHelloWorld (sa { manifestName = "perfwrap.json" })) (runWaitForMessage "payload" <$> parseExtendStackArgs
(sa { manifestName = "perfwrap.json"
, app = format ("sleep " % s) "5"
}
)
)
(progDesc (progDesc
"Test 2: Setup stack and check that a hello world app sends \ "Test 2: Setup stack and check that a hello world app sends \
\message back to cmd. Uses argo-perf-wrapper." \message back to cmd. Uses argo-perf-wrapper."
) )
) )
<> help "Type of action to run" <> help
"Type of test to run. There are extensive options under each action,\
\ but be careful, these do not all have the same defaults. The default\
\ values are printed when you call --help on these actions."
) )
main :: IO () main :: IO ()
main = do main = do
manifests <- getEnv "MANIFESTS" manifests <- getEnv "MANIFESTS"
let sa = def { manifestDir = decodeString manifests } let a = def { manifestDir = decodeString manifests }
join $ execParser (info (opts sa <**> helper) idm) join $ execParser (info (opts a <**> helper) idm)
runApp :: StackArgs -> Text -> IO ()
runApp sa myApp = runSimpleStack $ sa { app = myApp }
runHelloWorld :: StackArgs -> IO () runCheckCmdOutput :: Text -> StackArgs -> IO ()
runHelloWorld a@StackArgs {..} = do runCheckCmdOutput message a@StackArgs {..} = do
let passText = "HelloWorldFromApp" runSimpleStack a
let passPattern = text passText readTextFile cmd_err >>= \x -> case match (has (text message)) x of
runSimpleStack $ a { app = format ("echo " % s) passText } [] ->
readTextFile cmd_err >>= \x -> case match (has passPattern) x of die $ "Test failure: Cmd did not recieve the '" <> message <> "' message."
[] -> die "Hello world app failed to run."
_ -> _ ->
sh sh
$ printInfo $ printInfo
"The hello world app executed properly in a \ "Test success: The hello world app executed properly in a \
\container and its message was received by `cmd`.\n" \ container and its message was received by `cmd`.\n"
runWaitForMessage :: Text -> StackArgs -> IO ()
runWaitForMessage message a@StackArgs {..} = do
runSimpleStackWithCriterion criteria a
die
("Test failure: did not find string '" <> message <> "' in daemon stdout.")
where
criteria :: (Shell (Either Line Line) -> Shell (Either Line Line))
criteria s = s >>= \case
Left out -> case match (has (text "payload")) (lineToText out) of
[] -> return $ Left out
_ -> do
printInfo
$ "Test success: Found line containing '"
<> message
<> "' in daemon stdout."
exit ExitSuccess
Right err -> return $ Right err
runClean :: StackArgs -> IO () runClean :: StackArgs -> IO ()
runClean StackArgs {..} = sh $ cleanLeftovers workingDirectory runClean = sh . cleanLeftovers
daemon_out
daemon_err
cmd_out
cmd_err
time_file
nrm_log
runDaemon :: StackArgs -> IO () runDaemon :: StackArgs -> IO ()
runDaemon StackArgs {..} = runDaemon a = sh $ prepareDaemonShell a >>= liftIO
sh
$ prepareDaemonShell workingDirectory dargs daemon_out daemon_err nrm_log
>>= liftIO
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment