refactor: clean up tests/ root — delete junk, sort into subdirs
Deleted (7 files): - test_discovery.py, test_windsurf_integration.py (trivial assert True stubs) - pytest_simple.ini (unused --collect-only config) - conftest_path.py (duplicate of conftest.py path setup) - conftest_fixtures.py, conftest_full.py (unused conftest variants) Moved to integration/ (6 files): - test_blockchain_final.py, test_blockchain_nodes.py, test_blockchain_simple.py - test_basic_integration.py, test_integration_simple.py, test_working_integration.py Moved to fixtures/: - mock_blockchain_node.py tests/ root now has only conftest.py and README.md.
This commit is contained in:
@@ -1,468 +0,0 @@
|
||||
"""
|
||||
Comprehensive test fixtures for AITBC testing
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import asyncio
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Any, Generator
|
||||
from unittest.mock import Mock, AsyncMock
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
# Import all necessary modules
|
||||
from apps.coordinator_api.src.app.main import app as coordinator_app
|
||||
from apps.wallet_daemon.src.app.main import app as wallet_app
|
||||
from apps.blockchain_node.src.aitbc_chain.node import BlockchainNode
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def event_loop():
|
||||
"""Create an instance of the default event loop for the test session."""
|
||||
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def coordinator_client():
|
||||
"""Create a test client for coordinator API"""
|
||||
return TestClient(coordinator_app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wallet_client():
|
||||
"""Create a test client for wallet daemon"""
|
||||
return TestClient(wallet_app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def blockchain_client():
|
||||
"""Create a test client for blockchain node"""
|
||||
node = BlockchainNode()
|
||||
return TestClient(node.app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def marketplace_client():
|
||||
"""Create a test client for marketplace"""
|
||||
from apps.marketplace.src.app.main import app as marketplace_app
|
||||
return TestClient(marketplace_app)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tenant():
|
||||
"""Create a sample tenant for testing"""
|
||||
return {
|
||||
"id": "tenant-123",
|
||||
"name": "Test Tenant",
|
||||
"created_at": datetime.utcnow(),
|
||||
"status": "active"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_user():
|
||||
"""Create a sample user for testing"""
|
||||
return {
|
||||
"id": "user-123",
|
||||
"email": "test@example.com",
|
||||
"tenant_id": "tenant-123",
|
||||
"role": "user",
|
||||
"created_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_wallet_data():
|
||||
"""Sample wallet creation data"""
|
||||
return {
|
||||
"name": "Test Wallet",
|
||||
"type": "hd",
|
||||
"currency": "AITBC"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_wallet():
|
||||
"""Sample wallet object"""
|
||||
return {
|
||||
"id": "wallet-123",
|
||||
"address": "0x1234567890abcdef1234567890abcdef12345678",
|
||||
"user_id": "user-123",
|
||||
"balance": "1000.0",
|
||||
"status": "active",
|
||||
"created_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_job_data():
|
||||
"""Sample job creation data"""
|
||||
return {
|
||||
"job_type": "ai_inference",
|
||||
"parameters": {
|
||||
"model": "gpt-4",
|
||||
"prompt": "Test prompt",
|
||||
"max_tokens": 100,
|
||||
"temperature": 0.7
|
||||
},
|
||||
"priority": "normal",
|
||||
"timeout": 300
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_job():
|
||||
"""Sample job object"""
|
||||
return {
|
||||
"id": "job-123",
|
||||
"job_type": "ai_inference",
|
||||
"status": "pending",
|
||||
"tenant_id": "tenant-123",
|
||||
"created_at": datetime.utcnow(),
|
||||
"parameters": {
|
||||
"model": "gpt-4",
|
||||
"prompt": "Test prompt"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_transaction():
|
||||
"""Sample transaction object"""
|
||||
return {
|
||||
"hash": "0x1234567890abcdef",
|
||||
"from": "0xsender1234567890",
|
||||
"to": "0xreceiver1234567890",
|
||||
"value": "1000",
|
||||
"gas": "21000",
|
||||
"gas_price": "20",
|
||||
"nonce": 1,
|
||||
"status": "pending"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_block():
|
||||
"""Sample block object"""
|
||||
return {
|
||||
"number": 100,
|
||||
"hash": "0xblock1234567890",
|
||||
"parent_hash": "0xparent0987654321",
|
||||
"timestamp": datetime.utcnow(),
|
||||
"transactions": [],
|
||||
"validator": "0xvalidator123"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_account():
|
||||
"""Sample account object"""
|
||||
return {
|
||||
"address": "0xaccount1234567890",
|
||||
"balance": "1000000",
|
||||
"nonce": 25,
|
||||
"code_hash": "0xempty"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def signed_receipt():
|
||||
"""Sample signed receipt"""
|
||||
return {
|
||||
"job_id": "job-123",
|
||||
"hash": "0xreceipt123456",
|
||||
"signature": "sig789012345",
|
||||
"miner_id": "miner-123",
|
||||
"timestamp": datetime.utcnow().isoformat()
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tenant_quota():
|
||||
"""Sample tenant quota"""
|
||||
return {
|
||||
"tenant_id": "tenant-123",
|
||||
"jobs_per_day": 1000,
|
||||
"jobs_per_month": 30000,
|
||||
"max_concurrent": 50,
|
||||
"storage_gb": 100
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def validator_address():
|
||||
"""Sample validator address"""
|
||||
return "0xvalidator1234567890abcdef"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def miner_address():
|
||||
"""Sample miner address"""
|
||||
return "0xminer1234567890abcdef"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_transactions():
|
||||
"""List of sample transactions"""
|
||||
return [
|
||||
{
|
||||
"hash": "0xtx123",
|
||||
"from": "0xaddr1",
|
||||
"to": "0xaddr2",
|
||||
"value": "100"
|
||||
},
|
||||
{
|
||||
"hash": "0xtx456",
|
||||
"from": "0xaddr3",
|
||||
"to": "0xaddr4",
|
||||
"value": "200"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_block(sample_transactions):
|
||||
"""Sample block with transactions"""
|
||||
return {
|
||||
"number": 100,
|
||||
"hash": "0xblockhash123",
|
||||
"parent_hash": "0xparenthash456",
|
||||
"transactions": sample_transactions,
|
||||
"timestamp": datetime.utcnow(),
|
||||
"validator": "0xvalidator123"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_database():
|
||||
"""Mock database session"""
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
yield session
|
||||
session.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_redis():
|
||||
"""Mock Redis client"""
|
||||
from unittest.mock import Mock
|
||||
redis_mock = Mock()
|
||||
redis_mock.get.return_value = None
|
||||
redis_mock.set.return_value = True
|
||||
redis_mock.delete.return_value = 1
|
||||
return redis_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_web3():
|
||||
"""Mock Web3 instance"""
|
||||
from unittest.mock import Mock
|
||||
web3_mock = Mock()
|
||||
web3_mock.eth.contract.return_value = Mock()
|
||||
web3_mock.eth.get_balance.return_value = 1000000
|
||||
web3_mock.eth.gas_price = 20
|
||||
return web3_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def browser():
|
||||
"""Selenium WebDriver fixture for E2E tests"""
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
options.add_argument("--no-sandbox")
|
||||
options.add_argument("--disable-dev-shm-usage")
|
||||
|
||||
driver = webdriver.Chrome(options=options)
|
||||
driver.implicitly_wait(10)
|
||||
yield driver
|
||||
driver.quit()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mobile_browser():
|
||||
"""Mobile browser fixture for responsive testing"""
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
options.add_argument("--no-sandbox")
|
||||
options.add_argument("--disable-dev-shm-usage")
|
||||
|
||||
mobile_emulation = {
|
||||
"deviceMetrics": {"width": 375, "height": 667, "pixelRatio": 2.0},
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)"
|
||||
}
|
||||
options.add_experimental_option("mobileEmulation", mobile_emulation)
|
||||
|
||||
driver = webdriver.Chrome(options=options)
|
||||
driver.implicitly_wait(10)
|
||||
yield driver
|
||||
driver.quit()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def base_url():
|
||||
"""Base URL for E2E tests"""
|
||||
return "http://localhost:8000"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_file_storage():
|
||||
"""Mock file storage service"""
|
||||
from unittest.mock import Mock
|
||||
storage_mock = Mock()
|
||||
storage_mock.upload.return_value = {"url": "http://example.com/file.txt"}
|
||||
storage_mock.download.return_value = b"file content"
|
||||
storage_mock.delete.return_value = True
|
||||
return storage_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_email_service():
|
||||
"""Mock email service"""
|
||||
from unittest.mock import Mock
|
||||
email_mock = Mock()
|
||||
email_mock.send.return_value = {"message_id": "msg-123"}
|
||||
email_mock.send_verification.return_value = {"token": "token-456"}
|
||||
return email_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_notification_service():
|
||||
"""Mock notification service"""
|
||||
from unittest.mock import Mock
|
||||
notification_mock = Mock()
|
||||
notification_mock.send_push.return_value = True
|
||||
notification_mock.send_webhook.return_value = {"status": "sent"}
|
||||
return notification_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_api_key():
|
||||
"""Sample API key"""
|
||||
return {
|
||||
"id": "key-123",
|
||||
"key": "aitbc_test_key_1234567890",
|
||||
"name": "Test API Key",
|
||||
"permissions": ["read", "write"],
|
||||
"created_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_service_listing():
|
||||
"""Sample marketplace service listing"""
|
||||
return {
|
||||
"id": "service-123",
|
||||
"name": "AI Inference Service",
|
||||
"description": "High-performance AI inference",
|
||||
"provider_id": "provider-123",
|
||||
"pricing": {
|
||||
"per_token": 0.0001,
|
||||
"per_minute": 0.01
|
||||
},
|
||||
"capabilities": ["text-generation", "image-generation"],
|
||||
"status": "active"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_booking():
|
||||
"""Sample booking object"""
|
||||
return {
|
||||
"id": "booking-123",
|
||||
"service_id": "service-123",
|
||||
"client_id": "client-123",
|
||||
"status": "confirmed",
|
||||
"start_time": datetime.utcnow() + timedelta(hours=1),
|
||||
"end_time": datetime.utcnow() + timedelta(hours=2),
|
||||
"total_cost": "10.0"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_blockchain_node():
|
||||
"""Mock blockchain node for testing"""
|
||||
from unittest.mock import Mock
|
||||
node_mock = Mock()
|
||||
node_mock.start.return_value = {"status": "running"}
|
||||
node_mock.stop.return_value = {"status": "stopped"}
|
||||
node_mock.get_block.return_value = {"number": 100, "hash": "0x123"}
|
||||
node_mock.submit_transaction.return_value = {"hash": "0xtx456"}
|
||||
return node_mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_zk_proof():
|
||||
"""Sample zero-knowledge proof"""
|
||||
return {
|
||||
"proof": "zk_proof_123456",
|
||||
"public_inputs": ["x", "y"],
|
||||
"verification_key": "vk_789012"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_confidential_data():
|
||||
"""Sample confidential transaction data"""
|
||||
return {
|
||||
"encrypted_payload": "encrypted_data_123",
|
||||
"commitment": "commitment_hash_456",
|
||||
"nullifier": "nullifier_789",
|
||||
"merkle_proof": {
|
||||
"root": "root_hash",
|
||||
"path": ["hash1", "hash2", "hash3"],
|
||||
"indices": [0, 1, 0]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_ipfs():
|
||||
"""Mock IPFS client"""
|
||||
from unittest.mock import Mock
|
||||
ipfs_mock = Mock()
|
||||
ipfs_mock.add.return_value = {"Hash": "QmHash123"}
|
||||
ipfs_mock.cat.return_value = b"IPFS content"
|
||||
ipfs_mock.pin.return_value = {"Pins": ["QmHash123"]}
|
||||
return ipfs_mock
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cleanup_mocks():
|
||||
"""Cleanup after each test"""
|
||||
yield
|
||||
# Add any cleanup code here
|
||||
pass
|
||||
|
||||
|
||||
# Performance testing fixtures
|
||||
@pytest.fixture
|
||||
def performance_metrics():
|
||||
"""Collect performance metrics during test"""
|
||||
import time
|
||||
start_time = time.time()
|
||||
yield {"start": start_time}
|
||||
end_time = time.time()
|
||||
return {"duration": end_time - start_time}
|
||||
|
||||
|
||||
# Load testing fixtures
|
||||
@pytest.fixture
|
||||
def load_test_config():
|
||||
"""Configuration for load testing"""
|
||||
return {
|
||||
"concurrent_users": 100,
|
||||
"ramp_up_time": 30,
|
||||
"test_duration": 300,
|
||||
"target_rps": 50
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
"""
|
||||
Shared test configuration and fixtures for AITBC
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import pytest
|
||||
import json
|
||||
import tempfile
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Any, Generator, AsyncGenerator
|
||||
from unittest.mock import Mock, AsyncMock
|
||||
from sqlalchemy import create_engine, event
|
||||
from sqlalchemy.orm import sessionmaker, Session
|
||||
from sqlalchemy.pool import StaticPool
|
||||
from fastapi.testclient import TestClient
|
||||
import redis
|
||||
from cryptography.hazmat.primitives.asymmetric import ed25519
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
|
||||
# Import AITBC modules
|
||||
from apps.coordinator_api.src.app.main import app as coordinator_app
|
||||
from apps.coordinator_api.src.app.database import get_db
|
||||
from apps.coordinator_api.src.app.models import Base
|
||||
from apps.coordinator_api.src.app.models.multitenant import Tenant, TenantUser, TenantQuota
|
||||
from apps.wallet_daemon.src.app.main import app as wallet_app
|
||||
from packages.py.aitbc_crypto import sign_receipt, verify_receipt
|
||||
from packages.py.aitbc_sdk import AITBCClient
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def event_loop():
|
||||
"""Create an instance of the default event loop for the test session."""
|
||||
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||
yield loop
|
||||
loop.close()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_config():
|
||||
"""Test configuration settings."""
|
||||
return {
|
||||
"database_url": "sqlite:///:memory:",
|
||||
"redis_url": "redis://localhost:6379/1", # Use test DB
|
||||
"test_tenant_id": "test-tenant-123",
|
||||
"test_user_id": "test-user-456",
|
||||
"test_api_key": "test-api-key-789",
|
||||
"coordinator_url": "http://localhost:8001",
|
||||
"wallet_url": "http://localhost:8002",
|
||||
"blockchain_url": "http://localhost:8545",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def test_engine(test_config):
|
||||
"""Create a test database engine."""
|
||||
engine = create_engine(
|
||||
test_config["database_url"],
|
||||
connect_args={"check_same_thread": False},
|
||||
poolclass=StaticPool,
|
||||
)
|
||||
Base.metadata.create_all(bind=engine)
|
||||
yield engine
|
||||
Base.metadata.drop_all(bind=engine)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db_session(test_engine) -> Generator[Session, None, None]:
|
||||
"""Create a database session for testing."""
|
||||
connection = test_engine.connect()
|
||||
transaction = connection.begin()
|
||||
session = sessionmaker(autocommit=False, autoflush=False, bind=connection)()
|
||||
|
||||
# Begin a nested transaction
|
||||
nested = connection.begin_nested()
|
||||
|
||||
@event.listens_for(session, "after_transaction_end")
|
||||
def end_savepoint(session, transaction):
|
||||
"""Rollback to the savepoint after each test."""
|
||||
nonlocal nested
|
||||
if not nested.is_active:
|
||||
nested = connection.begin_nested()
|
||||
|
||||
yield session
|
||||
|
||||
# Rollback all changes
|
||||
session.close()
|
||||
transaction.rollback()
|
||||
connection.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_redis():
|
||||
"""Create a test Redis client."""
|
||||
client = redis.Redis.from_url("redis://localhost:6379/1", decode_responses=True)
|
||||
# Clear test database
|
||||
client.flushdb()
|
||||
yield client
|
||||
client.flushdb()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def coordinator_client(db_session):
|
||||
"""Create a test client for the coordinator API."""
|
||||
def override_get_db():
|
||||
yield db_session
|
||||
|
||||
coordinator_app.dependency_overrides[get_db] = override_get_db
|
||||
with TestClient(coordinator_app) as client:
|
||||
yield client
|
||||
coordinator_app.dependency_overrides.clear()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wallet_client():
|
||||
"""Create a test client for the wallet daemon."""
|
||||
with TestClient(wallet_app) as client:
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tenant(db_session):
|
||||
"""Create a sample tenant for testing."""
|
||||
tenant = Tenant(
|
||||
id="test-tenant-123",
|
||||
name="Test Tenant",
|
||||
status="active",
|
||||
created_at=datetime.utcnow(),
|
||||
updated_at=datetime.utcnow(),
|
||||
)
|
||||
db_session.add(tenant)
|
||||
db_session.commit()
|
||||
return tenant
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tenant_user(db_session, sample_tenant):
|
||||
"""Create a sample tenant user for testing."""
|
||||
user = TenantUser(
|
||||
tenant_id=sample_tenant.id,
|
||||
user_id="test-user-456",
|
||||
role="admin",
|
||||
created_at=datetime.utcnow(),
|
||||
)
|
||||
db_session.add(user)
|
||||
db_session.commit()
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tenant_quota(db_session, sample_tenant):
|
||||
"""Create sample tenant quota for testing."""
|
||||
quota = TenantQuota(
|
||||
tenant_id=sample_tenant.id,
|
||||
resource_type="api_calls",
|
||||
limit=10000,
|
||||
used=0,
|
||||
period="monthly",
|
||||
created_at=datetime.utcnow(),
|
||||
updated_at=datetime.utcnow(),
|
||||
)
|
||||
db_session.add(quota)
|
||||
db_session.commit()
|
||||
return quota
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_job_data():
|
||||
"""Sample job data for testing."""
|
||||
return {
|
||||
"job_type": "ai_inference",
|
||||
"parameters": {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"prompt": "Test prompt",
|
||||
"max_tokens": 100,
|
||||
},
|
||||
"requirements": {
|
||||
"gpu_memory": "8GB",
|
||||
"compute_time": 30,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_receipt_data():
|
||||
"""Sample receipt data for testing."""
|
||||
return {
|
||||
"job_id": "test-job-123",
|
||||
"miner_id": "test-miner-456",
|
||||
"coordinator_id": "test-coordinator-789",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"result": {
|
||||
"output": "Test output",
|
||||
"confidence": 0.95,
|
||||
"tokens_used": 50,
|
||||
},
|
||||
"signature": "test-signature",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_keypair():
|
||||
"""Generate a test Ed25519 keypair for signing."""
|
||||
private_key = ed25519.Ed25519PrivateKey.generate()
|
||||
public_key = private_key.public_key()
|
||||
return private_key, public_key
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def signed_receipt(sample_receipt_data, test_keypair):
|
||||
"""Create a signed receipt for testing."""
|
||||
private_key, public_key = test_keypair
|
||||
|
||||
# Serialize receipt without signature
|
||||
receipt_copy = sample_receipt_data.copy()
|
||||
receipt_copy.pop("signature", None)
|
||||
receipt_json = json.dumps(receipt_copy, sort_keys=True, separators=(',', ':'))
|
||||
|
||||
# Sign the receipt
|
||||
signature = private_key.sign(receipt_json.encode())
|
||||
|
||||
# Add signature to receipt
|
||||
receipt_copy["signature"] = signature.hex()
|
||||
receipt_copy["public_key"] = public_key.public_bytes(
|
||||
encoding=serialization.Encoding.Raw,
|
||||
format=serialization.PublicFormat.Raw
|
||||
).hex()
|
||||
|
||||
return receipt_copy
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def aitbc_client(test_config):
|
||||
"""Create an AITBC client for testing."""
|
||||
return AITBCClient(
|
||||
base_url=test_config["coordinator_url"],
|
||||
api_key=test_config["test_api_key"],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_miner_service():
|
||||
"""Mock miner service for testing."""
|
||||
service = AsyncMock()
|
||||
service.register_miner = AsyncMock(return_value={"miner_id": "test-miner-456"})
|
||||
service.heartbeat = AsyncMock(return_value={"status": "active"})
|
||||
service.fetch_jobs = AsyncMock(return_value=[])
|
||||
service.submit_result = AsyncMock(return_value={"job_id": "test-job-123"})
|
||||
return service
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_blockchain_node():
|
||||
"""Mock blockchain node for testing."""
|
||||
node = AsyncMock()
|
||||
node.get_block = AsyncMock(return_value={"number": 100, "hash": "0x123"})
|
||||
node.get_transaction = AsyncMock(return_value={"hash": "0x456", "status": "confirmed"})
|
||||
node.submit_transaction = AsyncMock(return_value={"hash": "0x789", "status": "pending"})
|
||||
node.subscribe_blocks = AsyncMock()
|
||||
node.subscribe_transactions = AsyncMock()
|
||||
return node
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_gpu_service():
|
||||
"""Sample GPU service definition."""
|
||||
return {
|
||||
"id": "llm-inference",
|
||||
"name": "LLM Inference Service",
|
||||
"category": "ai_ml",
|
||||
"description": "Large language model inference",
|
||||
"requirements": {
|
||||
"gpu_memory": "16GB",
|
||||
"cuda_version": "11.8",
|
||||
"driver_version": "520.61.05",
|
||||
},
|
||||
"pricing": {
|
||||
"per_hour": 0.50,
|
||||
"per_token": 0.0001,
|
||||
},
|
||||
"capabilities": [
|
||||
"text-generation",
|
||||
"chat-completion",
|
||||
"embedding",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_cross_chain_data():
|
||||
"""Sample cross-chain settlement data."""
|
||||
return {
|
||||
"source_chain": "ethereum",
|
||||
"target_chain": "polygon",
|
||||
"source_tx_hash": "0xabcdef123456",
|
||||
"target_address": "0x1234567890ab",
|
||||
"amount": "1000",
|
||||
"token": "USDC",
|
||||
"bridge_id": "layerzero",
|
||||
"nonce": 12345,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def confidential_transaction_data():
|
||||
"""Sample confidential transaction data."""
|
||||
return {
|
||||
"sender": "0x1234567890abcdef",
|
||||
"receiver": "0xfedcba0987654321",
|
||||
"amount": 1000,
|
||||
"asset": "AITBC",
|
||||
"confidential": True,
|
||||
"ciphertext": "encrypted_data_here",
|
||||
"viewing_key": "viewing_key_here",
|
||||
"proof": "zk_proof_here",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_hsm_client():
|
||||
"""Mock HSM client for testing."""
|
||||
client = AsyncMock()
|
||||
client.generate_key = AsyncMock(return_value={"key_id": "test-key-123"})
|
||||
client.sign_data = AsyncMock(return_value={"signature": "test-signature"})
|
||||
client.verify_signature = AsyncMock(return_value={"valid": True})
|
||||
client.encrypt_data = AsyncMock(return_value={"ciphertext": "encrypted_data"})
|
||||
client.decrypt_data = AsyncMock(return_value={"plaintext": "decrypted_data"})
|
||||
return client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_directory():
|
||||
"""Create a temporary directory for testing."""
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
yield temp_dir
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_config_file(temp_directory):
|
||||
"""Create a sample configuration file."""
|
||||
config = {
|
||||
"coordinator": {
|
||||
"host": "localhost",
|
||||
"port": 8001,
|
||||
"database_url": "sqlite:///test.db",
|
||||
},
|
||||
"blockchain": {
|
||||
"host": "localhost",
|
||||
"port": 8545,
|
||||
"chain_id": 1337,
|
||||
},
|
||||
"wallet": {
|
||||
"host": "localhost",
|
||||
"port": 8002,
|
||||
"keystore_path": temp_directory,
|
||||
},
|
||||
}
|
||||
|
||||
config_path = temp_directory / "config.json"
|
||||
with open(config_path, "w") as f:
|
||||
json.dump(config, f)
|
||||
|
||||
return config_path
|
||||
|
||||
|
||||
# Async fixtures
|
||||
|
||||
@pytest.fixture
|
||||
async def async_aitbc_client(test_config):
|
||||
"""Create an async AITBC client for testing."""
|
||||
client = AITBCClient(
|
||||
base_url=test_config["coordinator_url"],
|
||||
api_key=test_config["test_api_key"],
|
||||
)
|
||||
yield client
|
||||
await client.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def websocket_client():
|
||||
"""Create a WebSocket client for testing."""
|
||||
import websockets
|
||||
|
||||
uri = "ws://localhost:8546"
|
||||
async with websockets.connect(uri) as websocket:
|
||||
yield websocket
|
||||
|
||||
|
||||
# Performance testing fixtures
|
||||
|
||||
@pytest.fixture
|
||||
def performance_config():
|
||||
"""Configuration for performance tests."""
|
||||
return {
|
||||
"concurrent_users": 100,
|
||||
"ramp_up_time": 30, # seconds
|
||||
"test_duration": 300, # seconds
|
||||
"think_time": 1, # seconds
|
||||
}
|
||||
|
||||
|
||||
# Security testing fixtures
|
||||
|
||||
@pytest.fixture
|
||||
def malicious_payloads():
|
||||
"""Collection of malicious payloads for security testing."""
|
||||
return {
|
||||
"sql_injection": "'; DROP TABLE jobs; --",
|
||||
"xss": "<script>alert('xss')</script>",
|
||||
"path_traversal": "../../../etc/passwd",
|
||||
"overflow": "A" * 10000,
|
||||
"unicode": "\ufeff\u200b\u200c\u200d",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rate_limit_config():
|
||||
"""Rate limiting configuration for testing."""
|
||||
return {
|
||||
"requests_per_minute": 60,
|
||||
"burst_size": 10,
|
||||
"window_size": 60,
|
||||
}
|
||||
|
||||
|
||||
# Helper functions
|
||||
|
||||
def create_test_job(job_id: str = None, **kwargs) -> Dict[str, Any]:
|
||||
"""Create a test job with default values."""
|
||||
return {
|
||||
"id": job_id or f"test-job-{datetime.utcnow().timestamp()}",
|
||||
"status": "pending",
|
||||
"created_at": datetime.utcnow().isoformat(),
|
||||
"updated_at": datetime.utcnow().isoformat(),
|
||||
"job_type": kwargs.get("job_type", "ai_inference"),
|
||||
"parameters": kwargs.get("parameters", {}),
|
||||
"requirements": kwargs.get("requirements", {}),
|
||||
"tenant_id": kwargs.get("tenant_id", "test-tenant-123"),
|
||||
}
|
||||
|
||||
|
||||
def create_test_receipt(job_id: str = None, **kwargs) -> Dict[str, Any]:
|
||||
"""Create a test receipt with default values."""
|
||||
return {
|
||||
"id": f"receipt-{job_id or 'test'}",
|
||||
"job_id": job_id or "test-job-123",
|
||||
"miner_id": kwargs.get("miner_id", "test-miner-456"),
|
||||
"coordinator_id": kwargs.get("coordinator_id", "test-coordinator-789"),
|
||||
"timestamp": kwargs.get("timestamp", datetime.utcnow().isoformat()),
|
||||
"result": kwargs.get("result", {"output": "test"}),
|
||||
"signature": kwargs.get("signature", "test-signature"),
|
||||
}
|
||||
|
||||
|
||||
def assert_valid_receipt(receipt: Dict[str, Any]):
|
||||
"""Assert that a receipt has valid structure."""
|
||||
required_fields = ["id", "job_id", "miner_id", "coordinator_id", "timestamp", "result", "signature"]
|
||||
for field in required_fields:
|
||||
assert field in receipt, f"Receipt missing required field: {field}"
|
||||
|
||||
# Validate timestamp format
|
||||
assert isinstance(receipt["timestamp"], str), "Timestamp should be a string"
|
||||
|
||||
# Validate result structure
|
||||
assert isinstance(receipt["result"], dict), "Result should be a dictionary"
|
||||
|
||||
|
||||
# Marks for different test types
|
||||
pytest.mark.unit = pytest.mark.unit
|
||||
pytest.mark.integration = pytest.mark.integration
|
||||
pytest.mark.e2e = pytest.mark.e2e
|
||||
pytest.mark.performance = pytest.mark.performance
|
||||
pytest.mark.security = pytest.mark.security
|
||||
pytest.mark.slow = pytest.mark.slow
|
||||
@@ -1,19 +0,0 @@
|
||||
"""Configure Python path for pytest discovery"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Add project root to sys.path
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
# Add package source directories
|
||||
sys.path.insert(0, str(project_root / "packages" / "py" / "aitbc-core" / "src"))
|
||||
sys.path.insert(0, str(project_root / "packages" / "py" / "aitbc-crypto" / "src"))
|
||||
sys.path.insert(0, str(project_root / "packages" / "py" / "aitbc-p2p" / "src"))
|
||||
sys.path.insert(0, str(project_root / "packages" / "py" / "aitbc-sdk" / "src"))
|
||||
|
||||
# Add app source directories
|
||||
sys.path.insert(0, str(project_root / "apps" / "coordinator-api" / "src"))
|
||||
sys.path.insert(0, str(project_root / "apps" / "wallet-daemon" / "src"))
|
||||
sys.path.insert(0, str(project_root / "apps" / "blockchain-node" / "src"))
|
||||
@@ -1,10 +0,0 @@
|
||||
[tool:pytest]
|
||||
# Simple pytest configuration for test discovery
|
||||
|
||||
# Test discovery patterns
|
||||
python_files = test_*.py *_test.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
|
||||
# Minimal options for discovery
|
||||
addopts = --collect-only
|
||||
@@ -1,9 +0,0 @@
|
||||
"""Test file to verify pytest discovery is working"""
|
||||
|
||||
def test_pytest_discovery():
|
||||
"""Simple test to verify pytest can discover test files"""
|
||||
assert True
|
||||
|
||||
def test_another_discovery_test():
|
||||
"""Another test to verify multiple tests are discovered"""
|
||||
assert 1 + 1 == 2
|
||||
@@ -1,26 +0,0 @@
|
||||
"""
|
||||
Test file to verify Windsorf test integration is working
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_pytest_discovery():
|
||||
"""Simple test to verify pytest can discover this file"""
|
||||
assert True
|
||||
|
||||
|
||||
def test_windsurf_integration():
|
||||
"""Test that Windsurf test runner is working"""
|
||||
assert "windsurf" in "windsurf test integration"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("input,expected", [
|
||||
(1, 2),
|
||||
(2, 4),
|
||||
(3, 6),
|
||||
])
|
||||
def test_multiplication(input, expected):
|
||||
"""Parameterized test example"""
|
||||
result = input * 2
|
||||
assert result == expected
|
||||
Reference in New Issue
Block a user