#!/usr/bin/env python3 """ Comprehensive Test Suite for Multi-Network Bitcoin Wallet Manager Tests all network modes with edge cases and security validation """ import json import datetime from typing import Dict, List, Any, Tuple import unittest from multi_network_wallet import ( MultiNetworkWalletManager, BitcoinNetwork, SecurityValidator ) from network_validator import NetworkConfigValidator from security_validator import ( PrivateKeySecurityValidator, SecurityAuditor, SecurityLevel ) class TestMultiNetworkWallet(unittest.TestCase): """Test cases for multi-network wallet functionality""" def setUp(self): """Set up test fixtures""" self.networks = [BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET, BitcoinNetwork.REGTEST] self.test_credentials = { "username": "test_user_12345678", "password": "SecureTestPassword123!@#" } def test_network_initialization(self): """Test wallet manager initialization for all networks""" for network in self.networks: with self.subTest(network=network): manager = MultiNetworkWalletManager(network) self.assertEqual(manager.network, network) self.assertIsNotNone(manager.config) self.assertFalse(manager.connected) self.assertIsNone(manager.wallet_info) def test_network_configuration_validation(self): """Test network configuration validation""" validator = NetworkConfigValidator() for network in self.networks: with self.subTest(network=network): result = validator.validate_complete_config(network) # All default configurations should be valid self.assertTrue(result.is_valid, f"Config validation failed for {network.value}") self.assertGreater(result.security_score, 70) # Check for essential config items are present in validation rules self.assertIn("magic_bytes", validator.validation_rules) self.assertIn("port_security", validator.validation_rules) def test_connection_simulation(self): """Test connection simulation for all networks""" for network in self.networks: with self.subTest(network=network): manager = MultiNetworkWalletManager(network) # Test invalid credentials bad_result = manager.simulate_connection("short", "weak") self.assertFalse(bad_result["success"]) self.assertIn("Invalid RPC credentials", bad_result["error"]) # Test valid credentials good_result = manager.simulate_connection( self.test_credentials["username"], self.test_credentials["password"] ) self.assertTrue(good_result["success"]) self.assertEqual(good_result["network"], network.value) self.assertTrue(good_result["connection_time"]) # Disconnect for next test manager.connected = False def test_wallet_creation(self): """Test wallet creation across all networks""" for network in self.networks: with self.subTest(network=network): manager = MultiNetworkWalletManager(network) manager.connected = True # Simulate connection # Test valid wallet creation result = manager.create_wallet("test_wallet", "strong_passphrase") self.assertTrue(result["success"]) self.assertEqual(result["network"], network.value) self.assertTrue(result["encrypted"]) self.assertIsNotNone(result["addresses"]["receiving"]) self.assertIsNotNone(result["addresses"]["change"]) # Test invalid wallet names invalid_names = ["", "a" * 101, "wallet<>", "wallet/name"] for invalid_name in invalid_names: bad_result = manager.create_wallet(invalid_name) self.assertFalse(bad_result["success"]) def test_network_switching(self): """Test network switching functionality""" manager = MultiNetworkWalletManager(BitcoinNetwork.MAINNET) # Test switching when not connected result = manager.switch_network(BitcoinNetwork.TESTNET) self.assertTrue(result["success"]) self.assertEqual(manager.network, BitcoinNetwork.TESTNET) # Test switching when connected (should fail) manager.connected = True result = manager.switch_network(BitcoinNetwork.REGTEST) self.assertFalse(result["success"]) self.assertIn("Cannot switch network while connected", result["error"]) def test_private_key_import(self): """Test private key import validation""" manager = MultiNetworkWalletManager(BitcoinNetwork.TESTNET) manager.connected = True # Test valid private key format (example) valid_key = "L5EZftvrYaSudioKJRm4iWfJNPZzmFTQqYq9R5dGGKZBUs7j4Mt9" result = manager.import_private_key(valid_key, "test_import") self.assertTrue(result["success"]) self.assertEqual(result["network"], BitcoinNetwork.TESTNET.value) # Test invalid private key formats invalid_keys = [ "invalid_key", "123", "too_short", "L" + "a" * 60 # Invalid base58 ] for invalid_key in invalid_keys: result = manager.import_private_key(invalid_key) self.assertFalse(result["success"]) def test_address_validation(self): """Test address validation across networks""" validator = SecurityValidator() # Test mainnet addresses mainnet_addresses = { "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa": True, # Valid legacy "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh": True, # Valid bech32 "invalid_address": False, "1invalid": False } for address, expected in mainnet_addresses.items(): result = validator.validate_address_format(address, BitcoinNetwork.MAINNET) self.assertEqual(result, expected, f"Address {address} validation failed") # Test testnet addresses testnet_addresses = { "mipcBbFg9gmiCh1Bcfs9vE5EUhU8YxEfjL": True, # Valid testnet "2MzQwSSnBHWHqAFqtbgEAEtVeCesct6x9cj": True, # Valid testnet P2SH "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa": False # Mainnet address on testnet } for address, expected in testnet_addresses.items(): result = validator.validate_address_format(address, BitcoinNetwork.TESTNET) self.assertEqual(result, expected, f"Testnet address {address} validation failed") class TestSecurityValidation(unittest.TestCase): """Test security validation functionality""" def setUp(self): """Set up test fixtures""" self.validator = PrivateKeySecurityValidator() self.auditor = SecurityAuditor() def test_private_key_security_validation(self): """Test private key security validation""" # Test valid private key valid_key = "L5EZftvrYaSudioKJRm4iWfJNPZzmFTQqYq9R5dGGKZBUs7j4Mt9" result = self.validator.validate_private_key_security(valid_key) self.assertTrue(result["valid"]) self.assertGreater(result["entropy_score"], 3.0) # Test invalid format invalid_key = "not_a_valid_key" result = self.validator.validate_private_key_security(invalid_key) self.assertFalse(result["valid"]) self.assertIn("Invalid WIF format", result["issues"]) def test_wallet_encryption_validation(self): """Test wallet passphrase validation""" # Test weak passphrase weak_pass = "weak123" result = self.validator.validate_wallet_encryption(weak_pass) self.assertFalse(result["valid"]) self.assertEqual(result["security_level"], SecurityLevel.LOW.value) # Test strong passphrase strong_pass = "VerySecurePassphrase!@#$%^&*()_+2024" result = self.validator.validate_wallet_encryption(strong_pass) self.assertTrue(result["valid"]) self.assertEqual(result["security_level"], SecurityLevel.HIGH.value) self.assertGreater(result["strength_score"], 75) def test_security_audit(self): """Test security auditing functionality""" # Test wallet creation audit audit = self.auditor.audit_wallet_creation( "secure_wallet_123", "SecureWalletPassphrase!@#2024", BitcoinNetwork.MAINNET ) self.assertTrue(audit.passed) self.assertIsNotNone(audit.audit_timestamp) # Test private key operation audit key_audit = self.auditor.audit_private_key_operation( "import", "L5EZftvrYaSudioKJRm4iWfJNPZzmFTQqYq9R5dGGKZBUs7j4Mt9", "test" ) self.assertIsNotNone(key_audit.level) self.assertEqual(len(self.auditor.audit_log), 2) class TestEdgeCases(unittest.TestCase): """Test edge cases and error conditions""" def test_empty_inputs(self): """Test handling of empty inputs""" manager = MultiNetworkWalletManager() manager.connected = True # Simulate connection # Test empty wallet name result = manager.create_wallet("") self.assertFalse(result["success"]) self.assertIn("Invalid wallet name", result["error"]) # Test empty private key result = manager.import_private_key("") self.assertFalse(result["success"]) def test_extreme_values(self): """Test extreme input values""" manager = MultiNetworkWalletManager() manager.connected = True # Test very long wallet name long_name = "a" * 200 result = manager.create_wallet(long_name) self.assertFalse(result["success"]) self.assertIn("too long", result["error"]) # Test special characters in wallet name special_names = ["wallet<>", "wallet|pipe", "wallet\"quote", "wallet/apostrophe"] for name in special_names: result = manager.create_wallet(name) self.assertFalse(result["success"]) def test_network_conflicts(self): """Test network conflict scenarios""" validator = NetworkConfigValidator() # Test that networks have unique configurations mainnet_config = NETWORK_CONFIGS[BitcoinNetwork.MAINNET] testnet_config = NETWORK_CONFIGS[BitcoinNetwork.TESTNET] # Ports should be different self.assertNotEqual(mainnet_config.rpc_port, testnet_config.rpc_port) # Magic bytes should be different self.assertNotEqual(mainnet_config.magic_bytes, testnet_config.magic_bytes) def run_comprehensive_tests(): """Run all test suites and generate report""" print("=== Multi-Network Bitcoin Wallet Test Suite ===\n") # Create test suite test_suite = unittest.TestSuite() # Add test cases test_classes = [ TestMultiNetworkWallet, TestSecurityValidation, TestEdgeCases ] for test_class in test_classes: tests = unittest.TestLoader().loadTestsFromTestCase(test_class) test_suite.addTests(tests) # Run tests runner = unittest.TextTestRunner(verbosity=2) result = runner.run(test_suite) # Generate test report report = { "test_run_time": datetime.datetime.now().isoformat(), "total_tests": result.testsRun, "failures": len(result.failures), "errors": len(result.errors), "success_rate": (result.testsRun - len(result.failures) - len(result.errors)) / result.testsRun * 100, "test_results": [] } # Add detailed failure information for test, traceback in result.failures: report["test_results"].append({ "test": str(test), "status": "FAILED", "traceback": traceback }) for test, traceback in result.errors: report["test_results"].append({ "test": str(test), "status": "ERROR", "traceback": traceback }) # Save test report with open("test_report.json", "w") as f: json.dump(report, f, indent=2) print(f"\n=== Test Report ===") print(f"Total Tests: {report['total_tests']}") print(f"Success Rate: {report['success_rate']:.1f}%") print(f"Failures: {report['failures']}") print(f"Errors: {report['errors']}") print(f"Report saved to: test_report.json") return result.wasSuccessful() def demo_comprehensive_functionality(): """Demonstrate all functionality working together""" print("=== Comprehensive Multi-Network Demo ===\n") # Test all networks networks = [BitcoinNetwork.MAINNET, BitcoinNetwork.TESTNET, BitcoinNetwork.REGTEST] for network in networks: print(f"--- {network.value.upper()} Network Demo ---") # Initialize wallet manager manager = MultiNetworkWalletManager(network) # Show network info info = manager.get_network_info() print(f"Network: {info['network']}") print(f"RPC Port: {info['config']['rpc_port']}") # Validate configuration validator = NetworkConfigValidator() validation = validator.validate_complete_config(network) print(f"Config Valid: {'✅' if validation.is_valid else '❌'}") print(f"Security Score: {validation.security_score:.1f}/100") # Connect conn_result = manager.simulate_connection("demo_user", "DemoPass123!@#") if conn_result['success']: print(f"✅ Connected to {conn_result['server_version']}") # Create secure wallet secure_pass = PrivateKeySecurityValidator().generate_secure_wallet_passphrase() wallet_result = manager.create_wallet(f"demo_{network.value}", secure_pass) if wallet_result['success']: print(f"✅ Wallet created: {wallet_result['wallet_name']}") print(f"Receive Address: {wallet_result['addresses']['receiving']}") print(f"Encrypted: {'✅' if wallet_result['encrypted'] else '❌'}") print() # Security audit summary print("--- Security Audit Summary ---") auditor = SecurityAuditor() print(f"Audit log entries: {len(auditor.audit_log)}") if auditor.audit_log: latest_audit = auditor.audit_log[-1] print(f"Latest audit status: {'✅ PASSED' if latest_audit.passed else '❌ FAILED'}") print(f"Security level: {latest_audit.level.value}") if __name__ == "__main__": # Import required for demo from multi_network_wallet import NETWORK_CONFIGS # Run comprehensive functionality demo demo_comprehensive_functionality() print("\n" + "="*50 + "\n") # Run test suite success = run_comprehensive_tests() if success: print("✅ All tests passed! Multi-network implementation is ready.") else: print("❌ Some tests failed. Review test_report.json for details.")