Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Execute testnet tests in parallel #5695

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
14 changes: 2 additions & 12 deletions .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
# see https://github.com/haskell/stm/issues/76
ghc: ["9.6", "9.10"]
cabal: ["3.12"]
n: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
sys:
- { os: windows-latest, shell: 'C:/msys64/usr/bin/bash.exe -e {0}' }
- { os: ubuntu-latest, shell: bash }
Expand All @@ -62,17 +63,6 @@ jobs:
MSYS2_PATH_TYPE: inherit
MSYSTEM: MINGW64

concurrency:
group: >
a+${{ github.event_name }}
b+${{ github.workflow_ref }}
c+${{ github.job }}
d+${{ matrix.ghc }}
e+${{ matrix.cabal }}
f+${{ matrix.sys.os }}
g+${{ (startsWith(github.ref, 'refs/heads/gh-readonly-queue/') && github.run_id) || github.event.pull_request.number || github.ref }}
cancel-in-progress: true

steps:
- name: Concurrency group
run: >
Expand Down Expand Up @@ -180,7 +170,7 @@ jobs:
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: failed-test-workspaces-${{ matrix.sys.os }}-ghc${{ matrix.ghc }}-cabal${{ matrix.cabal }}.tgz
name: failed-test-workspaces-${{ matrix.sys.os }}-ghc${{ matrix.ghc }}-cabal${{ matrix.cabal }}-${{ matrix.n }}.tgz
path: ${{ runner.temp }}/workspaces.tgz

- name: "Tar artifacts"
Expand Down
4 changes: 2 additions & 2 deletions cardano-node-chairman/cardano-node-chairman.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ test-suite chairman-tests

type: exitcode-stdio-1.0

build-depends: cardano-testnet
build-depends: , cardano-api
, cardano-testnet
, cardano-crypto-class ^>= 2.1.2
, data-default-class
, filepath
Expand All @@ -79,7 +80,6 @@ test-suite chairman-tests
, random
, resourcet
, tasty
, tasty-hedgehog
, unliftio

other-modules: Spec.Chairman.Chairman
Expand Down
14 changes: 7 additions & 7 deletions cardano-node-chairman/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ import qualified Cardano.Crypto.Init as Crypto

import Prelude

import Data.String (IsString (..))
import qualified System.Environment as E
import System.IO (BufferMode (LineBuffering), hSetBuffering, hSetEncoding, stdout, utf8)

import Testnet.Property.Run (ignoreOnWindows)

import qualified Test.Tasty as T
import qualified Test.Tasty.Hedgehog as H
import qualified Test.Tasty.Ingredients as T

import qualified Spec.Chairman.Cardano
import qualified Spec.Network

tests :: IO T.TestTree
tests = do
let t0 = H.testPropertyNamed "isPortOpen False" (fromString "isPortOpen False") Spec.Network.hprop_isPortOpen_False
let t1 = H.testPropertyNamed "isPortOpen True" (fromString "isPortOpen True" ) Spec.Network.hprop_isPortOpen_True
-- TODO: Conway broken in conway
-- let t2 = H.testPropertyNamed "chairman" (fromString "chairman" ) Spec.Chairman.Cardano.hprop_chairman
let t0 = ignoreOnWindows "isPortOpen False" Spec.Network.hprop_isPortOpen_False
let t1 = ignoreOnWindows "isPortOpen True" Spec.Network.hprop_isPortOpen_True
let t2 = ignoreOnWindows "chairman" Spec.Chairman.Cardano.hprop_chairman

