Skip to content

Commit 0bcc2de

Browse files
committed
Restore integration test
1 parent 1eb52ee commit 0bcc2de

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
{-# LANGUAGE BlockArguments #-}
2+
{-# LANGUAGE DisambiguateRecordFields #-}
3+
{-# LANGUAGE NamedFieldPuns #-}
4+
{-# LANGUAGE OverloadedStrings #-}
5+
{-# LANGUAGE ScopedTypeVariables #-}
6+
{-# LANGUAGE TypeApplications #-}
7+
8+
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
9+
10+
{- HLINT ignore "Redundant id" -}
11+
{- HLINT ignore "Redundant return" -}
12+
{- HLINT ignore "Use head" -}
13+
{- HLINT ignore "Use let" -}
14+
15+
module Test.Cli.Babbage.LeadershipSchedule
16+
( hprop_leadershipSchedule
17+
) where
18+
19+
import Cardano.CLI.Shelley.Output (QueryTipLocalStateOutput (..))
20+
import Control.Monad (void)
21+
import Data.List ((\\))
22+
import Data.Monoid (Last (..))
23+
import GHC.Stack (callStack)
24+
import Hedgehog (Property)
25+
import Prelude
26+
import System.Environment (getEnvironment)
27+
import System.FilePath ((</>))
28+
29+
import qualified Data.Aeson as J
30+
import qualified Data.Aeson.Types as J
31+
import qualified Data.List as L
32+
import qualified Data.Time.Clock as DTC
33+
import qualified Hedgehog as H
34+
import qualified Hedgehog.Extras.Stock.IO.Network.Sprocket as IO
35+
import qualified Hedgehog.Extras.Test.Base as H
36+
import qualified Hedgehog.Extras.Test.File as H
37+
import qualified Hedgehog.Extras.Test.Process as H
38+
import qualified System.Directory as IO
39+
import qualified System.Info as SYS
40+
import qualified Testnet.Util.Base as H
41+
42+
import Cardano.Testnet
43+
import Testnet.Util.Assert
44+
import Testnet.Util.Process
45+
import Testnet.Util.Runtime
46+
47+
hprop_leadershipSchedule :: Property
48+
hprop_leadershipSchedule = H.integrationRetryWorkspace 2 "babbage-leadership-schedule" $ \tempAbsBasePath' -> do
49+
H.note_ SYS.os
50+
base <- H.note =<< H.noteIO . IO.canonicalizePath =<< H.getProjectBase
51+
configurationTemplate <- H.noteShow $ base </> "configuration/defaults/byron-mainnet/configuration.yaml"
52+
conf@Conf { tempBaseAbsPath, tempAbsPath } <- H.noteShowM $
53+
mkConf (ProjectBase base) (YamlFilePath configurationTemplate) tempAbsBasePath' Nothing
54+
55+
work <- H.note $ tempAbsPath </> "work"
56+
H.createDirectoryIfMissing work
57+
58+
let
59+
testnetOptions = BabbageOnlyTestnetOptions $ babbageDefaultTestnetOptions
60+
{ babbageNodeLoggingFormat = NodeLoggingFormatAsJson
61+
}
62+
tr@TestnetRuntime
63+
{ testnetMagic
64+
, poolNodes
65+
-- , wallets
66+
-- , delegators
67+
} <- testnet testnetOptions conf
68+
69+
poolNode1 <- H.headM poolNodes
70+
71+
env <- H.evalIO getEnvironment
72+
73+
poolSprocket1 <- H.noteShow $ nodeSprocket $ poolRuntime poolNode1
74+
75+
execConfig <- H.noteShow H.ExecConfig
76+
{ H.execConfigEnv = Last $ Just $
77+
[ ("CARDANO_NODE_SOCKET_PATH", IO.sprocketArgumentName poolSprocket1)
78+
]
79+
-- The environment must be passed onto child process on Windows in order to
80+
-- successfully start that process.
81+
<> env
82+
, H.execConfigCwd = Last $ Just tempBaseAbsPath
83+
}
84+
85+
tipDeadline <- H.noteShowM $ DTC.addUTCTime 210 <$> H.noteShowIO DTC.getCurrentTime
86+
87+
H.byDeadlineM 10 tipDeadline "Wait for two epochs" $ do
88+
void $ execCli' execConfig
89+
[ "query", "tip"
90+
, "--testnet-magic", show @Int testnetMagic
91+
, "--out-file", work </> "current-tip.json"
92+
]
93+
94+
tipJson <- H.leftFailM . H.readJsonFile $ work </> "current-tip.json"
95+
tip <- H.noteShowM $ H.jsonErrorFail $ J.fromJSON @QueryTipLocalStateOutput tipJson
96+
97+
currEpoch <- case mEpoch tip of
98+
Nothing -> H.failMessage callStack "cardano-cli query tip returned Nothing for EpochNo"
99+
Just currEpoch -> return currEpoch
100+
101+
H.note_ $ "Current Epoch: " <> show currEpoch
102+
H.assert $ currEpoch > 2
103+
104+
stakePoolId <- filter ( /= '\n') <$> execCli
105+
[ "stake-pool", "id"
106+
, "--cold-verification-key-file", poolNodeKeysColdVkey $ poolKeys poolNode1
107+
]
108+
109+
let poolVrfSkey = poolNodeKeysVrfSkey $ poolKeys poolNode1
110+
111+
id do
112+
scheduleFile <- H.noteTempFile tempAbsPath "schedule.log"
113+
114+
leadershipScheduleDeadline <- H.noteShowM $ DTC.addUTCTime 180 <$> H.noteShowIO DTC.getCurrentTime
115+
116+
H.byDeadlineM 5 leadershipScheduleDeadline "Failed to query for leadership schedule" $ do
117+
void $ execCli' execConfig
118+
[ "query", "leadership-schedule"
119+
, "--testnet-magic", show @Int testnetMagic
120+
, "--genesis", shelleyGenesisFile tr
121+
, "--stake-pool-id", stakePoolId
122+
, "--vrf-signing-key-file", poolVrfSkey
123+
, "--out-file", scheduleFile
124+
, "--current"
125+
]
126+
127+
scheduleJson <- H.leftFailM $ H.readJsonFile scheduleFile
128+
129+
expectedLeadershipSlotNumbers <- H.noteShowM $ fmap (fmap slotNumber) $ H.leftFail $ J.parseEither (J.parseJSON @[LeadershipSlot]) scheduleJson
130+
131+
maxSlotExpected <- H.noteShow $ maximum expectedLeadershipSlotNumbers
132+
133+
H.assert $ not (L.null expectedLeadershipSlotNumbers)
134+
135+
leadershipDeadline <- H.noteShowM $ DTC.addUTCTime 90 <$> H.noteShowIO DTC.getCurrentTime
136+
137+
-- We need enough time to pass such that the expected leadership slots generated by the
138+
-- leadership-schedule command have actually occurred.
139+
leaderSlots <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
140+
someLeaderSlots <- getRelevantLeaderSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
141+
if L.null someLeaderSlots
142+
then H.failure
143+
else do
144+
maxActualSlot <- H.noteShow $ maximum someLeaderSlots
145+
H.assert $ maxActualSlot >= maxSlotExpected
146+
pure someLeaderSlots
147+
148+
H.noteShow_ expectedLeadershipSlotNumbers
149+
H.noteShow_ leaderSlots
150+
151+
-- As there are no BFT nodes, the next leadership schedule should match slots assigned exactly
152+
H.assert $ L.null (expectedLeadershipSlotNumbers \\ leaderSlots)
153+
154+
id do
155+
scheduleFile <- H.noteTempFile tempAbsPath "schedule.log"
156+
157+
leadershipScheduleDeadline <- H.noteShowM $ DTC.addUTCTime 180 <$> H.noteShowIO DTC.getCurrentTime
158+
159+
H.byDeadlineM 5 leadershipScheduleDeadline "Failed to query for leadership schedule" $ do
160+
void $ execCli' execConfig
161+
[ "query", "leadership-schedule"
162+
, "--testnet-magic", show @Int testnetMagic
163+
, "--genesis", shelleyGenesisFile tr
164+
, "--stake-pool-id", stakePoolId
165+
, "--vrf-signing-key-file", poolVrfSkey
166+
, "--out-file", scheduleFile
167+
, "--next"
168+
]
169+
170+
scheduleJson <- H.leftFailM $ H.readJsonFile scheduleFile
171+
172+
expectedLeadershipSlotNumbers <- H.noteShowM $ fmap (fmap slotNumber) $ H.leftFail $ J.parseEither (J.parseJSON @[LeadershipSlot]) scheduleJson
173+
maxSlotExpected <- H.noteShow $ maximum expectedLeadershipSlotNumbers
174+
175+
H.assert $ not (L.null expectedLeadershipSlotNumbers)
176+
177+
leadershipDeadline <- H.noteShowM $ DTC.addUTCTime 90 <$> H.noteShowIO DTC.getCurrentTime
178+
179+
-- We need enough time to pass such that the expected leadership slots generated by the
180+
-- leadership-schedule command have actually occurred.
181+
leaderSlots <- H.byDeadlineM 10 leadershipDeadline "Wait for chain to surpass all expected leadership slots" $ do
182+
someLeaderSlots <- getRelevantLeaderSlots (poolNodeStdout poolNode1) (minimum expectedLeadershipSlotNumbers)
183+
if L.null someLeaderSlots
184+
then H.failure
185+
else do
186+
maxActualSlot <- H.noteShow $ maximum someLeaderSlots
187+
H.assert $ maxActualSlot >= maxSlotExpected
188+
pure someLeaderSlots
189+
190+
H.noteShow_ expectedLeadershipSlotNumbers
191+
H.noteShow_ leaderSlots
192+
193+
-- As there are no BFT nodes, the next leadership schedule should match slots assigned exactly
194+
H.assert $ L.null (expectedLeadershipSlotNumbers \\ leaderSlots)

0 commit comments

Comments
 (0)