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

test_: status cli migration #6063

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ __pycache__/
report/results.xml
tests-functional/coverage
tests-functional/reports
tests-functional/signals
tests-functional/local
tests-functional/status-backend
tests-functional/*.log

# generated files
Expand Down
11 changes: 11 additions & 0 deletions pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"include": ["tests-functional"],
"reportMissingImports": true,
"reportOptionalMemberAccess": false,
"reportGeneralTypeIssues": false,
"reportInvalidStringEscapeSequence": false,
"reportWildcardImportFromLibrary": false,
"venvPath": ".",
"venv": ".venv",
"typeCheckingMode": "off"
}
11 changes: 11 additions & 0 deletions tests-functional/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
- id: black
args: [--line-length=150]

- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.326
hooks:
- id: pyright
17 changes: 12 additions & 5 deletions tests-functional/README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ Functional tests for status-go
- [Overview](#overview)
- [How to Install](#how-to-install)
- [How to Run](#how-to-run)
- [Running Tests](#running-tests)
- [Running Tests](#running-tests)
- [Implementation details](#implementation-details)

## How to Install

* Install [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)
* Install [Python 3.10.14](https://www.python.org/downloads/)
* In `./tests-functional`, run `pip install -r requirements.txt`
* **Optional (for test development)**: Use Python virtual environment for better dependency management. You can follow the guide [here](https://akrabat.com/creating-virtual-environments-with-pyenv/):
1. Install [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/)
2. Install [Python 3.10.14](https://www.python.org/downloads/)
3. **Set up a virtual environment (recommended):**
- In `./tests-functional`, run:
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
- **Optional (for test development)**: Use Python virtual environment for better dependency management. You can follow the guide [here](https://akrabat.com/creating-virtual-environments-with-pyenv/)


## How to Run

Expand Down
48 changes: 0 additions & 48 deletions tests-functional/clients/signals.py

This file was deleted.

30 changes: 13 additions & 17 deletions tests-functional/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,20 @@
"HTTPPort": 3333,
"HTTPVirtualHosts": ["*", "status-go"],
"APIModules": "eth,admin,wallet,accounts,waku,wakuext,ethclient",
"WalletConfig": {
"Enabled": true
},
"WakuConfig": {
"Enabled": false
},
"WalletConfig": {"Enabled": true},
"WakuConfig": {"Enabled": false},
"Networks": [
{
"ChainID": 31337,
"ChainName": "Anvil",
"RPCURL": "http://anvil:8545",
"ShortName": "eth",
"NativeCurrencyName": "Ether",
"NativeCurrencySymbol": "ETH",
"NativeCurrencyDecimals": 18,
"IsTest": false,
"Layer": 1,
"Enabled": true
}
"ChainID": 31337,
"ChainName": "Anvil",
"RPCURL": "http://anvil:8545",
"ShortName": "eth",
"NativeCurrencyName": "Ether",
"NativeCurrencySymbol": "ETH",
"NativeCurrencyDecimals": 18,
"IsTest": false,
"Layer": 1,
"Enabled": true
}
]
}
24 changes: 12 additions & 12 deletions tests-functional/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import inspect
import os
import threading
from dataclasses import dataclass

import pytest as pytest
from src.libs.custom_logger import get_custom_logger

logger = get_custom_logger(__name__)


def pytest_addoption(parser):
Expand Down Expand Up @@ -58,30 +61,27 @@ def pytest_configure(config):
option.base_dir = os.path.dirname(os.path.abspath(__file__))


@pytest.fixture(scope="session", autouse=True)
@pytest.fixture(scope="session", autouse=False)
def init_status_backend():
await_signals = [
logger.info(f"Running fixture setup: {inspect.currentframe().f_code.co_name}")

await_signals = [
"mediaserver.started",
"node.started",
"node.ready",
"node.login",

"wallet", # TODO: a test per event of a different type
]

from clients.status_backend import StatusBackend
backend_client = StatusBackend(
await_signals=await_signals
)
from src.node.clients.status_backend import StatusBackend

websocket_thread = threading.Thread(
target=backend_client._connect
)
backend_client = StatusBackend(await_signals=await_signals)

websocket_thread = threading.Thread(target=backend_client._connect)
websocket_thread.daemon = True
websocket_thread.start()

backend_client.init_status_backend()
backend_client.init_status_backend(data_dir="/")
backend_client.restore_account_and_wait_for_rpc_client_to_start()

yield backend_client
23 changes: 0 additions & 23 deletions tests-functional/constants.py

This file was deleted.

10 changes: 7 additions & 3 deletions tests-functional/pytest.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[pytest]
addopts = -s -v --tb=short

addopts = -s -v --instafail --tb=short --color=auto
log_cli=true
log_level=INFO

log_file = log/test.log
log_cli_format = %(asctime)s %(name)s %(levelname)s %(message)s
log_file_format = %(asctime)s %(name)s %(levelname)s %(message)s
timeout = 300
markers =
rpc
wallet
Expand All @@ -14,3 +16,5 @@ markers =
init
transaction
create_account
filterwarnings =
ignore::DeprecationWarning
6 changes: 6 additions & 0 deletions tests-functional/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ pytest==6.2.4
requests==2.31.0
genson~=1.2.2
websocket-client~=1.4.2
tenacity~=9.0.0
black~=24.10.0
pyright~=1.1.388
pytest-instafail==0.5.0
pre-commit~=4.0.1
pytest-timeout~=2.2.0
57 changes: 57 additions & 0 deletions tests-functional/src/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import os
import random
from dataclasses import dataclass
import uuid


def create_unique_data_dir(base_dir: str, index: int) -> str:
unique_id = str(uuid.uuid4())[:8]
unique_dir = os.path.join(base_dir, f"data_{index}_{unique_id}")
os.makedirs(unique_dir, exist_ok=True)
return unique_dir


@dataclass
class Account:
address: str
private_key: str
password: str
passphrase: str


user_1 = Account(
address="0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
password="Strong12345",
passphrase="test test test test test test test test test test test junk",
)
user_2 = Account(
address="0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
private_key="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
password="Strong12345",
passphrase="test test test test test test test test test test nest junk",
)

PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
STATUS_BACKEND_URL = os.getenv("STATUS_BACKEND_URL", "http://127.0.0.1")
API_REQUEST_TIMEOUT = int(os.getenv("API_REQUEST_TIMEOUT", "15"))

SOURCE_DIR = os.path.join(PROJECT_ROOT, "build/bin")
DEST_DIR = os.path.join(PROJECT_ROOT, "tests-functional")
BINARY_PATH = os.path.join(SOURCE_DIR, "status-backend")
DATA_DIR = os.path.join(PROJECT_ROOT, "tests-functional/local")
SIGNALS_DIR = os.path.join(DEST_DIR, "signals")
LOCAL_DATA_DIR1 = create_unique_data_dir(DATA_DIR, random.randint(1, 100))
LOCAL_DATA_DIR2 = create_unique_data_dir(DATA_DIR, random.randint(1, 100))
RESOURCES_FOLDER = os.path.join(PROJECT_ROOT, "resources")

ACCOUNT_PAYLOAD_DEFAULTS = {
"displayName": "user",
"password": "test_password",
"customizationColor": "primary",
}

NUM_CONTACT_REQUESTS = int(os.getenv("NUM_CONTACT_REQUESTS", "5"))
NUM_MESSAGES = int(os.getenv("NUM_MESSAGES", "20"))
DELAY_BETWEEN_MESSAGES = int(os.getenv("NUM_MESSAGES", "1"))
EVENT_SIGNAL_TIMEOUT_SEC = int(os.getenv("EVENT_SIGNAL_TIMEOUT_SEC", "5"))
Empty file.
29 changes: 29 additions & 0 deletions tests-functional/src/libs/base_api_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import requests
import json
from tenacity import retry, stop_after_delay, wait_fixed
from src.libs.custom_logger import get_custom_logger

logger = get_custom_logger(__name__)


class BaseAPIClient:
def __init__(self, base_url):
self.base_url = base_url

@retry(stop=stop_after_delay(10), wait=wait_fixed(0.5), reraise=True)
def send_post_request(self, endpoint, payload=None, headers=None, timeout=10):
if headers is None:
headers = {"Content-Type": "application/json"}
if payload is None:
payload = {}

url = f"{self.base_url}/{endpoint}"
logger.info(f"Sending POST request to {url} with payload: {json.dumps(payload)}")
try:
response = requests.post(url, headers=headers, data=json.dumps(payload), timeout=timeout)
response.raise_for_status()
logger.info(f"Response received: {response.status_code} - {response.text}")
return response.json()
except requests.exceptions.RequestException as e:
logger.error(f"Request to {url} failed: {str(e)}")
raise
50 changes: 50 additions & 0 deletions tests-functional/src/libs/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json
from time import sleep
from src.libs.custom_logger import get_custom_logger
import subprocess
import shutil
import os
from datetime import datetime
from src.constants import PROJECT_ROOT, BINARY_PATH, DEST_DIR, SIGNALS_DIR
from pathlib import Path


logger = get_custom_logger(__name__)
Path(SIGNALS_DIR).mkdir(parents=True, exist_ok=True)


def delay(num_seconds):
logger.debug(f"Sleeping for {num_seconds} seconds")
sleep(num_seconds)


def write_signal_to_file(signal_data):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
signal_file_path = os.path.join(SIGNALS_DIR, f"signals_log_{timestamp}.json")
with open(signal_file_path, "a+") as file:
json.dump(signal_data, file)
file.write("\n")


def build_and_copy_binary():
logger.info(f"Building status-backend binary in {PROJECT_ROOT}")
result = subprocess.run(["make", "status-backend"], cwd=PROJECT_ROOT, capture_output=True, text=True)

if result.returncode != 0:
logger.info("Build failed with the following output:")
logger.info(result.stderr)
return False

if not os.path.exists(BINARY_PATH):
logger.info("Binary build failed or not found! Exiting.")
return False

logger.info(f"Copying binary to {DEST_DIR}")
shutil.copy(BINARY_PATH, DEST_DIR)

if os.path.exists(os.path.join(DEST_DIR, "status-backend")):
logger.info("Binary successfully copied to tests-functional directory.")
return True
else:
logger.info("Failed to copy binary to the tests-functional directory.")
return False
Loading