Skip to content

Commit

Permalink
🔨 Refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nagdahimanshu committed May 31, 2024
1 parent 008339f commit f3e60c2
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 787 deletions.
2 changes: 1 addition & 1 deletion PLUGIN_SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Smart contracts covered by this plugin are:
| Lisk Mainnet | - | TokenClaim | `0xD7BE2Fd98BfD64c1dfCf6c013fC593eF09219994` |
| Lisk Mainnet | - | Reward | `0xD35ca9577a9DADa7624a35EC10C2F55031f0Ab1f` |
| Lisk Mainnet | - | Airdrop | `TODO` |
| Lisk Mainnet | - | Governor | `0x58a61b1807a7bDA541855DaAEAEe89b1DDA48568TODO` |
| Lisk Mainnet | - | Governor | `0x58a61b1807a7bDA541855DaAEAEe89b1DDA48568` |


## Functions
Expand Down
11 changes: 2 additions & 9 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
# Tests

This directory contains non-regression tests for the Boilerplate plugin.
This directory contains non-regression tests for the Lisk App Plugin.
The tests craft APDUs, send them to the application, and assert the RAPDUs results and the screen content.
You will need to adapt / enrich the test database with tests relevant to your plugin.
The presence of functional testing of your plugin and an associated CI is mandatory.

The [Speculos](https://github.com/LedgerHQ/speculos) tool is used to emulate the device and its applications.
The [Ragger](https://github.com/LedgerHQ/ragger) test framework (pytest based) is used to manage the Speculos instance and provide useful helper functions (APDU exchanges, screen navigation, etc).
Both framework are developed by Ledger, if you have trouble using them, we invite you to get in touch with us on our [Discord](https://developers.ledger.com/contact/).
For this reason, the usage of the Ragger framework for your tests is greatly recommended.


## Binaries

Expand All @@ -28,12 +23,10 @@ Example of the correct file tree with Ethereum compiled for all targets.
The first method is to use the Ledger VSCode extension to automatically manage dependencies
The second method is to go in the Ethereum project, compile the application, and dispatch the `build/` output directory.
A third method is to re-use the Ethereum build used in the CI, and available as artifact.
For example in the [plugin-boilerplate CI](https://github.com/LedgerHQ/app-plugin-boilerplate/actions/workflows/build_and_functional_tests.yml).


## Launching the tests

The plugin boilerplate app comes with functional tests
The Lisk App Plugin comes with functional tests


### macOS / Windows
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
73 changes: 6 additions & 67 deletions tests/test_airdrop.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,12 @@
from pathlib import Path
import json
import os
import datetime

from hexbytes import HexBytes

from web3 import Web3
from eth_typing import ChainId

from ledger_app_clients.ethereum.client import EthAppClient
import ledger_app_clients.ethereum.response_parser as ResponseParser
from ledger_app_clients.ethereum.utils import get_selector_from_data, recover_transaction
from ragger.navigator import NavInsID

from .utils import get_appname_from_makefile, DERIVATION_PATH

from .utils import run_test, load_contract

ROOT_SCREENSHOT_PATH = Path(__file__).parent
ABIS_FOLDER = "%s/abis" % (os.path.dirname(__file__))

PLUGIN_NAME = get_appname_from_makefile()

# TODO: Update address with abi
with open("%s/0x9fA3CA453EbfB7a6d1085153D83a2988eE822BD0.abi.json" % (ABIS_FOLDER)) as file:
contract = Web3().eth.contract(
abi=json.load(file),
# Get address from filename
address=bytes.fromhex(os.path.basename(file.name).split(".")[0].split("x")[-1])
)
contract = load_contract(
"9fA3CA453EbfB7a6d1085153D83a2988eE822BD0",
"airdrop"
)

def test_claim_airdrop(backend, firmware, navigator, test_name, wallet_addr):
client = EthAppClient(backend)

data = contract.encodeABI("claimAirdrop", [
bytes.fromhex("77abc2dd8ca5021dbb8e91e63f574b1e440764d2"),
4915507196,
Expand All @@ -40,40 +15,4 @@ def test_claim_airdrop(backend, firmware, navigator, test_name, wallet_addr):
]
])

# first setup the external plugin
client.set_external_plugin(PLUGIN_NAME,
contract.address,
# Extract function selector from the encoded data
get_selector_from_data(data))

tx_params = {
"nonce": 20,
"maxFeePerGas": Web3.to_wei(145, "gwei"),
"maxPriorityFeePerGas": Web3.to_wei(1.5, "gwei"),
"gas": 173290,
"to": contract.address,
"value": Web3.to_wei(0.1, "ether"),
"chainId": ChainId.ETH,
"data": data
}

# send the transaction
with client.sign(DERIVATION_PATH, tx_params):
# Validate the on-screen request by performing the navigation appropriate for this device
if firmware.device.startswith("nano"):
navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK,
[NavInsID.BOTH_CLICK],
"Accept",
ROOT_SCREENSHOT_PATH,
test_name)
else:
navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
[NavInsID.USE_CASE_REVIEW_CONFIRM,
NavInsID.USE_CASE_STATUS_DISMISS],
"Hold to sign",
ROOT_SCREENSHOT_PATH,
test_name)
# verify signature
vrs = ResponseParser.signature(client.response().data)
addr = recover_transaction(tx_params, vrs)
assert addr == wallet_addr.get()
run_test(contract, data, backend, firmware, navigator, test_name, wallet_addr)
113 changes: 7 additions & 106 deletions tests/test_claim.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,12 @@
from pathlib import Path
import json
import os
import datetime

from hexbytes import HexBytes

from web3 import Web3
from eth_typing import ChainId

from ledger_app_clients.ethereum.client import EthAppClient
import ledger_app_clients.ethereum.response_parser as ResponseParser
from ledger_app_clients.ethereum.utils import get_selector_from_data, recover_transaction
from ragger.navigator import NavInsID

from .utils import get_appname_from_makefile, DERIVATION_PATH


ROOT_SCREENSHOT_PATH = Path(__file__).parent
ABIS_FOLDER = "%s/abis" % (os.path.dirname(__file__))

PLUGIN_NAME = get_appname_from_makefile()
from .utils import run_test, load_contract


with open("%s/0xD7BE2Fd98BfD64c1dfCf6c013fC593eF09219994.abi.json" % (ABIS_FOLDER)) as file:
contract = Web3().eth.contract(
abi=json.load(file),
# Get address from filename
address=bytes.fromhex(os.path.basename(file.name).split(".")[0].split("x")[-1])
)
contract = load_contract(
"D7BE2Fd98BfD64c1dfCf6c013fC593eF09219994",
"claim"
)

def test_claim_regular_account(backend, firmware, navigator, test_name, wallet_addr):
client = EthAppClient(backend)

data = contract.encodeABI("claimRegularAccount", [
[
bytes.fromhex("9ca797d905e78f38685b61f62521632ef486bc6ce3e707d2af41b7fe146303c1"),
Expand All @@ -50,47 +25,9 @@ def test_claim_regular_account(backend, firmware, navigator, test_name, wallet_a
)
])

# first setup the external plugin
client.set_external_plugin(PLUGIN_NAME,
contract.address,
# Extract function selector from the encoded data
get_selector_from_data(data))

tx_params = {
"nonce": 20,
"maxFeePerGas": Web3.to_wei(145, "gwei"),
"maxPriorityFeePerGas": Web3.to_wei(1.5, "gwei"),
"gas": 173290,
"to": contract.address,
"value": Web3.to_wei(0.1, "ether"),
"chainId": ChainId.ETH,
"data": data
}

# send the transaction
with client.sign(DERIVATION_PATH, tx_params):
# Validate the on-screen request by performing the navigation appropriate for this device
if firmware.device.startswith("nano"):
navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK,
[NavInsID.BOTH_CLICK],
"Accept",
ROOT_SCREENSHOT_PATH,
test_name)
else:
navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
[NavInsID.USE_CASE_REVIEW_CONFIRM,
NavInsID.USE_CASE_STATUS_DISMISS],
"Hold to sign",
ROOT_SCREENSHOT_PATH,
test_name)
# verify signature
vrs = ResponseParser.signature(client.response().data)
addr = recover_transaction(tx_params, vrs)
assert addr == wallet_addr.get()
run_test(contract, data, backend, firmware, navigator, test_name, wallet_addr)

