11{-# LANGUAGE DataKinds #-}
22{-# LANGUAGE GADTs #-}
3+ {-# LANGUAGE NamedFieldPuns #-}
34{-# LANGUAGE OverloadedStrings #-}
45{-# LANGUAGE ScopedTypeVariables #-}
56{-# LANGUAGE TypeApplications #-}
67
78module Testnet.Components.Query
89 ( QueryTip
910 , EpochStateView
11+ , checkDRepsNumber
1012 , getEpochState
1113 , queryTip
1214 , waitUntilEpoch
@@ -19,6 +21,8 @@ module Testnet.Components.Query
1921 ) where
2022
2123import Cardano.Api as Api
24+ import Cardano.Api.Ledger (StandardCrypto )
25+ import qualified Cardano.Api.Ledger as L
2226import Cardano.Api.Shelley (ShelleyLedgerEra , fromShelleyTxIn , fromShelleyTxOut )
2327
2428import Cardano.CLI.Types.Output
@@ -28,6 +32,7 @@ import qualified Cardano.Ledger.UTxO as L
2832import Control.Exception.Safe (MonadCatch )
2933import Control.Monad
3034import Control.Monad.Trans.Resource
35+ import Control.Monad.Trans.State.Strict (put )
3136import Data.Aeson
3237import Data.Bifunctor (bimap )
3338import Data.IORef
@@ -44,6 +49,7 @@ import GHC.Stack
4449import Lens.Micro ((^.) )
4550import System.Directory (doesFileExist , removeFile )
4651
52+ import qualified Testnet.Process.Cli as P
4753import qualified Testnet.Process.Run as H
4854import Testnet.Property.Assert
4955import Testnet.Property.Utils (runInBackground )
@@ -218,3 +224,65 @@ findLargestUtxoForPaymentKey epochStateView sbe address =
218224 . H. nothingFailM
219225 $ findLargestUtxoWithAddress epochStateView sbe (paymentKeyInfoAddr address)
220226
227+
228+ -- | @checkDRepsNumber config socket execConfig n@
229+ -- wait for the number of DReps being @n@ for two epochs. If
230+ -- this number is not attained before two epochs, the test is failed.
231+ checkDRepsNumber ::
232+ (HasCallStack , MonadIO m , MonadCatch m , MonadTest m )
233+ => ShelleyBasedEra ConwayEra -- ^ The era in which the test runs
234+ -> NodeConfigFile 'In
235+ -> SocketPath
236+ -> H. ExecConfig
237+ -> Int
238+ -> m ()
239+ checkDRepsNumber sbe configurationFile socketPath execConfig expectedDRepsNb = do
240+ QueryTipLocalStateOutput {mEpoch} <- P. execCliStdoutToJson execConfig [ " query" , " tip" ]
241+ currentEpoch <- H. evalMaybe mEpoch
242+ let terminationEpoch = succ . succ $ currentEpoch
243+ void $ H. evalMaybeM $ checkDRepsNumber' sbe configurationFile socketPath terminationEpoch expectedDRepsNb
244+
245+ -- | @checkDRepsNumber' config socket terminationEpoch n@
246+ -- wait until @terminationEpoch@ for the number of DReps being @n@. If
247+ -- this number is not attained before @terminationEpoch@, the test is failed.
248+ -- So if you call this function, you are expecting the number of DReps to already
249+ -- be @n@, or to be @n@ before @terminationEpoch@
250+ checkDRepsNumber' ::
251+ (HasCallStack , MonadIO m , MonadTest m )
252+ => ShelleyBasedEra ConwayEra -- ^ The era in which the test runs
253+ -> NodeConfigFile In
254+ -> SocketPath
255+ -> EpochNo -- ^ The termination epoch: the constitution proposal must be found *before* this epoch
256+ -> Int -- ^ The expected numbers of DReps. If this number is not reached until the termination epoch, this function fails the test.
257+ -> m (Maybe [L. DRepState StandardCrypto ]) -- ^ The DReps when the expected number of DReps was attained.
258+ checkDRepsNumber' sbe nodeConfigFile socketPath maxEpoch expectedDRepsNb = do
259+ result <- runExceptT $ foldEpochState nodeConfigFile socketPath QuickValidation maxEpoch Nothing
260+ $ \ (AnyNewEpochState actualEra newEpochState) -> do
261+ case testEquality sbe actualEra of
262+ Just Refl -> do
263+ let dreps = Map. elems $ shelleyBasedEraConstraints sbe newEpochState
264+ ^. L. nesEsL
265+ . L. esLStateL
266+ . L. lsCertStateL
267+ . L. certVStateL
268+ . L. vsDRepsL
269+ if length dreps == expectedDRepsNb then do
270+ put $ Just dreps
271+ pure ConditionMet
272+ else
273+ pure ConditionNotMet
274+ Nothing -> do
275+ error $ " Eras mismatch! expected: " <> show sbe <> " , actual: " <> show actualEra
276+ case result of
277+ Left (FoldBlocksApplyBlockError (TerminationEpochReached epochNo)) -> do
278+ H. note_ $ unlines
279+ [ " waitDRepsNumber: drep number did not become " <> show expectedDRepsNb <> " before termination epoch: " <> show epochNo
280+ , " This is likely an error of this test." ]
281+ H. failure
282+ Left err -> do
283+ H. note_ $ unlines
284+ [ " waitDRepsNumber: could not reach termination epoch: " <> docToString (prettyError err)
285+ , " This is probably an error unrelated to this test." ]
286+ H. failure
287+ Right (_, val) ->
288+ return val
0 commit comments