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 10, 2024
1 parent 00a14d6 commit 5b9fc05
Show file tree
Hide file tree
Showing 9 changed files with 901 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@ cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data.txt -text
cardano-cli/test/cardano-cli-golden/files/input/example_anchor_data2.txt -text
cardano-cli/test/cardano-cli-test/files/input/example_anchor_data.txt -text
cardano-cli/test/cardano-cli-test/files/input/example_anchor_data2.txt -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.alonzo.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.byron.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.conway.spec.json -text
cardano-cli/test/cardano-cli-test/files/input/check-node-configuration/genesis.shelley.spec.json -text
2 changes: 2 additions & 0 deletions cardano-cli/cardano-cli.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -331,10 +331,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.DRepMetadata
Expand Down
164 changes: 164 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,164 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Test.Cli.CheckNodeConfiguration where

import Cardano.Api

import qualified Cardano.CLI.Run.Debug.CheckNodeConfiguration as CNC
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 (FileSem, bracketSem, execCardanoCLI, execDetailCardanoCLI,
newFileSem)

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

-- | Semaphore protecting against locked file error, when running properties concurrently.
nodeConfigSem :: FileSem
nodeConfigSem = newFileSem "test/cardano-cli-test/files/input/check-node-configuration/node-config.json"
{-# NOINLINE nodeConfigSem #-}

-- 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.
bracketSem nodeConfigSem $ \nodeConfigFile ->
H.noteM_ $
execCardanoCLI
[ "debug"
, "check-node-configuration"
, "--node-configuration-file"
, nodeConfigFile
]

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 ->
bracketSem nodeConfigSem $ \_ -> 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) = CNC.eraToStringKey era
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 5b9fc05

Please sign in to comment.