@@ -65,7 +65,7 @@ import Testnet.Filepath
6565import Testnet.Handlers (interruptNodesOnSigINT )
6666import Testnet.Orphans ()
6767import Testnet.Process.RunIO (execCli' , execCli_ , liftIOAnnotated , mkExecConfig )
68- import Testnet.Property.Assert (assertChainExtended , assertExpectedSposInLedgerState )
68+ import Testnet.Property.Assert (assertExpectedSposInLedgerState )
6969import Testnet.Runtime as TR
7070import Testnet.Start.Types
7171import Testnet.Types as TR hiding (shelleyGenesis )
@@ -74,8 +74,9 @@ import qualified Hedgehog.Extras as H
7474import qualified Hedgehog.Extras.Stock.IO.Network.Port as H
7575import Hedgehog.Internal.Property (failException )
7676
77- import RIO (MonadUnliftIO , RIO (.. ), runRIO , throwString )
77+ import RIO (MonadUnliftIO , RIO (.. ), runRIO , throwString , timeout )
7878import RIO.Orphans (ResourceMap )
79+ import RIO.State (put )
7980import UnliftIO.Async
8081import UnliftIO.Exception (stringException )
8182
@@ -226,8 +227,7 @@ cardanoTestnet
226227 , updateTimestamps
227228 } = do
228229 let CardanoTestnetOptions
229- { cardanoNodeLoggingFormat= nodeLoggingFormat
230- , cardanoEnableNewEpochStateLogging= enableNewEpochStateLogging
230+ { cardanoEnableNewEpochStateLogging= enableNewEpochStateLogging
231231 , cardanoNodes
232232 } = testnetOptions
233233 nPools = cardanoNumPools testnetOptions
@@ -282,7 +282,7 @@ cardanoTestnet
282282 liftIOAnnotated $ writeFile (nodeDataDir </> " port" ) (show portNumber)
283283 let topologyPath = tmpAbsPath </> Defaults. defaultNodeDataDir i </> " topology.json"
284284 tBytes <- liftIOAnnotated $ LBS. readFile topologyPath
285- case eitherDecode tBytes of
285+ case eitherDecode tBytes of
286286 Right (abstractTopology :: P2P. NetworkTopology NodeId ) -> do
287287 topology <- mapM idToRemoteAddressP2P abstractTopology
288288 liftIOAnnotated $ LBS. writeFile topologyPath $ encode topology
@@ -349,11 +349,8 @@ cardanoTestnet
349349 -- Interrupt cardano nodes when the main process is interrupted
350350 liftIOAnnotated $ interruptNodesOnSigINT testnetNodes'
351351
352- -- FIXME: use foldEpochState waiting for chain extensions
353- now <- liftIOAnnotated DTC. getCurrentTime
354- let deadline = DTC. addUTCTime 45 now
355- forM_ testnetNodes' $ \ nodeStdoutFile -> do
356- assertChainExtended deadline nodeLoggingFormat nodeStdoutFile
352+ -- Make sure that all nodes are healthy by waiting for a chain extension
353+ mapConcurrently_ (waitForBlockThrow 45 (File nodeConfigFile)) testnetNodes'
357354
358355 let runtime = TestnetRuntime
359356 { configurationFile = File nodeConfigFile
@@ -397,6 +394,37 @@ cardanoTestnet
397394 mkTestnetNodeKeyPaths :: Int -> SpoNodeKeys
398395 mkTestnetNodeKeyPaths n = makePathsAbsolute $ Defaults. defaultSpoKeys n
399396
397+ -- wait for new blocks or throw an exception if there are none in the timeout period
398+ waitForBlockThrow :: MonadUnliftIO m
399+ => MonadCatch m
400+ => Int -- ^ timeout in seconds
401+ -> NodeConfigFile 'In
402+ -> TestnetNode
403+ -> m ()
404+ waitForBlockThrow timeoutSeconds nodeConfigFile node@ TestnetNode {nodeName} = do
405+ result <- timeout (timeoutSeconds * 1_000_000 ) $
406+ runExceptT . foldEpochState
407+ nodeConfigFile
408+ (nodeSocketPath node)
409+ QuickValidation
410+ (EpochNo maxBound )
411+ minBound
412+ $ \ _ slotNo blockNo -> do
413+ put slotNo
414+ pure $ if blockNo >= 1
415+ then ConditionMet -- we got one block
416+ else ConditionNotMet
417+
418+ case result of
419+ Just (Right (ConditionMet , _)) -> pure ()
420+ Just (Right (ConditionNotMet , slotNo)) ->
421+ throwString $ nodeName <> " was unable to produce any blocks. Reached slot " <> show slotNo
422+ Just (Left err) ->
423+ throwString $ " foldBlocks on " <> nodeName <> " encountered an error while producing blocks: " <> show (prettyError err)
424+ _ ->
425+ throwString $ nodeName <> " was unable to produce any blocks for " <> show timeoutSeconds <> " s"
426+
427+
400428-- | A convenience wrapper around `createTestnetEnv` and `cardanoTestnet`
401429createAndRunTestnet :: ()
402430 => HasCallStack
@@ -420,8 +448,8 @@ retryOnAddressInUseError
420448retryOnAddressInUseError act = withFrozenCallStack $ go maximumTimeout retryTimeout
421449 where
422450 go :: HasCallStack => NominalDiffTime -> NominalDiffTime -> ExceptT NodeStartFailure m a
423- go timeout interval
424- | timeout <= 0 = withFrozenCallStack $ do
451+ go timeout' interval
452+ | timeout' <= 0 = withFrozenCallStack $ do
425453 act
426454 | otherwise = withFrozenCallStack $ do
427455 ! time <- liftIOAnnotated DTC. getCurrentTime
@@ -430,7 +458,7 @@ retryOnAddressInUseError act = withFrozenCallStack $ go maximumTimeout retryTime
430458 liftIOAnnotated $ threadDelay (round $ interval * 1_000_000 )
431459 ! time' <- liftIOAnnotated DTC. getCurrentTime
432460 let elapsedTime = time' `diffUTCTime` time
433- newTimeout = timeout - elapsedTime
461+ newTimeout = timeout' - elapsedTime
434462 go newTimeout interval
435463 e -> throwError e
436464
0 commit comments