test_: run functional tests on host (no container) (#6159)
* test_: run on host
This commit is contained in:
parent
ef177c1c63
commit
1795620df0
|
@ -30,6 +30,7 @@ LABEL source="https://github.com/status-im/status-go"
|
|||
LABEL description="status-go is an underlying part of Status - a browser, messenger, and gateway to a decentralized world."
|
||||
|
||||
RUN apk add --no-cache ca-certificates bash libgcc libstdc++ curl
|
||||
RUN mkdir -p /usr/status-user && chmod -R 777 /usr/status-user
|
||||
RUN mkdir -p /static/keys
|
||||
RUN mkdir -p /static/configs
|
||||
|
||||
|
|
|
@ -26,15 +26,35 @@ mkdir -p "${test_results_path}"
|
|||
all_compose_files="-f ${root_path}/docker-compose.anvil.yml -f ${root_path}/docker-compose.test.status-go.yml"
|
||||
project_name="status-go-func-tests-$(date +%s)"
|
||||
|
||||
export STATUS_BACKEND_COUNT=10
|
||||
export STATUS_BACKEND_URLS=$(eval echo http://${project_name}-status-backend-{1..${STATUS_BACKEND_COUNT}}:3333 | tr ' ' ,)
|
||||
|
||||
# Run functional tests
|
||||
echo -e "${GRN}Running tests${RST}, HEAD: $(git rev-parse HEAD)"
|
||||
docker compose -p ${project_name} ${all_compose_files} up -d --build --scale status-backend=${STATUS_BACKEND_COUNT} --remove-orphans
|
||||
# Remove orphans
|
||||
docker ps -a --filter "name=status-go-func-tests-*-status-backend-*" --filter "status=exited" -q | xargs -r docker rm
|
||||
|
||||
echo -e "${GRN}Running tests-rpc${RST}" # Follow the logs, wait for them to finish
|
||||
docker compose -p ${project_name} ${all_compose_files} logs -f tests-rpc > "${root_path}/tests-rpc.log"
|
||||
# Run docker
|
||||
echo -e "${GRN}Running tests${RST}, HEAD: $(git rev-parse HEAD)"
|
||||
docker compose -p ${project_name} ${all_compose_files} up -d --build --remove-orphans
|
||||
|
||||
# Set up virtual environment
|
||||
venv_path="${root_path}/.venv"
|
||||
|
||||
if [[ -d "${venv_path}" ]]; then
|
||||
echo -e "${GRN}Using existing virtual environment${RST}"
|
||||
else
|
||||
echo -e "${GRN}Creating new virtual environment${RST}"
|
||||
python3 -m venv "${venv_path}"
|
||||
fi
|
||||
|
||||
source "${venv_path}/bin/activate"
|
||||
|
||||
# Upgrade pip and install requirements
|
||||
echo -e "${GRN}Installing dependencies${RST}"
|
||||
pip install --upgrade pip
|
||||
pip install -r "${root_path}/requirements.txt"
|
||||
|
||||
# Run functional tests
|
||||
pytest -m rpc --docker_project_name=${project_name} --codecov_dir=${binary_coverage_reports_path} --junitxml=${test_results_path}/report.xml
|
||||
exit_code=$?
|
||||
|
||||
# Stop containers
|
||||
echo -e "${GRN}Stopping docker containers${RST}"
|
||||
|
@ -45,9 +65,6 @@ echo -e "${GRN}Saving logs${RST}"
|
|||
docker compose -p ${project_name} ${all_compose_files} logs status-go > "${root_path}/statusd.log"
|
||||
docker compose -p ${project_name} ${all_compose_files} logs status-backend > "${root_path}/status-backend.log"
|
||||
|
||||
# Retrieve exit code
|
||||
exit_code=$(docker inspect ${project_name}-tests-rpc-1 -f '{{.State.ExitCode}}');
|
||||
|
||||
# Cleanup containers
|
||||
echo -e "${GRN}Removing docker containers${RST}"
|
||||
docker compose -p ${project_name} ${all_compose_files} down
|
||||
|
|
|
@ -25,12 +25,13 @@ Functional tests for status-go
|
|||
* Status-im contracts will be deployed to the network
|
||||
|
||||
### Run tests
|
||||
- In `./tests-functional` run `docker compose -f docker-compose.anvil.yml -f docker-compose.test.status-go.yml -f docker-compose.status-go.local.yml up --build --scale status-backend=10 --remove-orphans`, as result:
|
||||
* a container with [status-go as daemon](https://github.com/status-im/status-go/issues/5175) will be created with APIModules exposed on `0.0.0.0:3333`
|
||||
- In `./tests-functional` run `docker compose -f docker-compose.anvil.yml -f docker-compose.test.status-go.yml -f docker-compose.status-go.local.yml up --build --remove-orphans`, as result:
|
||||
* a container with [status-backend](https://github.com/status-im/status-go/pull/5847) will be created with endpoint exposed on `0.0.0.0:3333`
|
||||
* status-go will use [anvil](https://book.getfoundry.sh/reference/anvil/) as RPCURL with ChainID 31337
|
||||
* all Status-im contracts will be deployed to the network
|
||||
* Status-im contracts will be deployed to the network
|
||||
|
||||
* In `./tests-functional/tests` directory run `pytest -m wallet`
|
||||
* In `./tests-functional/tests` directory run `pytest -m rpc`
|
||||
* To run tests against binary run `pytest -m <your mark> --url=http:<binary_url>:<binary_port> --user_dir=/<path>`
|
||||
|
||||
## Implementation details
|
||||
|
||||
|
|
|
@ -4,23 +4,31 @@ import time
|
|||
import random
|
||||
import threading
|
||||
import requests
|
||||
from tenacity import retry, stop_after_delay, wait_fixed
|
||||
import docker
|
||||
import os
|
||||
|
||||
from tenacity import retry, stop_after_delay, wait_fixed
|
||||
from clients.signals import SignalClient
|
||||
from clients.rpc import RpcClient
|
||||
from datetime import datetime
|
||||
from conftest import option
|
||||
from constants import user_1, DEFAULT_DISPLAY_NAME
|
||||
from constants import user_1, DEFAULT_DISPLAY_NAME, USER_DIR
|
||||
|
||||
|
||||
class StatusBackend(RpcClient, SignalClient):
|
||||
|
||||
def __init__(self, await_signals=[], url=None):
|
||||
try:
|
||||
url = url if url else random.choice(option.status_backend_urls)
|
||||
except IndexError:
|
||||
raise Exception("Not enough status-backend containers, please add more")
|
||||
option.status_backend_urls.remove(url)
|
||||
def __init__(self, await_signals=[]):
|
||||
|
||||
if option.status_backend_url:
|
||||
url = option.status_backend_url
|
||||
else:
|
||||
self.docker_client = docker.from_env()
|
||||
host_port = random.choice(option.status_backend_port_range)
|
||||
|
||||
self.container = self._start_container(host_port)
|
||||
url = f"http://127.0.0.1:{host_port}"
|
||||
option.status_backend_port_range.remove(host_port)
|
||||
|
||||
|
||||
self.api_url = f"{url}/statusgo"
|
||||
self.ws_url = f"{url}".replace("http", "ws")
|
||||
|
@ -29,14 +37,70 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
RpcClient.__init__(self, self.rpc_url)
|
||||
SignalClient.__init__(self, self.ws_url, await_signals)
|
||||
|
||||
self._health_check()
|
||||
|
||||
websocket_thread = threading.Thread(target=self._connect)
|
||||
websocket_thread.daemon = True
|
||||
websocket_thread.start()
|
||||
|
||||
def _start_container(self, host_port):
|
||||
docker_project_name = option.docker_project_name
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||||
image_name = f"{docker_project_name}-status-backend:latest"
|
||||
container_name = f"{docker_project_name}-status-backend-{timestamp}"
|
||||
|
||||
coverage_path = option.codecov_dir if option.codecov_dir else os.path.abspath("./coverage/binary")
|
||||
|
||||
container_args = {
|
||||
"image": image_name,
|
||||
"detach": True,
|
||||
"name": container_name,
|
||||
"labels": {"com.docker.compose.project": docker_project_name},
|
||||
"entrypoint": [
|
||||
"status-backend",
|
||||
"--address", "0.0.0.0:3333",
|
||||
],
|
||||
"ports": {"3333/tcp": host_port},
|
||||
"environment": {
|
||||
"GOCOVERDIR": "/coverage/binary",
|
||||
},
|
||||
"volumes": {
|
||||
coverage_path: {
|
||||
"bind": "/coverage/binary",
|
||||
"mode": "rw",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if "FUNCTIONAL_TESTS_DOCKER_UID" in os.environ:
|
||||
container_args["user"] = os.environ["FUNCTIONAL_TESTS_DOCKER_UID"]
|
||||
|
||||
container = self.docker_client.containers.run(**container_args)
|
||||
|
||||
network = self.docker_client.networks.get(
|
||||
f"{docker_project_name}_default")
|
||||
network.connect(container)
|
||||
|
||||
option.status_backend_containers.append(container.id)
|
||||
return container
|
||||
|
||||
def _health_check(self):
|
||||
start_time = time.time()
|
||||
while True:
|
||||
try:
|
||||
self.api_valid_request(method="Fleets", data=[])
|
||||
break
|
||||
except Exception as e:
|
||||
if time.time() - start_time > 20:
|
||||
raise Exception(e)
|
||||
time.sleep(1)
|
||||
|
||||
def api_request(self, method, data, url=None):
|
||||
url = url if url else self.api_url
|
||||
url = f"{url}/{method}"
|
||||
logging.info(f"Sending POST request to url {url} with data: {json.dumps(data, sort_keys=True, indent=4)}")
|
||||
logging.info(
|
||||
f"Sending POST request to url {url} with data: {json.dumps(data, sort_keys=True, indent=4)}")
|
||||
response = requests.post(url, json=data)
|
||||
logging.info(f"Got response: {response.content}")
|
||||
return response
|
||||
|
@ -46,7 +110,8 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
assert response.content
|
||||
logging.info(f"Got response: {response.content}")
|
||||
try:
|
||||
assert not response.json()["error"]
|
||||
error = response.json()["error"]
|
||||
assert not error, f"Error: {error}"
|
||||
except json.JSONDecodeError:
|
||||
raise AssertionError(
|
||||
f"Invalid JSON in response: {response.content}")
|
||||
|
@ -58,7 +123,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
self.verify_is_valid_api_response(response)
|
||||
return response
|
||||
|
||||
def init_status_backend(self, data_dir="/"):
|
||||
def init_status_backend(self, data_dir=USER_DIR):
|
||||
method = "InitializeApplication"
|
||||
data = {
|
||||
"dataDir": data_dir,
|
||||
|
@ -68,7 +133,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
}
|
||||
return self.api_valid_request(method, data)
|
||||
|
||||
def create_account_and_login(self, data_dir="/", display_name=DEFAULT_DISPLAY_NAME, password=user_1.password):
|
||||
def create_account_and_login(self, data_dir=USER_DIR, display_name=DEFAULT_DISPLAY_NAME, password=user_1.password):
|
||||
method = "CreateAccountAndLogin"
|
||||
data = {
|
||||
"rootDataDir": data_dir,
|
||||
|
@ -81,7 +146,7 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
}
|
||||
return self.api_valid_request(method, data)
|
||||
|
||||
def restore_account_and_login(self, data_dir="/",display_name=DEFAULT_DISPLAY_NAME, user=user_1,
|
||||
def restore_account_and_login(self, data_dir=USER_DIR, display_name=DEFAULT_DISPLAY_NAME, user=user_1,
|
||||
network_id=31337):
|
||||
method = "RestoreAccountAndLogin"
|
||||
data = {
|
||||
|
@ -136,7 +201,8 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
return
|
||||
except AssertionError:
|
||||
time.sleep(3)
|
||||
raise TimeoutError(f"RPC client was not started after {timeout} seconds")
|
||||
raise TimeoutError(
|
||||
f"RPC client was not started after {timeout} seconds")
|
||||
|
||||
@retry(stop=stop_after_delay(10), wait=wait_fixed(0.5), reraise=True)
|
||||
def start_messenger(self, params=[]):
|
||||
|
@ -173,7 +239,8 @@ class StatusBackend(RpcClient, SignalClient):
|
|||
for account in accounts:
|
||||
if account.get("name") == display_name:
|
||||
return account.get("public-key")
|
||||
raise ValueError(f"Public key not found for display name: {display_name}")
|
||||
raise ValueError(
|
||||
f"Public key not found for display name: {display_name}")
|
||||
|
||||
def send_contact_request(self, params=[]):
|
||||
method = "wakuext_sendContactRequest"
|
||||
|
|
|
@ -1,32 +1,16 @@
|
|||
import os
|
||||
import threading
|
||||
from dataclasses import dataclass
|
||||
|
||||
import docker
|
||||
import pytest as pytest
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--rpc_url_statusd",
|
||||
"--status_backend_url",
|
||||
action="store",
|
||||
help="",
|
||||
default="http://0.0.0.0:3333",
|
||||
)
|
||||
parser.addoption(
|
||||
"--ws_url_statusd",
|
||||
action="store",
|
||||
help="",
|
||||
default="ws://0.0.0.0:8354",
|
||||
)
|
||||
parser.addoption(
|
||||
"--status_backend_urls",
|
||||
action="store",
|
||||
help="",
|
||||
default=[
|
||||
f"http://0.0.0.0:{3314 + i}" for i in range(
|
||||
int(os.getenv("STATUS_BACKEND_COUNT", 10))
|
||||
)
|
||||
],
|
||||
default=None,
|
||||
)
|
||||
parser.addoption(
|
||||
"--anvil_url",
|
||||
|
@ -40,6 +24,24 @@ def pytest_addoption(parser):
|
|||
help="",
|
||||
default="Strong12345",
|
||||
)
|
||||
parser.addoption(
|
||||
"--docker_project_name",
|
||||
action="store",
|
||||
help="",
|
||||
default="tests-functional",
|
||||
)
|
||||
parser.addoption(
|
||||
"--codecov_dir",
|
||||
action="store",
|
||||
help="",
|
||||
default=None,
|
||||
)
|
||||
parser.addoption(
|
||||
"--user_dir",
|
||||
action="store",
|
||||
help="",
|
||||
default=None,
|
||||
)
|
||||
|
||||
@dataclass
|
||||
class Option:
|
||||
|
@ -52,6 +54,24 @@ option = Option()
|
|||
def pytest_configure(config):
|
||||
global option
|
||||
option = config.option
|
||||
if type(option.status_backend_urls) is str:
|
||||
option.status_backend_urls = option.status_backend_urls.split(",")
|
||||
|
||||
executor_number = int(os.getenv('EXECUTOR_NUMBER', 5))
|
||||
base_port = 7000
|
||||
range_size = 100
|
||||
|
||||
start_port = base_port + (executor_number * range_size)
|
||||
|
||||
option.status_backend_port_range = list(range(start_port, start_port + range_size - 1))
|
||||
option.status_backend_containers = []
|
||||
|
||||
option.base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def pytest_unconfigure():
|
||||
docker_client = docker.from_env()
|
||||
for container_id in option.status_backend_containers:
|
||||
try:
|
||||
container = docker_client.containers.get(container_id)
|
||||
container.stop(timeout=30)
|
||||
container.remove()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from dataclasses import dataclass
|
||||
from conftest import option
|
||||
import os
|
||||
|
||||
|
||||
|
@ -26,4 +27,5 @@ DEFAULT_DISPLAY_NAME = "Mr_Meeseeks"
|
|||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
||||
TESTS_DIR = os.path.join(PROJECT_ROOT, "tests-functional")
|
||||
SIGNALS_DIR = os.path.join(TESTS_DIR, "signals")
|
||||
LOG_SIGNALS_TO_FILE = False # used for debugging purposes
|
||||
LOG_SIGNALS_TO_FILE = False # used for debugging purposes
|
||||
USER_DIR = option.user_dir if option.user_dir else "/usr/status-user"
|
||||
|
|
|
@ -2,10 +2,6 @@ services:
|
|||
anvil:
|
||||
ports:
|
||||
- 8545:8545
|
||||
status-go:
|
||||
ports:
|
||||
- 3333:3333
|
||||
- 8354:8354
|
||||
status-backend:
|
||||
ports:
|
||||
- 3314-3324:3333
|
||||
|
|
|
@ -1,32 +1,4 @@
|
|||
services:
|
||||
status-go:
|
||||
user: ${FUNCTIONAL_TESTS_DOCKER_UID}
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: _assets/build/Dockerfile
|
||||
args:
|
||||
build_tags: gowaku_no_rln,enable_private_api
|
||||
build_target: statusd
|
||||
build_flags: -cover
|
||||
entrypoint: [
|
||||
"statusd",
|
||||
"-c", "/static/configs/config.json",
|
||||
"--server", "0.0.0.0:8354",
|
||||
"--seed-phrase", "test test test test test test test test test test test junk",
|
||||
"--password", "Strong12345",
|
||||
"--dir", "/tmp/status-go-data", # Keep in sync with `config.json/DataDir` value. Later this arg will not be needed.
|
||||
]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -X POST --data '{\"jsonrpc\":\"2.0\",\"method\":\"net_version\",\"params\":[],\"id\":1}' -H 'Content-Type: application/json' http://0.0.0.0:3333 || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 120
|
||||
environment:
|
||||
GOCOVERDIR: "/coverage/binary"
|
||||
volumes:
|
||||
- ./coverage/binary:/coverage/binary
|
||||
stop_signal: SIGINT
|
||||
|
||||
status-backend:
|
||||
user: ${INTEGRATION_TESTS_DOCKER_UID}
|
||||
build:
|
||||
|
@ -50,27 +22,3 @@ services:
|
|||
volumes:
|
||||
- ./coverage/binary:/coverage/binary
|
||||
stop_signal: SIGINT
|
||||
|
||||
tests-rpc:
|
||||
user: ${FUNCTIONAL_TESTS_DOCKER_UID}
|
||||
depends_on:
|
||||
status-go:
|
||||
condition: service_healthy
|
||||
status-backend:
|
||||
condition: service_healthy
|
||||
deploy-communities-contracts:
|
||||
condition: service_completed_successfully
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.tests-rpc
|
||||
entrypoint: [
|
||||
"pytest",
|
||||
"-m", "rpc",
|
||||
"--anvil_url=http://anvil:8545",
|
||||
"--rpc_url_statusd=http://status-go:3333",
|
||||
"--status_backend_urls=${STATUS_BACKEND_URLS}",
|
||||
"--ws_url_statusd=ws://status-go:8354",
|
||||
"--junitxml=/tests-rpc/reports/report.xml"
|
||||
]
|
||||
volumes:
|
||||
- .:/tests-rpc
|
||||
|
|
|
@ -6,3 +6,4 @@ genson~=1.2.2
|
|||
websocket-client~=1.4.2
|
||||
tenacity~=9.0.0
|
||||
pytest-dependency~=0.6.0
|
||||
docker==7.1.0
|
||||
|
|
|
@ -179,8 +179,8 @@ class NetworkConditionTestCase:
|
|||
|
||||
class OneToOneMessageTestCase(NetworkConditionTestCase):
|
||||
|
||||
def initialize_backend(self, await_signals, display_name=DEFAULT_DISPLAY_NAME, url=None):
|
||||
backend = StatusBackend(await_signals=await_signals, url=url)
|
||||
def initialize_backend(self, await_signals, display_name=DEFAULT_DISPLAY_NAME):
|
||||
backend = StatusBackend(await_signals=await_signals)
|
||||
backend.init_status_backend()
|
||||
backend.create_account_and_login(display_name=display_name)
|
||||
backend.start_messenger()
|
||||
|
|
|
@ -4,21 +4,21 @@ import pytest
|
|||
|
||||
from conftest import option
|
||||
from constants import user_1, user_2
|
||||
from test_cases import SignalTestCase
|
||||
from test_cases import StatusBackendTestCase
|
||||
from clients.signals import SignalType
|
||||
|
||||
@pytest.mark.rpc
|
||||
@pytest.mark.transaction
|
||||
@pytest.mark.wallet
|
||||
class TestTransactionFromRoute(SignalTestCase):
|
||||
class TestTransactionFromRoute(StatusBackendTestCase):
|
||||
await_signals = [
|
||||
SignalType.NODE_LOGIN.value,
|
||||
SignalType.WALLET_SUGGESTED_ROUTES.value,
|
||||
SignalType.WALLET_ROUTER_SIGN_TRANSACTIONS.value,
|
||||
SignalType.WALLET_ROUTER_SENDING_TRANSACTIONS_STARTED.value,
|
||||
SignalType.WALLET_TRANSACTION_STATUS_CHANGED.value,
|
||||
SignalType.WALLET_ROUTER_TRANSACTIONS_SENT.value,
|
||||
]
|
||||
|
||||
def test_tx_from_route(self):
|
||||
|
||||
_uuid = str(uuid.uuid4())
|
||||
|
@ -44,7 +44,7 @@ class TestTransactionFromRoute(SignalTestCase):
|
|||
]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
routes = self.signal_client.wait_for_signal(SignalType.WALLET_SUGGESTED_ROUTES.value)
|
||||
routes = self.rpc_client.wait_for_signal(SignalType.WALLET_SUGGESTED_ROUTES.value)
|
||||
assert routes['event']['Uuid'] == _uuid
|
||||
|
||||
method = "wallet_buildTransactionsFromRoute"
|
||||
|
@ -56,7 +56,7 @@ class TestTransactionFromRoute(SignalTestCase):
|
|||
]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
wallet_router_sign_transactions = self.signal_client.wait_for_signal(
|
||||
wallet_router_sign_transactions = self.rpc_client.wait_for_signal(
|
||||
SignalType.WALLET_ROUTER_SIGN_TRANSACTIONS.value)
|
||||
|
||||
assert wallet_router_sign_transactions['event']['signingDetails']['signOnKeycard'] == False
|
||||
|
@ -97,19 +97,18 @@ class TestTransactionFromRoute(SignalTestCase):
|
|||
]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
tx_status = self.signal_client.wait_for_signal(
|
||||
tx_status = self.rpc_client.wait_for_signal(
|
||||
SignalType.WALLET_TRANSACTION_STATUS_CHANGED.value)
|
||||
|
||||
assert tx_status["event"]["chainId"] == 31337
|
||||
assert tx_status["event"]["status"] == "Success"
|
||||
tx_hash = tx_status["event"]["hash"]
|
||||
|
||||
method = "eth_getTransactionByHash"
|
||||
params = [tx_hash]
|
||||
method = "ethclient_transactionByHash"
|
||||
params = [self.network_id, tx_hash]
|
||||
|
||||
response = self.rpc_client.rpc_valid_request(method, params, url=option.anvil_url)
|
||||
tx_details = response.json()["result"]
|
||||
response = self.rpc_client.rpc_valid_request(method, params)
|
||||
tx_details = response.json()["result"]["tx"]
|
||||
|
||||
assert tx_details["value"] == amount_in
|
||||
assert tx_details["to"].upper() == user_2.address.upper()
|
||||
assert tx_details["from"].upper() == user_1.address.upper()
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
import json
|
||||
import random
|
||||
|
||||
import wallet_utils
|
||||
import pytest
|
||||
|
||||
from constants import user_1
|
||||
from test_cases import SignalTestCase
|
||||
|
||||
import wallet_utils
|
||||
|
||||
import logging
|
||||
from test_cases import StatusBackendTestCase
|
||||
from clients.signals import SignalType
|
||||
|
||||
EventActivityFilteringDone = "wallet-activity-filtering-done"
|
||||
EventActivityFilteringUpdate = "wallet-activity-filtering-entries-updated"
|
||||
|
@ -20,8 +17,10 @@ def validate_entry(entry, tx_data):
|
|||
|
||||
@pytest.mark.wallet
|
||||
@pytest.mark.rpc
|
||||
class TestWalletActivitySession(SignalTestCase):
|
||||
await_signals = ["wallet",
|
||||
class TestWalletActivitySession(StatusBackendTestCase):
|
||||
await_signals = [
|
||||
SignalType.NODE_LOGIN.value,
|
||||
"wallet",
|
||||
"wallet.suggested.routes",
|
||||
"wallet.router.sign-transactions",
|
||||
"wallet.router.sending-transactions-started",
|
||||
|
@ -29,13 +28,12 @@ class TestWalletActivitySession(SignalTestCase):
|
|||
"wallet.router.transactions-sent"]
|
||||
|
||||
def setup_method(self):
|
||||
super().setup_method()
|
||||
self.request_id = str(random.randint(1, 8888))
|
||||
|
||||
def test_wallet_start_activity_filter_session(self):
|
||||
tx_data = [] # (routes, build_tx, tx_signatures, tx_status)
|
||||
# Set up a transactions for account before starting session
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client, self.signal_client))
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client))
|
||||
|
||||
# Start activity session
|
||||
method = "wallet_startActivityFilterSessionV2"
|
||||
|
@ -43,9 +41,9 @@ class TestWalletActivitySession(SignalTestCase):
|
|||
{"period": {"startTimestamp": 0, "endTimestamp": 0}, "types": [], "statuses": [],
|
||||
"counterpartyAddresses": [], "assets": [], "collectibles": [], "filterOutAssets": False,
|
||||
"filterOutCollectibles": False}, 10]
|
||||
self.signal_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone)
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone)
|
||||
response = self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
event_response = self.signal_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
|
||||
# Check response
|
||||
sessionID = int(response.json()["result"])
|
||||
|
@ -60,10 +58,10 @@ class TestWalletActivitySession(SignalTestCase):
|
|||
validate_entry(message['activities'][0], tx_data[-1])
|
||||
|
||||
# Trigger new transaction
|
||||
self.signal_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivitySessionUpdated and signal['event']['requestId'] == sessionID)
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client, self.signal_client))
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivitySessionUpdated and signal['event']['requestId'] == sessionID)
|
||||
tx_data.append(wallet_utils.send_router_transaction(self.rpc_client))
|
||||
print(tx_data[-1])
|
||||
event_response = self.signal_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
|
||||
# Check response event
|
||||
assert int(event_response['requestId']) == sessionID
|
||||
|
@ -73,9 +71,9 @@ class TestWalletActivitySession(SignalTestCase):
|
|||
# Reset activity session
|
||||
method = "wallet_resetActivityFilterSession"
|
||||
params = [sessionID, 10]
|
||||
self.signal_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone and signal['event']['requestId'] == sessionID)
|
||||
self.rpc_client.prepare_wait_for_signal("wallet", 1, lambda signal : signal["event"]["type"] == EventActivityFilteringDone and signal['event']['requestId'] == sessionID)
|
||||
response = self.rpc_client.rpc_valid_request(method, params, self.request_id)
|
||||
event_response = self.signal_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
event_response = self.rpc_client.wait_for_signal("wallet", timeout=10)['event']
|
||||
|
||||
# Check response event
|
||||
assert int(event_response['requestId']) == sessionID
|
||||
|
|
|
@ -15,7 +15,7 @@ def verify_json_schema(response, method):
|
|||
jsonschema.validate(instance=response,
|
||||
schema=json.load(schema))
|
||||
|
||||
def get_suggested_routes(rpc_client, signal_client, **kwargs):
|
||||
def get_suggested_routes(rpc_client, **kwargs):
|
||||
_uuid = str(uuid.uuid4())
|
||||
amount_in = "0xde0b6b3a7640000"
|
||||
|
||||
|
@ -43,15 +43,15 @@ def get_suggested_routes(rpc_client, signal_client, **kwargs):
|
|||
f"Warning: The key '{key}' does not exist in the input_params parameters and will be ignored.")
|
||||
params = [input_params]
|
||||
|
||||
signal_client.prepare_wait_for_signal("wallet.suggested.routes", 1)
|
||||
rpc_client.prepare_wait_for_signal("wallet.suggested.routes", 1)
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
routes = signal_client.wait_for_signal("wallet.suggested.routes")
|
||||
routes = rpc_client.wait_for_signal("wallet.suggested.routes")
|
||||
assert routes['event']['Uuid'] == _uuid
|
||||
|
||||
return routes['event']
|
||||
|
||||
def build_transactions_from_route(rpc_client, signal_client, uuid, **kwargs):
|
||||
def build_transactions_from_route(rpc_client, uuid, **kwargs):
|
||||
method = "wallet_buildTransactionsFromRoute"
|
||||
build_tx_params = {
|
||||
"uuid": uuid,
|
||||
|
@ -66,7 +66,7 @@ def build_transactions_from_route(rpc_client, signal_client, uuid, **kwargs):
|
|||
params = [build_tx_params]
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
wallet_router_sign_transactions = signal_client.wait_for_signal("wallet.router.sign-transactions")
|
||||
wallet_router_sign_transactions = rpc_client.wait_for_signal("wallet.router.sign-transactions")
|
||||
|
||||
assert wallet_router_sign_transactions['event']['signingDetails']['signOnKeycard'] == False
|
||||
transaction_hashes = wallet_router_sign_transactions['event']['signingDetails']['hashes']
|
||||
|
@ -101,7 +101,7 @@ def sign_messages(rpc_client, hashes):
|
|||
tx_signatures[hash] = signature
|
||||
return tx_signatures
|
||||
|
||||
def send_router_transactions_with_signatures(rpc_client, signal_client, uuid, tx_signatures):
|
||||
def send_router_transactions_with_signatures(rpc_client, uuid, tx_signatures):
|
||||
method = "wallet_sendRouterTransactionsWithSignatures"
|
||||
params = [
|
||||
{
|
||||
|
@ -111,18 +111,18 @@ def send_router_transactions_with_signatures(rpc_client, signal_client, uuid, tx
|
|||
]
|
||||
_ = rpc_client.rpc_valid_request(method, params)
|
||||
|
||||
tx_status = signal_client.wait_for_signal(
|
||||
tx_status = rpc_client.wait_for_signal(
|
||||
"wallet.transaction.status-changed")
|
||||
|
||||
assert tx_status["event"]["status"] == "Success"
|
||||
|
||||
return tx_status["event"]
|
||||
|
||||
def send_router_transaction(rpc_client, signal_client, **kwargs):
|
||||
routes = get_suggested_routes(rpc_client, signal_client, **kwargs)
|
||||
build_tx = build_transactions_from_route(rpc_client, signal_client, routes['Uuid'])
|
||||
def send_router_transaction(rpc_client, **kwargs):
|
||||
routes = get_suggested_routes(rpc_client, **kwargs)
|
||||
build_tx = build_transactions_from_route(rpc_client, routes['Uuid'])
|
||||
tx_signatures = sign_messages(rpc_client, build_tx['signingDetails']['hashes'])
|
||||
tx_status = send_router_transactions_with_signatures(rpc_client, signal_client, routes['Uuid'], tx_signatures)
|
||||
tx_status = send_router_transactions_with_signatures(rpc_client, routes['Uuid'], tx_signatures)
|
||||
return {
|
||||
"routes": routes,
|
||||
"build_tx": build_tx,
|
||||
|
|
Loading…
Reference in New Issue