Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PH] Use EOSMechanics contract with Performance Test #713

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions tests/TestHarness/Cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def __init__(self, walletd=False, localCluster=True, host="localhost", port=8888
defproduceraPrvtKey: Defproducera account private key
defproducerbPrvtKey: Defproducerb account private key
"""
self.accounts={}
self.accounts=[]
self.nodes=[]
self.unstartedNodes=[]
self.localCluster=localCluster
Expand Down Expand Up @@ -705,7 +705,9 @@ def createAccountKeys(count):

# create account keys and import into wallet. Wallet initialization will be user responsibility
# also imports defproducera and defproducerb accounts
def populateWallet(self, accountsCount, wallet, accountNames: list=None):
def populateWallet(self, accountsCount, wallet, accountNames: list=None, createProducerAccounts: bool=False):
if accountsCount == 0 and len(accountNames) == 0:
return True
if self.walletMgr is None:
Utils.Print("ERROR: WalletMgr hasn't been initialized.")
return False
Expand All @@ -718,15 +720,16 @@ def populateWallet(self, accountsCount, wallet, accountNames: list=None):
Utils.Print("Account keys creation failed.")
return False

Utils.Print("Importing keys for account %s into wallet %s." % (self.defproduceraAccount.name, wallet.name))
if not self.walletMgr.importKey(self.defproduceraAccount, wallet):
Utils.Print("ERROR: Failed to import key for account %s" % (self.defproduceraAccount.name))
return False
if createProducerAccounts:
Utils.Print("Importing keys for account %s into wallet %s." % (self.defproduceraAccount.name, wallet.name))
if not self.walletMgr.importKey(self.defproduceraAccount, wallet):
Utils.Print("ERROR: Failed to import key for account %s" % (self.defproduceraAccount.name))
return False

Utils.Print("Importing keys for account %s into wallet %s." % (self.defproducerbAccount.name, wallet.name))
if not self.walletMgr.importKey(self.defproducerbAccount, wallet):
Utils.Print("ERROR: Failed to import key for account %s" % (self.defproducerbAccount.name))
return False
Utils.Print("Importing keys for account %s into wallet %s." % (self.defproducerbAccount.name, wallet.name))
if not self.walletMgr.importKey(self.defproducerbAccount, wallet):
Utils.Print("ERROR: Failed to import key for account %s" % (self.defproducerbAccount.name))
return False

if accountNames is not None:
for idx, name in enumerate(accountNames):
Expand All @@ -737,8 +740,8 @@ def populateWallet(self, accountsCount, wallet, accountNames: list=None):
if not self.walletMgr.importKey(account, wallet):
Utils.Print("ERROR: Failed to import key for account %s" % (account.name))
return False
self.accounts.append(account)

self.accounts=accounts
return True

def getNodeP2pPort(self, nodeId: int):
Expand Down Expand Up @@ -1592,20 +1595,21 @@ def cleanup(self):
os.remove(f)

# Create accounts and validates that the last transaction is received on root node
def createAccounts(self, creator, waitForTransBlock=True, stakedDeposit=1000, validationNodeIndex=0):
def createAccounts(self, creator, nameList: list, waitForTransBlock=True, stakedDeposit=1000, validationNodeIndex=0):
if self.accounts is None:
return True

transId=None
for account in self.accounts:
if Utils.Debug: Utils.Print("Create account %s." % (account.name))
if Utils.Debug: Utils.Print("Validation node %s" % validationNodeIndex)
trans=self.createAccountAndVerify(account, creator, stakedDeposit, validationNodeIndex=validationNodeIndex)
if trans is None:
Utils.Print("ERROR: Failed to create account %s." % (account.name))
return False
if Utils.Debug: Utils.Print("Account %s created." % (account.name))
transId=Node.getTransId(trans)
ret = self.biosNode.getEosAccount(account.name)
if (len(nameList) == 0 and ret is None) or account.name in nameList:
if Utils.Debug: Utils.Print("Create account %s." % (account.name))
if Utils.Debug: Utils.Print("Validation node %s" % validationNodeIndex)
trans=self.createAccountAndVerify(account, creator, stakedDeposit, validationNodeIndex=validationNodeIndex)
if trans is None:
Utils.Print("ERROR: Failed to create account %s." % (account.name))
return False
if Utils.Debug: Utils.Print("Account %s created." % (account.name))
transId=Node.getTransId(trans)

if waitForTransBlock and transId is not None:
node=self.nodes[validationNodeIndex]
Expand Down
8 changes: 4 additions & 4 deletions tests/TestHarness/launch_transaction_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def launch(self, waitToComplete=True):
f'--actions-data {self.actionsData} '
f'--actions-auths {self.actionsAuths} '
f'--peer-endpoint {self.peerEndpoint} '
f'--port {self.port}'
f'--port {self.port} '
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
)
self.subprocess_ret_codes.append(
subprocess.Popen([
Expand All @@ -91,7 +91,7 @@ def launch(self, waitToComplete=True):
'--actions-data', f'{self.actionsData}',
'--actions-auths', f'{self.actionsAuths}',
'--peer-endpoint', f'{self.peerEndpoint}',
'--port', f'{self.port}'
'--port', f'{self.port}',
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
])
)
else:
Expand All @@ -108,7 +108,7 @@ def launch(self, waitToComplete=True):
f'--target-tps {targetTps} '
f'--log-dir {self.logDir} '
f'--peer-endpoint {self.peerEndpoint} '
f'--port {self.port}'
f'--port {self.port} '
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
)
self.subprocess_ret_codes.append(
subprocess.Popen([
Expand All @@ -123,7 +123,7 @@ def launch(self, waitToComplete=True):
'--target-tps', f'{targetTps}',
'--log-dir', f'{self.logDir}',
'--peer-endpoint', f'{self.peerEndpoint}',
'--port', f'{self.port}'
'--port', f'{self.port}',
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
])
)
exitCodes=None
Expand Down
4 changes: 3 additions & 1 deletion tests/performance_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ 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)
configure_file(cpuTrxData.json cpuTrxData.json COPYONLY)
configure_file(userTrxDataTransfer.json userTrxDataTransfer.json COPYONLY)
configure_file(userTrxDataNewAccount.json userTrxDataNewAccount.json COPYONLY)

add_test(NAME performance_test_basic COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 20 --tps-limit-per-generator 10 --test-duration-sec 5 --clean-run WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME performance_test_basic COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 20 --tps-limit-per-generator 10 --clean-run WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
add_test(NAME performance_test_basic_ex_transfer_trx_spec COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 20 --tps-limit-per-generator 10 --test-duration-sec 5 --clean-run --user-trx-data-file tests/performance_tests/userTrxDataTransfer.json WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME performance_test_basic_ex_new_acct_trx_spec COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 20 --tps-limit-per-generator 10 --test-duration-sec 5 --clean-run --user-trx-data-file tests/performance_tests/userTrxDataNewAccount.json WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME performance_test_basic_ex_cpu_trx_spec COMMAND tests/performance_tests/performance_test_basic.py -v -p 1 -n 1 --target-tps 20 --tps-limit-per-generator 10 --clean-run --user-trx-data-file tests/performance_tests/cpuTrxData.json WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
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)
Expand Down
16 changes: 16 additions & 0 deletions tests/performance_tests/cpuTrxData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"initAccounts": ["c"],
"abiFile": "unittests/contracts/eosio.mechanics/contracts/eosmechanics.abi",
"actions": [
{
"actionName": "cpu",
"actionData": {
},
"actionAuthAcct": "c",
"authorization": {
"actor": "c",
"permission": "active"
}
}
]
}
40 changes: 28 additions & 12 deletions tests/performance_tests/performance_test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class SpecifiedContract:
contractDir: str = "unittests/contracts/eosio.system"
wasmFile: str = "eosio.system.wasm"
abiFile: str = "eosio.system.abi"
account: Account = Account(accountName)
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved

pnodes: int = 1
totalNodes: int = 2
Expand Down Expand Up @@ -276,18 +277,30 @@ def launchCluster(self):
)

def setupWalletAndAccounts(self, accountCnt: int=2, accountNames: list=None):
self.wallet = self.walletMgr.create('default')
self.accountNames=[]
newAccountNames=[]
self.accountPrivKeys=[]
if accountNames is not None:
self.cluster.populateWallet(accountsCount=len(accountNames), wallet=self.wallet, accountNames=accountNames)
self.cluster.createAccounts(self.cluster.eosioAccount, stakedDeposit=0, validationNodeIndex=self.validationNodeId)
for index in range(0, len(accountNames)):
self.accountNames.append(self.cluster.accounts[index].name)
self.accountPrivKeys.append(self.cluster.accounts[index].activePrivateKey)
for name in accountNames:
if name == self.clusterConfig.specifiedContract.accountName:
self.cluster.accounts.append(self.clusterConfig.specifiedContract.account)
self.accountNames.append(self.clusterConfig.specifiedContract.account.name)
self.accountPrivKeys.append(self.clusterConfig.specifiedContract.account.ownerPrivateKey)
self.accountPrivKeys.append(self.clusterConfig.specifiedContract.account.activePrivateKey)
else:
ret = self.cluster.biosNode.getEosAccount(name)
if ret is None:
newAccountNames.append(name)
self.cluster.populateWallet(accountsCount=len(newAccountNames), wallet=self.wallet, accountNames=newAccountNames, createProducerAccounts=True)
self.cluster.createAccounts(self.cluster.eosioAccount, newAccountNames, stakedDeposit=0, validationNodeIndex=self.validationNodeId)
if len(newAccountNames) != 0:
for index in range(len(self.accountNames), len(accountNames)):
self.accountNames.append(self.cluster.accounts[index].name)
self.accountPrivKeys.append(self.cluster.accounts[index].activePrivateKey)
self.accountPrivKeys.append(self.cluster.accounts[index].ownerPrivateKey)
else:
self.cluster.populateWallet(accountsCount=accountCnt, wallet=self.wallet)
self.cluster.createAccounts(self.cluster.eosioAccount, stakedDeposit=0, validationNodeIndex=self.validationNodeId)
self.cluster.populateWallet(accountsCount=accountCnt, wallet=self.wallet, createProducerAccounts=True)
self.cluster.createAccounts(self.cluster.eosioAccount, newAccountNames, stakedDeposit=0, validationNodeIndex=self.validationNodeId)
for index in range(0, accountCnt):
self.accountNames.append(self.cluster.accounts[index].name)
self.accountPrivKeys.append(self.cluster.accounts[index].activePrivateKey)
Expand All @@ -297,17 +310,20 @@ def readUserTrxDataFromFile(self, userTrxDataFile: Path):
self.userTrxDataDict = json.load(f)

def setupContract(self):
if (self.clusterConfig.specifiedContract.accountName != self.cluster.eosioAccount.name):
if self.clusterConfig.specifiedContract.accountName != self.cluster.eosioAccount.name:
specifiedAccount = Account(self.clusterConfig.specifiedContract.accountName)
specifiedAccount.name = self.clusterConfig.specifiedContract.accountName
specifiedAccount.ownerPublicKey = self.clusterConfig.specifiedContract.ownerPublicKey
specifiedAccount.ownerPrivateKey = self.clusterConfig.specifiedContract.ownerPrivateKey
specifiedAccount.activePublicKey = self.clusterConfig.specifiedContract.activePublicKey
specifiedAccount.activePrivateKey = self.clusterConfig.specifiedContract.activePrivateKey
self.cluster.createAccountAndVerify(specifiedAccount, self.cluster.eosioAccount, validationNodeIndex=self.validationNodeId)
self.clusterConfig.specifiedContract.account = specifiedAccount
print("Publishing contract")
transaction=self.cluster.biosNode.publishContract(specifiedAccount, self.clusterConfig.specifiedContract.contractDir,
self.clusterConfig.specifiedContract.wasmFile,
self.clusterConfig.specifiedContract.abiFile, waitForTransBlock=True)

if transaction is None:
print("ERROR: Failed to publish contract.")
return None
Expand All @@ -327,6 +343,7 @@ def runTpsTest(self) -> PtbTpsTestResult:
self.producerNode = self.cluster.getNode(self.producerNodeId)
self.producerP2pPort = self.cluster.getNodeP2pPort(self.producerNodeId)
self.validationNode = self.cluster.getNode(self.validationNodeId)
self.wallet = self.walletMgr.create('default')
self.setupContract()
info = self.producerNode.getInfo()
chainId = info['chain_id']
Expand All @@ -344,7 +361,6 @@ def runTpsTest(self) -> PtbTpsTestResult:
print(f"Creating accounts specified in userTrxData: {self.userTrxDataDict['initAccounts']}")
self.setupWalletAndAccounts(accountCnt=len(self.userTrxDataDict['initAccounts']), accountNames=self.userTrxDataDict['initAccounts'])
abiFile = self.userTrxDataDict['abiFile']

actionsDataJson = json.dumps(self.userTrxDataDict['actions'])

authorizations={}
Expand All @@ -369,13 +385,11 @@ def runTpsTest(self) -> PtbTpsTestResult:

self.data.startBlock = self.waitForEmptyBlocks(self.validationNode, self.emptyBlockGoal)
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=self.ptbConfig.targetTps, tpsLimitPerGenerator=self.ptbConfig.tpsLimitPerGenerator)

trxGenLauncher = TransactionGeneratorsLauncher(chainId=chainId, lastIrreversibleBlockId=lib_id, contractOwnerAccount=self.clusterConfig.specifiedContract.accountName,
accts=','.join(map(str, self.accountNames)), privateKeys=','.join(map(str, self.accountPrivKeys)),
trxGenDurationSec=self.ptbConfig.testTrxGenDurationSec, logDir=self.trxGenLogDirPath,
abiFile=abiFile, actionsData=actionsDataJson, actionsAuths=actionsAuthsJson,
peerEndpoint=self.producerNode.host, port=self.producerP2pPort, tpsTrxGensConfig=tpsTrxGensConfig)

trxGenExitCodes = trxGenLauncher.launch()
print(f"Transaction Generator exit codes: {trxGenExitCodes}")
for exitCode in trxGenExitCodes:
Expand Down Expand Up @@ -436,6 +450,8 @@ def analyzeResultsAndReport(self, testResult: PtbTpsTestResult):
completedRun=testResult.completedRun)

jsonReport = None
self.ptbConfig.quiet = True
self.ptbConfig.delReport = True
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
if not self.ptbConfig.quiet or not self.ptbConfig.delReport:
jsonReport = log_reader.reportAsJSON(self.report)

Expand Down
4 changes: 2 additions & 2 deletions tests/trx_generator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ int main(int argc, char** argv) {

if(vmap.count("accounts")) {
boost::split(account_str_vector, accts, boost::is_any_of(","));
if(!transaction_specified && account_str_vector.size() < 2) {
ilog("Initialization error: requires at minimum 2 transfer accounts");
if(account_str_vector.size() < 1) {
ilog("Initialization error: requires at minimum 1 account");
oschwaldp-oci marked this conversation as resolved.
Show resolved Hide resolved
cli.print(std::cerr);
return INITIALIZE_FAIL;
}
Expand Down
1 change: 1 addition & 0 deletions unittests/contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ add_subdirectory(eosio.msig)
add_subdirectory(eosio.system)
add_subdirectory(eosio.token)
add_subdirectory(eosio.wrap)
add_subdirectory(eosio.mechanics)
1 change: 1 addition & 0 deletions unittests/contracts/eosio.mechanics/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/contracts/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/contracts/)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should do the same thing as the other CMakeLists.txt of eosio.wrap and eosio.token etc

21 changes: 21 additions & 0 deletions unittests/contracts/eosio.mechanics/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We likely want to submodule this in instead of copying it.
Not sure if we need to copy this license file out with other license files.
Thoughts on best way to use this? @arhag @spoonincode @wanderingbort

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo, since we don't distribute the file any further than the builddir (that is, we neither include it in a package nor as part of make install), we probably don't need to do anything with the license besides just ensure it's there next to the source file(s) it pertains to. As you've done.

As far as submodule vs not, I'm unsure. It does feel like a submodule might be more proper but then again it feels awfully heavy for something like this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as submodule vs not, I'm unsure. It does feel like a submodule might be more proper but then again it feels awfully heavy for something like this.

@ClaytonCalabrese said he had to make minor modifications to it to work with our cmake setup. Probably the best course is to just copy it in as this PR has it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yeah, if we've modified it that's probably best


Copyright (c) 2018 Aloha EOS

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading