Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions cardano-tracer/cardano-tracer.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,30 @@ test-suite cardano-tracer-test-ext
-rtsopts
-with-rtsopts=-N

test-suite cardano-tracer-restart
import: project-config
type: exitcode-stdio-1.0

-- we expect unixy paths
if os(windows)
buildable: False

hs-source-dirs: test/restart-test
main-is: restart-test.hs

build-tool-depends: cardano-tracer:cardano-tracer
, cardano-tracer:demo-forwarder

-- keep this minimal: what the script actually uses
build-depends: base
, directory
, filepath
, process

ghc-options: -threaded
-rtsopts
-with-rtsopts=-N

benchmark cardano-tracer-bench
import: project-config
type: exitcode-stdio-1.0
Expand Down
8 changes: 8 additions & 0 deletions cardano-tracer/test/restart-test/restart-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
networkMagic: 42
network:
tag: AcceptAt
contents: "sock"
logging:
- logRoot: "/tmp/cardano-tracer-restart-test-logs"
logMode: FileMode
logFormat: ForMachine
138 changes: 138 additions & 0 deletions cardano-tracer/test/restart-test/restart-test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
{-# LANGUAGE ScopedTypeVariables #-}

module Main where

import Control.Concurrent (threadDelay)
import Control.Exception (IOException, catch, finally)
import Control.Monad (unless, void, when)
import System.Directory (doesFileExist, getCurrentDirectory, listDirectory,
removePathForcibly)
import System.Exit (exitFailure)
import System.FilePath (takeDirectory, (</>))
import System.IO (hPutStrLn, stderr)
import System.Process (CreateProcess (..), ProcessHandle, StdStream (..), createProcess,
proc, terminateProcess, waitForProcess)

main :: IO ()
main = do
let dir = "/tmp/cardano-tracer-restart-test-logs"
sock = "sock"
logLink = dir </> (sock ++ "@0") </> "node.json"
waitSecs = 5

cfg <- resolveConfigPath

-- Fresh start.
catchIgnore (removePathForcibly dir)

-- Run demo-forwarder
forwarderH <- startProc "demo-forwarder" [sock, "Initiator"]

let cleanup = catchIgnore (removePathForcibly dir)

-- Ensure the forwarder is killed and logs cleaned at the very end
finally
(do
-- Start first cardano-tracer
tracer1H <- startProc "cardano-tracer" ["--config", cfg]

finally
(do
sleepSeconds waitSecs
ensureNonEmpty logLink
"Nothing has been written to the file with trace messages"

-- Kill first tracer
terminateProcess tracer1H
void (waitForProcess tracer1H)

sleepSeconds 2

-- Start second tracer
tracer2H <- startProc "cardano-tracer" ["--config", cfg]

finally
(do
sleepSeconds waitSecs
ensureNonEmpty logLink
"Nothing has been written to the file since the restart of cardano-tracer"

let logDir = dir </> (sock ++ "@0")
entries <- listDirectory logDir
let candidates = filter (not . isSpecialEntry) entries
let count = length candidates
when (count /= 2) $ do
hPutStrLn stderr $
"Two log files are expected to be present, found: " ++ show count
exitFailure)
(safeTerminate tracer2H))
(safeTerminate tracer1H))
(do
safeTerminate forwarderH
cleanup)

--------------------------------------------------------------------------------
-- Helpers

startProc :: FilePath -> [String] -> IO ProcessHandle
startProc cmd args = do
(_, _, _, ph) <- createProcess (proc cmd args)
{ std_in = Inherit
, std_out = Inherit
, std_err = Inherit
}
pure ph

sleepSeconds :: Int -> IO ()
sleepSeconds s = threadDelay (s * 1000000)

ensureNonEmpty :: FilePath -> String -> IO ()
ensureNonEmpty fp errMsg = do
exists <- doesFileExist fp
unless exists $ failWith errMsg
sz <- getFileSize fp
when (sz == 0) $ failWith errMsg
where
failWith msg = hPutStrLn stderr msg >> exitFailure

getFileSize :: FilePath -> IO Integer
getFileSize fp = do
contents <- readFile fp
pure (toInteger (length contents))

safeTerminate :: ProcessHandle -> IO ()
safeTerminate ph = terminateProcess ph >> void (waitForProcess ph)

catchIgnore :: IO () -> IO ()
catchIgnore act = act `catch` \(_ :: IOException) -> pure ()

isDot :: FilePath -> Bool
isDot "." = True
isDot ".." = True
isDot _ = False

isCurrentLog :: FilePath -> Bool
isCurrentLog "node.json" = True
isCurrentLog _ = False

isSpecialEntry :: FilePath -> Bool
isSpecialEntry fp = isDot fp || isCurrentLog fp

resolveConfigPath :: IO FilePath
resolveConfigPath = go =<< getCurrentDirectory
where
configRelative root =
root </> "cardano-tracer" </> "test" </> "restart-test" </> "restart-config.yaml"

go dir = do
let cfgPath = configRelative dir
exists <- doesFileExist cfgPath
if exists
then pure cfgPath
else do
let parent = takeDirectory dir
if parent == dir
then do
hPutStrLn stderr "Unable to locate restart-config.yaml"
exitFailure
else go parent
Loading