From cf4097217f9ecc408a34a29ed1e557c898656860 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Tue, 6 Dec 2022 16:19:10 -0600 Subject: [PATCH 01/15] Provide *PluginArgs dataclasses to capture and validate nodeos config options. Each *PluginArgs dataclass captures the command line argument and default for each option as specificed in nodeos. New test validate_nodeos_plugin_args uses nodeos's --help command to parse out each plugin's available options and defaults to validate current status vs. the *PluginArgs classes. Any addition, removal, update will cause a test failure with note of what has changed. This will allow easy maintenance going forward. --- tests/performance_tests/CMakeLists.txt | 12 + tests/performance_tests/ChainPluginArgs.py | 207 ++++++++++++++++++ .../performance_tests/HttpClientPluginArgs.py | 48 ++++ tests/performance_tests/HttpPluginArgs.py | 99 +++++++++ tests/performance_tests/NetPluginArgs.py | 99 +++++++++ tests/performance_tests/ProducerPluginArgs.py | 126 +++++++++++ .../ResourceMonitorPluginArgs.py | 54 +++++ .../SignatureProviderPluginArgs.py | 45 ++++ .../StateHistoryPluginArgs.py | 66 ++++++ tests/performance_tests/TraceApiPluginArgs.py | 60 +++++ tests/performance_tests/performance_test.py | 23 +- .../performance_test_basic.py | 89 +++----- .../validate_nodeos_plugin_args.py | 119 ++++++++++ 13 files changed, 979 insertions(+), 68 deletions(-) create mode 100755 tests/performance_tests/ChainPluginArgs.py create mode 100755 tests/performance_tests/HttpClientPluginArgs.py create mode 100755 tests/performance_tests/HttpPluginArgs.py create mode 100755 tests/performance_tests/NetPluginArgs.py create mode 100755 tests/performance_tests/ProducerPluginArgs.py create mode 100755 tests/performance_tests/ResourceMonitorPluginArgs.py create mode 100755 tests/performance_tests/SignatureProviderPluginArgs.py create mode 100755 tests/performance_tests/StateHistoryPluginArgs.py create mode 100755 tests/performance_tests/TraceApiPluginArgs.py create mode 100755 tests/performance_tests/validate_nodeos_plugin_args.py diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index ae63924623..cff889c4ce 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -7,7 +7,19 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/launch_transaction_generators.py ${CM configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_2_0_14.txt.gz ${CMAKE_CURRENT_BINARY_DIR}/nodeos_log_2_0_14.txt.gz COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_3_2.txt.gz ${CMAKE_CURRENT_BINARY_DIR}/nodeos_log_3_2.txt.gz COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/genesis.json ${CMAKE_CURRENT_BINARY_DIR}/genesis.json COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/validate_nodeos_plugin_args.py ${CMAKE_CURRENT_BINARY_DIR}/validate_nodeos_plugin_args.py COPYONLY) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ChainPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ChainPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpClientPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpClientPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/NetPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/NetPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ProducerPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ProducerPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ResourceMonitorPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ResourceMonitorPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/SignatureProviderPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/SignatureProviderPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/StateHistoryPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/StateHistoryPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TraceApiPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/TraceApiPluginArgs.py COPYONLY) add_test(NAME performance_test_basic COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 6000 --tps-limit-per-generator 1500 --clean-run WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME log_reader_tests COMMAND tests/performance_tests/log_reader_tests.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test(NAME validate_nodeos_plugin_args COMMAND tests/performance_tests/validate_nodeos_plugin_args.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST performance_test_basic PROPERTY LABELS nonparallelizable_tests) diff --git a/tests/performance_tests/ChainPluginArgs.py b/tests/performance_tests/ChainPluginArgs.py new file mode 100755 index 0000000000..9bdcb3e07a --- /dev/null +++ b/tests/performance_tests/ChainPluginArgs.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class ChainPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "chain_plugin" + blocksDir: str=None + _blocksDirNodeosDefault: str='"blocks"' + _blocksDirNodeosArg: str="--blocks-dir" + protocolFeaturesDir: str=None + _protocolFeaturesDirNodeosDefault: str='"protocol_features"' + _protocolFeaturesDirNodeosArg: str="--protocol-features-dir" + checkpoint: str=None + _checkpointNodeosDefault: str=None + _checkpointNodeosArg: str="--checkpoint" + wasmRuntime: str=None + _wasmRuntimeNodeosDefault: str='eos-vm-jit' + _wasmRuntimeNodeosArg: str="--wasm-runtime" + profileAccount: str=None + _profileAccountNodeosDefault: str=None + _profileAccountNodeosArg: str="--profile-account" + abiSerializerMaxTimeMs: int=None + _abiSerializerMaxTimeMsNodeosDefault: int=15 + _abiSerializerMaxTimeMsNodeosArg: str="--abi-serializer-max-time-ms" + chainStateDbSizeMb: int=None + _chainStateDbSizeMbNodeosDefault: int=1024 + _chainStateDbSizeMbNodeosArg: str="--chain-state-db-size-mb" + chainStateDbGuardSizeMb: int=None + _chainStateDbGuardSizeMbNodeosDefault: int=128 + _chainStateDbGuardSizeMbNodeosArg: str="--chain-state-db-guard-size-mb" + signatureCpuBillablePct: int=None + _signatureCpuBillablePctNodeosDefault: int=50 + _signatureCpuBillablePctNodeosArg: str="--signature-cpu-billable-pct" + chainThreads: int=None + _chainThreadsNodeosDefault: int=2 + _chainThreadsNodeosArg: str="--chain-threads" + contractsConsole: bool=None + _contractsConsoleNodeosDefault: bool=False + _contractsConsoleNodeosArg: str="--contracts-console" + deepMind: bool=None + _deepMindNodeosDefault: bool=False + _deepMindNodeosArg: str="--deep-mind" + actorWhitelist: str=None + _actorWhitelistNodeosDefault: str=None + _actorWhitelistNodeosArg: str="--actor-whitelist" + actorBlacklist: str=None + _actorBlacklistNodeosDefault: str=None + _actorBlacklistNodeosArg: str="--actor-blacklist" + contractWhitelist: str=None + _contractWhitelistNodeosDefault: str=None + _contractWhitelistNodeosArg: str="--contract-whitelist" + contractBlacklist: str=None + _contractBlacklistNodeosDefault: str=None + _contractBlacklistNodeosArg: str="--contract-blacklist" + actionBlacklist: str=None + _actionBlacklistNodeosDefault: str=None + _actionBlacklistNodeosArg: str="--action-blacklist" + keyBlacklist: str=None + _keyBlacklistNodeosDefault: str=None + _keyBlacklistNodeosArg: str="--key-blacklist" + senderBypassWhiteblacklist: str=None + _senderBypassWhiteblacklistNodeosDefault: str=None + _senderBypassWhiteblacklistNodeosArg: str="--sender-bypass-whiteblacklist" + readMode: str=None + _readModeNodeosDefault: str='head' + _readModeNodeosArg: str="--read-mode" + apiAcceptTransactions: int=None + _apiAcceptTransactionsNodeosDefault: int=1 + _apiAcceptTransactionsNodeosArg: str="--api-accept-transactions" + validationMode: str=None + _validationModeNodeosDefault: str='full' + _validationModeNodeosArg: str="--validation-mode" + disableRamBillingNotifyChecks: bool=None + _disableRamBillingNotifyChecksNodeosDefault: bool=False + _disableRamBillingNotifyChecksNodeosArg: str="--disable-ram-billing-notify-checks" + maximumVariableSignatureLength: int=None + _maximumVariableSignatureLengthNodeosDefault: int=16384 + _maximumVariableSignatureLengthNodeosArg: str="--maximum-variable-signature-length" + trustedProducer: str=None + _trustedProducerNodeosDefault: str=None + _trustedProducerNodeosArg: str="--trusted-producer" + databaseMapMode: str=None + _databaseMapModeNodeosDefault: str='mapped' + _databaseMapModeNodeosArg: str="--database-map-mode" + eosVmOcCacheSizeMb: int=None + _eosVmOcCacheSizeMbNodeosDefault: int=1024 + _eosVmOcCacheSizeMbNodeosArg: str="--eos-vm-oc-cache-size-mb" + eosVmOcCompileThreads: int=None + _eosVmOcCompileThreadsNodeosDefault: int=1 + _eosVmOcCompileThreadsNodeosArg: str="--eos-vm-oc-compile-threads" + eosVmOcEnable: bool=None + _eosVmOcEnableNodeosDefault: bool=False + _eosVmOcEnableNodeosArg: str="--eos-vm-oc-enable" + enableAccountQueries: int=None + _enableAccountQueriesNodeosDefault: int=0 + _enableAccountQueriesNodeosArg: str="--enable-account-queries" + maxNonprivilegedInlineActionSize: int=None + _maxNonprivilegedInlineActionSizeNodeosDefault: int=4096 + _maxNonprivilegedInlineActionSizeNodeosArg: str="--max-nonprivileged-inline-action-size" + transactionRetryMaxStorageSizeGb: int=None + _transactionRetryMaxStorageSizeGbNodeosDefault: int=None + _transactionRetryMaxStorageSizeGbNodeosArg: str="--transaction-retry-max-storage-size-gb" + transactionRetryIntervalSec: int=None + _transactionRetryIntervalSecNodeosDefault: int=20 + _transactionRetryIntervalSecNodeosArg: str="--transaction-retry-interval-sec" + transactionRetryMaxExpirationSec: int=None + _transactionRetryMaxExpirationSecNodeosDefault: int=120 + _transactionRetryMaxExpirationSecNodeosArg: str="--transaction-retry-max-expiration-sec" + transactionFinalityStatusMaxStorageSizeGb: int=None + _transactionFinalityStatusMaxStorageSizeGbNodeosDefault: int=None + _transactionFinalityStatusMaxStorageSizeGbNodeosArg: str="--transaction-finality-status-max-storage-size-gb" + transactionFinalityStatusSuccessDurationSec: int=None + _transactionFinalityStatusSuccessDurationSecNodeosDefault: int=180 + _transactionFinalityStatusSuccessDurationSecNodeosArg: str="--transaction-finality-status-success-duration-sec" + transactionFinalityStatusFailureDurationSec: int=None + _transactionFinalityStatusFailureDurationSecNodeosDefault: int=180 + _transactionFinalityStatusFailureDurationSecNodeosArg: str="--transaction-finality-status-failure-duration-sec" + integrityHashOnStart: bool=None + _integrityHashOnStartNodeosDefault: bool=False + _integrityHashOnStartNodeosArg: str="--integrity-hash-on-start" + integrityHashOnStop: bool=None + _integrityHashOnStopNodeosDefault: bool=False + _integrityHashOnStopNodeosArg: str="--integrity-hash-on-stop" + blockLogRetainBlocks: int=None + _blockLogRetainBlocksNodeosDefault: int=False + _blockLogRetainBlocksNodeosArg: str="--block-log-retain-blocks" + genesisJson: str=None + _genesisJsonNodeosDefault: str=None + _genesisJsonNodeosArg: str="--genesis-json" + genesisTimestamp: str=None + _genesisTimestampNodeosDefault: str=None + _genesisTimestampNodeosArg: str="--genesis-timestamp" + printGenesisJson: bool=None + _printGenesisJsonNodeosDefault: bool=False + _printGenesisJsonNodeosArg: str="--print-genesis-json" + extractGenesisJson: bool=None + _extractGenesisJsonNodeosDefault: bool=False + _extractGenesisJsonNodeosArg: str="--extract-genesis-json" + printBuildInfo: bool=None + _printBuildInfoNodeosDefault: bool=False + _printBuildInfoNodeosArg: str="--print-build-info" + extractBuildInfo=None + _extractBuildInfoNodeosDefault=None + _extractBuildInfoNodeosArg: str="--extract-build-info" + forceAllChecks: bool=None + _forceAllChecksNodeosDefault: bool=False + _forceAllChecksNodeosArg: str="--force-all-checks" + disableReplayOpts: bool=None + _disableReplayOptsNodeosDefault: bool=False + _disableReplayOptsNodeosArg: str="--disable-replay-opts" + replayBlockchain: bool=None + _replayBlockchainNodeosDefault: bool=False + _replayBlockchainNodeosArg: str="--replay-blockchain" + hardReplayBlockchain: bool=None + _hardReplayBlockchainNodeosDefault: bool=False + _hardReplayBlockchainNodeosArg: str="--hard-replay-blockchain" + deleteAllBlocks: bool=None + _deleteAllBlocksNodeosDefault: bool=False + _deleteAllBlocksNodeosArg: str="--delete-all-blocks" + truncateAtBlock: int=None + _truncateAtBlockNodeosDefault: int=0 + _truncateAtBlockNodeosArg: str="--truncate-at-block" + terminateAtBlock: int=None + _terminateAtBlockNodeosDefault: int=0 + _terminateAtBlockNodeosArg: str="--terminate-at-block" + snapshot: str=None + _snapshotNodeosDefault: str=None + _snapshotNodeosArg: str="--snapshot" + + def threads(self, threads: int): + self.chainThreads=threads + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = ChainPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/HttpClientPluginArgs.py b/tests/performance_tests/HttpClientPluginArgs.py new file mode 100755 index 0000000000..c033d31e7e --- /dev/null +++ b/tests/performance_tests/HttpClientPluginArgs.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class HttpClientPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "http_client_plugin" + httpsClientRootCert: str=None + _httpsClientRootCertNodeosDefault: str=None + _httpsClientRootCertNodeosArg: str="--https-client-root-cert" + httpsClientValidatePeers: int=None + _httpsClientValidatePeersNodeosDefault: int=1 + _httpsClientValidatePeersNodeosArg: str="--https-client-validate-peers" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = HttpClientPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/HttpPluginArgs.py b/tests/performance_tests/HttpPluginArgs.py new file mode 100755 index 0000000000..41aa6eee1c --- /dev/null +++ b/tests/performance_tests/HttpPluginArgs.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class HttpPluginArgs: + _pluginNamespace: str="eosio" + _pluginName: str="http_plugin" + unixSocketPath: str=None + _unixSocketPathNodeosDefault: str=None + _unixSocketPathNodeosArg: str="--unix-socket-path" + httpServerAddress: str=None + _httpServerAddressNodeosDefault: str="127.0.0.1:8888" + _httpServerAddressNodeosArg: str="--http-server-address" + httpsServerAddress: str=None + _httpsServerAddressNodeosDefault: str=None + _httpsServerAddressNodeosArg: str="--https-server-address" + httpsCertificateChainFile: str=None + _httpsCertificateChainFileNodeosDefault: str=None + _httpsCertificateChainFileNodeosArg: str="--https-certificate-chain-file" + httpsPrivateKeyFile: str=None + _httpsPrivateKeyFileNodeosDefault: str=None + _httpsPrivateKeyFileNodeosArg: str="--https-private-key-file" + httpsEcdhCurve: str=None + _httpsEcdhCurveNodeosDefault: str='secp384r1' + _httpsEcdhCurveNodeosArg: str="--https-ecdh-curve" + accessControlAllowOrigin: str=None + _accessControlAllowOriginNodeosDefault: str=None + _accessControlAllowOriginNodeosArg: str="--access-control-allow-origin" + accessControlAllowHeaders: str=None + _accessControlAllowHeadersNodeosDefault: str=None + _accessControlAllowHeadersNodeosArg: str="--access-control-allow-headers" + accessControlMaxAge: int=None + _accessControlMaxAgeNodeosDefault: int=None + _accessControlMaxAgeNodeosArg: str="--access-control-max-age" + accessControlAllowCredentials: bool=None + _accessControlAllowCredentialsNodeosDefault: bool=False + _accessControlAllowCredentialsNodeosArg: str="--access-control-allow-credentials" + maxBodySize: int=None + _maxBodySizeNodeosDefault: int=2097152 + _maxBodySizeNodeosArg: str="--max-body-size" + httpMaxBytesInFlightMb: int=None + _httpMaxBytesInFlightMbNodeosDefault: int=500 + _httpMaxBytesInFlightMbNodeosArg: str="--http-max-bytes-in-flight-mb" + httpMaxInFlightRequests: int=None + _httpMaxInFlightRequestsNodeosDefault: int=-1 + _httpMaxInFlightRequestsNodeosArg: str="--http-max-in-flight-requests" + httpMaxResponseTimeMs: int=None + _httpMaxResponseTimeMsNodeosDefault: int=30 + _httpMaxResponseTimeMsNodeosArg: str="--http-max-response-time-ms" + verboseHttpErrors: bool=None + _verboseHttpErrorsNodeosDefault: bool=False + _verboseHttpErrorsNodeosArg: str="--verbose-http-errors" + httpValidateHost: int=None + _httpValidateHostNodeosDefault: int=1 + _httpValidateHostNodeosArg: str="--http-validate-host" + httpAlias: str=None + _httpAliasNodeosDefault: str=None + _httpAliasNodeosArg: str="--http-alias" + httpThreads: int=None + _httpThreadsNodeosDefault: int=2 + _httpThreadsNodeosArg: str="--http-threads" + httpKeepAlive: int=None + _httpKeepAliveNodeosDefault: int=1 + _httpKeepAliveNodeosArg: str="--http-keep-alive" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = HttpPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NetPluginArgs.py new file mode 100755 index 0000000000..75ed490ba9 --- /dev/null +++ b/tests/performance_tests/NetPluginArgs.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class NetPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "net_plugin" + p2pListenEndpoint: str=None + _p2pListenEndpointNodeosDefault: str="0.0.0.0:9876" + _p2pListenEndpointNodeosArg: str="--p2p-listen-endpoint" + p2pServerAddress: str=None + _p2pServerAddressNodeosDefault: str=None + _p2pServerAddressNodeosArg: str="--p2p-server-address" + p2pPeerAddress: str=None + _p2pPeerAddressNodeosDefault: str=None + _p2pPeerAddressNodeosArg: str="--p2p-peer-address" + p2pMaxNodesPerHost: int=None + _p2pMaxNodesPerHostNodeosDefault: int=1 + _p2pMaxNodesPerHostNodeosArg: str="--p2p-max-nodes-per-host" + p2pAcceptTransactions: int=None + _p2pAcceptTransactionsNodeosDefault: int=1 + _p2pAcceptTransactionsNodeosArg: str="--p2p-accept-transactions" + agentName: str=None + _agentNameNodeosDefault: str='EOS Test Agent' + _agentNameNodeosArg: str="--agent-name" + allowedConnection: str=None + _allowedConnectionNodeosDefault: str='any' + _allowedConnectionNodeosArg: str="--allowed-connection" + peerKey: str=None + _peerKeyNodeosDefault: str=None + _peerKeyNodeosArg: str="--peer-key" + peerPrivateKey: str=None + _peerPrivateKeyNodeosDefault: str=None + _peerPrivateKeyNodeosArg: str="--peer-private-key" + maxClients: int=None + _maxClientsNodeosDefault: int=25 + _maxClientsNodeosArg: str="--max-clients" + connectionCleanupPeriod: int=None + _connectionCleanupPeriodNodeosDefault: int=30 + _connectionCleanupPeriodNodeosArg: str="--connection-cleanup-period" + maxCleanupTimeMsec: int=None + _maxCleanupTimeMsecNodeosDefault: int=10 + _maxCleanupTimeMsecNodeosArg: str="--max-cleanup-time-msec" + p2pDedupCacheExpireTimeSec: int=None + _p2pDedupCacheExpireTimeSecNodeosDefault: int=10 + _p2pDedupCacheExpireTimeSecNodeosArg: str="--p2p-dedup-cache-expire-time-sec" + netThreads: int=None + _netThreadsNodeosDefault: int=2 + _netThreadsNodeosArg: str="--net-threads" + syncFetchSpan: int=None + _syncFetchSpanNodeosDefault: int=100 + _syncFetchSpanNodeosArg: str="--sync-fetch-span" + useSocketReadWatermark: int=None + _useSocketReadWatermarkNodeosDefault: int=0 + _useSocketReadWatermarkNodeosArg: str="--use-socket-read-watermark" + peerLogFormat: str=None + _peerLogFormatNodeosDefault: str="[\"${_name}\" - ${_cid} ${_ip}:${_port}] " + _peerLogFormatNodeosArg: str="--peer-log-format" + p2pKeepaliveIntervalMs: int=None + _p2pKeepaliveIntervalMsNodeosDefault: int=10000 + _p2pKeepaliveIntervalMsNodeosArg: str="--p2p-keepalive-interval-ms" + + def threads(self, threads: int): + self.netThreads=threads + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = NetPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/ProducerPluginArgs.py b/tests/performance_tests/ProducerPluginArgs.py new file mode 100755 index 0000000000..0fd7795591 --- /dev/null +++ b/tests/performance_tests/ProducerPluginArgs.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class ProducerPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "producer_plugin" + enableStaleProduction: bool=None + _enableStaleProductionNodeosDefault: bool=False + _enableStaleProductionNodeosArg: str="--enable-stale-production" + pauseOnStartup: bool=None + _pauseOnStartupNodeosDefault: bool=False + _pauseOnStartupNodeosArg: str="--pause-on-startup" + maxTransactionTime: int=None + _maxTransactionTimeNodeosDefault: int=30 + _maxTransactionTimeNodeosArg: str="--max-transaction-time" + maxIrreversibleBlockAge: int=None + _maxIrreversibleBlockAgeNodeosDefault: int=-1 + _maxIrreversibleBlockAgeNodeosArg: str="--max-irreversible-block-age" + producerName: str=None + _producerNameNodeosDefault: str=None + _producerNameNodeosArg: str="--producer-name" + privateKey: str=None + _privateKeyNodeosDefault: str=None + _privateKeyNodeosArg: str="--private-key" + signatureProvider: str=None + _signatureProviderNodeosDefault: str="EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV=KEY:5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3" + _signatureProviderNodeosArg: str="--signature-provider" + greylistAccount: str=None + _greylistAccountNodeosDefault: str=None + _greylistAccountNodeosArg: str="--greylist-account" + greylistLimit: int=None + _greylistLimitNodeosDefault: int=1000 + _greylistLimitNodeosArg: str="--greylist-limit" + produceTimeOffsetUs: int=None + _produceTimeOffsetUsNodeosDefault: int=0 + _produceTimeOffsetUsNodeosArg: str="--produce-time-offset-us" + lastBlockTimeOffsetUs: int=None + _lastBlockTimeOffsetUsNodeosDefault: int=-200000 + _lastBlockTimeOffsetUsNodeosArg: str="--last-block-time-offset-us" + cpuEffortPercent: int=None + _cpuEffortPercentNodeosDefault: int=80 + _cpuEffortPercentNodeosArg: str="--cpu-effort-percent" + lastBlockCpuEffortPercent: int=None + _lastBlockCpuEffortPercentNodeosDefault: int=80 + _lastBlockCpuEffortPercentNodeosArg: str="--last-block-cpu-effort-percent" + maxBlockCpuUsageThresholdUs: int=None + _maxBlockCpuUsageThresholdUsNodeosDefault: int=5000 + _maxBlockCpuUsageThresholdUsNodeosArg: str="--max-block-cpu-usage-threshold-us" + maxBlockNetUsageThresholdBytes: int=None + _maxBlockNetUsageThresholdBytesNodeosDefault: int=1024 + _maxBlockNetUsageThresholdBytesNodeosArg: str="--max-block-net-usage-threshold-bytes" + maxScheduledTransactionTimePerBlockMs: int=None + _maxScheduledTransactionTimePerBlockMsNodeosDefault: int=100 + _maxScheduledTransactionTimePerBlockMsNodeosArg: str="--max-scheduled-transaction-time-per-block-ms" + subjectiveCpuLeewayUs: int=None + _subjectiveCpuLeewayUsNodeosDefault: int=31000 + _subjectiveCpuLeewayUsNodeosArg: str="--subjective-cpu-leeway-us" + subjectiveAccountMaxFailures: int=None + _subjectiveAccountMaxFailuresNodeosDefault: int=3 + _subjectiveAccountMaxFailuresNodeosArg: str="--subjective-account-max-failures" + subjectiveAccountDecayTimeMinutes: int=None + _subjectiveAccountDecayTimeMinutesNodeosDefault: int=1440 + _subjectiveAccountDecayTimeMinutesNodeosArg: str="--subjective-account-decay-time-minutes" + incomingDeferRatio: int=None + _incomingDeferRatioNodeosDefault: int=1 + _incomingDeferRatioNodeosArg: str="--incoming-defer-ratio" + incomingTransactionQueueSizeMb: int=None + _incomingTransactionQueueSizeMbNodeosDefault: int=1024 + _incomingTransactionQueueSizeMbNodeosArg: str="--incoming-transaction-queue-size-mb" + disableSubjectiveBilling: int=None + _disableSubjectiveBillingNodeosDefault: int=1 + _disableSubjectiveBillingNodeosArg: str="--disable-subjective-billing" + disableSubjectiveAccountBilling: bool=None + _disableSubjectiveAccountBillingNodeosDefault: bool=False + _disableSubjectiveAccountBillingNodeosArg: str="--disable-subjective-account-billing" + disableSubjectiveP2pBilling: int=None + _disableSubjectiveP2pBillingNodeosDefault: int=1 + _disableSubjectiveP2pBillingNodeosArg: str="--disable-subjective-p2p-billing" + disableSubjectiveApiBilling: int=None + _disableSubjectiveApiBillingNodeosDefault: int=1 + _disableSubjectiveApiBillingNodeosArg: str="--disable-subjective-api-billing" + producerThreads: int=None + _producerThreadsNodeosDefault: int=2 + _producerThreadsNodeosArg: str="--producer-threads" + snapshotsDir: str=None + _snapshotsDirNodeosDefault: str='"snapshots"' + _snapshotsDirNodeosArg: str="--snapshots-dir" + + def threads(self, threads: int): + self.producerThreads=threads + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = ProducerPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/ResourceMonitorPluginArgs.py b/tests/performance_tests/ResourceMonitorPluginArgs.py new file mode 100755 index 0000000000..2103c8ee28 --- /dev/null +++ b/tests/performance_tests/ResourceMonitorPluginArgs.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class ResourceMonitorPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "resource_monitor_plugin" + resourceMonitorIntervalSeconds: int=None + _resourceMonitorIntervalSecondsNodeosDefault: int=2 + _resourceMonitorIntervalSecondsNodeosArg: str="--resource-monitor-interval-seconds" + resourceMonitorSpaceThreshold: int=None + _resourceMonitorSpaceThresholdNodeosDefault: int=90 + _resourceMonitorSpaceThresholdNodeosArg: str="--resource-monitor-space-threshold" + resourceMonitorNotShutdownOnThresholdExceeded: bool=None + _resourceMonitorNotShutdownOnThresholdExceededNodeosDefault: bool=False + _resourceMonitorNotShutdownOnThresholdExceededNodeosArg: str="--resource-monitor-not-shutdown-on-threshold-exceeded" + resourceMonitorWarningInterval: int=None + _resourceMonitorWarningIntervalNodeosDefault: int=30 + _resourceMonitorWarningIntervalNodeosArg: str="--resource-monitor-warning-interval" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = ResourceMonitorPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/SignatureProviderPluginArgs.py b/tests/performance_tests/SignatureProviderPluginArgs.py new file mode 100755 index 0000000000..a6d7a0bbc2 --- /dev/null +++ b/tests/performance_tests/SignatureProviderPluginArgs.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class SignatureProviderPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "signature_provider_plugin" + keosdProviderTimeout: int=None + _keosdProviderTimeoutNodeosDefault: int=5 + _keosdProviderTimeoutNodeosArg: str="--keosd-provider-timeout" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = SignatureProviderPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/StateHistoryPluginArgs.py b/tests/performance_tests/StateHistoryPluginArgs.py new file mode 100755 index 0000000000..4e4d133edb --- /dev/null +++ b/tests/performance_tests/StateHistoryPluginArgs.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class StateHistoryPluginArgs: + _pluginNamespace: str = "eosio" + _pluginName: str = "state_history_plugin" + stateHistoryDir: str=None + _stateHistoryDirNodeosDefault: str='"state-history"' + _stateHistoryDirNodeosArg: str="--state-history-dir" + traceHistory: bool=None + _traceHistoryNodeosDefault: bool=False + _traceHistoryNodeosArg: str="--trace-history" + chainStateHistory: bool=None + _chainStateHistoryNodeosDefault: bool=False + _chainStateHistoryNodeosArg: str="--chain-state-history" + stateHistoryEndpoint: str=None + _stateHistoryEndpointNodeosDefault: str="127.0.0.1:8080" + _stateHistoryEndpointNodeosArg: str="--state-history-endpoint" + stateHistoryUnixSocketPath: str=None + _stateHistoryUnixSocketPathNodeosDefault: str=None + _stateHistoryUnixSocketPathNodeosArg: str="--state-history-unix-socket-path" + traceHistoryDebugMode: bool=None + _traceHistoryDebugModeNodeosDefault: bool=False + _traceHistoryDebugModeNodeosArg: str="--trace-history-debug-mode" + stateHistoryLogRetainBlocks: bool=None + _stateHistoryLogRetainBlocksNodeosDefault: bool=False + _stateHistoryLogRetainBlocksNodeosArg: str="--state-history-log-retain-blocks" + deleteStateHistory: bool=None + _deleteStateHistoryNodeosDefault: bool=False + _deleteStateHistoryNodeosArg: str="--delete-state-history" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = StateHistoryPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/TraceApiPluginArgs.py b/tests/performance_tests/TraceApiPluginArgs.py new file mode 100755 index 0000000000..a415caccc7 --- /dev/null +++ b/tests/performance_tests/TraceApiPluginArgs.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class TraceApiPluginArgs: + _pluginNamespace: str="eosio" + _pluginName: str="trace_api_plugin" + traceDir: str=None + _traceDirNodeosDefault: str='"traces"' + _traceDirNodeosArg: str="--trace-dir" + traceSliceStride: int=None + _traceSliceStrideNodeosDefault: int=10000 + _traceSliceStrideNodeosArg: str="--trace-slice-stride" + traceMinimumIrreversibleHistoryBlocks: int=None + _traceMinimumIrreversibleHistoryBlocksNodeosDefault: int=-1 + _traceMinimumIrreversibleHistoryBlocksNodeosArg: str="--trace-minimum-irreversible-history-blocks" + traceMinimumUncompressedIrreversibleHistoryBlocks: int=None + _traceMinimumUncompressedIrreversibleHistoryBlocksNodeosDefault: int=-1 + _traceMinimumUncompressedIrreversibleHistoryBlocksNodeosArg: str="--trace-minimum-uncompressed-irreversible-history-blocks" + traceRpcAbi: str=None + _traceRpcAbiNodeosDefault: str=None + _traceRpcAbiNodeosArg: str="--trace-rpc-abi" + traceNoAbis: bool=None + _traceNoAbisNodeosDefault: bool=False + _traceNoAbisNodeosArg: str="--trace-no-abis" + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" + +def main(): + pluginArgs = TraceApiPluginArgs() + print(pluginArgs.supportedNodeosArgs()) + exit(0) + +if __name__ == '__main__': + main() diff --git a/tests/performance_tests/performance_test.py b/tests/performance_tests/performance_test.py index be8b925249..b0edc31437 100755 --- a/tests/performance_tests/performance_test.py +++ b/tests/performance_tests/performance_test.py @@ -11,8 +11,11 @@ harnessPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(harnessPath) +from ChainPluginArgs import ChainPluginArgs +from HttpPluginArgs import HttpPluginArgs +from NetPluginArgs import NetPluginArgs +from ProducerPluginArgs import ProducerPluginArgs from TestHarness import TestHelper, Utils -from TestHarness.TestHelper import AppArgs from performance_test_basic import PerformanceTestBasic, PtbArgumentsHandler from platform import release, system from dataclasses import dataclass, asdict, field @@ -230,7 +233,7 @@ def optimizePluginThreadCount(self, optPlugin: PluginThreadOpt, optType: Plugin for threadCount in range(minThreadCount, maxThreadCount+1): print(f"Running {optPlugin.value} thread count optimization check with {threadCount} {optPlugin.value} threads") - getattr(clusterConfig.extraNodeosArgs, optPlugin.value + 'PluginArgs').threads = threadCount + getattr(clusterConfig.extraNodeosArgs, optPlugin.value + 'PluginArgs').threads(threadCount) binSearchResults = self.performPtbBinarySearch(clusterConfig=clusterConfig, logDirRoot=self.loggingConfig.pluginThreadOptLogsDirPath, delReport=True, quiet=False, delPerfLogs=True) @@ -497,14 +500,14 @@ def main(): verbose=args.v) ENA = PerformanceTestBasic.ClusterConfig.ExtraNodeosArgs - chainPluginArgs = ENA.ChainPluginArgs(signatureCpuBillablePct=args.signature_cpu_billable_pct, chainStateDbSizeMb=args.chain_state_db_size_mb, - threads=args.chain_threads, databaseMapMode=args.database_map_mode) - producerPluginArgs = ENA.ProducerPluginArgs(disableSubjectiveBilling=args.disable_subjective_billing, - lastBlockTimeOffsetUs=args.last_block_time_offset_us, produceTimeOffsetUs=args.produce_time_offset_us, - cpuEffortPercent=args.cpu_effort_percent, lastBlockCpuEffortPercent=args.last_block_cpu_effort_percent, - threads=args.producer_threads) - httpPluginArgs = ENA.HttpPluginArgs(httpMaxResponseTimeMs=args.http_max_response_time_ms) - netPluginArgs = ENA.NetPluginArgs(threads=args.net_threads) + chainPluginArgs = ChainPluginArgs(signatureCpuBillablePct=args.signature_cpu_billable_pct, chainStateDbSizeMb=args.chain_state_db_size_mb, + chainThreads=args.chain_threads, databaseMapMode=args.database_map_mode) + producerPluginArgs = ProducerPluginArgs(disableSubjectiveBilling=args.disable_subjective_billing, + lastBlockTimeOffsetUs=args.last_block_time_offset_us, produceTimeOffsetUs=args.produce_time_offset_us, + cpuEffortPercent=args.cpu_effort_percent, lastBlockCpuEffortPercent=args.last_block_cpu_effort_percent, + producerThreads=args.producer_threads) + httpPluginArgs = HttpPluginArgs(httpMaxResponseTimeMs=args.http_max_response_time_ms) + netPluginArgs = NetPluginArgs(netThreads=args.net_threads) extraNodeosArgs = ENA(chainPluginArgs=chainPluginArgs, httpPluginArgs=httpPluginArgs, producerPluginArgs=producerPluginArgs, netPluginArgs=netPluginArgs) testClusterConfig = PerformanceTestBasic.ClusterConfig(pnodes=args.p, totalNodes=args.n, topo=args.s, genesisPath=args.genesis, prodsEnableTraceApi=args.prods_enable_trace_api, extraNodeosArgs=extraNodeosArgs) diff --git a/tests/performance_tests/performance_test_basic.py b/tests/performance_tests/performance_test_basic.py index 9f9ba61137..a7b10cebc1 100755 --- a/tests/performance_tests/performance_test_basic.py +++ b/tests/performance_tests/performance_test_basic.py @@ -1,24 +1,30 @@ #!/usr/bin/env python3 import argparse +import dataclasses import os +import re import sys -import subprocess import shutil import signal -from unittest import TestResult import log_reader -import inspect import launch_transaction_generators as ltg harnessPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(harnessPath) +from ChainPluginArgs import ChainPluginArgs +from HttpClientPluginArgs import HttpClientPluginArgs +from HttpPluginArgs import HttpPluginArgs +from NetPluginArgs import NetPluginArgs +from ProducerPluginArgs import ProducerPluginArgs +from ResourceMonitorPluginArgs import ResourceMonitorPluginArgs +from SignatureProviderPluginArgs import SignatureProviderPluginArgs +from StateHistoryPluginArgs import StateHistoryPluginArgs +from TraceApiPluginArgs import TraceApiPluginArgs from TestHarness import Cluster, TestHelper, Utils, WalletMgr -from TestHarness.TestHelper import AppArgs from dataclasses import dataclass, asdict, field from datetime import datetime -from math import ceil class PerformanceTestBasic: @dataclass @@ -48,57 +54,24 @@ def __post_init__(self): class ClusterConfig: @dataclass class ExtraNodeosArgs: - @dataclass - class ChainPluginArgs: - signatureCpuBillablePct: int = 0 - chainStateDbSizeMb: int = 10 * 1024 - threads: int = 3 - databaseMapMode: str = "mapped" - - def __str__(self) -> str: - return f"--signature-cpu-billable-pct {self.signatureCpuBillablePct} \ - --chain-state-db-size-mb {self.chainStateDbSizeMb} \ - --chain-threads {self.threads} \ - --database-map-mode {self.databaseMapMode}" - - @dataclass - class NetPluginArgs: - threads: int = 2 - - def __str__(self) -> str: - return f"--net-threads {self.threads}" - - @dataclass - class ProducerPluginArgs: - disableSubjectiveBilling: bool = True - lastBlockTimeOffsetUs: int = 0 - produceTimeOffsetUs: int = 0 - cpuEffortPercent: int = 100 - lastBlockCpuEffortPercent: int = 100 - threads: int = 6 - - def __str__(self) -> str: - return f"--disable-subjective-billing {self.disableSubjectiveBilling} \ - --last-block-time-offset-us {self.lastBlockTimeOffsetUs} \ - --produce-time-offset-us {self.produceTimeOffsetUs} \ - --cpu-effort-percent {self.cpuEffortPercent} \ - --last-block-cpu-effort-percent {self.lastBlockCpuEffortPercent} \ - --producer-threads {self.threads}" - - @dataclass - class HttpPluginArgs: - httpMaxResponseTimeMs: int = 990000 - - def __str__(self) -> str: - return f"--http-max-response-time-ms {self.httpMaxResponseTimeMs}" chainPluginArgs: ChainPluginArgs = ChainPluginArgs() - producerPluginArgs: ProducerPluginArgs = ProducerPluginArgs() + httpClientPluginArgs: HttpClientPluginArgs = HttpClientPluginArgs() httpPluginArgs: HttpPluginArgs = HttpPluginArgs() netPluginArgs: NetPluginArgs = NetPluginArgs() + producerPluginArgs: ProducerPluginArgs = ProducerPluginArgs() + resourceMonitorPluginArgs: ResourceMonitorPluginArgs = ResourceMonitorPluginArgs() + signatureProviderPluginArgs: SignatureProviderPluginArgs = SignatureProviderPluginArgs() + stateHistoryPluginArgs: StateHistoryPluginArgs = StateHistoryPluginArgs() + traceApiPluginArgs: TraceApiPluginArgs = TraceApiPluginArgs() def __str__(self) -> str: - return f" {self.httpPluginArgs} {self.producerPluginArgs} {self.chainPluginArgs} {self.netPluginArgs}" + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*PluginArgs", field.name) + if match is not None: + args.append(f"{getattr(self, field.name)}") + return " ".join(args) pnodes: int = 1 totalNodes: int = 2 @@ -503,15 +476,15 @@ def main(): testHelperConfig = PerformanceTestBasic.TestHelperConfig(killAll=args.clean_run, dontKill=args.leave_running, keepLogs=not args.del_perf_logs, dumpErrorDetails=args.dump_error_details, delay=args.d, nodesFile=args.nodes_file, verbose=args.v) + chainPluginArgs = ChainPluginArgs(signatureCpuBillablePct=args.signature_cpu_billable_pct, chainStateDbSizeMb=args.chain_state_db_size_mb, + chainThreads=args.chain_threads, databaseMapMode=args.database_map_mode) + producerPluginArgs = ProducerPluginArgs(disableSubjectiveBilling=args.disable_subjective_billing, + lastBlockTimeOffsetUs=args.last_block_time_offset_us, produceTimeOffsetUs=args.produce_time_offset_us, + cpuEffortPercent=args.cpu_effort_percent, lastBlockCpuEffortPercent=args.last_block_cpu_effort_percent, + producerThreads=args.producer_threads) + httpPluginArgs = HttpPluginArgs(httpMaxResponseTimeMs=args.http_max_response_time_ms) + netPluginArgs = NetPluginArgs(netThreads=args.net_threads) ENA = PerformanceTestBasic.ClusterConfig.ExtraNodeosArgs - chainPluginArgs = ENA.ChainPluginArgs(signatureCpuBillablePct=args.signature_cpu_billable_pct, chainStateDbSizeMb=args.chain_state_db_size_mb, - threads=args.chain_threads, databaseMapMode=args.database_map_mode) - producerPluginArgs = ENA.ProducerPluginArgs(disableSubjectiveBilling=args.disable_subjective_billing, - lastBlockTimeOffsetUs=args.last_block_time_offset_us, produceTimeOffsetUs=args.produce_time_offset_us, - cpuEffortPercent=args.cpu_effort_percent, lastBlockCpuEffortPercent=args.last_block_cpu_effort_percent, - threads=args.producer_threads) - httpPluginArgs = ENA.HttpPluginArgs(httpMaxResponseTimeMs=args.http_max_response_time_ms) - netPluginArgs = ENA.NetPluginArgs(threads=args.net_threads) extraNodeosArgs = ENA(chainPluginArgs=chainPluginArgs, httpPluginArgs=httpPluginArgs, producerPluginArgs=producerPluginArgs, netPluginArgs=netPluginArgs) testClusterConfig = PerformanceTestBasic.ClusterConfig(pnodes=args.p, totalNodes=args.n, topo=args.s, genesisPath=args.genesis, prodsEnableTraceApi=args.prods_enable_trace_api, extraNodeosArgs=extraNodeosArgs) diff --git a/tests/performance_tests/validate_nodeos_plugin_args.py b/tests/performance_tests/validate_nodeos_plugin_args.py new file mode 100755 index 0000000000..a13e7021f5 --- /dev/null +++ b/tests/performance_tests/validate_nodeos_plugin_args.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +import re +import subprocess + +from ChainPluginArgs import ChainPluginArgs +from HttpClientPluginArgs import HttpClientPluginArgs +from HttpPluginArgs import HttpPluginArgs +from NetPluginArgs import NetPluginArgs +from ProducerPluginArgs import ProducerPluginArgs +from ResourceMonitorPluginArgs import ResourceMonitorPluginArgs +from SignatureProviderPluginArgs import SignatureProviderPluginArgs +from StateHistoryPluginArgs import StateHistoryPluginArgs +from TraceApiPluginArgs import TraceApiPluginArgs + +testSuccessful = False + +def parseNodeosConfigOptions() -> dict: + result = subprocess.run(["programs/nodeos/nodeos", "--help"], capture_output=True, text=True) + + myStr = result.stdout + myStr = myStr.rstrip("\n") + myStr = re.sub(":\n\s+-",':@@@\n -', string=myStr) + myStr = re.sub("\n\n",'\n@@@', string=myStr) + myStr = re.sub("Application Options:\n",'', string=myStr) + pluginSections = re.split("(@@@.*?@@@\n)", string=myStr) + + sec=0 + for section in pluginSections: + sec=sec+1 + + def pairwise(iterable): + "s -> (s0, s1), (s2, s3), (s4, s5), ..." + a = iter(iterable) + return zip(a, a) + + pluginOptsDict = {} + for section, options in pairwise(pluginSections[1:]): + myOpts = re.sub("\s+", " ", options) + myOpts = re.sub("\n", " ", myOpts) + myOpts = re.sub(" --", "\n--",string = myOpts) + splitOpts=re.split("\n", myOpts) + + argDefaultsDict = {} + for opt in splitOpts[1:]: + secondSplit = re.split("(--[\w\-]+)", opt)[1:] + argument=secondSplit[0] + argDefaultDesc=secondSplit[1].lstrip("\s") + default = None + match = re.search("\(=.*?\)", argDefaultDesc) + if match is not None: + value = match.group(0)[2:-1] + try: + default = int(value) + except ValueError: + default = str(value) + argDefaultsDict[argument] = default + + section=re.sub("@@@", "", section) + section=re.sub("\n", "", section) + sectionSplit=re.split("::", section) + configSection = section + if len(sectionSplit) > 1: + configSection=sectionSplit[1] + + if configSection[-1] == ":": + configSection = configSection[:-1] + + if pluginOptsDict.get(configSection) is not None: + pluginOptsDict[configSection].update(argDefaultsDict) + else: + pluginOptsDict[configSection] = argDefaultsDict + return pluginOptsDict + +nodeosPluginOptsDict = parseNodeosConfigOptions() + +curListOfSupportedPlugins = [ChainPluginArgs(), HttpClientPluginArgs(), HttpPluginArgs(), NetPluginArgs(), ProducerPluginArgs(), + ResourceMonitorPluginArgs(), SignatureProviderPluginArgs(), StateHistoryPluginArgs(), TraceApiPluginArgs()] + +curListOfUnsupportedOptionGroups = ["txn_test_gen_plugin", "Application Config Options", "Application Command Line Options"] + +#Check whether nodeos has added any plugin configuration sections +for confSection in nodeosPluginOptsDict.keys(): + assert confSection in [paClass._pluginName for paClass in curListOfSupportedPlugins] or confSection in curListOfUnsupportedOptionGroups, f"ERROR: New config section \"{confSection}\" added to nodeos which may require updates." + +def argStrToAttrName(argStr: str) -> str: + attrName="".join([x.capitalize() for x in argStr.split('-')]).replace('--','') + attrName="".join([attrName[0].lower(), attrName[1:]]) + return attrName + +for supportedPlugin in curListOfSupportedPlugins: + #Check whether nodeos has removed any plugin configuration sections + assert supportedPlugin._pluginName in nodeosPluginOptsDict, f"ERROR: Supported config section \"{supportedPlugin}\" no longer supported by nodeos." + + for opt in supportedPlugin.supportedNodeosArgs(): + #Check whether nodeos has removed any arguments in a plugin + assert opt in nodeosPluginOptsDict[supportedPlugin._pluginName].keys(), f"ERROR: nodeos no longer supports \"{opt}\" in \"{supportedPlugin._pluginName}\"." + + + ourDefault = getattr(supportedPlugin, f"_{argStrToAttrName(opt)}NodeosDefault") + nodeosCurDefault = nodeosPluginOptsDict[supportedPlugin._pluginName][opt] + if type(ourDefault) == bool and nodeosCurDefault is None: + nodeosCurDefault=False + #Check whether our defaults no longer match nodeos's + assert ourDefault == nodeosCurDefault, f"ERROR: {type(supportedPlugin)}'s default for \"{opt}\" is {ourDefault} and no longer matches nodeos's default {nodeosCurDefault} in \"{supportedPlugin._pluginName}\"." + + #Check whether nodeos has added/updated any argument defaults + for nodeosOpt, defaultValue in nodeosPluginOptsDict[supportedPlugin._pluginName].items(): + assert nodeosOpt in supportedPlugin.supportedNodeosArgs(), f"ERROR: New nodeos option \"{nodeosOpt}\". Support for this option needs to be added to {type(supportedPlugin)}." + + ourDefault = getattr(supportedPlugin, f"_{argStrToAttrName(nodeosOpt)}NodeosDefault") + if type(ourDefault) == bool and defaultValue is None: + defaultValue=False + assert defaultValue == ourDefault, f"ERROR: nodeos's default for \"{nodeosOpt}\" is {nodeosCurDefault} and no longer matches {type(supportedPlugin)}'s default: {ourDefault} in \"{supportedPlugin._pluginName}\"." + +testSuccessful = True + +exitCode = 0 if testSuccessful else 1 +exit(exitCode) From 23aea602b19913e250e59e38e8c7055fbe9b73b9 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Tue, 6 Dec 2022 17:50:58 -0600 Subject: [PATCH 02/15] Fixup some of the config options. --- tests/performance_tests/ChainPluginArgs.py | 22 +++++++++---------- .../performance_tests/HttpClientPluginArgs.py | 4 ++-- tests/performance_tests/HttpPluginArgs.py | 2 +- tests/performance_tests/NetPluginArgs.py | 10 ++++----- tests/performance_tests/ProducerPluginArgs.py | 4 ++-- .../ResourceMonitorPluginArgs.py | 4 ++-- .../SignatureProviderPluginArgs.py | 4 ++-- .../StateHistoryPluginArgs.py | 8 +++---- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/performance_tests/ChainPluginArgs.py b/tests/performance_tests/ChainPluginArgs.py index 9bdcb3e07a..528585bddb 100755 --- a/tests/performance_tests/ChainPluginArgs.py +++ b/tests/performance_tests/ChainPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class ChainPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "chain_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="chain_plugin" blocksDir: str=None _blocksDirNodeosDefault: str='"blocks"' _blocksDirNodeosArg: str="--blocks-dir" @@ -19,7 +19,7 @@ class ChainPluginArgs: _checkpointNodeosDefault: str=None _checkpointNodeosArg: str="--checkpoint" wasmRuntime: str=None - _wasmRuntimeNodeosDefault: str='eos-vm-jit' + _wasmRuntimeNodeosDefault: str="eos-vm-jit" _wasmRuntimeNodeosArg: str="--wasm-runtime" profileAccount: str=None _profileAccountNodeosDefault: str=None @@ -67,13 +67,13 @@ class ChainPluginArgs: _senderBypassWhiteblacklistNodeosDefault: str=None _senderBypassWhiteblacklistNodeosArg: str="--sender-bypass-whiteblacklist" readMode: str=None - _readModeNodeosDefault: str='head' + _readModeNodeosDefault: str="head" _readModeNodeosArg: str="--read-mode" apiAcceptTransactions: int=None _apiAcceptTransactionsNodeosDefault: int=1 _apiAcceptTransactionsNodeosArg: str="--api-accept-transactions" validationMode: str=None - _validationModeNodeosDefault: str='full' + _validationModeNodeosDefault: str="full" _validationModeNodeosArg: str="--validation-mode" disableRamBillingNotifyChecks: bool=None _disableRamBillingNotifyChecksNodeosDefault: bool=False @@ -85,7 +85,7 @@ class ChainPluginArgs: _trustedProducerNodeosDefault: str=None _trustedProducerNodeosArg: str="--trusted-producer" databaseMapMode: str=None - _databaseMapModeNodeosDefault: str='mapped' + _databaseMapModeNodeosDefault: str="mapped" _databaseMapModeNodeosArg: str="--database-map-mode" eosVmOcCacheSizeMb: int=None _eosVmOcCacheSizeMbNodeosDefault: int=1024 @@ -127,7 +127,7 @@ class ChainPluginArgs: _integrityHashOnStopNodeosDefault: bool=False _integrityHashOnStopNodeosArg: str="--integrity-hash-on-stop" blockLogRetainBlocks: int=None - _blockLogRetainBlocksNodeosDefault: int=False + _blockLogRetainBlocksNodeosDefault: int=None _blockLogRetainBlocksNodeosArg: str="--block-log-retain-blocks" genesisJson: str=None _genesisJsonNodeosDefault: str=None @@ -138,14 +138,14 @@ class ChainPluginArgs: printGenesisJson: bool=None _printGenesisJsonNodeosDefault: bool=False _printGenesisJsonNodeosArg: str="--print-genesis-json" - extractGenesisJson: bool=None - _extractGenesisJsonNodeosDefault: bool=False + extractGenesisJson: str=None + _extractGenesisJsonNodeosDefault: str=None _extractGenesisJsonNodeosArg: str="--extract-genesis-json" printBuildInfo: bool=None _printBuildInfoNodeosDefault: bool=False _printBuildInfoNodeosArg: str="--print-build-info" - extractBuildInfo=None - _extractBuildInfoNodeosDefault=None + extractBuildInfo: str=None + _extractBuildInfoNodeosDefault: str=None _extractBuildInfoNodeosArg: str="--extract-build-info" forceAllChecks: bool=None _forceAllChecksNodeosDefault: bool=False diff --git a/tests/performance_tests/HttpClientPluginArgs.py b/tests/performance_tests/HttpClientPluginArgs.py index c033d31e7e..297b3b2494 100755 --- a/tests/performance_tests/HttpClientPluginArgs.py +++ b/tests/performance_tests/HttpClientPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class HttpClientPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "http_client_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="http_client_plugin" httpsClientRootCert: str=None _httpsClientRootCertNodeosDefault: str=None _httpsClientRootCertNodeosArg: str="--https-client-root-cert" diff --git a/tests/performance_tests/HttpPluginArgs.py b/tests/performance_tests/HttpPluginArgs.py index 41aa6eee1c..254277889c 100755 --- a/tests/performance_tests/HttpPluginArgs.py +++ b/tests/performance_tests/HttpPluginArgs.py @@ -25,7 +25,7 @@ class HttpPluginArgs: _httpsPrivateKeyFileNodeosDefault: str=None _httpsPrivateKeyFileNodeosArg: str="--https-private-key-file" httpsEcdhCurve: str=None - _httpsEcdhCurveNodeosDefault: str='secp384r1' + _httpsEcdhCurveNodeosDefault: str="secp384r1" _httpsEcdhCurveNodeosArg: str="--https-ecdh-curve" accessControlAllowOrigin: str=None _accessControlAllowOriginNodeosDefault: str=None diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NetPluginArgs.py index 75ed490ba9..5d36d90d1b 100755 --- a/tests/performance_tests/NetPluginArgs.py +++ b/tests/performance_tests/NetPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class NetPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "net_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="net_plugin" p2pListenEndpoint: str=None _p2pListenEndpointNodeosDefault: str="0.0.0.0:9876" _p2pListenEndpointNodeosArg: str="--p2p-listen-endpoint" @@ -25,10 +25,10 @@ class NetPluginArgs: _p2pAcceptTransactionsNodeosDefault: int=1 _p2pAcceptTransactionsNodeosArg: str="--p2p-accept-transactions" agentName: str=None - _agentNameNodeosDefault: str='EOS Test Agent' + _agentNameNodeosDefault: str="EOS Test Agent" _agentNameNodeosArg: str="--agent-name" allowedConnection: str=None - _allowedConnectionNodeosDefault: str='any' + _allowedConnectionNodeosDefault: str="any" _allowedConnectionNodeosArg: str="--allowed-connection" peerKey: str=None _peerKeyNodeosDefault: str=None @@ -58,7 +58,7 @@ class NetPluginArgs: _useSocketReadWatermarkNodeosDefault: int=0 _useSocketReadWatermarkNodeosArg: str="--use-socket-read-watermark" peerLogFormat: str=None - _peerLogFormatNodeosDefault: str="[\"${_name}\" - ${_cid} ${_ip}:${_port}] " + _peerLogFormatNodeosDefault: str="["${_name}" - ${_cid} ${_ip}:${_port}] " _peerLogFormatNodeosArg: str="--peer-log-format" p2pKeepaliveIntervalMs: int=None _p2pKeepaliveIntervalMsNodeosDefault: int=10000 diff --git a/tests/performance_tests/ProducerPluginArgs.py b/tests/performance_tests/ProducerPluginArgs.py index 0fd7795591..f487cb63e2 100755 --- a/tests/performance_tests/ProducerPluginArgs.py +++ b/tests/performance_tests/ProducerPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class ProducerPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "producer_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="producer_plugin" enableStaleProduction: bool=None _enableStaleProductionNodeosDefault: bool=False _enableStaleProductionNodeosArg: str="--enable-stale-production" diff --git a/tests/performance_tests/ResourceMonitorPluginArgs.py b/tests/performance_tests/ResourceMonitorPluginArgs.py index 2103c8ee28..913ed37e44 100755 --- a/tests/performance_tests/ResourceMonitorPluginArgs.py +++ b/tests/performance_tests/ResourceMonitorPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class ResourceMonitorPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "resource_monitor_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="resource_monitor_plugin" resourceMonitorIntervalSeconds: int=None _resourceMonitorIntervalSecondsNodeosDefault: int=2 _resourceMonitorIntervalSecondsNodeosArg: str="--resource-monitor-interval-seconds" diff --git a/tests/performance_tests/SignatureProviderPluginArgs.py b/tests/performance_tests/SignatureProviderPluginArgs.py index a6d7a0bbc2..95efb3ae99 100755 --- a/tests/performance_tests/SignatureProviderPluginArgs.py +++ b/tests/performance_tests/SignatureProviderPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class SignatureProviderPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "signature_provider_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="signature_provider_plugin" keosdProviderTimeout: int=None _keosdProviderTimeoutNodeosDefault: int=5 _keosdProviderTimeoutNodeosArg: str="--keosd-provider-timeout" diff --git a/tests/performance_tests/StateHistoryPluginArgs.py b/tests/performance_tests/StateHistoryPluginArgs.py index 4e4d133edb..a0559607a9 100755 --- a/tests/performance_tests/StateHistoryPluginArgs.py +++ b/tests/performance_tests/StateHistoryPluginArgs.py @@ -7,8 +7,8 @@ @dataclass class StateHistoryPluginArgs: - _pluginNamespace: str = "eosio" - _pluginName: str = "state_history_plugin" + _pluginNamespace: str="eosio" + _pluginName: str="state_history_plugin" stateHistoryDir: str=None _stateHistoryDirNodeosDefault: str='"state-history"' _stateHistoryDirNodeosArg: str="--state-history-dir" @@ -27,8 +27,8 @@ class StateHistoryPluginArgs: traceHistoryDebugMode: bool=None _traceHistoryDebugModeNodeosDefault: bool=False _traceHistoryDebugModeNodeosArg: str="--trace-history-debug-mode" - stateHistoryLogRetainBlocks: bool=None - _stateHistoryLogRetainBlocksNodeosDefault: bool=False + stateHistoryLogRetainBlocks: int=None + _stateHistoryLogRetainBlocksNodeosDefault: int=None _stateHistoryLogRetainBlocksNodeosArg: str="--state-history-log-retain-blocks" deleteStateHistory: bool=None _deleteStateHistoryNodeosDefault: bool=False From 8655e4dca1abbe9da71accf6ec7a46e9e458aaf1 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Tue, 6 Dec 2022 17:52:28 -0600 Subject: [PATCH 03/15] Script that generates *PluginArgs.py dataclass files from nodeos --help output. --- ...generate_nodeos_plugin_args_class_files.py | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100755 tests/performance_tests/generate_nodeos_plugin_args_class_files.py diff --git a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py new file mode 100755 index 0000000000..cb56ba3f89 --- /dev/null +++ b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python3 + +import re +import subprocess + +def main(): + cmd="programs/nodeos/nodeos --help" + result = subprocess.run(["programs/nodeos/nodeos", "--help"], capture_output=True, text=True) + + myStr = result.stdout + myStr = myStr.rstrip("\n") + myStr = re.sub(":\n\s+-",':@@@\n -', string=myStr) + myStr = re.sub("\n\n",'\n@@@', string=myStr) + myStr = re.sub("Application Options:\n",'', string=myStr) + pluginSections = re.split("(@@@.*?@@@\n)", string=myStr) + + + sec=0 + for section in pluginSections: + sec=sec+1 + + def pairwise(iterable): + "s -> (s0, s1), (s2, s3), (s4, s5), ..." + a = iter(iterable) + return zip(a, a) + + pluginOptsDict = {} + for section, options in pairwise(pluginSections[1:]): + myOpts = re.sub("\s+", " ", options) + myOpts = re.sub("\n", " ", myOpts) + myOpts = re.sub(" --", "\n--",string = myOpts) + splitOpts=re.split("\n", myOpts) + + argDescDict = {} + for opt in splitOpts[1:]: + secondSplit = re.split("(--[\w\-]+)", opt)[1:] + argument=secondSplit[0] + argDefaultDesc=secondSplit[1].lstrip("\s") + argDescDict[argument] = argDefaultDesc + # print(f"argDefaultDesc: {argDefaultDesc}") + section=re.sub("@@@", "", section) + section=re.sub("\n", "", section) + sectionSplit=re.split("::", section) + configSection = section + if len(sectionSplit) > 1: + configSection=sectionSplit[1] + + if pluginOptsDict.get(configSection) is not None: + pluginOptsDict[configSection].update(argDescDict) + else: + pluginOptsDict[configSection] = argDescDict + + newDict = {} + for key, value in pluginOptsDict.items(): + newPlugin="".join([x.capitalize() for x in key.split('_')]).replace(":","") + + newArgs = {} + for key, value in value.items(): + newKey="".join([x.capitalize() for x in key.split('-')]).replace('--','') + newKey="".join([newKey[0].lower(), newKey[1:]]) + newArgs[newKey]=value + newDict[newPlugin]=newArgs + + def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): + newPlugin="".join([x.capitalize() for x in plugin.split('_')]).replace(":","") + pluginArgsFile=f"../tests/performance_tests/{newPlugin}Args.py" + with open(pluginArgsFile, 'w') as dataclassFile: + chainPluginArgs = dataFieldDict[newPlugin] + + dataclassFile.write(f"#!/usr/bin/env python3\n\n") + dataclassFile.write(f"import dataclasses\n") + dataclassFile.write(f"import re\n\n") + dataclassFile.write(f"from dataclasses import dataclass\n\n") + dataclassFile.write(f"@dataclass\nclass {newPlugin}Args:\n") + dataclassFile.write(f" _pluginNamespace: str=\"eosio\"\n") + dataclassFile.write(f" _pluginName: str=\"{plugin[:-1]}\"\n") + + for key, value in pluginOptsDict[plugin].items(): + newKey="".join([x.capitalize() for x in key.split('-')]).replace('--','') + newKey="".join([newKey[0].lower(), newKey[1:]]) + value = chainPluginArgs[newKey] + match = re.search("\(=.*?\)", value) + if match is not None: + value = match.group(0)[2:-1] + try: + numVal = int(value) + dataclassFile.write(f" {newKey}: int=None\n") + dataclassFile.write(f" _{newKey}NodeosDefault: int={numVal}\n") + dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") + except ValueError: + strValue = str(value) + quote = "\'" if strValue[0] == "\"" else "\"" + dataclassFile.write(f" {newKey}: str=None\n") + dataclassFile.write(f" _{newKey}NodeosDefault: str={quote}{strValue}{quote}\n") + dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") + else: + if re.search("deepmind", newKey, re.IGNORECASE) or \ + re.search("tracehistory", newKey, re.IGNORECASE) or \ + re.search("tracenoabis", newKey, re.IGNORECASE) or \ + re.search("chainstatehistory", newKey, re.IGNORECASE) or \ + re.search("console", newKey, re.IGNORECASE) or \ + re.search("print", newKey, re.IGNORECASE) or \ + re.search("verbose", newKey, re.IGNORECASE) or \ + re.search("debug", newKey, re.IGNORECASE) or \ + re.search("force", newKey, re.IGNORECASE) or \ + re.search("onthreshold", newKey, re.IGNORECASE) or \ + re.search("allowcredentials", newKey, re.IGNORECASE) or \ + re.search("delete", newKey, re.IGNORECASE) or \ + re.search("replay", newKey, re.IGNORECASE) or \ + re.search("onstart", newKey, re.IGNORECASE) or \ + re.search("onstop", newKey, re.IGNORECASE) or \ + re.search("enable", newKey, re.IGNORECASE) or \ + re.search("disable", newKey, re.IGNORECASE): + dataclassFile.write(f" {newKey}: bool=None\n") + dataclassFile.write(f" _{newKey}NodeosDefault: bool=False\n") + dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") + elif re.search("sizegb", newKey, re.IGNORECASE) or \ + re.search("maxage", newKey, re.IGNORECASE) or \ + re.search("retainblocks", newKey, re.IGNORECASE): + dataclassFile.write(f" {newKey}: int=None\n") + dataclassFile.write(f" _{newKey}NodeosDefault: int=None\n") + dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") + else: + dataclassFile.write(f" {newKey}: str=None\n") + dataclassFile.write(f" _{newKey}NodeosDefault: str=None\n") + dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") + + def writeThreadSetter(pluginName: str) -> str: + if (re.search("chain", pluginName, re.IGNORECASE) or re.search("net", pluginName, re.IGNORECASE) or re.search("producer", pluginName, re.IGNORECASE)): + attrName = re.sub("PluginArgs", "", pluginName).lower() + return f"""\ + def threads(self, threads: int): + self.{attrName}Threads=threads\n\n""" + else: + return "" + + def writeSupportedNodeosArgs() -> str: + return f"""\ + def supportedNodeosArgs(self) -> list:\n\ + args = []\n\ + for field in dataclasses.fields(self):\n\ + match = re.search("\w*NodeosArg", field.name)\n\ + if match is not None:\n\ + args.append(getattr(self, field.name))\n\ + return args\n\n""" + + def writeStrFxn() -> str: + return f"""\ + def __str__(self) -> str:\n\ + args = [] \n\ + for field in dataclasses.fields(self):\n\ + match = re.search("[^_]", field.name[0])\n\ + if match is not None:\n\ + default = getattr(self, f"_{{field.name}}NodeosDefault")\n\ + current = getattr(self, field.name)\n\ + if current is not None and current != default:\n\ + if type(current) is bool: + args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}}") + else: + args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}} {{getattr(self, field.name)}}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else ""\n\n""" + + def writeMainFxn(pluginName: str) -> str: + return f"""\ +def main():\n\ + pluginArgs = {pluginName}()\n\ + print(pluginArgs.supportedNodeosArgs())\n\ + exit(0)\n\n\ +if __name__ == '__main__':\n\ + main()\n""" + + def writeHelpers(pluginName: str) -> str: + return "\n" + writeThreadSetter(pluginName) + writeSupportedNodeosArgs() + writeStrFxn() + writeMainFxn(pluginName) + # return f"""\n def supportedNodeosArgs(self) -> list:\n\ + # args = []\n\ + # for field in dataclasses.fields(self):\n\ + # match = re.search("\w*NodeosArg", field.name)\n\ + # if match is not None:\n\ + # args.append(getattr(self, field.name))\n\ + # return args\n\n\ + # def __str__(self) -> str:\n\ + # args = [] \n\ + # for field in dataclasses.fields(self):\n\ + # match = re.search("[^_]", field.name[0])\n\ + # if match is not None:\n\ + # default = getattr(self, f"_{{field.name}}NodeosDefault")\n\ + # current = getattr(self, field.name)\n\ + # if current is not None and current != default:\n\ + # args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}} {{getattr(self, field.name)}}")\n\ + # return " ".join(args)\n\n\ + # def main():\n\ + # pluginArgs = {pluginName}()\n\ + # print(pluginArgs.supportedNodeosArgs())\n\ + # exit(0)\n\n\ + # if __name__ == '__main__':\n\ + # main()\n""" + + dataclassFile.write(writeHelpers(f"{newPlugin}Args")) + + writeDataclass(plugin="chain_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="http_client_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="http_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="net_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="producer_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="resource_monitor_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="signature_provider_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="state_history_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + writeDataclass(plugin="trace_api_plugin:", dataFieldDict=newDict, pluginOptsDict=pluginOptsDict) + + exit(0) + +if __name__ == '__main__': + main() From 6936b4144f4ca6b9d039ec3154e95716bc584a6c Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Tue, 6 Dec 2022 19:45:12 -0600 Subject: [PATCH 04/15] Fixup invalid syntax error. --- tests/performance_tests/NetPluginArgs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NetPluginArgs.py index 5d36d90d1b..8156475c66 100755 --- a/tests/performance_tests/NetPluginArgs.py +++ b/tests/performance_tests/NetPluginArgs.py @@ -58,7 +58,7 @@ class NetPluginArgs: _useSocketReadWatermarkNodeosDefault: int=0 _useSocketReadWatermarkNodeosArg: str="--use-socket-read-watermark" peerLogFormat: str=None - _peerLogFormatNodeosDefault: str="["${_name}" - ${_cid} ${_ip}:${_port}] " + _peerLogFormatNodeosDefault: str='["${_name}" - ${_cid} ${_ip}:${_port}] ' _peerLogFormatNodeosArg: str="--peer-log-format" p2pKeepaliveIntervalMs: int=None _p2pKeepaliveIntervalMsNodeosDefault: int=10000 From 7dc7133cd041448ea8ae5c4db7b7f34ce6ec49ff Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Tue, 6 Dec 2022 19:48:07 -0600 Subject: [PATCH 05/15] Fixup generator for proper quote detection and selection. --- ...generate_nodeos_plugin_args_class_files.py | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py index cb56ba3f89..fdc7ef8246 100755 --- a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py @@ -89,7 +89,7 @@ def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") except ValueError: strValue = str(value) - quote = "\'" if strValue[0] == "\"" else "\"" + quote = "\'" if re.search("\"", strValue) else "\"" dataclassFile.write(f" {newKey}: str=None\n") dataclassFile.write(f" _{newKey}NodeosDefault: str={quote}{strValue}{quote}\n") dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") @@ -172,29 +172,6 @@ def main():\n\ def writeHelpers(pluginName: str) -> str: return "\n" + writeThreadSetter(pluginName) + writeSupportedNodeosArgs() + writeStrFxn() + writeMainFxn(pluginName) - # return f"""\n def supportedNodeosArgs(self) -> list:\n\ - # args = []\n\ - # for field in dataclasses.fields(self):\n\ - # match = re.search("\w*NodeosArg", field.name)\n\ - # if match is not None:\n\ - # args.append(getattr(self, field.name))\n\ - # return args\n\n\ - # def __str__(self) -> str:\n\ - # args = [] \n\ - # for field in dataclasses.fields(self):\n\ - # match = re.search("[^_]", field.name[0])\n\ - # if match is not None:\n\ - # default = getattr(self, f"_{{field.name}}NodeosDefault")\n\ - # current = getattr(self, field.name)\n\ - # if current is not None and current != default:\n\ - # args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}} {{getattr(self, field.name)}}")\n\ - # return " ".join(args)\n\n\ - # def main():\n\ - # pluginArgs = {pluginName}()\n\ - # print(pluginArgs.supportedNodeosArgs())\n\ - # exit(0)\n\n\ - # if __name__ == '__main__':\n\ - # main()\n""" dataclassFile.write(writeHelpers(f"{newPlugin}Args")) From 0cd997ff6e547526afdf7379c2b911cdfd7d0113 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 08:21:05 -0600 Subject: [PATCH 06/15] Provide BasePluginArgs base class. BasePluginArgs provides generic implementations of __str__ and supportedNodeosArgs functions for use in each *PluginArgs classes. Update generation script to no longer generate base class functions, but to inherit from base class. --- tests/performance_tests/BasePluginArgs.py | 32 +++++++++++++++ tests/performance_tests/CMakeLists.txt | 1 + tests/performance_tests/ChainPluginArgs.py | 29 +------------- .../performance_tests/HttpClientPluginArgs.py | 29 +------------- tests/performance_tests/HttpPluginArgs.py | 29 +------------- tests/performance_tests/NetPluginArgs.py | 29 +------------- tests/performance_tests/ProducerPluginArgs.py | 29 +------------- .../ResourceMonitorPluginArgs.py | 29 +------------- .../SignatureProviderPluginArgs.py | 29 +------------- .../StateHistoryPluginArgs.py | 29 +------------- tests/performance_tests/TraceApiPluginArgs.py | 29 +------------- ...generate_nodeos_plugin_args_class_files.py | 39 +++---------------- 12 files changed, 56 insertions(+), 277 deletions(-) create mode 100755 tests/performance_tests/BasePluginArgs.py diff --git a/tests/performance_tests/BasePluginArgs.py b/tests/performance_tests/BasePluginArgs.py new file mode 100755 index 0000000000..e6fdbca810 --- /dev/null +++ b/tests/performance_tests/BasePluginArgs.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import dataclasses +import re + +from dataclasses import dataclass + +@dataclass +class BasePluginArgs: + + def supportedNodeosArgs(self) -> list: + args = [] + for field in dataclasses.fields(self): + match = re.search("\w*NodeosArg", field.name) + if match is not None: + args.append(getattr(self, field.name)) + return args + + def __str__(self) -> str: + args = [] + for field in dataclasses.fields(self): + match = re.search("[^_]", field.name[0]) + if match is not None: + default = getattr(self, f"_{field.name}NodeosDefault") + current = getattr(self, field.name) + if current is not None and current != default: + if type(current) is bool: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") + else: + args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") + + return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index cff889c4ce..1796fc95d1 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -9,6 +9,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_3_2.txt.gz ${CMAKE_CURRENT configure_file(${CMAKE_CURRENT_SOURCE_DIR}/genesis.json ${CMAKE_CURRENT_BINARY_DIR}/genesis.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/validate_nodeos_plugin_args.py ${CMAKE_CURRENT_BINARY_DIR}/validate_nodeos_plugin_args.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BasePluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/BasePluginArgs.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ChainPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ChainPluginArgs.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpClientPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpClientPluginArgs.py COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpPluginArgs.py COPYONLY) diff --git a/tests/performance_tests/ChainPluginArgs.py b/tests/performance_tests/ChainPluginArgs.py index 528585bddb..da2d59d440 100755 --- a/tests/performance_tests/ChainPluginArgs.py +++ b/tests/performance_tests/ChainPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class ChainPluginArgs: +class ChainPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="chain_plugin" blocksDir: str=None @@ -175,29 +173,6 @@ class ChainPluginArgs: def threads(self, threads: int): self.chainThreads=threads - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = ChainPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/HttpClientPluginArgs.py b/tests/performance_tests/HttpClientPluginArgs.py index 297b3b2494..b5a7f517b7 100755 --- a/tests/performance_tests/HttpClientPluginArgs.py +++ b/tests/performance_tests/HttpClientPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class HttpClientPluginArgs: +class HttpClientPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="http_client_plugin" httpsClientRootCert: str=None @@ -16,29 +14,6 @@ class HttpClientPluginArgs: _httpsClientValidatePeersNodeosDefault: int=1 _httpsClientValidatePeersNodeosArg: str="--https-client-validate-peers" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = HttpClientPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/HttpPluginArgs.py b/tests/performance_tests/HttpPluginArgs.py index 254277889c..cb3d86335b 100755 --- a/tests/performance_tests/HttpPluginArgs.py +++ b/tests/performance_tests/HttpPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class HttpPluginArgs: +class HttpPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="http_plugin" unixSocketPath: str=None @@ -67,29 +65,6 @@ class HttpPluginArgs: _httpKeepAliveNodeosDefault: int=1 _httpKeepAliveNodeosArg: str="--http-keep-alive" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = HttpPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NetPluginArgs.py index 8156475c66..fcfe148968 100755 --- a/tests/performance_tests/NetPluginArgs.py +++ b/tests/performance_tests/NetPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class NetPluginArgs: +class NetPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="net_plugin" p2pListenEndpoint: str=None @@ -67,29 +65,6 @@ class NetPluginArgs: def threads(self, threads: int): self.netThreads=threads - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = NetPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/ProducerPluginArgs.py b/tests/performance_tests/ProducerPluginArgs.py index f487cb63e2..0f9aa9646f 100755 --- a/tests/performance_tests/ProducerPluginArgs.py +++ b/tests/performance_tests/ProducerPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class ProducerPluginArgs: +class ProducerPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="producer_plugin" enableStaleProduction: bool=None @@ -94,29 +92,6 @@ class ProducerPluginArgs: def threads(self, threads: int): self.producerThreads=threads - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = ProducerPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/ResourceMonitorPluginArgs.py b/tests/performance_tests/ResourceMonitorPluginArgs.py index 913ed37e44..3cfe8f3fed 100755 --- a/tests/performance_tests/ResourceMonitorPluginArgs.py +++ b/tests/performance_tests/ResourceMonitorPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class ResourceMonitorPluginArgs: +class ResourceMonitorPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="resource_monitor_plugin" resourceMonitorIntervalSeconds: int=None @@ -22,29 +20,6 @@ class ResourceMonitorPluginArgs: _resourceMonitorWarningIntervalNodeosDefault: int=30 _resourceMonitorWarningIntervalNodeosArg: str="--resource-monitor-warning-interval" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = ResourceMonitorPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/SignatureProviderPluginArgs.py b/tests/performance_tests/SignatureProviderPluginArgs.py index 95efb3ae99..c03fb0d02d 100755 --- a/tests/performance_tests/SignatureProviderPluginArgs.py +++ b/tests/performance_tests/SignatureProviderPluginArgs.py @@ -1,41 +1,16 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class SignatureProviderPluginArgs: +class SignatureProviderPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="signature_provider_plugin" keosdProviderTimeout: int=None _keosdProviderTimeoutNodeosDefault: int=5 _keosdProviderTimeoutNodeosArg: str="--keosd-provider-timeout" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = SignatureProviderPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/StateHistoryPluginArgs.py b/tests/performance_tests/StateHistoryPluginArgs.py index a0559607a9..306c44895c 100755 --- a/tests/performance_tests/StateHistoryPluginArgs.py +++ b/tests/performance_tests/StateHistoryPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class StateHistoryPluginArgs: +class StateHistoryPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="state_history_plugin" stateHistoryDir: str=None @@ -34,29 +32,6 @@ class StateHistoryPluginArgs: _deleteStateHistoryNodeosDefault: bool=False _deleteStateHistoryNodeosArg: str="--delete-state-history" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = StateHistoryPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/TraceApiPluginArgs.py b/tests/performance_tests/TraceApiPluginArgs.py index a415caccc7..3734c2fcb7 100755 --- a/tests/performance_tests/TraceApiPluginArgs.py +++ b/tests/performance_tests/TraceApiPluginArgs.py @@ -1,12 +1,10 @@ #!/usr/bin/env python3 -import dataclasses -import re - from dataclasses import dataclass +from BasePluginArgs import BasePluginArgs @dataclass -class TraceApiPluginArgs: +class TraceApiPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" _pluginName: str="trace_api_plugin" traceDir: str=None @@ -28,29 +26,6 @@ class TraceApiPluginArgs: _traceNoAbisNodeosDefault: bool=False _traceNoAbisNodeosArg: str="--trace-no-abis" - def supportedNodeosArgs(self) -> list: - args = [] - for field in dataclasses.fields(self): - match = re.search("\w*NodeosArg", field.name) - if match is not None: - args.append(getattr(self, field.name)) - return args - - def __str__(self) -> str: - args = [] - for field in dataclasses.fields(self): - match = re.search("[^_]", field.name[0]) - if match is not None: - default = getattr(self, f"_{field.name}NodeosDefault") - current = getattr(self, field.name) - if current is not None and current != default: - if type(current) is bool: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')}") - else: - args.append(f"{getattr(self, f'_{field.name}NodeosArg')} {getattr(self, field.name)}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else "" - def main(): pluginArgs = TraceApiPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py index fdc7ef8246..98b04fe213 100755 --- a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py @@ -37,7 +37,6 @@ def pairwise(iterable): argument=secondSplit[0] argDefaultDesc=secondSplit[1].lstrip("\s") argDescDict[argument] = argDefaultDesc - # print(f"argDefaultDesc: {argDefaultDesc}") section=re.sub("@@@", "", section) section=re.sub("\n", "", section) sectionSplit=re.split("::", section) @@ -67,11 +66,10 @@ def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): with open(pluginArgsFile, 'w') as dataclassFile: chainPluginArgs = dataFieldDict[newPlugin] - dataclassFile.write(f"#!/usr/bin/env python3\n\n") - dataclassFile.write(f"import dataclasses\n") - dataclassFile.write(f"import re\n\n") - dataclassFile.write(f"from dataclasses import dataclass\n\n") - dataclassFile.write(f"@dataclass\nclass {newPlugin}Args:\n") + dataclassFile.write(f"#!/usr/bin/env python3\n\n") + dataclassFile.write(f"from dataclasses import dataclass\n") + dataclassFile.write(f"from BasePluginArgs import BasePluginArgs\n\n") + dataclassFile.write(f"@dataclass\nclass {newPlugin}Args(BasePluginArgs):\n") dataclassFile.write(f" _pluginNamespace: str=\"eosio\"\n") dataclassFile.write(f" _pluginName: str=\"{plugin[:-1]}\"\n") @@ -134,33 +132,6 @@ def threads(self, threads: int): else: return "" - def writeSupportedNodeosArgs() -> str: - return f"""\ - def supportedNodeosArgs(self) -> list:\n\ - args = []\n\ - for field in dataclasses.fields(self):\n\ - match = re.search("\w*NodeosArg", field.name)\n\ - if match is not None:\n\ - args.append(getattr(self, field.name))\n\ - return args\n\n""" - - def writeStrFxn() -> str: - return f"""\ - def __str__(self) -> str:\n\ - args = [] \n\ - for field in dataclasses.fields(self):\n\ - match = re.search("[^_]", field.name[0])\n\ - if match is not None:\n\ - default = getattr(self, f"_{{field.name}}NodeosDefault")\n\ - current = getattr(self, field.name)\n\ - if current is not None and current != default:\n\ - if type(current) is bool: - args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}}") - else: - args.append(f"{{getattr(self, f'_{{field.name}}NodeosArg')}} {{getattr(self, field.name)}}") - - return "--plugin " + self._pluginNamespace + "::" + self._pluginName + " " + " ".join(args) if len(args) > 0 else ""\n\n""" - def writeMainFxn(pluginName: str) -> str: return f"""\ def main():\n\ @@ -171,7 +142,7 @@ def main():\n\ main()\n""" def writeHelpers(pluginName: str) -> str: - return "\n" + writeThreadSetter(pluginName) + writeSupportedNodeosArgs() + writeStrFxn() + writeMainFxn(pluginName) + return "\n" + writeThreadSetter(pluginName) + writeMainFxn(pluginName) dataclassFile.write(writeHelpers(f"{newPlugin}Args")) From d1d717d8b05c69fad7190029d43e126c5197d1d3 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 08:46:05 -0600 Subject: [PATCH 07/15] Remove threads setter function and use setattr instead. --- tests/performance_tests/ChainPluginArgs.py | 3 --- tests/performance_tests/NetPluginArgs.py | 3 --- tests/performance_tests/ProducerPluginArgs.py | 3 --- .../generate_nodeos_plugin_args_class_files.py | 11 +---------- tests/performance_tests/performance_test.py | 2 +- 5 files changed, 2 insertions(+), 20 deletions(-) diff --git a/tests/performance_tests/ChainPluginArgs.py b/tests/performance_tests/ChainPluginArgs.py index da2d59d440..aa075e3f11 100755 --- a/tests/performance_tests/ChainPluginArgs.py +++ b/tests/performance_tests/ChainPluginArgs.py @@ -170,9 +170,6 @@ class ChainPluginArgs(BasePluginArgs): _snapshotNodeosDefault: str=None _snapshotNodeosArg: str="--snapshot" - def threads(self, threads: int): - self.chainThreads=threads - def main(): pluginArgs = ChainPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NetPluginArgs.py index fcfe148968..6774a58267 100755 --- a/tests/performance_tests/NetPluginArgs.py +++ b/tests/performance_tests/NetPluginArgs.py @@ -62,9 +62,6 @@ class NetPluginArgs(BasePluginArgs): _p2pKeepaliveIntervalMsNodeosDefault: int=10000 _p2pKeepaliveIntervalMsNodeosArg: str="--p2p-keepalive-interval-ms" - def threads(self, threads: int): - self.netThreads=threads - def main(): pluginArgs = NetPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/ProducerPluginArgs.py b/tests/performance_tests/ProducerPluginArgs.py index 0f9aa9646f..4cb8ee8781 100755 --- a/tests/performance_tests/ProducerPluginArgs.py +++ b/tests/performance_tests/ProducerPluginArgs.py @@ -89,9 +89,6 @@ class ProducerPluginArgs(BasePluginArgs): _snapshotsDirNodeosDefault: str='"snapshots"' _snapshotsDirNodeosArg: str="--snapshots-dir" - def threads(self, threads: int): - self.producerThreads=threads - def main(): pluginArgs = ProducerPluginArgs() print(pluginArgs.supportedNodeosArgs()) diff --git a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py index 98b04fe213..433a6d63c3 100755 --- a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/generate_nodeos_plugin_args_class_files.py @@ -123,15 +123,6 @@ def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): dataclassFile.write(f" _{newKey}NodeosDefault: str=None\n") dataclassFile.write(f" _{newKey}NodeosArg: str=\"{key}\"\n") - def writeThreadSetter(pluginName: str) -> str: - if (re.search("chain", pluginName, re.IGNORECASE) or re.search("net", pluginName, re.IGNORECASE) or re.search("producer", pluginName, re.IGNORECASE)): - attrName = re.sub("PluginArgs", "", pluginName).lower() - return f"""\ - def threads(self, threads: int): - self.{attrName}Threads=threads\n\n""" - else: - return "" - def writeMainFxn(pluginName: str) -> str: return f"""\ def main():\n\ @@ -142,7 +133,7 @@ def main():\n\ main()\n""" def writeHelpers(pluginName: str) -> str: - return "\n" + writeThreadSetter(pluginName) + writeMainFxn(pluginName) + return "\n" + writeMainFxn(pluginName) dataclassFile.write(writeHelpers(f"{newPlugin}Args")) diff --git a/tests/performance_tests/performance_test.py b/tests/performance_tests/performance_test.py index b0edc31437..10794c7bb6 100755 --- a/tests/performance_tests/performance_test.py +++ b/tests/performance_tests/performance_test.py @@ -233,7 +233,7 @@ def optimizePluginThreadCount(self, optPlugin: PluginThreadOpt, optType: Plugin for threadCount in range(minThreadCount, maxThreadCount+1): print(f"Running {optPlugin.value} thread count optimization check with {threadCount} {optPlugin.value} threads") - getattr(clusterConfig.extraNodeosArgs, optPlugin.value + 'PluginArgs').threads(threadCount) + setattr(getattr(clusterConfig.extraNodeosArgs, optPlugin.value + 'PluginArgs'), f"{optPlugin.value}Threads", threadCount) binSearchResults = self.performPtbBinarySearch(clusterConfig=clusterConfig, logDirRoot=self.loggingConfig.pluginThreadOptLogsDirPath, delReport=True, quiet=False, delPerfLogs=True) From 7703c6ef087e1d8a0cc0fe5aa67f7e23cb626473 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 08:49:27 -0600 Subject: [PATCH 08/15] Remove cruft. --- tests/performance_tests/validate_nodeos_plugin_args.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/performance_tests/validate_nodeos_plugin_args.py b/tests/performance_tests/validate_nodeos_plugin_args.py index a13e7021f5..f2cd2f0b1d 100755 --- a/tests/performance_tests/validate_nodeos_plugin_args.py +++ b/tests/performance_tests/validate_nodeos_plugin_args.py @@ -25,10 +25,6 @@ def parseNodeosConfigOptions() -> dict: myStr = re.sub("Application Options:\n",'', string=myStr) pluginSections = re.split("(@@@.*?@@@\n)", string=myStr) - sec=0 - for section in pluginSections: - sec=sec+1 - def pairwise(iterable): "s -> (s0, s1), (s2, s3), (s4, s5), ..." a = iter(iterable) From cdb1342fc849019d0353e550a054b33aed0ce398 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 10:58:58 -0600 Subject: [PATCH 09/15] Create NodeosPluginArgs python package --- tests/performance_tests/CMakeLists.txt | 13 ++----------- .../{ => NodeosPluginArgs}/BasePluginArgs.py | 0 .../NodeosPluginArgs/CMakeLists.txt | 11 +++++++++++ .../{ => NodeosPluginArgs}/ChainPluginArgs.py | 0 .../{ => NodeosPluginArgs}/HttpClientPluginArgs.py | 0 .../{ => NodeosPluginArgs}/HttpPluginArgs.py | 0 .../{ => NodeosPluginArgs}/NetPluginArgs.py | 0 .../{ => NodeosPluginArgs}/ProducerPluginArgs.py | 0 .../ResourceMonitorPluginArgs.py | 0 .../SignatureProviderPluginArgs.py | 0 .../StateHistoryPluginArgs.py | 0 .../{ => NodeosPluginArgs}/TraceApiPluginArgs.py | 0 .../performance_tests/NodeosPluginArgs/__init__.py | 12 ++++++++++++ .../generate_nodeos_plugin_args_class_files.py | 3 +-- tests/performance_tests/performance_test.py | 5 +---- tests/performance_tests/performance_test_basic.py | 10 +--------- 16 files changed, 28 insertions(+), 26 deletions(-) rename tests/performance_tests/{ => NodeosPluginArgs}/BasePluginArgs.py (100%) create mode 100644 tests/performance_tests/NodeosPluginArgs/CMakeLists.txt rename tests/performance_tests/{ => NodeosPluginArgs}/ChainPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/HttpClientPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/HttpPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/NetPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/ProducerPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/ResourceMonitorPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/SignatureProviderPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/StateHistoryPluginArgs.py (100%) rename tests/performance_tests/{ => NodeosPluginArgs}/TraceApiPluginArgs.py (100%) create mode 100644 tests/performance_tests/NodeosPluginArgs/__init__.py rename tests/performance_tests/{ => NodeosPluginArgs}/generate_nodeos_plugin_args_class_files.py (98%) diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 1796fc95d1..61704ef84d 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -9,18 +9,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_3_2.txt.gz ${CMAKE_CURRENT configure_file(${CMAKE_CURRENT_SOURCE_DIR}/genesis.json ${CMAKE_CURRENT_BINARY_DIR}/genesis.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/validate_nodeos_plugin_args.py ${CMAKE_CURRENT_BINARY_DIR}/validate_nodeos_plugin_args.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BasePluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/BasePluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ChainPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ChainPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpClientPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpClientPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/NetPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/NetPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ProducerPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ProducerPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ResourceMonitorPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ResourceMonitorPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/SignatureProviderPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/SignatureProviderPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/StateHistoryPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/StateHistoryPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TraceApiPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/TraceApiPluginArgs.py COPYONLY) - add_test(NAME performance_test_basic COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 6000 --tps-limit-per-generator 1500 --clean-run WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME log_reader_tests COMMAND tests/performance_tests/log_reader_tests.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME validate_nodeos_plugin_args COMMAND tests/performance_tests/validate_nodeos_plugin_args.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) set_property(TEST performance_test_basic PROPERTY LABELS nonparallelizable_tests) + +add_subdirectory( NodeosPluginArgs ) diff --git a/tests/performance_tests/BasePluginArgs.py b/tests/performance_tests/NodeosPluginArgs/BasePluginArgs.py similarity index 100% rename from tests/performance_tests/BasePluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/BasePluginArgs.py diff --git a/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt b/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt new file mode 100644 index 0000000000..6ac9f90d02 --- /dev/null +++ b/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt @@ -0,0 +1,11 @@ +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BasePluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/BasePluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ChainPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ChainPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpClientPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpClientPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/NetPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/NetPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ProducerPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ProducerPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ResourceMonitorPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ResourceMonitorPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/SignatureProviderPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/SignatureProviderPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/StateHistoryPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/StateHistoryPluginArgs.py COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TraceApiPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/TraceApiPluginArgs.py COPYONLY) diff --git a/tests/performance_tests/ChainPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py similarity index 100% rename from tests/performance_tests/ChainPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py diff --git a/tests/performance_tests/HttpClientPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py similarity index 100% rename from tests/performance_tests/HttpClientPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py diff --git a/tests/performance_tests/HttpPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py similarity index 100% rename from tests/performance_tests/HttpPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py diff --git a/tests/performance_tests/NetPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py similarity index 100% rename from tests/performance_tests/NetPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py diff --git a/tests/performance_tests/ProducerPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py similarity index 100% rename from tests/performance_tests/ProducerPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py diff --git a/tests/performance_tests/ResourceMonitorPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py similarity index 100% rename from tests/performance_tests/ResourceMonitorPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py diff --git a/tests/performance_tests/SignatureProviderPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py similarity index 100% rename from tests/performance_tests/SignatureProviderPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py diff --git a/tests/performance_tests/StateHistoryPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py similarity index 100% rename from tests/performance_tests/StateHistoryPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py diff --git a/tests/performance_tests/TraceApiPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py similarity index 100% rename from tests/performance_tests/TraceApiPluginArgs.py rename to tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py diff --git a/tests/performance_tests/NodeosPluginArgs/__init__.py b/tests/performance_tests/NodeosPluginArgs/__init__.py new file mode 100644 index 0000000000..af58fe3fdd --- /dev/null +++ b/tests/performance_tests/NodeosPluginArgs/__init__.py @@ -0,0 +1,12 @@ +__all__ = ['BasePluginArgs', 'ChainPluginArgs', 'HttpClientPluginArgs', 'HttpPluginArgs', 'NetPluginArgs', 'ProducerPluginArgs', 'ResourceMonitorPluginArgs', 'SignatureProviderPluginArgs', 'StateHistoryPluginArgs', 'TraceApiPluginArgs'] + +from .BasePluginArgs import BasePluginArgs +from .ChainPluginArgs import ChainPluginArgs +from .HttpClientPluginArgs import HttpClientPluginArgs +from .HttpPluginArgs import HttpPluginArgs +from .NetPluginArgs import NetPluginArgs +from .ProducerPluginArgs import ProducerPluginArgs +from .ResourceMonitorPluginArgs import ResourceMonitorPluginArgs +from .SignatureProviderPluginArgs import SignatureProviderPluginArgs +from .StateHistoryPluginArgs import StateHistoryPluginArgs +from .TraceApiPluginArgs import TraceApiPluginArgs diff --git a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py similarity index 98% rename from tests/performance_tests/generate_nodeos_plugin_args_class_files.py rename to tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py index 433a6d63c3..bc5644caa6 100755 --- a/tests/performance_tests/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py @@ -4,7 +4,6 @@ import subprocess def main(): - cmd="programs/nodeos/nodeos --help" result = subprocess.run(["programs/nodeos/nodeos", "--help"], capture_output=True, text=True) myStr = result.stdout @@ -62,7 +61,7 @@ def pairwise(iterable): def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): newPlugin="".join([x.capitalize() for x in plugin.split('_')]).replace(":","") - pluginArgsFile=f"../tests/performance_tests/{newPlugin}Args.py" + pluginArgsFile=f"../tests/performance_tests/NodeosPluginArgs/{newPlugin}Args.py" with open(pluginArgsFile, 'w') as dataclassFile: chainPluginArgs = dataFieldDict[newPlugin] diff --git a/tests/performance_tests/performance_test.py b/tests/performance_tests/performance_test.py index 10794c7bb6..ff42e4a55f 100755 --- a/tests/performance_tests/performance_test.py +++ b/tests/performance_tests/performance_test.py @@ -11,10 +11,7 @@ harnessPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(harnessPath) -from ChainPluginArgs import ChainPluginArgs -from HttpPluginArgs import HttpPluginArgs -from NetPluginArgs import NetPluginArgs -from ProducerPluginArgs import ProducerPluginArgs +from NodeosPluginArgs import ChainPluginArgs, HttpPluginArgs, NetPluginArgs, ProducerPluginArgs from TestHarness import TestHelper, Utils from performance_test_basic import PerformanceTestBasic, PtbArgumentsHandler from platform import release, system diff --git a/tests/performance_tests/performance_test_basic.py b/tests/performance_tests/performance_test_basic.py index a7b10cebc1..ef89aee9f2 100755 --- a/tests/performance_tests/performance_test_basic.py +++ b/tests/performance_tests/performance_test_basic.py @@ -13,15 +13,7 @@ harnessPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(harnessPath) -from ChainPluginArgs import ChainPluginArgs -from HttpClientPluginArgs import HttpClientPluginArgs -from HttpPluginArgs import HttpPluginArgs -from NetPluginArgs import NetPluginArgs -from ProducerPluginArgs import ProducerPluginArgs -from ResourceMonitorPluginArgs import ResourceMonitorPluginArgs -from SignatureProviderPluginArgs import SignatureProviderPluginArgs -from StateHistoryPluginArgs import StateHistoryPluginArgs -from TraceApiPluginArgs import TraceApiPluginArgs +from NodeosPluginArgs import ChainPluginArgs, HttpClientPluginArgs, HttpPluginArgs, NetPluginArgs, ProducerPluginArgs, ResourceMonitorPluginArgs, SignatureProviderPluginArgs, StateHistoryPluginArgs, TraceApiPluginArgs from TestHarness import Cluster, TestHelper, Utils, WalletMgr from dataclasses import dataclass, asdict, field from datetime import datetime From bea0ec01956aa70c13355c0d38079517a186369e Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 11:53:23 -0600 Subject: [PATCH 10/15] Fix imports. --- tests/performance_tests/validate_nodeos_plugin_args.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/performance_tests/validate_nodeos_plugin_args.py b/tests/performance_tests/validate_nodeos_plugin_args.py index f2cd2f0b1d..948eed9b6a 100755 --- a/tests/performance_tests/validate_nodeos_plugin_args.py +++ b/tests/performance_tests/validate_nodeos_plugin_args.py @@ -3,15 +3,7 @@ import re import subprocess -from ChainPluginArgs import ChainPluginArgs -from HttpClientPluginArgs import HttpClientPluginArgs -from HttpPluginArgs import HttpPluginArgs -from NetPluginArgs import NetPluginArgs -from ProducerPluginArgs import ProducerPluginArgs -from ResourceMonitorPluginArgs import ResourceMonitorPluginArgs -from SignatureProviderPluginArgs import SignatureProviderPluginArgs -from StateHistoryPluginArgs import StateHistoryPluginArgs -from TraceApiPluginArgs import TraceApiPluginArgs +from NodeosPluginArgs import ChainPluginArgs, HttpClientPluginArgs, HttpPluginArgs, NetPluginArgs, ProducerPluginArgs, ResourceMonitorPluginArgs, SignatureProviderPluginArgs, StateHistoryPluginArgs, TraceApiPluginArgs testSuccessful = False From cc6879c46737d304dd502e091edce04b2c75d675 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 12:11:16 -0600 Subject: [PATCH 11/15] Fix module name. --- tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py | 2 +- .../performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py | 2 +- tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py | 2 +- tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py | 2 +- tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py | 2 +- .../NodeosPluginArgs/ResourceMonitorPluginArgs.py | 2 +- .../NodeosPluginArgs/SignatureProviderPluginArgs.py | 2 +- .../NodeosPluginArgs/StateHistoryPluginArgs.py | 2 +- tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py | 2 +- .../NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py index aa075e3f11..4706868269 100755 --- a/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class ChainPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py index b5a7f517b7..6c60aec9f9 100755 --- a/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class HttpClientPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py index cb3d86335b..7881907081 100755 --- a/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class HttpPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py index 6774a58267..cb467102d3 100755 --- a/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class NetPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py index 4cb8ee8781..015e6720f4 100755 --- a/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class ProducerPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py index 3cfe8f3fed..ce9f453522 100755 --- a/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class ResourceMonitorPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py index c03fb0d02d..cfd9847d29 100755 --- a/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class SignatureProviderPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py index 306c44895c..005f1a13b6 100755 --- a/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class StateHistoryPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py index 3734c2fcb7..19d345479d 100755 --- a/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass -from BasePluginArgs import BasePluginArgs +from .BasePluginArgs import BasePluginArgs @dataclass class TraceApiPluginArgs(BasePluginArgs): diff --git a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py index bc5644caa6..e104168d37 100755 --- a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py @@ -67,7 +67,7 @@ def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): dataclassFile.write(f"#!/usr/bin/env python3\n\n") dataclassFile.write(f"from dataclasses import dataclass\n") - dataclassFile.write(f"from BasePluginArgs import BasePluginArgs\n\n") + dataclassFile.write(f"from .BasePluginArgs import BasePluginArgs\n\n") dataclassFile.write(f"@dataclass\nclass {newPlugin}Args(BasePluginArgs):\n") dataclassFile.write(f" _pluginNamespace: str=\"eosio\"\n") dataclassFile.write(f" _pluginName: str=\"{plugin[:-1]}\"\n") From 52b7903d92b667fd836e97aa649c3021ba4c3f72 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 14:17:54 -0600 Subject: [PATCH 12/15] Remove redundant paths in CMake files. --- tests/performance_tests/CMakeLists.txt | 20 ++++++++--------- .../NodeosPluginArgs/CMakeLists.txt | 22 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/performance_tests/CMakeLists.txt b/tests/performance_tests/CMakeLists.txt index 61704ef84d..a06043b380 100644 --- a/tests/performance_tests/CMakeLists.txt +++ b/tests/performance_tests/CMakeLists.txt @@ -1,13 +1,13 @@ -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/performance_test_basic.py ${CMAKE_CURRENT_BINARY_DIR}/performance_test_basic.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/performance_test.py ${CMAKE_CURRENT_BINARY_DIR}/performance_test.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/log_reader.py ${CMAKE_CURRENT_BINARY_DIR}/log_reader.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/read_log_data.py ${CMAKE_CURRENT_BINARY_DIR}/read_log_data.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/log_reader_tests.py ${CMAKE_CURRENT_BINARY_DIR}/log_reader_tests.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/launch_transaction_generators.py ${CMAKE_CURRENT_BINARY_DIR}/launch_transaction_generators.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_2_0_14.txt.gz ${CMAKE_CURRENT_BINARY_DIR}/nodeos_log_2_0_14.txt.gz COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/nodeos_log_3_2.txt.gz ${CMAKE_CURRENT_BINARY_DIR}/nodeos_log_3_2.txt.gz COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/genesis.json ${CMAKE_CURRENT_BINARY_DIR}/genesis.json COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/validate_nodeos_plugin_args.py ${CMAKE_CURRENT_BINARY_DIR}/validate_nodeos_plugin_args.py COPYONLY) +configure_file(performance_test_basic.py performance_test_basic.py COPYONLY) +configure_file(performance_test.py performance_test.py COPYONLY) +configure_file(log_reader.py log_reader.py COPYONLY) +configure_file(read_log_data.py read_log_data.py COPYONLY) +configure_file(log_reader_tests.py log_reader_tests.py COPYONLY) +configure_file(launch_transaction_generators.py launch_transaction_generators.py COPYONLY) +configure_file(nodeos_log_2_0_14.txt.gz nodeos_log_2_0_14.txt.gz COPYONLY) +configure_file(nodeos_log_3_2.txt.gz nodeos_log_3_2.txt.gz COPYONLY) +configure_file(genesis.json genesis.json COPYONLY) +configure_file(validate_nodeos_plugin_args.py validate_nodeos_plugin_args.py COPYONLY) add_test(NAME performance_test_basic COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 6000 --tps-limit-per-generator 1500 --clean-run WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_test(NAME log_reader_tests COMMAND tests/performance_tests/log_reader_tests.py WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt b/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt index 6ac9f90d02..57833a3942 100644 --- a/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt +++ b/tests/performance_tests/NodeosPluginArgs/CMakeLists.txt @@ -1,11 +1,11 @@ -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BasePluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/BasePluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ChainPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ChainPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpClientPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpClientPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/HttpPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/HttpPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/NetPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/NetPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ProducerPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ProducerPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ResourceMonitorPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/ResourceMonitorPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/SignatureProviderPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/SignatureProviderPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/StateHistoryPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/StateHistoryPluginArgs.py COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TraceApiPluginArgs.py ${CMAKE_CURRENT_BINARY_DIR}/TraceApiPluginArgs.py COPYONLY) +configure_file(__init__.py __init__.py COPYONLY) +configure_file(BasePluginArgs.py BasePluginArgs.py COPYONLY) +configure_file(ChainPluginArgs.py ChainPluginArgs.py COPYONLY) +configure_file(HttpClientPluginArgs.py HttpClientPluginArgs.py COPYONLY) +configure_file(HttpPluginArgs.py HttpPluginArgs.py COPYONLY) +configure_file(NetPluginArgs.py NetPluginArgs.py COPYONLY) +configure_file(ProducerPluginArgs.py ProducerPluginArgs.py COPYONLY) +configure_file(ResourceMonitorPluginArgs.py ResourceMonitorPluginArgs.py COPYONLY) +configure_file(SignatureProviderPluginArgs.py SignatureProviderPluginArgs.py COPYONLY) +configure_file(StateHistoryPluginArgs.py StateHistoryPluginArgs.py COPYONLY) +configure_file(TraceApiPluginArgs.py TraceApiPluginArgs.py COPYONLY) From 792a0f8559656403d63b8c87ee952ff6b4cee140 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 14:50:31 -0600 Subject: [PATCH 13/15] Add purpose and limitations statement to generation script. Also add note to each generated class calling out that it was generated. --- .../NodeosPluginArgs/ChainPluginArgs.py | 4 ++ .../NodeosPluginArgs/HttpClientPluginArgs.py | 4 ++ .../NodeosPluginArgs/HttpPluginArgs.py | 4 ++ .../NodeosPluginArgs/NetPluginArgs.py | 4 ++ .../NodeosPluginArgs/ProducerPluginArgs.py | 4 ++ .../ResourceMonitorPluginArgs.py | 4 ++ .../SignatureProviderPluginArgs.py | 4 ++ .../StateHistoryPluginArgs.py | 4 ++ .../NodeosPluginArgs/TraceApiPluginArgs.py | 4 ++ ...generate_nodeos_plugin_args_class_files.py | 51 +++++++++++++++++++ 10 files changed, 87 insertions(+) diff --git a/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py index 4706868269..41268994a8 100755 --- a/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ChainPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class ChainPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py index 6c60aec9f9..1a3bd81a1b 100755 --- a/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/HttpClientPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class HttpClientPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py index 7881907081..25b2336dc4 100755 --- a/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/HttpPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class HttpPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py index cb467102d3..a8e8bbc962 100755 --- a/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/NetPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class NetPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py index 015e6720f4..98a234e788 100755 --- a/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ProducerPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class ProducerPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py index ce9f453522..cc731d9133 100755 --- a/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/ResourceMonitorPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class ResourceMonitorPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py index cfd9847d29..39d9ddf0dd 100755 --- a/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/SignatureProviderPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class SignatureProviderPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py index 005f1a13b6..732909a2b8 100755 --- a/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/StateHistoryPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class StateHistoryPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py b/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py index 19d345479d..9ef9f5f222 100755 --- a/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py +++ b/tests/performance_tests/NodeosPluginArgs/TraceApiPluginArgs.py @@ -3,6 +3,10 @@ from dataclasses import dataclass from .BasePluginArgs import BasePluginArgs +""" +This file/class was generated by generate_nodeos_plugin_args_class_files.py +""" + @dataclass class TraceApiPluginArgs(BasePluginArgs): _pluginNamespace: str="eosio" diff --git a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py index e104168d37..c9f063d8cb 100755 --- a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py @@ -3,6 +3,54 @@ import re import subprocess +""" +The purpose of this script is to attempt to generate *PluginArgs.py files, containing respective dataclass objects, +to encapsulate the configurations options available for each plugin as currently documented in nodeos's --help command. + +It currently makes use of the compiled nodeos program and runs the --help command, capturing the output. +It then parses the output, breaking down the presented configuration options by plugin section (ignoring applicaiton and test plugin config options). +This provides a rudimentary list of plugins supported, config options for each plugin, and attempts to acertain default values and types. +The script then uses the parsed output to generate *PluginArgs.py scripts, placing them in the NodeosPluginArgs directory. + +Currently it generates the following scripts: +- ChainPluginArgs.py +- HttpClientPluginArgs.py +- HttpPluginArgs.py +- NetPluginArgs.py +- ProducerPluginArgs.py +- ResourceMonitorPluginArgs.py +- SignatureProviderPluginArgs.py +- StateHistoryPluginArgs.py +- TraceApiPluginArgs.py + +Each *PluginArgs.py file contains one dataclass that captures the available configuration options for that plugin via nodeos command line. + +Each config options is represented by 3 member variables, for example: +1) blocksDir: str=None + --This is the field that will be populated when the dataclass is used by other scripts to configure nodeos +2) _blocksDirNodeosDefault: str='"blocks"' + --This field captures the default value in the nodeos output. This will be compared against the first field to see if the configuration option will be required on the command line to override the default value when running nodeos. +3) _blocksDirNodeosArg: str="--blocks-dir" + --This field captures the command line config option for use when creating the command line string + +The BasePluginArgs class provides implemenations for 2 useful functions for each of these classes: +1) supportedNodeosArgs + -- Provides a list of all the command line config options currently supported by the dataclass +2) __str__ + -- Provides the command line argument string for the current configuration to pass to nodeos + (this only provides command line options where configured values differ from defaults) + +Some current limitations: +- There are some hardoded edge cases when trying to determine the types associated with certain default argument parameters. + These may need to be updated to account for new/different options as they are added/removed/modified by nodeos + +Note: +- To help with maintainability the validate_nodeos_plugin_args.py test script is provided which validates the current + *PluginArgs dataclass configuration objects against the current nodeos --help output to notify developers when + configuration options have changed and updates are required. +""" + + def main(): result = subprocess.run(["programs/nodeos/nodeos", "--help"], capture_output=True, text=True) @@ -68,6 +116,9 @@ def writeDataclass(plugin:str, dataFieldDict:dict, pluginOptsDict:dict): dataclassFile.write(f"#!/usr/bin/env python3\n\n") dataclassFile.write(f"from dataclasses import dataclass\n") dataclassFile.write(f"from .BasePluginArgs import BasePluginArgs\n\n") + dataclassFile.write(f"\"\"\"\n") + dataclassFile.write(f"This file/class was generated by generate_nodeos_plugin_args_class_files.py\n") + dataclassFile.write(f"\"\"\"\n\n") dataclassFile.write(f"@dataclass\nclass {newPlugin}Args(BasePluginArgs):\n") dataclassFile.write(f" _pluginNamespace: str=\"eosio\"\n") dataclassFile.write(f" _pluginName: str=\"{plugin[:-1]}\"\n") From 2e4495e651a9df196a0dd5710c854b64aa585e68 Mon Sep 17 00:00:00 2001 From: Peter Oschwald Date: Wed, 7 Dec 2022 14:58:44 -0600 Subject: [PATCH 14/15] Add suggestion to regen classes if test fails due to updated nodeos config options. --- .../validate_nodeos_plugin_args.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/performance_tests/validate_nodeos_plugin_args.py b/tests/performance_tests/validate_nodeos_plugin_args.py index 948eed9b6a..47be3f08ef 100755 --- a/tests/performance_tests/validate_nodeos_plugin_args.py +++ b/tests/performance_tests/validate_nodeos_plugin_args.py @@ -7,6 +7,9 @@ testSuccessful = False +regenSuggestion = "Try updating *PluginArgs classes to nodeos's current config options by running the script: generate_nodeos_plugin_args_class_files.py. \ + Updates to generation script may be required if a plugin was added/removed or in some default parameter cases." + def parseNodeosConfigOptions() -> dict: result = subprocess.run(["programs/nodeos/nodeos", "--help"], capture_output=True, text=True) @@ -69,7 +72,7 @@ def pairwise(iterable): #Check whether nodeos has added any plugin configuration sections for confSection in nodeosPluginOptsDict.keys(): - assert confSection in [paClass._pluginName for paClass in curListOfSupportedPlugins] or confSection in curListOfUnsupportedOptionGroups, f"ERROR: New config section \"{confSection}\" added to nodeos which may require updates." + assert confSection in [paClass._pluginName for paClass in curListOfSupportedPlugins] or confSection in curListOfUnsupportedOptionGroups, f"ERROR: New config section \"{confSection}\" added to nodeos which may require updates. {regenSuggestion}" def argStrToAttrName(argStr: str) -> str: attrName="".join([x.capitalize() for x in argStr.split('-')]).replace('--','') @@ -78,11 +81,11 @@ def argStrToAttrName(argStr: str) -> str: for supportedPlugin in curListOfSupportedPlugins: #Check whether nodeos has removed any plugin configuration sections - assert supportedPlugin._pluginName in nodeosPluginOptsDict, f"ERROR: Supported config section \"{supportedPlugin}\" no longer supported by nodeos." + assert supportedPlugin._pluginName in nodeosPluginOptsDict, f"ERROR: Supported config section \"{supportedPlugin}\" no longer supported by nodeos. {regenSuggestion}" for opt in supportedPlugin.supportedNodeosArgs(): #Check whether nodeos has removed any arguments in a plugin - assert opt in nodeosPluginOptsDict[supportedPlugin._pluginName].keys(), f"ERROR: nodeos no longer supports \"{opt}\" in \"{supportedPlugin._pluginName}\"." + assert opt in nodeosPluginOptsDict[supportedPlugin._pluginName].keys(), f"ERROR: nodeos no longer supports \"{opt}\" in \"{supportedPlugin._pluginName}\". {regenSuggestion}" ourDefault = getattr(supportedPlugin, f"_{argStrToAttrName(opt)}NodeosDefault") @@ -90,16 +93,16 @@ def argStrToAttrName(argStr: str) -> str: if type(ourDefault) == bool and nodeosCurDefault is None: nodeosCurDefault=False #Check whether our defaults no longer match nodeos's - assert ourDefault == nodeosCurDefault, f"ERROR: {type(supportedPlugin)}'s default for \"{opt}\" is {ourDefault} and no longer matches nodeos's default {nodeosCurDefault} in \"{supportedPlugin._pluginName}\"." + assert ourDefault == nodeosCurDefault, f"ERROR: {type(supportedPlugin)}'s default for \"{opt}\" is {ourDefault} and no longer matches nodeos's default {nodeosCurDefault} in \"{supportedPlugin._pluginName}\". {regenSuggestion}" #Check whether nodeos has added/updated any argument defaults for nodeosOpt, defaultValue in nodeosPluginOptsDict[supportedPlugin._pluginName].items(): - assert nodeosOpt in supportedPlugin.supportedNodeosArgs(), f"ERROR: New nodeos option \"{nodeosOpt}\". Support for this option needs to be added to {type(supportedPlugin)}." + assert nodeosOpt in supportedPlugin.supportedNodeosArgs(), f"ERROR: New nodeos option \"{nodeosOpt}\". Support for this option needs to be added to {type(supportedPlugin)}. {regenSuggestion}" ourDefault = getattr(supportedPlugin, f"_{argStrToAttrName(nodeosOpt)}NodeosDefault") if type(ourDefault) == bool and defaultValue is None: defaultValue=False - assert defaultValue == ourDefault, f"ERROR: nodeos's default for \"{nodeosOpt}\" is {nodeosCurDefault} and no longer matches {type(supportedPlugin)}'s default: {ourDefault} in \"{supportedPlugin._pluginName}\"." + assert defaultValue == ourDefault, f"ERROR: nodeos's default for \"{nodeosOpt}\" is {nodeosCurDefault} and no longer matches {type(supportedPlugin)}'s default: {ourDefault} in \"{supportedPlugin._pluginName}\". {regenSuggestion}" testSuccessful = True From 45c6376270747c7ce115b360959551ebd09d1599 Mon Sep 17 00:00:00 2001 From: jgiszczak Date: Wed, 7 Dec 2022 15:11:11 -0600 Subject: [PATCH 15/15] Fix typos and formatting. --- .../generate_nodeos_plugin_args_class_files.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py index c9f063d8cb..1c200d2481 100755 --- a/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py +++ b/tests/performance_tests/NodeosPluginArgs/generate_nodeos_plugin_args_class_files.py @@ -7,8 +7,8 @@ The purpose of this script is to attempt to generate *PluginArgs.py files, containing respective dataclass objects, to encapsulate the configurations options available for each plugin as currently documented in nodeos's --help command. -It currently makes use of the compiled nodeos program and runs the --help command, capturing the output. -It then parses the output, breaking down the presented configuration options by plugin section (ignoring applicaiton and test plugin config options). +It makes use of the compiled nodeos program and runs the --help command, capturing the output. +It then parses the output, breaking down the presented configuration options by plugin section (ignoring application and test plugin config options). This provides a rudimentary list of plugins supported, config options for each plugin, and attempts to acertain default values and types. The script then uses the parsed output to generate *PluginArgs.py scripts, placing them in the NodeosPluginArgs directory. @@ -29,11 +29,12 @@ 1) blocksDir: str=None --This is the field that will be populated when the dataclass is used by other scripts to configure nodeos 2) _blocksDirNodeosDefault: str='"blocks"' - --This field captures the default value in the nodeos output. This will be compared against the first field to see if the configuration option will be required on the command line to override the default value when running nodeos. + --This field captures the default value in the nodeos output. This will be compared against the first field to see if the configuration + option will be required on the command line to override the default value when running nodeos. 3) _blocksDirNodeosArg: str="--blocks-dir" --This field captures the command line config option for use when creating the command line string -The BasePluginArgs class provides implemenations for 2 useful functions for each of these classes: +The BasePluginArgs class provides implementations for 2 useful functions for each of these classes: 1) supportedNodeosArgs -- Provides a list of all the command line config options currently supported by the dataclass 2) __str__ @@ -41,7 +42,7 @@ (this only provides command line options where configured values differ from defaults) Some current limitations: -- There are some hardoded edge cases when trying to determine the types associated with certain default argument parameters. +- There are some hardcoded edge cases when trying to determine the types associated with certain default argument parameters. These may need to be updated to account for new/different options as they are added/removed/modified by nodeos Note: