-
Notifications
You must be signed in to change notification settings - Fork 21
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
#86drpnck9 - Refactor example_tests/test_update_contract.py to use Bo… #1229
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,96 @@ | ||
import json | ||
|
||
from boa3_test.tests.boa_test import BoaTest # needs to be the first import to avoid circular imports | ||
from neo3.contracts.contract import CONTRACT_HASHES | ||
from neo3.wallet import account | ||
|
||
from boa3.internal import constants | ||
from boa3.internal.neo.vm.type.String import String | ||
from boa3.internal.neo3.vm import VMState | ||
from boa3_test.tests.test_drive import neoxp | ||
from boa3_test.tests.test_drive.testrunner.boa_test_runner import BoaTestRunner | ||
from boa3_test.tests import boatestcase | ||
from boa3_test.tests.event import UpdateEvent | ||
|
||
|
||
class TestUpdateContractTemplate(BoaTest): | ||
class TestUpdateContractTemplate(boatestcase.BoaTestCase): | ||
default_folder: str = 'examples' | ||
|
||
OWNER = neoxp.utils.get_account_by_name('owner') | ||
OTHER_ACCOUNT = neoxp.utils.get_account_by_name('testAccount1') | ||
owner: account.Account | ||
other_account: account.Account | ||
|
||
GAS_TO_DEPLOY = 1000 * 10 ** 8 | ||
|
||
def test_update_contract_compile(self): | ||
path = self.get_contract_path('update_contract.py') | ||
path_new = self.get_contract_path('examples/auxiliary_contracts', 'update_contract.py') | ||
self.compile(path) | ||
self.compile(path_new) | ||
@classmethod | ||
def setupTestCase(cls): | ||
cls.owner = cls.node.wallet.account_new(label='owner', password='123') | ||
cls.other_account = cls.node.wallet.account_new(label='otherAccount', password='123') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
|
||
def test_update_contract(self): | ||
path, _ = self.get_deploy_file_paths('update_contract.py') | ||
runner = BoaTestRunner(runner_id=self.method_name()) | ||
super().setupTestCase() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
invokes = [] | ||
expected_results = [] | ||
@classmethod | ||
async def asyncSetupClass(cls) -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
await super().asyncSetupClass() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
|
||
test_account = self.OTHER_ACCOUNT | ||
test_account_script_hash = test_account.script_hash.to_array() | ||
await cls.transfer(CONTRACT_HASHES.GAS_TOKEN, cls.genesis.script_hash, cls.owner.script_hash, 100) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
await cls.transfer(CONTRACT_HASHES.GAS_TOKEN, cls.genesis.script_hash, cls.other_account.script_hash, 100) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
|
||
runner.add_gas(self.OWNER.address, self.GAS_TO_DEPLOY) | ||
update_contract = runner.deploy_contract(path, account=self.OWNER) | ||
runner.update_contracts(export_checkpoint=True) | ||
await cls.set_up_contract('update_contract.py', signing_account=cls.owner) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please consider using a more descriptive name for the variable |
||
tx_deploy_notifications = runner.get_transaction_result(update_contract.tx_id).executions[0].notifications | ||
# Transfer emitted when deploying the smart contract | ||
self.assertEqual(2, len(tx_deploy_notifications)) | ||
self.assertEqual(1, len([notification | ||
for notification in tx_deploy_notifications if notification.name == 'Transfer'])) | ||
self.assertEqual(1, len([notification | ||
for notification in tx_deploy_notifications if notification.name == 'Deploy'])) | ||
def test_update_contract_compile(self): | ||
self.assertCompile('update_contract.py') | ||
self.assertCompile('update_contract.py', root_folder='examples/auxiliary_contracts') | ||
|
||
async def test_update_contract(self): | ||
# Saving user's balance before calling method to compare it later | ||
tokens_before = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
# The bugged method is being called and the user is able to receive tokens for free | ||
invokes.append(runner.call_contract(path, 'method', test_account_script_hash)) | ||
expected_results.append(None) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.other_account]) | ||
self.assertIsNone(result) | ||
|
||
tokens_after = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
runner.execute() | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(1, len(transfer_events)) | ||
|
||
# The amount of tokens will be higher after calling the method | ||
self.assertGreater(tokens_after.result, tokens_before.result) | ||
|
||
transfer_events = runner.get_events('Transfer', origin=update_contract) | ||
self.assertEqual(1, len(transfer_events)) | ||
self.assertGreater(tokens_after, tokens_before) | ||
|
||
# new smart contract that has the bug fixed | ||
path_new = self.get_contract_path('examples/auxiliary_contracts', 'update_contract.py') | ||
new_nef, new_manifest = self.get_bytes_output(path_new) | ||
new_nef, new_manifest = self.get_serialized_output(path_new) | ||
|
||
arg_manifest = String(json.dumps(new_manifest, separators=(',', ':'))).to_bytes() | ||
|
||
# The smart contract will be updated to fix the bug in the method | ||
invokes.append(runner.call_contract(path, 'update_sc', new_nef, arg_manifest, None)) | ||
expected_results.append(None) | ||
|
||
runner.execute(account=self.OWNER) | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
result, notifications = await self.call('update_sc', [new_nef, arg_manifest, None], return_type=None, signing_accounts=[self.owner]) | ||
self.assertIsNone(result) | ||
|
||
# An `Update` event was be emitted after the update | ||
event_update = runner.get_events('Update') | ||
self.assertEqual(1, len(event_update)) | ||
|
||
runner.run_contract(path, 'update_sc', new_nef, arg_manifest, None, account=self.OWNER) | ||
update_events = self.filter_events(notifications, notification_type=UpdateEvent) | ||
self.assertEqual(1, len(update_events)) | ||
|
||
# Saving user's balance before calling method to compare it later | ||
tokens_before = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
# Now, when method is called, it won't mint new tokens to any user that called it | ||
invokes.append(runner.call_contract(path, 'method', test_account_script_hash)) | ||
expected_results.append(None) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.other_account]) | ||
self.assertIsNone(result) | ||
|
||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(0, len(transfer_events)) | ||
|
||
# The amount of tokens now is the same before and after calling the method | ||
tokens_after = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
self.assertEqual(tokens_after, tokens_before) | ||
|
||
runner.get_contract(constants.NEO_SCRIPT) | ||
# If the signing account is the owner, then the method works, and it will mint the new tokens | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
runner.execute(account=test_account) | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.owner]) | ||
self.assertIsNone(result) | ||
|
||
self.assertEqual(tokens_after.result, tokens_before.result) | ||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(1, len(transfer_events)) | ||
|
||
# The amount of tokens will be higher after calling the method | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
for x in range(len(invokes)): | ||
self.assertEqual(expected_results[x], invokes[x].result) | ||
self.assertGreater(tokens_after, tokens_before) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider using a more descriptive name for the variable
cls
. It would improve code readability.