pure $ T.testGroup "test/Spec.hs"
[ T.testGroup "Spec"
[ T.testGroup "Chairman"
[ T.testGroup "Cardano" [] -- [t2]
[ T.testGroup "Cardano" [t2]
]
, T.testGroup "Network" [t0, t1]
]
Expand Down
11 changes: 5 additions & 6 deletions cardano-node-chairman/test/Spec/Chairman/Cardano.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@

module Spec.Chairman.Cardano where

import Cardano.Testnet (NodeRuntime (nodeName), allNodes,
cardanoTestnetDefault, mkConf)
import Cardano.Testnet (allNodes, cardanoTestnetDefault, mkConf)

import Data.Default.Class

import Testnet.Property.Util (integrationRetryWorkspace)

import qualified Hedgehog as H

import Spec.Chairman.Chairman (chairmanOver)

-- TODO: Conway broken in conway
hprop_chairman :: H.Property
hprop_chairman = integrationRetryWorkspace 2 "cardano-chairman" $ \tempAbsPath' -> do
hprop_chairman = integrationRetryWorkspace 0 "cardano-chairman" $ \tempAbsPath' -> do
conf <- mkConf tempAbsPath'

allNodes' <- fmap nodeName . allNodes <$> cardanoTestnetDefault def def conf
allNodes' <- allNodes <$> cardanoTestnetDefault def def conf

chairmanOver 120 50 conf allNodes'
chairmanOver 120 40 conf allNodes'
19 changes: 8 additions & 11 deletions cardano-node-chairman/test/Spec/Chairman/Chairman.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,41 @@ module Spec.Chairman.Chairman
( chairmanOver
) where

import Cardano.Api (unFile)

import Cardano.Testnet (TmpAbsolutePath (TmpAbsolutePath), makeLogDir)
import qualified Cardano.Testnet as H

import Control.Monad (when)
import Data.Functor ((<&>))
import GHC.Stack
import qualified System.Environment as IO
import System.Exit (ExitCode (..))
import System.FilePath.Posix ((</>))
import qualified System.IO as IO
import qualified System.Process as IO

import Testnet.Types (NodeRuntime, nodeSocketPath)

import qualified Hedgehog as H
import Hedgehog.Extras.Stock.IO.Network.Sprocket (Sprocket (..))
import qualified Hedgehog.Extras.Stock.IO.Network.Sprocket as IO
import Hedgehog.Extras.Test.Base (Integration)
import qualified Hedgehog.Extras.Test.Base as H
import qualified Hedgehog.Extras.Test.File as H
import qualified Hedgehog.Extras.Test.Process as H

{- HLINT ignore "Reduce duplication" -}
{- HLINT ignore "Redundant <&>" -}
{- HLINT ignore "Redundant flip" -}

mkSprocket :: FilePath -> FilePath -> String -> Sprocket
mkSprocket tempBaseAbsPath socketDir node = Sprocket tempBaseAbsPath (socketDir </> node)

chairmanOver :: Int -> Int -> H.Conf -> [String] -> Integration ()
chairmanOver :: HasCallStack => Int -> Int -> H.Conf -> [NodeRuntime] -> Integration ()
chairmanOver timeoutSeconds requiredProgress H.Conf {H.tempAbsPath} allNodes = do
maybeChairman <- H.evalIO $ IO.lookupEnv "DISABLE_CHAIRMAN"
let tempAbsPath' = H.unTmpAbsPath tempAbsPath
logDir = makeLogDir $ TmpAbsolutePath tempAbsPath'
tempBaseAbsPath = H.makeTmpBaseAbsPath $ TmpAbsolutePath tempAbsPath'
socketDir = H.makeSocketDir $ TmpAbsolutePath tempAbsPath'
when (maybeChairman /= Just "1") $ do
nodeStdoutFile <- H.noteTempFile logDir $ "chairman" <> ".stdout.log"
nodeStderrFile <- H.noteTempFile logDir $ "chairman" <> ".stderr.log"

sprockets <- H.noteEach $ fmap (mkSprocket tempBaseAbsPath socketDir) allNodes
sprockets <- H.noteEach $ unFile . nodeSocketPath <$> allNodes

hNodeStdout <- H.evalIO $ IO.openFile nodeStdoutFile IO.WriteMode
hNodeStderr <- H.evalIO $ IO.openFile nodeStderrFile IO.WriteMode
Expand All @@ -54,7 +51,7 @@ chairmanOver timeoutSeconds requiredProgress H.Conf {H.tempAbsPath} allNodes = d
, "--config", tempAbsPath' </> "configuration.yaml"
, "--require-progress", show @Int requiredProgress
]
<> (sprockets >>= (\sprocket -> ["--socket-path", IO.sprocketArgumentName sprocket]))
<> (sprockets >>= (\sprocket -> ["--socket-path", sprocket]))
) <&>
( \cp -> cp
{ IO.std_in = IO.CreatePipe
Expand Down
7 changes: 5 additions & 2 deletions cardano-testnet/src/Testnet/Components/Configuration.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
Expand Down Expand Up @@ -61,7 +62,8 @@ import System.FilePath.Posix (takeDirectory, (</>))
import Testnet.Defaults
import Testnet.Filepath
import Testnet.Process.Run (execCli_)
import Testnet.Start.Types (CardanoTestnetOptions (..), anyEraToString, anyShelleyBasedEraToString, eraToString)
import Testnet.Start.Types (CardanoTestnetOptions (..), anyEraToString,
anyShelleyBasedEraToString, eraToString)

import Hedgehog
import qualified Hedgehog as H
Expand Down Expand Up @@ -119,6 +121,7 @@ numSeededUTxOKeys :: Int
numSeededUTxOKeys = 3

newtype NumPools = NumPools Int
deriving (Show, Eq, Ord, Num) via Int

numPools :: CardanoTestnetOptions -> NumPools
numPools CardanoTestnetOptions { cardanoNodes } = NumPools $ length cardanoNodes
Expand Down Expand Up @@ -181,7 +184,7 @@ createSPOGenesisAndFiles (NumPools numPoolNodes) (NumDReps numDelReps) maxSupply
, "--spec-alonzo", inputGenesisAlonzoFp
, "--spec-conway", inputGenesisConwayFp
, "--testnet-magic", show testnetMagic
, "--pools", show numPoolNodes
, "--pools", "1" -- show numPoolNodes
, "--total-supply", show maxSupply
, "--delegated-supply", show (maxSupply `div` 2) -- Required until https://github.com/IntersectMBO/cardano-cli/pull/874 is integrated
, "--stake-delegators", show numStakeDelegators
Expand Down
6 changes: 3 additions & 3 deletions cardano-testnet/src/Testnet/Defaults.hs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ module Testnet.Defaults
, plutusV3Script
) where

import Cardano.Api (CardanoEra (..), File (..), pshow, ShelleyBasedEra (..),
toCardanoEra, unsafeBoundedRational, AnyShelleyBasedEra (..))
import Cardano.Api (AnyShelleyBasedEra (..), CardanoEra (..), File (..),
ShelleyBasedEra (..), pshow, toCardanoEra, unsafeBoundedRational)
import qualified Cardano.Api.Shelley as Api

import Cardano.Ledger.Alonzo.Core (PParams (..))
Expand Down Expand Up @@ -433,7 +433,7 @@ defaultShelleyGenesis asbe startTime maxSupply options = do
activeSlotsCoeff = round (shelleyActiveSlotsCoeff * 100) % 100
-- make security param k satisfy: epochLength = 10 * k / f
-- TODO: find out why this actually degrates network stability - turned off for now
-- securityParam = ceiling $ fromIntegral epochLength * cardanoActiveSlotsCoeff / 10
-- securityParam = ceiling $ fromIntegral epochLength * shelleyActiveSlotsCoeff / 10
pVer = eraToProtocolVersion asbe
protocolParams = Api.sgProtocolParams Api.shelleyGenesisDefaults
protocolParamsWithPVer = protocolParams & ppProtocolVersionL' .~ pVer
Expand Down
34 changes: 21 additions & 13 deletions cardano-testnet/src/Testnet/Start/Cardano.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import qualified Data.Time.Clock as DTC
import Data.Word (Word64)
import GHC.Stack
import qualified GHC.Stack as GHC
import qualified System.Directory as IO
import System.FilePath ((</>))
import qualified System.Info as OS
import Text.Printf (printf)
Expand All @@ -71,8 +72,8 @@ import qualified Hedgehog.Extras.Stock.OS as OS

-- | There are certain conditions that need to be met in order to run
-- a valid node cluster.
testnetMinimumConfigurationRequirements :: MonadTest m => NumPools -> m ()
testnetMinimumConfigurationRequirements (NumPools n) =
testnetMinimumConfigurationRequirements :: HasCallStack => MonadTest m => NumPools -> m ()
testnetMinimumConfigurationRequirements (NumPools n) = withFrozenCallStack $
when (n < 2) $ do
H.noteShow_ ("Need at least two nodes to run a cluster, but got: " <> show n)
H.failure
Expand Down Expand Up @@ -239,7 +240,7 @@ cardanoTestnet
mkNodeName :: Int -> String
mkNodeName i = "pool" <> show i

poolKeys <- H.noteShow $ flip fmap [1..numPoolNodes] $ \n ->
poolKeys <- H.noteShow $ flip fmap [1..1] $ \n ->
-- TODO: use Testnet.Defaults.defaultSpoKeys here
PoolNodeKeys
{ poolNodeKeysCold =
Expand Down Expand Up @@ -308,8 +309,10 @@ cardanoTestnet
-- Byron related
forM_ (zip [1..] portNumbers) $ \(i, portNumber) -> do
let iStr = printf "%03d" (i - 1)
H.renameFile (tmpAbsPath </> "byron-gen-command" </> "delegate-keys." <> iStr <> ".key") (tmpAbsPath </> poolKeyDir i </> "byron-delegate.key")
H.renameFile (tmpAbsPath </> "byron-gen-command" </> "delegation-cert." <> iStr <> ".json") (tmpAbsPath </> poolKeyDir i </> "byron-delegation.cert")
when (i == 1) $ do
H.renameFile (tmpAbsPath </> "byron-gen-command" </> "delegate-keys." <> iStr <> ".key") (tmpAbsPath </> poolKeyDir i </> "byron-delegate.key")
H.renameFile (tmpAbsPath </> "byron-gen-command" </> "delegation-cert." <> iStr <> ".json") (tmpAbsPath </> poolKeyDir i </> "byron-delegation.cert")
H.evalIO $ IO.createDirectoryIfMissing True $ tmpAbsPath </> poolKeyDir i
H.writeFile (tmpAbsPath </> poolKeyDir i </> "port") (show portNumber)

-- Make topology files
Expand All @@ -330,24 +333,29 @@ cardanoTestnet
keyDir = tmpAbsPath </> poolKeyDir i
H.note_ $ "Node name: " <> nodeName
eRuntime <- runExceptT . retryOnAddressInUseError $
startNode (TmpAbsolutePath tmpAbsPath) nodeName testnetDefaultIpv4Address port testnetMagic
startNode (TmpAbsolutePath tmpAbsPath) nodeName testnetDefaultIpv4Address port testnetMagic $
[ "run"
, "--config", unFile configurationFile
, "--topology", keyDir </> "topology.json"
, "--database-path", keyDir </> "db"
, "--shelley-kes-key", keyDir </> "kes.skey"
, "--shelley-vrf-key", keyDir </> "vrf.skey"
, "--byron-delegation-certificate", keyDir </> "byron-delegation.cert"
, "--byron-signing-key", keyDir </> "byron-delegate.key"
, "--shelley-operational-certificate", keyDir </> "opcert.cert"
]
] <>
(if i == 1 then
[ "--shelley-kes-key", keyDir </> "kes.skey"
, "--shelley-vrf-key", keyDir </> "vrf.skey"
, "--byron-delegation-certificate", keyDir </> "byron-delegation.cert"
, "--byron-signing-key", keyDir </> "byron-delegate.key"
, "--shelley-operational-certificate", keyDir </> "opcert.cert"
]
else [])
pure $ flip PoolNode key <$> eRuntime

let (failedNodes, poolNodes) = partitionEithers ePoolNodes
unless (null failedNodes) $ do
H.noteShow_ . vsep $ prettyError <$> failedNodes
H.failure

H.annotateShow $ nodeSprocket . poolRuntime <$> poolNodes

-- FIXME: use foldEpochState waiting for chain extensions
now <- H.noteShowIO DTC.getCurrentTime
deadline <- H.noteShow $ DTC.addUTCTime 45 now
Expand Down Expand Up @@ -388,7 +396,7 @@ cardanoTestnet

stakePoolsFp <- H.note $ tmpAbsPath </> "current-stake-pools.json"

assertExpectedSposInLedgerState stakePoolsFp nPools execConfig
assertExpectedSposInLedgerState stakePoolsFp 1 execConfig

when newEpochStateLogging $
TR.startLedgerNewEpochStateLogging runtime tempBaseAbsPath
Expand Down
2 changes: 1 addition & 1 deletion cardano-testnet/src/Testnet/Start/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ instance Default ShelleyTestnetOptions where
{ shelleyTestnetMagic = 42
, shelleyEpochLength = 500
, shelleySlotLength = 0.1
, shelleyActiveSlotsCoeff = 0.05
, shelleyActiveSlotsCoeff = 0.1
}

-- | Specify a BFT node (Pre-Babbage era only) or an SPO (Shelley era onwards only)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Evaluate" #-}

module Main
( main
Expand All @@ -20,11 +22,12 @@ import qualified Test.Tasty.Hedgehog as H
import qualified Test.Tasty.Ingredients as T

tests :: IO TestTree
tests = pure $ T.testGroup "Golden tests"
[ H.testPropertyNamed "golden_DefaultConfig" (fromString "golden_DefaultConfig") Cardano.Testnet.Test.Golden.Config.goldenDefaultConfigYaml
, H.testPropertyNamed "golden_HelpAll" (fromString "golden_HelpAll") Cardano.Testnet.Test.Golden.Help.golden_HelpAll
, H.testPropertyNamed "golden_HelpCmds" (fromString "golden_HelpCmds") Cardano.Testnet.Test.Golden.Help.golden_HelpCmds
]
tests = pure $ T.testGroup "Golden tests" $
const []
[ H.testPropertyNamed "golden_DefaultConfig" (fromString "golden_DefaultConfig") Cardano.Testnet.Test.Golden.Config.goldenDefaultConfigYaml
, H.testPropertyNamed "golden_HelpAll" (fromString "golden_HelpAll") Cardano.Testnet.Test.Golden.Help.golden_HelpAll
, H.testPropertyNamed "golden_HelpCmds" (fromString "golden_HelpCmds") Cardano.Testnet.Test.Golden.Help.golden_HelpCmds
]

ingredients :: [T.Ingredient]
ingredients = T.defaultIngredients
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ Available options:
Enable new epoch state logging to
logs/ledger-epoch-state.log
--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)
--epoch-length SLOTS Epoch length, in number of slots (default: 150000)
--slot-length SECONDS Slot length (default: 0.15)
--active-slots-coeff DOUBLE
Active slots co-efficient (default: 5.0e-2)
Active slots co-efficient (default: 0.1)
-h,--help Show this help text
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ hprop_plutus_v3 = integrationWorkspace "all-plutus-script-purposes" $ \tempAbsBa
]

-- 2. Successfully spend conway spending script
_ <- waitForBlocks epochStateView 2
txinCollateral <- findLargestUtxoForPaymentKey epochStateView sbe wallet1
plutusScriptTxIn <- fmap fst . retryUntilJustM epochStateView (WaitForBlocks 3) $
findLargestUtxoWithAddress epochStateView sbe $ Text.pack plutusSpendingScriptAddr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import qualified Hedgehog.Extras.Test.Base as H
import qualified Hedgehog.Extras.Test.TestWatchdog as H

hprop_stakeSnapshot :: Property
hprop_stakeSnapshot = integrationRetryWorkspace 2 "conway-stake-snapshot" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do
hprop_stakeSnapshot = integrationRetryWorkspace 0 "conway-stake-snapshot" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do
H.note_ SYS.os
conf@Conf { tempAbsPath } <- mkConf tempAbsBasePath'
let tempAbsPath' = unTmpAbsPath tempAbsPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import qualified Hedgehog.Extras.Test.TestWatchdog as H
-- | Execute me with:
-- @DISABLE_RETRIES=1 cabal test cardano-testnet-test --test-options '-p "/kes-period-info/"'@
hprop_kes_period_info :: Property
hprop_kes_period_info = integrationRetryWorkspace 2 "kes-period-info" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do
hprop_kes_period_info = integrationRetryWorkspace 0 "kes-period-info" $ \tempAbsBasePath' -> H.runWithDefaultWatchdog_ $ do
H.note_ SYS.os
conf@Conf { tempAbsPath=tempAbsPath@(TmpAbsolutePath work) }
-- TODO: Move yaml filepath specification into individual node options
Expand Down
Loading
Loading