Skip to content

Commit

Permalink
check-node-configuration: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
smelc committed Oct 4, 2024
1 parent fe4f77f commit 5836afd
Show file tree
Hide file tree
Showing 8 changed files with 891 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cardano-cli/cardano-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,12 @@ test-suite cardano-cli-test
text,
time,
transformers,
yaml,

build-tool-depends: tasty-discover:tasty-discover
other-modules:
Test.Cli.AddCostModels
Test.Cli.CheckNodeConfiguration
Test.Cli.CreateCardano
Test.Cli.CreateTestnetData
Test.Cli.FilePermissions
Expand Down
158 changes: 158 additions & 0 deletions cardano-cli/test/cardano-cli-test/Test/Cli/CheckNodeConfiguration.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Test.Cli.CheckNodeConfiguration where

import Cardano.Api

import Control.Monad (forM_)
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Encode.Pretty as Aeson
import qualified Data.Aeson.Key as Aeson
import qualified Data.Aeson.KeyMap as Aeson
import qualified Data.ByteString.Lazy as LBS
import Data.List (isInfixOf)
import qualified Data.Text as Text
import qualified Data.Yaml as Yaml
import GHC.IO.Exception (ExitCode (..))
import System.FilePath ((</>))

import Test.Cardano.CLI.Util (execCardanoCLI, execDetailCardanoCLI)

import Hedgehog (Property)
import qualified Hedgehog as H
import Hedgehog.Extras (propertyOnce)
import qualified Hedgehog.Extras as H

-- Execute this test with:
-- @cabal test cardano-cli-test --test-options '-p "/check node configuration success/"'@
hprop_check_node_configuration_success :: Property
hprop_check_node_configuration_success =
propertyOnce $ do
-- We test that the command doesn't crash, because otherwise
-- execCardanoCLI would fail.
H.noteM_ $
execCardanoCLI
[ "debug"
, "check-node-configuration"
, "--node-configuration-file"
, "test/cardano-cli-test/files/input/check-node-configuration/node-config.json"
]

data FiddleKind
= FiddleByron
| FiddleNonByron
| RemoveAll
deriving (Bounded, Enum)

-- Execute this test with:
-- @cabal test cardano-cli-test --test-options '-p "/check node configuration fiddle/"'@
hprop_check_node_configuration_fiddle :: Property
hprop_check_node_configuration_fiddle = do
let supplyValues :: [(FilePath, FiddleKind)] =
[(path, fiddleKind) | path <- [ "test/cardano-cli-test/files/input/check-node-configuration/node-config.json"
, "test/cardano-cli-test/files/input/check-node-configuration/node-config.yaml"],
fiddleKind <- [minBound .. maxBound]]

propertyOnce $ forM_ supplyValues $ \(nodeConfigPath, fiddleKind) -> H.moduleWorkspace "tmp" $ \tempDir -> do
let finalInputConfig = tempDir </> "node-config-changed.json"
wrongHash = Text.pack $ replicate 65 '0'

-- Install the genesis files in the sandbox
forM_
[AnyCardanoEra ByronEra, AnyCardanoEra AlonzoEra, AnyCardanoEra ConwayEra, AnyCardanoEra ShelleyEra] $ \era -> do
let filename = Text.unpack $ "genesis." <> Text.toLower (eraToStringKey era) <> ".spec.json"
genesisFile = "test/cardano-cli-test/files/input/check-node-configuration" </> filename
H.copyFile genesisFile (tempDir </> filename)

-- We make a hash value incorrect, and check that
-- check-node-configuration finds the mistake.
--
-- Then we call with --fix, and check that the command goes through

nodeConfigValue :: Aeson.Value <- Yaml.decodeFileThrow nodeConfigPath
nodeConfigObject :: Aeson.Object <-
case nodeConfigValue of
Aeson.Object obj -> pure obj
_ ->
do
H.note_ "Expected an Object, but got something else"
H.failure

-- We make a hash value incorrect, and check that
-- check-node-configuration finds the mistake.
--
-- Then we call with --fix, and check that the command goes through
-- when calling it again

-- Prepare file with incorrect hash

let finalConfigObject =
Aeson.Object $ case fiddleKind of
FiddleByron -> do
Aeson.insert "ByronGenesisHash" (Aeson.String wrongHash) nodeConfigObject
FiddleNonByron ->
Aeson.insert "AlonzoGenesisHash" (Aeson.String wrongHash) nodeConfigObject
RemoveAll ->
removeKeys (map (Aeson.fromText . eraToStringKey) eras) nodeConfigObject

-- Write file with incorrect hash
liftIO $ LBS.writeFile finalInputConfig $ Aeson.encodePretty finalConfigObject

(exitCode, _stdout, stderr) <-
H.noteShowM $
execDetailCardanoCLI
[ "debug"
, "check-node-configuration"
, "--node-configuration-file"
, finalInputConfig
]

case fiddleKind of
RemoveAll ->
-- We removed all hashes, so there's no error reported
pure ()
_ -> do
H.assertWith exitCode (ExitSuccess /=)
H.assertWith stderr ("Wrong genesis hash" `isInfixOf`)

-- Fix the hashes
H.noteM_ $
execCardanoCLI
[ "debug"
, "check-node-configuration"
, "--node-configuration-file"
, finalInputConfig
, "--fix"
]

-- Now call without --fix, to check that the command goes through
H.noteM_ $
execCardanoCLI
[ "debug"
, "check-node-configuration"
, "--node-configuration-file"
, finalInputConfig
]

-- Finally check that the fixed file is the same as the original

reloadedNodeConfigValue :: Aeson.Value <- H.readJsonFileOk finalInputConfig

reloadedNodeConfigValue H.=== nodeConfigValue
where
eras :: [AnyCardanoEra] = [minBound .. maxBound]
removeKeys :: [Aeson.Key] -> Aeson.Object -> Aeson.Object
removeKeys keys kv = foldr Aeson.delete kv keys

-- | Part of the JSON keys associated with the given era.
eraToStringKey :: AnyCardanoEra -> Text.Text
eraToStringKey (AnyCardanoEra era) =
case era of
ByronEra -> "Byron"
ShelleyEra -> "Shelley"
AllegraEra -> "Allegra"
MaryEra -> "Mary"
AlonzoEra -> "Alonzo"
BabbageEra -> "Babbage"
ConwayEra -> "Conway"
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{
"lovelacePerUTxOWord": 34482,
"executionPrices": {
"prSteps": {
"numerator": 721,
"denominator": 10000000
},
"prMem": {
"numerator": 577,
"denominator": 10000
}
},
"maxTxExUnits": {
"exUnitsMem": 10000000,
"exUnitsSteps": 10000000000
},
"maxBlockExUnits": {
"exUnitsMem": 50000000,
"exUnitsSteps": 40000000000
},
"maxValueSize": 5000,
"collateralPercentage": 150,
"maxCollateralInputs": 3,
"costModels": {
"PlutusV1": {
"sha2_256-memory-arguments": 4,
"equalsString-cpu-arguments-constant": 1000,
"cekDelayCost-exBudgetMemory": 100,
"lessThanEqualsByteString-cpu-arguments-intercept": 103599,
"divideInteger-memory-arguments-minimum": 1,
"appendByteString-cpu-arguments-slope": 621,
"blake2b-cpu-arguments-slope": 29175,
"iData-cpu-arguments": 150000,
"encodeUtf8-cpu-arguments-slope": 1000,
"unBData-cpu-arguments": 150000,
"multiplyInteger-cpu-arguments-intercept": 61516,
"cekConstCost-exBudgetMemory": 100,
"nullList-cpu-arguments": 150000,
"equalsString-cpu-arguments-intercept": 150000,
"trace-cpu-arguments": 150000,
"mkNilData-memory-arguments": 32,
"lengthOfByteString-cpu-arguments": 150000,
"cekBuiltinCost-exBudgetCPU": 29773,
"bData-cpu-arguments": 150000,
"subtractInteger-cpu-arguments-slope": 0,
"unIData-cpu-arguments": 150000,
"consByteString-memory-arguments-intercept": 0,
"divideInteger-memory-arguments-slope": 1,
"divideInteger-cpu-arguments-model-arguments-slope": 118,
"listData-cpu-arguments": 150000,
"headList-cpu-arguments": 150000,
"chooseData-memory-arguments": 32,
"equalsInteger-cpu-arguments-intercept": 136542,
"sha3_256-cpu-arguments-slope": 82363,
"sliceByteString-cpu-arguments-slope": 5000,
"unMapData-cpu-arguments": 150000,
"lessThanInteger-cpu-arguments-intercept": 179690,
"mkCons-cpu-arguments": 150000,
"appendString-memory-arguments-intercept": 0,
"modInteger-cpu-arguments-model-arguments-slope": 118,
"ifThenElse-cpu-arguments": 1,
"mkNilPairData-cpu-arguments": 150000,
"lessThanEqualsInteger-cpu-arguments-intercept": 145276,
"addInteger-memory-arguments-slope": 1,
"chooseList-memory-arguments": 32,
"constrData-memory-arguments": 32,
"decodeUtf8-cpu-arguments-intercept": 150000,
"equalsData-memory-arguments": 1,
"subtractInteger-memory-arguments-slope": 1,
"appendByteString-memory-arguments-intercept": 0,
"lengthOfByteString-memory-arguments": 4,
"headList-memory-arguments": 32,
"listData-memory-arguments": 32,
"consByteString-cpu-arguments-intercept": 150000,
"unIData-memory-arguments": 32,
"remainderInteger-memory-arguments-minimum": 1,
"bData-memory-arguments": 32,
"lessThanByteString-cpu-arguments-slope": 248,
"encodeUtf8-memory-arguments-intercept": 0,
"cekStartupCost-exBudgetCPU": 100,
"multiplyInteger-memory-arguments-intercept": 0,
"unListData-memory-arguments": 32,
"remainderInteger-cpu-arguments-model-arguments-slope": 118,
"cekVarCost-exBudgetCPU": 29773,
"remainderInteger-memory-arguments-slope": 1,
"cekForceCost-exBudgetCPU": 29773,
"sha2_256-cpu-arguments-slope": 29175,
"equalsInteger-memory-arguments": 1,
"indexByteString-memory-arguments": 1,
"addInteger-memory-arguments-intercept": 1,
"chooseUnit-cpu-arguments": 150000,
"sndPair-cpu-arguments": 150000,
"cekLamCost-exBudgetCPU": 29773,
"fstPair-cpu-arguments": 150000,
"quotientInteger-memory-arguments-minimum": 1,
"decodeUtf8-cpu-arguments-slope": 1000,
"lessThanInteger-memory-arguments": 1,
"lessThanEqualsInteger-cpu-arguments-slope": 1366,
"fstPair-memory-arguments": 32,
"modInteger-memory-arguments-intercept": 0,
"unConstrData-cpu-arguments": 150000,
"lessThanEqualsInteger-memory-arguments": 1,
"chooseUnit-memory-arguments": 32,
"sndPair-memory-arguments": 32,
"addInteger-cpu-arguments-intercept": 197209,
"decodeUtf8-memory-arguments-slope": 8,
"equalsData-cpu-arguments-intercept": 150000,
"mapData-cpu-arguments": 150000,
"mkPairData-cpu-arguments": 150000,
"quotientInteger-cpu-arguments-constant": 148000,
"consByteString-memory-arguments-slope": 1,
"cekVarCost-exBudgetMemory": 100,
"indexByteString-cpu-arguments": 150000,
"unListData-cpu-arguments": 150000,
"equalsInteger-cpu-arguments-slope": 1326,
"cekStartupCost-exBudgetMemory": 100,
"subtractInteger-cpu-arguments-intercept": 197209,
"divideInteger-cpu-arguments-model-arguments-intercept": 425507,
"divideInteger-memory-arguments-intercept": 0,
"cekForceCost-exBudgetMemory": 100,
"blake2b-cpu-arguments-intercept": 2477736,
"remainderInteger-cpu-arguments-constant": 148000,
"tailList-cpu-arguments": 150000,
"encodeUtf8-cpu-arguments-intercept": 150000,
"equalsString-cpu-arguments-slope": 1000,
"lessThanByteString-memory-arguments": 1,
"multiplyInteger-cpu-arguments-slope": 11218,
"appendByteString-cpu-arguments-intercept": 396231,
"lessThanEqualsByteString-cpu-arguments-slope": 248,
"modInteger-memory-arguments-slope": 1,
"addInteger-cpu-arguments-slope": 0,
"equalsData-cpu-arguments-slope": 10000,
"decodeUtf8-memory-arguments-intercept": 0,
"chooseList-cpu-arguments": 150000,
"constrData-cpu-arguments": 150000,
"equalsByteString-memory-arguments": 1,
"cekApplyCost-exBudgetCPU": 29773,
"quotientInteger-memory-arguments-slope": 1,
"verifySignature-cpu-arguments-intercept": 3345831,
"unMapData-memory-arguments": 32,
"mkCons-memory-arguments": 32,
"sliceByteString-memory-arguments-slope": 1,
"sha3_256-memory-arguments": 4,
"ifThenElse-memory-arguments": 1,
"mkNilPairData-memory-arguments": 32,
"equalsByteString-cpu-arguments-slope": 247,
"appendString-cpu-arguments-intercept": 150000,
"quotientInteger-cpu-arguments-model-arguments-slope": 118,
"cekApplyCost-exBudgetMemory": 100,
"equalsString-memory-arguments": 1,
"multiplyInteger-memory-arguments-slope": 1,
"cekBuiltinCost-exBudgetMemory": 100,
"remainderInteger-memory-arguments-intercept": 0,
"sha2_256-cpu-arguments-intercept": 2477736,
"remainderInteger-cpu-arguments-model-arguments-intercept": 425507,
"lessThanEqualsByteString-memory-arguments": 1,
"tailList-memory-arguments": 32,
"mkNilData-cpu-arguments": 150000,
"chooseData-cpu-arguments": 150000,
"unBData-memory-arguments": 32,
"blake2b-memory-arguments": 4,
"iData-memory-arguments": 32,
"nullList-memory-arguments": 32,
"cekDelayCost-exBudgetCPU": 29773,
"subtractInteger-memory-arguments-intercept": 1,
"lessThanByteString-cpu-arguments-intercept": 103599,
"consByteString-cpu-arguments-slope": 1000,
"appendByteString-memory-arguments-slope": 1,
"trace-memory-arguments": 32,
"divideInteger-cpu-arguments-constant": 148000,
"cekConstCost-exBudgetCPU": 29773,
"encodeUtf8-memory-arguments-slope": 8,
"quotientInteger-cpu-arguments-model-arguments-intercept": 425507,
"mapData-memory-arguments": 32,
"appendString-cpu-arguments-slope": 1000,
"modInteger-cpu-arguments-constant": 148000,
"verifySignature-cpu-arguments-slope": 1,
"unConstrData-memory-arguments": 32,
"quotientInteger-memory-arguments-intercept": 0,
"equalsByteString-cpu-arguments-constant": 150000,
"sliceByteString-memory-arguments-intercept": 0,
"mkPairData-memory-arguments": 32,
"equalsByteString-cpu-arguments-intercept": 112536,
"appendString-memory-arguments-slope": 1,
"lessThanInteger-cpu-arguments-slope": 497,
"modInteger-cpu-arguments-model-arguments-intercept": 425507,
"modInteger-memory-arguments-minimum": 1,
"sha3_256-cpu-arguments-intercept": 0,
"verifySignature-memory-arguments": 1,
"cekLamCost-exBudgetMemory": 100,
"sliceByteString-cpu-arguments-intercept": 150000
}
}
}
Loading

0 comments on commit 5836afd

Please sign in to comment.