Skip to content

Commit

Permalink
Additional check for not-leader slots in LeadershipSchedule tests
Browse files Browse the repository at this point in the history
  • Loading branch information
carbolymer committed Apr 17, 2023
1 parent 543b267 commit fcd3744
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
50 changes: 32 additions & 18 deletions cardano-testnet/src/Testnet/Util/Assert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
module Testnet.Util.Assert
( readJsonLines
, assertChainExtended
, getRelevantLeaderSlots
, getRelevantSlots
) where

import Prelude hiding (lines)
Expand Down Expand Up @@ -71,30 +71,44 @@ newtype Kind = Kind
{ kind :: Text
} deriving (Eq, Show)

data TraceNodeIsLeader = TraceNodeIsLeader
{ kind :: Text
, slot :: Int
} deriving (Eq, Show)

instance FromJSON TraceNodeIsLeader where
parseJSON = Aeson.withObject "TraceNodeIsLeader" $ \v -> do
k <- v .: "val" >>= (.: "kind")
if k == "TraceNodeIsLeader"
then TraceNodeIsLeader k <$> (v .: "val" >>= (.: "slot"))
else fail $ "Expected kind was TraceNodeIsLeader, found " <> show k <> "instead"
data TraceNode
= TraceNode
{ isLeader :: !Bool
, kind :: !Text
, slot :: !Int
}
deriving (Eq, Show)

instance FromJSON TraceNode where
parseJSON = Aeson.withObject "TraceNode" $ \v -> do
kind' <- v .: "val" >>= (.: "kind")
let slotP = v .: "val" >>= (.: "slot")
case kind' of
"TraceNodeIsLeader" -> TraceNode True kind' <$> slotP
"TraceNodeNotLeader" -> TraceNode False kind' <$> slotP
_ -> fail $ "Expected kind was TraceNodeIsLeader, found " <> show kind' <> "instead"

instance FromJSON Kind where
parseJSON = Aeson.withObject "Kind" $ \v ->
Kind <$> v .: "kind"

getRelevantLeaderSlots :: FilePath -> Int -> H.PropertyT (ReaderT IntegrationState (ResourceT IO)) [Int]
getRelevantLeaderSlots poolNodeStdoutFile slotLowerBound = do
getRelevantSlots :: FilePath -> Int -> H.PropertyT (ReaderT IntegrationState (ResourceT IO)) ([Int], [Int])
getRelevantSlots poolNodeStdoutFile slotLowerBound = do
vs <- readJsonLines poolNodeStdoutFile
let slots = L.map unLogEntry $ Maybe.mapMaybe (Aeson.parseMaybe Aeson.parseJSON) vs

leaderSlots <- H.noteShow
$ L.map (slot . unLogEntry)
$ Maybe.mapMaybe (Aeson.parseMaybe (Aeson.parseJSON @(LogEntry TraceNodeIsLeader)))
vs
$ map slot
$ filter isLeader slots
notLeaderSlots <- H.noteShow
$ map slot
$ filter (not . isLeader) slots

relevantLeaderSlots <- H.noteShow
$ L.filter (>= slotLowerBound)
leaderSlots
return relevantLeaderSlots
relevantNotLeaderSlots <- H.noteShow
$ L.filter (>= slotLowerBound)
notLeaderSlots

pure (relevantLeaderSlots, relevantNotLeaderSlots)
14 changes: 11 additions & 3 deletions cardano-testnet/test/Test/Cli/Alonzo/LeadershipSchedule.hs
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,19 @@ hprop_leadershipSchedule = integrationRetryWorkspace 2 "alonzo-leadership-schedu

-- We need enough time to pass such that the expected leadership slots generated by the
-- leadership-schedule command have actually occurred.
leaderSlots <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
someLeaderSlots <- getRelevantLeaderSlots (nodeStdout $ poolRuntime poolNode1) (minimum expectedLeadershipSlotNumbers)
(leaderSlots, notLeaderSlots) <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
(someLeaderSlots, someNotLeaderSlots) <- getRelevantSlots (nodeStdout $ poolRuntime poolNode1) (minimum expectedLeadershipSlotNumbers)
maxActualSlot <- H.noteShow $ maximum someLeaderSlots
H.assert $ maxActualSlot >= maxSlotExpected
pure someLeaderSlots
pure (someLeaderSlots, someNotLeaderSlots)

H.noteShow_ expectedLeadershipSlotNumbers
H.noteShow_ leaderSlots
H.noteShow_ notLeaderSlots

-- Double check that we've seen all slots
H.annotate "Slots not seen as TraceNodeIsLeader nor TraceNodeNotLeader"
([minimum expectedLeadershipSlotNumbers .. maxSlotExpected] \\ leaderSlots) \\ notLeaderSlots === []

-- It's possible for some slots to not be assigned in TPraos when BFT nodes are running.
-- TODO Remove BFT nodes from testnet and assert the schedule is equal to actual slots
Expand Down
25 changes: 18 additions & 7 deletions cardano-testnet/test/Test/Cli/Babbage/LeadershipSchedule.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import Control.Monad (void)
import Data.List ((\\))
import Data.Monoid (Last (..))
import GHC.Stack (callStack)
import Hedgehog (Property)
import Hedgehog (Property, (===))
import Prelude
import System.Environment (getEnvironment)
import System.FilePath ((</>))
Expand Down Expand Up @@ -136,17 +136,22 @@ hprop_leadershipSchedule = H.integrationRetryWorkspace 2 "babbage-leadership-sch

-- We need enough time to pass such that the expected leadership slots generated by the
-- leadership-schedule command have actually occurred.
leaderSlots <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
someLeaderSlots <- getRelevantLeaderSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
(leaderSlots, notLeaderSlots) <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
(someLeaderSlots, someNotLeaderSlots) <- getRelevantSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
if L.null someLeaderSlots
then H.failure
else do
maxActualSlot <- H.noteShow $ maximum someLeaderSlots
H.assert $ maxActualSlot >= maxSlotExpected
pure someLeaderSlots
pure (someLeaderSlots, someNotLeaderSlots)

H.noteShow_ expectedLeadershipSlotNumbers
H.noteShow_ leaderSlots
H.noteShow_ notLeaderSlots

-- Double check that we've seen all slots
H.annotate "Slots not seen as TraceNodeIsLeader nor TraceNodeNotLeader"
([minimum expectedLeadershipSlotNumbers .. maxSlotExpected] \\ leaderSlots) \\ notLeaderSlots === []

-- As there are no BFT nodes, the next leadership schedule should match slots assigned exactly
H.assert $ L.null (expectedLeadershipSlotNumbers \\ leaderSlots)
Expand Down Expand Up @@ -178,17 +183,23 @@ hprop_leadershipSchedule = H.integrationRetryWorkspace 2 "babbage-leadership-sch

-- We need enough time to pass such that the expected leadership slots generated by the
-- leadership-schedule command have actually occurred.
leaderSlots <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
someLeaderSlots <- getRelevantLeaderSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
(leaderSlots, notLeaderSlots) <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
(someLeaderSlots, someNotLeaderSlots) <- getRelevantSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
if L.null someLeaderSlots
then H.failure
else do
maxActualSlot <- H.noteShow $ maximum someLeaderSlots
H.assert $ maxActualSlot >= maxSlotExpected
pure someLeaderSlots
pure (someLeaderSlots, someNotLeaderSlots)

H.noteShow_ expectedLeadershipSlotNumbers
H.noteShow_ leaderSlots
H.noteShow_ notLeaderSlots

-- Double check that we've seen all slots
H.annotate "Slots not seen as TraceNodeIsLeader nor TraceNodeNotLeader"
([minimum expectedLeadershipSlotNumbers .. maxSlotExpected] \\ leaderSlots) \\ notLeaderSlots === []

-- As there are no BFT nodes, the next leadership schedule should match slots assigned exactly
H.assert $ L.null (expectedLeadershipSlotNumbers \\ leaderSlots)

0 comments on commit fcd3744

Please sign in to comment.