From aeb4adf1beb54bf852c6147b431fcffd340a12a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hurlin?= Date: Wed, 29 Jan 2025 16:47:32 +0100 Subject: [PATCH 1/2] cardano-tesnet: allow to specify output directory --- cardano-testnet/src/Parsers/Cardano.hs | 5 +++ cardano-testnet/src/Parsers/Run.hs | 2 +- cardano-testnet/src/Testnet/Filepath.hs | 2 + cardano-testnet/src/Testnet/Property/Run.hs | 46 ++++++++++++++------- cardano-testnet/src/Testnet/Start/Types.hs | 2 + 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/cardano-testnet/src/Parsers/Cardano.hs b/cardano-testnet/src/Parsers/Cardano.hs index aa4767e89ba..8d66e73f390 100644 --- a/cardano-testnet/src/Parsers/Cardano.hs +++ b/cardano-testnet/src/Parsers/Cardano.hs @@ -57,6 +57,11 @@ pCardanoTestnetCliOptions envCli = CardanoTestnetOptions <> OA.help "Enable new epoch state logging to logs/ledger-epoch-state.log" <> OA.showDefault ) + <*> optional (OA.strOption + ( OA.long "output-dir" + <> OA.help "Directory where to store files, sockets, and so on. It is created if it doesn't exist. If unset, a temporary directory is used." + <> OA.metavar "DIRECTORY" + )) where pAnyShelleyBasedEra' :: Parser AnyShelleyBasedEra pAnyShelleyBasedEra' = diff --git a/cardano-testnet/src/Parsers/Run.hs b/cardano-testnet/src/Parsers/Run.hs index 7ea49f8e920..2572faf2066 100644 --- a/cardano-testnet/src/Parsers/Run.hs +++ b/cardano-testnet/src/Parsers/Run.hs @@ -53,4 +53,4 @@ runTestnetCmd = \case runCardanoOptions :: CardanoTestnetCliOptions -> IO () runCardanoOptions (CardanoTestnetCliOptions testnetOptions shelleyOptions) = - runTestnet $ cardanoTestnetDefault testnetOptions shelleyOptions + runTestnet testnetOptions $ cardanoTestnetDefault testnetOptions shelleyOptions diff --git a/cardano-testnet/src/Testnet/Filepath.hs b/cardano-testnet/src/Testnet/Filepath.hs index 8bc36ee2712..e3aae3d20a6 100644 --- a/cardano-testnet/src/Testnet/Filepath.hs +++ b/cardano-testnet/src/Testnet/Filepath.hs @@ -25,6 +25,8 @@ makeSprocket makeSprocket tmpAbsPath node = Sprocket (makeTmpBaseAbsPath tmpAbsPath) (makeSocketDir tmpAbsPath node) +-- TODO rename me: since the introduction of --output-dir in the cardano-testnet +-- executable, this is a directory that can persist after the test ends. -- Temporary path used at runtime newtype TmpAbsolutePath = TmpAbsolutePath { unTmpAbsPath :: FilePath diff --git a/cardano-testnet/src/Testnet/Property/Run.hs b/cardano-testnet/src/Testnet/Property/Run.hs index 12699b2057a..9d6b810ba31 100644 --- a/cardano-testnet/src/Testnet/Property/Run.hs +++ b/cardano-testnet/src/Testnet/Property/Run.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE NamedFieldPuns #-} + module Testnet.Property.Run ( runTestnet -- Ignore tests on various OSs @@ -19,11 +21,13 @@ import Data.Bool (bool) import Data.String (IsString (..)) import qualified System.Console.ANSI as ANSI import System.Console.ANSI (Color (..), ColorIntensity (..), ConsoleLayer (..), SGR (..)) +import System.Directory import qualified System.Exit as IO import qualified System.Info as SYS import qualified System.IO as IO -import Testnet.Property.Util (integrationWorkspace) +import Testnet.Filepath +import Testnet.Property.Util (integration, integrationWorkspace) import Testnet.Start.Types import Hedgehog (Property) @@ -35,11 +39,11 @@ import qualified Test.Tasty.Hedgehog as H import Test.Tasty.Providers (testPassed) import Test.Tasty.Runners (Result (resultShortDescription), TestTree) -runTestnet :: (Conf -> H.Integration a) -> IO () -runTestnet tn = do +runTestnet :: CardanoTestnetOptions -> (Conf -> H.Integration a) -> IO () +runTestnet tnOpts tn = do tvRunning <- STM.newTVarIO False - void . H.check $ testnetProperty $ \c -> do + void . H.check $ testnetProperty tnOpts $ \c -> do void $ tn c H.evalIO . STM.atomically $ STM.writeTVar tvRunning True @@ -60,17 +64,29 @@ runTestnet tn = do IO.exitFailure -testnetProperty :: (Conf -> H.Integration ()) -> H.Property -testnetProperty tn = integrationWorkspace "testnet" $ \workspaceDir -> do - conf <- mkConf workspaceDir - - -- Fork a thread to keep alive indefinitely any resources allocated by testnet. - void . H.evalM . liftResourceT . resourceForkIO . forever . liftIO $ IO.threadDelay 10000000 - - void $ tn conf - - H.failure -- Intentional failure to force failure report - +testnetProperty :: CardanoTestnetOptions -> (Conf -> H.Integration ()) -> H.Property +testnetProperty CardanoTestnetOptions{cardanoOutputDir} tn = + case cardanoOutputDir of + Nothing -> do + integrationWorkspace "testnet" $ \workspaceDir -> do + mkConf workspaceDir >>= go + Just userOutputDir -> + integration $ do + absUserOutputDir <- H.evalIO $ makeAbsolute userOutputDir + dirExists <- H.evalIO $ doesDirectoryExist absUserOutputDir + (if dirExists then + -- Likely dangerous, but who are we to judge the user? + H.note_ $ "Reusing " <> absUserOutputDir + else do + liftIO $ createDirectory absUserOutputDir + H.note_ $ "Created " <> absUserOutputDir) + go $ Conf $ TmpAbsolutePath absUserOutputDir + where + go conf = do + -- Fork a thread to keep alive indefinitely any resources allocated by testnet. + void $ H.evalM . liftResourceT . resourceForkIO . forever . liftIO $ IO.threadDelay 10000000 + void $ tn conf + H.failure -- Intentional failure to force failure report -- Ignore properties on various OSs diff --git a/cardano-testnet/src/Testnet/Start/Types.hs b/cardano-testnet/src/Testnet/Start/Types.hs index 53764c27b6b..acb48095377 100644 --- a/cardano-testnet/src/Testnet/Start/Types.hs +++ b/cardano-testnet/src/Testnet/Start/Types.hs @@ -74,6 +74,7 @@ data CardanoTestnetOptions = CardanoTestnetOptions , cardanoNodeLoggingFormat :: NodeLoggingFormat , cardanoNumDReps :: NumDReps -- ^ The number of DReps to generate at creation , cardanoEnableNewEpochStateLogging :: Bool -- ^ if epoch state logging is enabled + , cardanoOutputDir :: Maybe FilePath -- ^ The output directory where to store files, sockets, and so on. If unset, a temporary directory is used. } deriving (Eq, Show) cardanoNumPools :: CardanoTestnetOptions -> NumPools @@ -105,6 +106,7 @@ instance Default CardanoTestnetOptions where , cardanoNodeLoggingFormat = NodeLoggingFormatAsJson , cardanoNumDReps = 3 , cardanoEnableNewEpochStateLogging = True + , cardanoOutputDir = Nothing } -- | Options that are implemented by writing fields in the Shelley genesis file. From 55313f515d0eb7c362d6144641159161c594eab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Hurlin?= Date: Wed, 29 Jan 2025 16:47:40 +0100 Subject: [PATCH 2/2] cardano-testnet: adapt golden files --- .../test/cardano-testnet-golden/files/golden/help.cli | 1 + .../test/cardano-testnet-golden/files/golden/help/cardano.cli | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/help.cli b/cardano-testnet/test/cardano-testnet-golden/files/golden/help.cli index a3432216cfa..1c61e8350e1 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/help.cli +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/help.cli @@ -13,6 +13,7 @@ Usage: cardano-testnet cardano [--num-pool-nodes COUNT] [--nodeLoggingFormat LOGGING_FORMAT] [--num-dreps NUMBER] [--enable-new-epoch-state-logging] + [--output-dir DIRECTORY] --testnet-magic INT [--epoch-length SLOTS] [--slot-length SECONDS] diff --git a/cardano-testnet/test/cardano-testnet-golden/files/golden/help/cardano.cli b/cardano-testnet/test/cardano-testnet-golden/files/golden/help/cardano.cli index 2e80dd747fa..2eeb2297e3a 100644 --- a/cardano-testnet/test/cardano-testnet-golden/files/golden/help/cardano.cli +++ b/cardano-testnet/test/cardano-testnet-golden/files/golden/help/cardano.cli @@ -11,6 +11,7 @@ Usage: cardano-testnet cardano [--num-pool-nodes COUNT] [--nodeLoggingFormat LOGGING_FORMAT] [--num-dreps NUMBER] [--enable-new-epoch-state-logging] + [--output-dir DIRECTORY] --testnet-magic INT [--epoch-length SLOTS] [--slot-length SECONDS] @@ -44,6 +45,9 @@ Available options: --enable-new-epoch-state-logging Enable new epoch state logging to logs/ledger-epoch-state.log + --output-dir DIRECTORY Directory where to store files, sockets, and so on. + It is created if it doesn't exist. If unset, a + temporary directory is used. --testnet-magic INT Specify a testnet magic id. --epoch-length SLOTS Epoch length, in number of slots (default: 500) --slot-length SECONDS Slot length (default: 0.1)