261 lines
10 KiB
Python
261 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Comprehensive Test Script for Debian Atomic Variants
|
|
Tests all variants using the alternative debootstrap + ostree solution
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import tempfile
|
|
import time
|
|
from pathlib import Path
|
|
from typing import List, Dict, Any
|
|
|
|
class DebianAtomicTester:
|
|
"""Test all Debian Atomic variants"""
|
|
|
|
def __init__(self, work_dir: str = None):
|
|
self.work_dir = Path(work_dir) if work_dir else Path(tempfile.mkdtemp(prefix="debian-atomic-test-"))
|
|
self.results = {}
|
|
|
|
def test_variant(self, variant: str) -> Dict[str, Any]:
|
|
"""Test a specific variant"""
|
|
print(f"\n{'='*60}")
|
|
print(f"Testing variant: {variant}")
|
|
print(f"{'='*60}")
|
|
|
|
start_time = time.time()
|
|
result = {
|
|
"variant": variant,
|
|
"status": "unknown",
|
|
"start_time": start_time,
|
|
"end_time": None,
|
|
"duration": None,
|
|
"errors": [],
|
|
"warnings": [],
|
|
"output": {}
|
|
}
|
|
|
|
try:
|
|
# Test the variant build
|
|
cmd = [
|
|
"python3", "create-debian-atomic.py", variant, str(self.work_dir / variant)
|
|
]
|
|
|
|
print(f"Running: {' '.join(cmd)}")
|
|
process = subprocess.run(
|
|
cmd,
|
|
capture_output=True,
|
|
text=True,
|
|
cwd=Path(__file__).parent
|
|
)
|
|
|
|
result["output"]["stdout"] = process.stdout
|
|
result["output"]["stderr"] = process.stderr
|
|
result["output"]["returncode"] = process.returncode
|
|
|
|
if process.returncode == 0:
|
|
result["status"] = "success"
|
|
print(f"✅ {variant} variant built successfully")
|
|
|
|
# Verify the repository was created
|
|
repo_path = self.work_dir / variant / "repo"
|
|
if repo_path.exists():
|
|
# Test OSTree operations
|
|
self.test_ostree_operations(repo_path, variant, result)
|
|
else:
|
|
result["warnings"].append("Repository directory not found")
|
|
|
|
else:
|
|
result["status"] = "failed"
|
|
result["errors"].append(f"Build failed with return code {process.returncode}")
|
|
print(f"❌ {variant} variant build failed")
|
|
if process.stderr:
|
|
print(f"Error: {process.stderr}")
|
|
|
|
except Exception as e:
|
|
result["status"] = "error"
|
|
result["errors"].append(f"Exception during build: {str(e)}")
|
|
print(f"❌ {variant} variant build error: {e}")
|
|
|
|
finally:
|
|
end_time = time.time()
|
|
result["end_time"] = end_time
|
|
result["duration"] = end_time - start_time
|
|
|
|
return result
|
|
|
|
def test_ostree_operations(self, repo_path: Path, variant: str, result: Dict[str, Any]):
|
|
"""Test basic OSTree operations on the repository"""
|
|
try:
|
|
print(f"Testing OSTree operations for {variant}")
|
|
|
|
# Test listing refs
|
|
cmd = ["ostree", "refs", "--repo", str(repo_path)]
|
|
process = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
refs = process.stdout.strip().split('\n') if process.stdout.strip() else []
|
|
|
|
result["output"]["ostree_refs"] = refs
|
|
print(f"OSTree refs: {refs}")
|
|
|
|
# Test listing commits
|
|
if refs:
|
|
ref = refs[0] # Use first ref
|
|
cmd = ["ostree", "log", "--repo", str(repo_path), ref]
|
|
process = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
result["output"]["ostree_log"] = process.stdout
|
|
print(f"OSTree log for {ref}: {process.stdout[:200]}...")
|
|
|
|
# Test commit info
|
|
cmd = ["ostree", "show", "--repo", str(repo_path), ref]
|
|
process = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
|
result["output"]["ostree_show"] = process.stdout
|
|
print(f"OSTree commit info: {process.stdout[:200]}...")
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
result["warnings"].append(f"OSTree operation failed: {e}")
|
|
print(f"Warning: OSTree operation failed: {e}")
|
|
except Exception as e:
|
|
result["warnings"].append(f"OSTree test error: {e}")
|
|
print(f"Warning: OSTree test error: {e}")
|
|
|
|
def test_all_variants(self) -> Dict[str, Any]:
|
|
"""Test all supported variants"""
|
|
variants = ["minimal", "gnome", "plasma", "cosmic", "sway", "budgie"]
|
|
|
|
print(f"Testing all Debian Atomic variants")
|
|
print(f"Work directory: {self.work_dir}")
|
|
print(f"Variants to test: {', '.join(variants)}")
|
|
|
|
for variant in variants:
|
|
self.results[variant] = self.test_variant(variant)
|
|
|
|
return self.results
|
|
|
|
def generate_report(self) -> str:
|
|
"""Generate a comprehensive test report"""
|
|
report = []
|
|
report.append("# Debian Atomic Variants Test Report")
|
|
report.append(f"Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
report.append(f"Work directory: {self.work_dir}")
|
|
report.append("")
|
|
|
|
# Summary
|
|
total = len(self.results)
|
|
successful = sum(1 for r in self.results.values() if r["status"] == "success")
|
|
failed = sum(1 for r in self.results.values() if r["status"] == "failed")
|
|
errors = sum(1 for r in self.results.values() if r["status"] == "error")
|
|
|
|
report.append("## Summary")
|
|
report.append(f"- Total variants tested: {total}")
|
|
report.append(f"- Successful builds: {successful}")
|
|
report.append(f"- Failed builds: {failed}")
|
|
report.append(f"- Build errors: {errors}")
|
|
report.append(f"- Success rate: {(successful/total)*100:.1f}%")
|
|
report.append("")
|
|
|
|
# Detailed results
|
|
report.append("## Detailed Results")
|
|
for variant, result in self.results.items():
|
|
status_emoji = "✅" if result["status"] == "success" else "❌"
|
|
report.append(f"### {status_emoji} {variant}")
|
|
report.append(f"- Status: {result['status']}")
|
|
report.append(f"- Duration: {result['duration']:.2f}s")
|
|
|
|
if result["errors"]:
|
|
report.append("- Errors:")
|
|
for error in result["errors"]:
|
|
report.append(f" - {error}")
|
|
|
|
if result["warnings"]:
|
|
report.append("- Warnings:")
|
|
for warning in result["warnings"]:
|
|
report.append(f" - {warning}")
|
|
|
|
if result["status"] == "success":
|
|
repo_path = self.work_dir / variant / "repo"
|
|
report.append(f"- Repository: {repo_path}")
|
|
if "ostree_refs" in result["output"]:
|
|
report.append(f"- OSTree refs: {', '.join(result['output']['ostree_refs'])}")
|
|
|
|
report.append("")
|
|
|
|
# Recommendations
|
|
report.append("## Recommendations")
|
|
if successful == total:
|
|
report.append("🎉 All variants built successfully! The alternative solution is working perfectly.")
|
|
elif successful > total / 2:
|
|
report.append("⚠️ Most variants built successfully, but some issues need investigation.")
|
|
else:
|
|
report.append("🚨 Multiple variants failed. The alternative solution needs significant work.")
|
|
|
|
report.append("")
|
|
report.append("## Next Steps")
|
|
if successful > 0:
|
|
report.append("1. Test bootable image generation with successful variants")
|
|
report.append("2. Integrate with deb-bootc-image-builder")
|
|
report.append("3. Validate system boot and functionality")
|
|
else:
|
|
report.append("1. Investigate and fix build failures")
|
|
report.append("2. Verify dependencies and environment")
|
|
report.append("3. Test individual components")
|
|
|
|
return "\n".join(report)
|
|
|
|
def cleanup(self):
|
|
"""Clean up test artifacts"""
|
|
try:
|
|
if self.work_dir.exists():
|
|
import shutil
|
|
shutil.rmtree(self.work_dir)
|
|
print(f"Cleaned up test directory: {self.work_dir}")
|
|
except Exception as e:
|
|
print(f"Warning: Could not clean up {self.work_dir}: {e}")
|
|
|
|
def main():
|
|
"""Main function"""
|
|
if len(sys.argv) > 1 and sys.argv[1] == "--keep":
|
|
work_dir = None
|
|
cleanup = False
|
|
print("Keeping test artifacts (--keep specified)")
|
|
else:
|
|
work_dir = None
|
|
cleanup = True
|
|
print("Test artifacts will be cleaned up automatically")
|
|
|
|
tester = DebianAtomicTester(work_dir)
|
|
|
|
try:
|
|
# Test all variants
|
|
results = tester.test_all_variants()
|
|
|
|
# Generate and display report
|
|
report = tester.generate_report()
|
|
print("\n" + "="*80)
|
|
print(report)
|
|
print("="*80)
|
|
|
|
# Save report to file
|
|
report_file = Path(__file__).parent / "test-report.md"
|
|
with open(report_file, 'w') as f:
|
|
f.write(report)
|
|
print(f"\nTest report saved to: {report_file}")
|
|
|
|
# Exit with appropriate code
|
|
successful = sum(1 for r in results.values() if r["status"] == "success")
|
|
total = len(results)
|
|
|
|
if successful == total:
|
|
print(f"\n🎉 All {total} variants tested successfully!")
|
|
sys.exit(0)
|
|
else:
|
|
print(f"\n⚠️ {successful}/{total} variants tested successfully")
|
|
sys.exit(1)
|
|
|
|
finally:
|
|
if cleanup:
|
|
tester.cleanup()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|