def test_claim_multisig_account(backend, firmware, navigator, test_name, wallet_addr):
client = EthAppClient(backend)

data = contract.encodeABI("claimMultisigAccount", [
[
bytes.fromhex("f90c3db9f834e9a33086969313a1f5aa2288933e69a065cb829ab7524f113340"),
Expand All @@ -116,40 +53,4 @@ def test_claim_multisig_account(backend, firmware, navigator, test_name, wallet_
]
])

# first setup the external plugin
client.set_external_plugin(PLUGIN_NAME,
contract.address,
# Extract function selector from the encoded data
get_selector_from_data(data))

tx_params = {
"nonce": 20,
"maxFeePerGas": Web3.to_wei(145, "gwei"),
"maxPriorityFeePerGas": Web3.to_wei(1.5, "gwei"),
"gas": 173290,
"to": contract.address,
"value": Web3.to_wei(0.1, "ether"),
"chainId": ChainId.ETH,
"data": data
}

# send the transaction
with client.sign(DERIVATION_PATH, tx_params):
# Validate the on-screen request by performing the navigation appropriate for this device
if firmware.device.startswith("nano"):
navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK,
[NavInsID.BOTH_CLICK],
"Accept",
ROOT_SCREENSHOT_PATH,
test_name)
else:
navigator.navigate_until_text_and_compare(NavInsID.USE_CASE_REVIEW_TAP,
[NavInsID.USE_CASE_REVIEW_CONFIRM,
NavInsID.USE_CASE_STATUS_DISMISS],
"Hold to sign",
ROOT_SCREENSHOT_PATH,
test_name)
# verify signature
vrs = ResponseParser.signature(client.response().data)
addr = recover_transaction(tx_params, vrs)
assert addr == wallet_addr.get()
run_test(contract, data, backend, firmware, navigator, test_name, wallet_addr)
Loading

0 comments on commit f3e60c2

Please sign in to comment.