2020-10-20 08:35:47 +00:00
|
|
|
# nim-confutils
|
|
|
|
# Copyright (c) 2020 Status Research & Development GmbH
|
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT
|
|
|
|
# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2020-10-31 10:44:03 +00:00
|
|
|
import
|
|
|
|
options, unittest, os,
|
|
|
|
stew/byteutils, ../confutils,
|
|
|
|
../confutils/[std/net]
|
|
|
|
|
|
|
|
import
|
|
|
|
toml_serialization, json_serialization,
|
|
|
|
../confutils/winreg/winreg_serialization,
|
|
|
|
../confutils/envvar/envvar_serialization
|
|
|
|
|
|
|
|
type
|
|
|
|
ValidatorPrivKey = object
|
|
|
|
field_a: int
|
|
|
|
field_b: string
|
|
|
|
|
|
|
|
CheckPoint = int
|
|
|
|
RuntimePreset = int
|
|
|
|
GraffitiBytes = array[16, byte]
|
|
|
|
WalletName = string
|
|
|
|
|
|
|
|
VCStartUpCmd = enum
|
|
|
|
VCNoCommand
|
|
|
|
|
|
|
|
ValidatorKeyPath = TypedInputFile[ValidatorPrivKey, Txt, "privkey"]
|
|
|
|
|
|
|
|
TestConf* = object
|
2022-02-27 18:41:25 +00:00
|
|
|
configFile* {.
|
|
|
|
desc: "Loads the configuration from a config file"
|
|
|
|
name: "config-file" }: Option[InputFile]
|
|
|
|
|
2020-10-31 10:44:03 +00:00
|
|
|
logLevel* {.
|
|
|
|
defaultValue: "DEBUG"
|
|
|
|
desc: "Sets the log level."
|
|
|
|
name: "log-level" }: string
|
|
|
|
|
|
|
|
logFile* {.
|
|
|
|
desc: "Specifies a path for the written Json log file"
|
|
|
|
name: "log-file" }: Option[OutFile]
|
|
|
|
|
|
|
|
dataDir* {.
|
|
|
|
defaultValue: config.defaultDataDir()
|
|
|
|
desc: "The directory where nimbus will store all blockchain data"
|
|
|
|
abbr: "d"
|
|
|
|
name: "data-dir" }: OutDir
|
|
|
|
|
|
|
|
nonInteractive* {.
|
|
|
|
desc: "Do not display interative prompts. Quit on missing configuration"
|
|
|
|
name: "non-interactive" }: bool
|
|
|
|
|
|
|
|
validators* {.
|
|
|
|
required
|
|
|
|
desc: "Attach a validator by supplying a keystore path"
|
|
|
|
abbr: "v"
|
|
|
|
name: "validator" }: seq[ValidatorKeyPath]
|
|
|
|
|
|
|
|
validatorsDirFlag* {.
|
|
|
|
desc: "A directory containing validator keystores"
|
|
|
|
name: "validators-dir" }: Option[InputDir]
|
|
|
|
|
|
|
|
secretsDirFlag* {.
|
|
|
|
desc: "A directory containing validator keystore passwords"
|
|
|
|
name: "secrets-dir" }: Option[InputDir]
|
|
|
|
|
|
|
|
case cmd* {.
|
|
|
|
command
|
|
|
|
defaultValue: VCNoCommand }: VCStartUpCmd
|
|
|
|
|
|
|
|
of VCNoCommand:
|
|
|
|
graffiti* {.
|
|
|
|
desc: "The graffiti value that will appear in proposed blocks. " &
|
|
|
|
"You can use a 0x-prefixed hex encoded string to specify raw bytes."
|
|
|
|
name: "graffiti" }: Option[GraffitiBytes]
|
|
|
|
|
|
|
|
stopAtEpoch* {.
|
|
|
|
defaultValue: 0
|
|
|
|
desc: "A positive epoch selects the epoch at which to stop"
|
|
|
|
name: "stop-at-epoch" }: uint64
|
|
|
|
|
|
|
|
rpcPort* {.
|
|
|
|
defaultValue: defaultEth2RpcPort
|
|
|
|
desc: "HTTP port of the server to connect to for RPC - for the validator duties in the pull model"
|
|
|
|
name: "rpc-port" }: Port
|
|
|
|
|
|
|
|
rpcAddress* {.
|
|
|
|
defaultValue: defaultAdminListenAddress(config)
|
|
|
|
desc: "Address of the server to connect to for RPC - for the validator duties in the pull model"
|
|
|
|
name: "rpc-address" }: ValidIpAddress
|
|
|
|
|
|
|
|
retryDelay* {.
|
|
|
|
defaultValue: 10
|
|
|
|
desc: "Delay in seconds between retries after unsuccessful attempts to connect to a beacon node"
|
|
|
|
name: "retry-delay" }: int
|
|
|
|
|
|
|
|
func defaultDataDir(conf: TestConf): string =
|
|
|
|
discard
|
|
|
|
|
|
|
|
func parseCmdArg*(T: type GraffitiBytes, input: TaintedString): T
|
|
|
|
{.raises: [ValueError, Defect].} =
|
|
|
|
discard
|
|
|
|
|
|
|
|
func completeCmdArg*(T: type GraffitiBytes, input: TaintedString): seq[string] =
|
|
|
|
@[]
|
|
|
|
|
|
|
|
func defaultAdminListenAddress*(conf: TestConf): ValidIpAddress =
|
|
|
|
(static ValidIpAddress.init("127.0.0.1"))
|
|
|
|
|
|
|
|
const
|
|
|
|
defaultEth2TcpPort* = 9000
|
|
|
|
defaultEth2RpcPort* = 9090
|
|
|
|
|
|
|
|
const
|
|
|
|
confPathCurrUser = "tests" / "config_files" / "current_user"
|
|
|
|
confPathSystemWide = "tests" / "config_files" / "system_wide"
|
|
|
|
|
|
|
|
# User might also need to extend the serializer capability
|
|
|
|
# for each of the registered formats.
|
|
|
|
# This is especially true for distinct types and some special types
|
|
|
|
# not covered by the standard implementation
|
|
|
|
|
|
|
|
proc readValue(r: var TomlReader,
|
|
|
|
value: var (InputFile | InputDir | OutFile | OutDir | ValidatorKeyPath)) =
|
|
|
|
type T = type value
|
2022-02-27 18:41:25 +00:00
|
|
|
value = T r.parseAsString()
|
2020-10-31 10:44:03 +00:00
|
|
|
|
|
|
|
proc readValue(r: var TomlReader, value: var ValidIpAddress) =
|
|
|
|
value = ValidIpAddress.init(r.parseAsString())
|
|
|
|
|
|
|
|
proc readValue(r: var TomlReader, value: var Port) =
|
|
|
|
value = r.parseInt(int).Port
|
|
|
|
|
|
|
|
proc readValue(r: var TomlReader, value: var GraffitiBytes) =
|
|
|
|
value = hexToByteArray[value.len](r.parseAsString())
|
|
|
|
|
|
|
|
proc readValue(r: var EnvvarReader,
|
|
|
|
value: var (InputFile | InputDir | OutFile | OutDir | ValidatorKeyPath)) =
|
|
|
|
type T = type value
|
|
|
|
value = r.readValue(string).T
|
|
|
|
|
|
|
|
proc readValue(r: var EnvvarReader, value: var ValidIpAddress) =
|
|
|
|
value = ValidIpAddress.init(r.readValue(string))
|
|
|
|
|
|
|
|
proc readValue(r: var EnvvarReader, value: var Port) =
|
|
|
|
value = r.readValue(int).Port
|
|
|
|
|
|
|
|
proc readValue(r: var EnvvarReader, value: var GraffitiBytes) =
|
|
|
|
value = hexToByteArray[value.len](r.readValue(string))
|
|
|
|
|
|
|
|
proc readValue(r: var WinregReader,
|
|
|
|
value: var (InputFile | InputDir | OutFile | OutDir | ValidatorKeyPath)) =
|
|
|
|
type T = type value
|
|
|
|
value = r.readValue(string).T
|
|
|
|
|
|
|
|
proc readValue(r: var WinregReader, value: var ValidIpAddress) =
|
|
|
|
value = ValidIpAddress.init(r.readValue(string))
|
|
|
|
|
|
|
|
proc readValue(r: var WinregReader, value: var Port) =
|
|
|
|
value = r.readValue(int).Port
|
|
|
|
|
|
|
|
proc readValue(r: var WinregReader, value: var GraffitiBytes) =
|
|
|
|
value = hexToByteArray[value.len](r.readValue(string))
|
|
|
|
|
|
|
|
proc testConfigFile() =
|
|
|
|
suite "config file test suite":
|
2022-02-27 18:41:25 +00:00
|
|
|
putEnv("prefixdata-dir", "ENV VAR DATADIR")
|
2020-11-02 09:02:35 +00:00
|
|
|
|
2020-10-31 10:44:03 +00:00
|
|
|
test "basic config file":
|
2022-02-27 18:41:25 +00:00
|
|
|
let conf = TestConf.load(secondarySources = proc (config: TestConf, sources: auto) =
|
2022-03-05 13:07:57 +00:00
|
|
|
sources.addConfigFile(Envvar, InputFile "prefix")
|
|
|
|
|
2022-02-27 18:41:25 +00:00
|
|
|
if config.configFile.isSome:
|
|
|
|
sources.addConfigFile(Toml, config.configFile.get)
|
|
|
|
else:
|
2022-03-05 13:07:57 +00:00
|
|
|
sources.addConfigFile(Toml, InputFile(confPathCurrUser / "testVendor" / "testApp.toml"))
|
|
|
|
sources.addConfigFile(Toml, InputFile(confPathSystemWide / "testVendor" / "testApp.toml"))
|
2022-02-27 18:41:25 +00:00
|
|
|
)
|
2020-10-31 10:44:03 +00:00
|
|
|
|
2020-11-02 09:02:35 +00:00
|
|
|
# dataDir is in env var
|
|
|
|
check conf.dataDir.string == "ENV VAR DATADIR"
|
|
|
|
|
|
|
|
# logFile is in current user config file
|
|
|
|
check conf.logFile.isSome()
|
|
|
|
check conf.logFile.get().string == "TOML CU LOGFILE"
|
|
|
|
|
|
|
|
# logLevel and rpcPort are in system wide config file
|
|
|
|
check conf.logLevel == "TOML SW DEBUG"
|
|
|
|
check conf.rpcPort.int == 1235
|
|
|
|
|
2020-10-31 10:44:03 +00:00
|
|
|
testConfigFile()
|