#!/usr/bin/env python3 """ Test Composer Build Management for Debian Forge This script tests the composer build management components including status monitoring and build history. """ import json import os import sys import tempfile import time from pathlib import Path from datetime import datetime # Add current directory to Python path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) def test_status_monitor_import(): """Test importing the status monitor""" print("Testing status monitor import...") try: from composer_status_monitor import StatusMonitor, StatusNotifier, ConsoleStatusDisplay, BuildProgress, BuildStatus print(" ✅ Status monitor imported successfully") return True except ImportError as e: print(f" ❌ Failed to import status monitor: {e}") return False def test_build_history_import(): """Test importing the build history""" print("\nTesting build history import...") try: from composer_build_history import BuildHistoryDB, BuildHistoryManager, BuildRecord print(" ✅ Build history imported successfully") return True except ImportError as e: print(f" ❌ Failed to import build history: {e}") return False def test_build_progress_dataclass(): """Test BuildProgress dataclass""" print("\nTesting BuildProgress dataclass...") try: from composer_status_monitor import BuildProgress progress = BuildProgress( stage="debootstrap", progress=0.5, message="Installing base system", timestamp=datetime.now() ) if progress.stage != "debootstrap": print(" ❌ Stage field not set correctly") return False if progress.progress != 0.5: print(" ❌ Progress field not set correctly") return False print(" ✅ BuildProgress dataclass works correctly") return True except Exception as e: print(f" ❌ BuildProgress test failed: {e}") return False def test_build_status_dataclass(): """Test BuildStatus dataclass""" print("\nTesting BuildStatus dataclass...") try: from composer_status_monitor import BuildStatus, BuildProgress progress_list = [ BuildProgress("debootstrap", 0.5, "Installing base system", datetime.now()) ] status = BuildStatus( build_id="test-123", status="RUNNING", created_at=datetime.now(), updated_at=datetime.now(), blueprint="debian-atomic-base", target="qcow2", architecture="amd64", progress=progress_list, logs=["Build started", "Debootstrap in progress"] ) if status.build_id != "test-123": print(" ❌ Build ID field not set correctly") return False if len(status.progress) != 1: print(" ❌ Progress list not set correctly") return False print(" ✅ BuildStatus dataclass works correctly") return True except Exception as e: print(f" ❌ BuildStatus test failed: {e}") return False def test_build_record_dataclass(): """Test BuildRecord dataclass""" print("\nTesting BuildRecord dataclass...") try: from composer_build_history import BuildRecord record = BuildRecord( build_id="test-123", blueprint="debian-atomic-base", target="qcow2", architecture="amd64", status="FINISHED", created_at=datetime.now(), completed_at=datetime.now(), duration=120.5, metadata={"priority": "normal"}, logs=["Build completed successfully"], artifacts=["debian-atomic-base.qcow2"], error_message=None ) if record.build_id != "test-123": print(" ❌ Build ID field not set correctly") return False if record.duration != 120.5: print(" ❌ Duration field not set correctly") return False print(" ✅ BuildRecord dataclass works correctly") return True except Exception as e: print(f" ❌ BuildRecord test failed: {e}") return False def test_build_history_database(): """Test build history database operations""" print("\nTesting build history database...") try: from composer_build_history import BuildHistoryDB, BuildRecord # Create temporary database with tempfile.NamedTemporaryFile(suffix='.db', delete=False) as f: db_path = f.name try: db = BuildHistoryDB(db_path) # Test adding a build record record = BuildRecord( build_id="test-db-123", blueprint="debian-atomic-base", target="qcow2", architecture="amd64", status="RUNNING", created_at=datetime.now(), completed_at=None, duration=None, metadata={}, logs=[], artifacts=[], error_message=None ) if not db.add_build(record): print(" ❌ Failed to add build record") return False # Test retrieving the build record retrieved = db.get_build("test-db-123") if not retrieved: print(" ❌ Failed to retrieve build record") return False if retrieved.build_id != "test-db-123": print(" ❌ Retrieved build ID doesn't match") return False # Test updating build status if not db.update_build_status("test-db-123", status="FINISHED", duration=60.0): print(" ❌ Failed to update build status") return False # Test statistics stats = db.get_build_statistics() if stats['total_builds'] != 1: print(" ❌ Statistics not working correctly") return False print(" ✅ Build history database works correctly") return True finally: # Clean up os.unlink(db_path) except Exception as e: print(f" ❌ Build history database test failed: {e}") return False def test_build_history_manager(): """Test build history manager""" print("\nTesting build history manager...") try: from composer_build_history import BuildHistoryManager # Create temporary database with tempfile.NamedTemporaryFile(suffix='.db', delete=False) as f: db_path = f.name try: manager = BuildHistoryManager(db_path) # Test starting a build if not manager.start_build("test-manager-123", "debian-atomic-base", "qcow2", "amd64"): print(" ❌ Failed to start build") return False # Test updating build progress if not manager.update_build_progress("test-manager-123", "RUNNING", logs=["Build in progress"]): print(" ❌ Failed to update build progress") return False # Test completing a build if not manager.update_build_progress("test-manager-123", "FINISHED", artifacts=["image.qcow2"]): print(" ❌ Failed to complete build") return False # Test getting build summary summary = manager.get_build_summary() if summary['total_builds'] != 1: print(" ❌ Build summary not working correctly") return False print(" ✅ Build history manager works correctly") return True finally: # Clean up os.unlink(db_path) except Exception as e: print(f" ❌ Build history manager test failed: {e}") return False def test_status_notifier(): """Test status notifier""" print("\nTesting status notifier...") try: from composer_status_monitor import StatusNotifier notifier = StatusNotifier() # Test notification notifier.notify("build_completed", "Build test-123 completed successfully") # Test notification history history = notifier.get_notification_history() if len(history) != 1: print(" ❌ Notification history not working correctly") return False if history[0]['type'] != "build_completed": print(" ❌ Notification type not set correctly") return False print(" ✅ Status notifier works correctly") return True except Exception as e: print(f" ❌ Status notifier test failed: {e}") return False def test_console_status_display(): """Test console status display""" print("\nTesting console status display...") try: from composer_status_monitor import ConsoleStatusDisplay, BuildStatus, BuildProgress display = ConsoleStatusDisplay() # Create test build status progress_list = [ BuildProgress("debootstrap", 0.75, "Installing packages", datetime.now()) ] status = BuildStatus( build_id="test-display-123", status="RUNNING", created_at=datetime.now(), updated_at=datetime.now(), blueprint="debian-atomic-base", target="qcow2", architecture="amd64", progress=progress_list, logs=["Build started", "Debootstrap in progress"], metadata=None ) # Test display (this should not fail) display.display_build_status(status) print(" ✅ Console status display works correctly") return True except Exception as e: print(f" ❌ Console status display test failed: {e}") return False def main(): """Main test function""" print("Composer Build Management Test for Debian Forge") print("=" * 60) tests = [ ("Status Monitor Import", test_status_monitor_import), ("Build History Import", test_build_history_import), ("BuildProgress Dataclass", test_build_progress_dataclass), ("BuildStatus Dataclass", test_build_status_dataclass), ("BuildRecord Dataclass", test_build_record_dataclass), ("Build History Database", test_build_history_database), ("Build History Manager", test_build_history_manager), ("Status Notifier", test_status_notifier), ("Console Status Display", test_console_status_display) ] results = [] for test_name, test_func in tests: try: result = test_func() results.append((test_name, result)) except Exception as e: print(f" ❌ {test_name} test failed with exception: {e}") results.append((test_name, False)) # Summary print("\n" + "=" * 60) print("TEST SUMMARY") print("=" * 60) passed = 0 total = len(results) for test_name, result in results: status = "✅ PASS" if result else "❌ FAIL" print(f"{test_name}: {status}") if result: passed += 1 print(f"\nOverall: {passed}/{total} tests passed") if passed == total: print("🎉 All tests passed! Composer build management is ready.") return 0 else: print("⚠️ Some tests failed. Please review the issues above.") return 1 if __name__ == '__main__': sys.exit(main())