Files
aitbc/cli/tests/test_exchange_island.py
aitbc d72945f20c
Some checks failed
Systemd Sync / sync-systemd (push) Waiting to run
CLI Tests / test-cli (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Documentation Validation / validate-docs (push) Has been cancelled
API Endpoint Tests / test-api-endpoints (push) Has been cancelled
network: add hub registration, Redis persistence, and federated mesh join protocol
- Change default P2P port from 7070 to 8001 in config and .env.example
- Add redis_url configuration option for hub persistence (default: redis://localhost:6379)
- Implement DNS-based hub registration/unregistration via HTTPS API endpoints
- Add Redis persistence for hub registrations with 1-hour TTL
- Add island join request/response protocol with member list and blockchain credentials
- Add GPU marketplace tracking (offers, bids, providers) in hub manager
- Add
2026-04-13 11:47:34 +02:00

253 lines
8.6 KiB
Python

"""
Unit tests for Exchange Island CLI commands
"""
import pytest
import json
import os
from pathlib import Path
from click.testing import CliRunner
from unittest.mock import patch, MagicMock
@pytest.fixture
def mock_credentials_file(tmp_path):
"""Create a temporary credentials file for testing"""
credentials = {
"island_id": "test-island-id-12345",
"island_name": "test-island",
"island_chain_id": "ait-test",
"credentials": {
"genesis_block_hash": "0x1234567890abcdef",
"genesis_address": "0xabcdef1234567890",
"rpc_endpoint": "http://localhost:8006",
"p2p_port": 8001
},
"members": [],
"joined_at": "2024-01-01T00:00:00"
}
# Monkey patch the credentials path
import aitbc_cli.utils.island_credentials as ic_module
original_path = ic_module.CREDENTIALS_PATH
ic_module.CREDENTIALS_PATH = str(tmp_path / "island_credentials.json")
# Write credentials to temp file
with open(ic_module.CREDENTIALS_PATH, 'w') as f:
json.dump(credentials, f)
yield credentials
# Cleanup
if os.path.exists(ic_module.CREDENTIALS_PATH):
os.remove(ic_module.CREDENTIALS_PATH)
ic_module.CREDENTIALS_PATH = original_path
@pytest.fixture
def mock_keystore(tmp_path):
"""Create a temporary keystore for testing"""
keystore = {
"test_key_id": {
"public_key_pem": "-----BEGIN PUBLIC KEY-----\ntest_public_key_data\n-----END PUBLIC KEY-----"
}
}
keystore_path = tmp_path / "validator_keys.json"
with open(keystore_path, 'w') as f:
json.dump(keystore, f)
# Monkey patch keystore path
import aitbc_cli.commands.exchange_island as ei_module
original_path = ei_module.__dict__.get('keystore_path')
yield str(keystore_path)
# Restore
if original_path:
ei_module.keystore_path = original_path
@pytest.fixture
def runner():
"""Create a Click CLI runner"""
return CliRunner()
def test_exchange_buy_command(mock_credentials_file, mock_keystore, runner):
"""Test exchange buy command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {"transaction_id": "test_tx_id"}
mock_client.return_value.__enter__.return_value.post.return_value = mock_response
result = runner.invoke(exchange_island, ['buy', '100', 'BTC', '--max-price', '0.00001'])
assert result.exit_code == 0
assert "Buy order created successfully" in result.output
def test_exchange_buy_command_invalid_amount(mock_credentials_file, runner):
"""Test exchange buy command with invalid amount"""
from aitbc_cli.commands.exchange_island import exchange_island
result = runner.invoke(exchange_island, ['buy', '-10', 'BTC'])
assert result.exit_code != 0
assert "must be greater than 0" in result.output
def test_exchange_sell_command(mock_credentials_file, mock_keystore, runner):
"""Test exchange sell command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {"transaction_id": "test_tx_id"}
mock_client.return_value.__enter__.return_value.post.return_value = mock_response
result = runner.invoke(exchange_island, ['sell', '100', 'ETH', '--min-price', '0.0005'])
assert result.exit_code == 0
assert "Sell order created successfully" in result.output
def test_exchange_sell_command_invalid_amount(mock_credentials_file, runner):
"""Test exchange sell command with invalid amount"""
from aitbc_cli.commands.exchange_island import exchange_island
result = runner.invoke(exchange_island, ['sell', '-10', 'ETH'])
assert result.exit_code != 0
assert "must be greater than 0" in result.output
def test_exchange_orderbook_command(mock_credentials_file, runner):
"""Test exchange orderbook command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = [
{
"action": "buy",
"order_id": "exchange_buy_test",
"user_id": "test_user",
"pair": "AIT/BTC",
"side": "buy",
"amount": 100.0,
"max_price": 0.00001,
"status": "open",
"created_at": "2024-01-01T00:00:00"
},
{
"action": "sell",
"order_id": "exchange_sell_test",
"user_id": "test_user2",
"pair": "AIT/BTC",
"side": "sell",
"amount": 100.0,
"min_price": 0.000009,
"status": "open",
"created_at": "2024-01-01T00:00:00"
}
]
mock_client.return_value.__enter__.return_value.get.return_value = mock_response
result = runner.invoke(exchange_island, ['orderbook', 'AIT/BTC'])
assert result.exit_code == 0
def test_exchange_rates_command(mock_credentials_file, runner):
"""Test exchange rates command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = []
mock_client.return_value.__enter__.return_value.get.return_value = mock_response
result = runner.invoke(exchange_island, ['rates'])
assert result.exit_code == 0
def test_exchange_orders_command(mock_credentials_file, runner):
"""Test exchange orders command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = [
{
"action": "buy",
"order_id": "exchange_buy_test",
"user_id": "test_user",
"pair": "AIT/BTC",
"side": "buy",
"amount": 100.0,
"max_price": 0.00001,
"status": "open",
"created_at": "2024-01-01T00:00:00"
}
]
mock_client.return_value.__enter__.return_value.get.return_value = mock_response
result = runner.invoke(exchange_island, ['orders'])
assert result.exit_code == 0
def test_exchange_cancel_command(mock_credentials_file, mock_keystore, runner):
"""Test exchange cancel command"""
from aitbc_cli.commands.exchange_island import exchange_island
with patch('aitbc_cli.commands.exchange_island.httpx.Client') as mock_client:
mock_response = MagicMock()
mock_response.status_code = 200
mock_client.return_value.__enter__.return_value.post.return_value = mock_response
result = runner.invoke(exchange_island, ['cancel', 'exchange_buy_test123'])
assert result.exit_code == 0
assert "cancelled successfully" in result.output
def test_exchange_orderbook_invalid_pair(mock_credentials_file, runner):
"""Test exchange orderbook command with invalid pair"""
from aitbc_cli.commands.exchange_island import exchange_island
result = runner.invoke(exchange_island, ['orderbook', 'INVALID/PAIR'])
assert result.exit_code != 0
def test_exchange_buy_invalid_currency(mock_credentials_file, runner):
"""Test exchange buy command with invalid currency"""
from aitbc_cli.commands.exchange_island import exchange_island
result = runner.invoke(exchange_island, ['buy', '100', 'INVALID'])
assert result.exit_code != 0
def test_exchange_sell_invalid_currency(mock_credentials_file, runner):
"""Test exchange sell command with invalid currency"""
from aitbc_cli.commands.exchange_island import exchange_island
result = runner.invoke(exchange_island, ['sell', '100', 'INVALID'])
assert result.exit_code != 0
if __name__ == "__main__":
pytest.main([__file__])