provisioning/tools/build/test-distribution.nu

491 lines
14 KiB
Plaintext
Raw Normal View History

2025-10-07 11:12:02 +01:00
#!/usr/bin/env nu
# Distribution testing tool - tests generated distributions for functionality
#
# Tests:
# - Binary execution and basic functionality
# - Core library loading and imports
# - Configuration system
# - Template rendering
# - Integration tests
use std log
def main [
--dist-dir: string = "dist" # Distribution directory to test
--test-types: string = "all" # Test types: all, basic, integration, performance
--platform: string = "" # Target platform (auto-detect if empty)
--temp-workspace: string = "" # Temporary workspace for tests (auto-generated if empty)
--cleanup # Cleanup test workspace after tests
--verbose # Enable verbose logging
2025-10-07 11:12:02 +01:00
--timeout: int = 300 # Test timeout in seconds
] {
2025-10-07 11:12:02 +01:00
let dist_root = ($dist_dir | path expand)
let platform_detected = if $platform == "" { detect_platform } else { $platform }
let temp_workspace = if $temp_workspace == "" {
$env.TMPDIR | path join $"provisioning-test-(random uuid)"
} else {
$temp_workspace | path expand
}
let test_config = {
dist_dir: $dist_root
test_types: ($test_types | split row "," | each { str trim })
platform: $platform_detected
temp_workspace: $temp_workspace
cleanup: $cleanup
verbose: $verbose
timeout: $timeout
}
log info $"Starting distribution testing with config: ($test_config)"
# Validate distribution directory
if not ($dist_root | path exists) {
log error $"Distribution directory does not exist: ($dist_root)"
exit 1
}
# Create temporary workspace
mkdir ($test_config.temp_workspace)
# Run different test categories
let test_categories = if "all" in $test_config.test_types {
["basic", "integration", "performance"]
} else {
$test_config.test_types
}
2025-10-07 11:12:02 +01:00
let test_results = $test_categories | each {|category|
match $category {
"basic" => { run_basic_tests $test_config }
"integration" => { run_integration_tests $test_config }
"performance" => { run_performance_tests $test_config }
_ => {
log warning $"Unknown test category: ($category)"
{ category: $category, status: "skipped", reason: "unknown category" }
2025-10-07 11:12:02 +01:00
}
}
}
2025-10-07 11:12:02 +01:00
# Generate test report
let test_report = generate_test_report $test_results $test_config
2025-10-07 11:12:02 +01:00
# Cleanup if requested
if $test_config.cleanup {
rm -rf ($test_config.temp_workspace)
log info "Cleaned up test workspace"
}
2025-10-07 11:12:02 +01:00
let summary = {
total_categories: ($test_results | length)
successful_categories: ($test_results | where status == "success" | length)
failed_categories: ($test_results | where status == "failed" | length)
test_config: $test_config
results: $test_results
report: $test_report
}
2025-10-07 11:12:02 +01:00
if $summary.failed_categories > 0 {
log error $"Distribution testing completed with ($summary.failed_categories) failed categories"
2025-10-07 11:12:02 +01:00
exit 1
} else {
log info $"Distribution testing completed successfully - all ($summary.total_categories) categories passed"
2025-10-07 11:12:02 +01:00
}
return $summary
2025-10-07 11:12:02 +01:00
}
# Detect current platform
def detect_platform [] {
2025-10-07 11:12:02 +01:00
match $nu.os-info.name {
"linux" => "linux"
"macos" => "macos"
"windows" => "windows"
_ => "unknown"
}
}
# Run basic functionality tests
def run_basic_tests [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Running basic functionality tests..."
let start_time = (date now)
# Test 1: Platform binaries exist and execute
let platform_test = test_platform_binaries $test_config
# Test 2: Core bundle integrity
let core_test = test_core_bundle $test_config
# Test 3: Configuration system
let config_test = test_configuration_system $test_config
# Test 4: Basic CLI functionality
let cli_test = test_basic_cli $test_config
let test_results = [$platform_test, $core_test, $config_test, $cli_test]
let tests_total = ($test_results | length)
let tests_passed = ($test_results | where status == "success" | length)
let test_errors = ($test_results | each {|t| $t.errors } | flatten)
2025-10-07 11:12:02 +01:00
let success_rate = (($tests_passed | into float) / ($tests_total | into float) * 100)
{
category: "basic"
status: (if ($test_errors | length) > 0 { "failed" } else { "success" })
tests_total: $tests_total
tests_passed: $tests_passed
success_rate: $success_rate
duration: ((date now) - $start_time)
errors: $test_errors
}
}
# Test platform binaries
def test_platform_binaries [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Testing platform binaries..."
let platform_dir = ($test_config.dist_dir | path join "platform")
let errors = []
2025-10-07 11:12:02 +01:00
if not ($platform_dir | path exists) {
return {
status: "failed"
errors: [{ test: "platform_binaries", error: "platform directory not found" }]
}
}
# Find platform binaries
let binaries = (ls $platform_dir | where type == file | get name)
if ($binaries | length) == 0 {
return {
status: "failed"
errors: [{ test: "platform_binaries", error: "no platform binaries found" }]
}
}
# Test each binary
let binary_results = $binaries | each {|binary|
let test_result = (do {
2025-10-07 11:12:02 +01:00
# Test if binary is executable and runs without error
^$binary --help e>| complete
} | complete)
if $test_result.exit_code != 0 {
log error $"Binary failed to execute: ($binary) - ($test_result.stderr)"
{
test: "binary_execution"
binary: $binary
status: "failed"
error: $test_result.stderr
2025-10-07 11:12:02 +01:00
}
} else {
log info $"Binary test passed: ($binary)"
{
2025-10-07 11:12:02 +01:00
test: "binary_execution"
binary: $binary
status: "success"
}
2025-10-07 11:12:02 +01:00
}
}
let errors = ($binary_results | where status == "failed")
2025-10-07 11:12:02 +01:00
return {
status: (if ($errors | length) > 0 { "failed" } else { "success" })
tested_binaries: ($binaries | length)
errors: $errors
}
}
# Test core bundle
def test_core_bundle [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Testing core bundle..."
let core_dir = ($test_config.dist_dir | path join "core")
if not ($core_dir | path exists) {
return {
status: "failed"
errors: [{ test: "core_bundle", error: "core directory not found" }]
}
}
# Test essential directories exist
let essential_dirs = ["bin", "lib"]
let dir_errors = $essential_dirs | each {|dir|
2025-10-07 11:12:02 +01:00
let dir_path = ($core_dir | path join $dir)
if not ($dir_path | path exists) {
{
2025-10-07 11:12:02 +01:00
test: "core_structure"
error: $"Essential directory missing: ($dir)"
}
2025-10-07 11:12:02 +01:00
}
} | flatten
let errors = $dir_errors
2025-10-07 11:12:02 +01:00
# Test provisioning CLI exists
let provisioning_cli = ($core_dir | path join "bin" "provisioning")
let cli_errors = if not ($provisioning_cli | path exists) {
[{
2025-10-07 11:12:02 +01:00
test: "provisioning_cli"
error: "provisioning CLI not found"
}]
2025-10-07 11:12:02 +01:00
} else {
# Test CLI execution
let cli_result = (do {
^$provisioning_cli help e>| complete
} | complete)
if $cli_result.exit_code != 0 {
[{
2025-10-07 11:12:02 +01:00
test: "provisioning_cli"
error: $"CLI execution failed: ($cli_result.stderr)"
}]
} else {
[]
2025-10-07 11:12:02 +01:00
}
}
# Test core libraries exist
let lib_dir = ($core_dir | path join "lib" "lib_provisioning")
let lib_errors = if not ($lib_dir | path exists) {
[{
2025-10-07 11:12:02 +01:00
test: "core_libraries"
error: "Core libraries directory not found"
}]
} else {
[]
2025-10-07 11:12:02 +01:00
}
let all_errors = ($errors | append $cli_errors | append $lib_errors)
2025-10-07 11:12:02 +01:00
return {
status: (if ($all_errors | length) > 0 { "failed" } else { "success" })
errors: $all_errors
2025-10-07 11:12:02 +01:00
}
}
# Test configuration system
def test_configuration_system [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Testing configuration system..."
let config_dir = ($test_config.dist_dir | path join "config")
if not ($config_dir | path exists) {
return {
status: "failed"
errors: [{ test: "configuration_system", error: "config directory not found" }]
}
}
# Test default config exists
let default_config = ($config_dir | path join "config.defaults.toml")
let errors = if not ($default_config | path exists) {
[{
2025-10-07 11:12:02 +01:00
test: "default_config"
error: "config.defaults.toml not found"
}]
2025-10-07 11:12:02 +01:00
} else {
# Test config parsing
let config_result = (do {
2025-10-07 11:12:02 +01:00
let config_data = (open $default_config)
log info $"Default config loaded successfully with ($config_data | columns | length) sections"
{ status: "success" }
} | complete)
if $config_result.exit_code != 0 {
[{
2025-10-07 11:12:02 +01:00
test: "config_parsing"
error: $"Failed to parse default config: ($config_result.stderr)"
}]
} else {
[]
2025-10-07 11:12:02 +01:00
}
}
return {
status: (if ($errors | length) > 0 { "failed" } else { "success" })
errors: $errors
}
}
# Test basic CLI functionality
def test_basic_cli [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Testing basic CLI functionality..."
let provisioning_cli = ($test_config.dist_dir | path join "core" "bin" "provisioning")
if not ($provisioning_cli | path exists) {
return {
status: "failed"
errors: [{ test: "basic_cli", error: "provisioning CLI not found" }]
}
}
# Test basic commands
let test_commands = ["version", "help", "env"]
let cmd_results = $test_commands | each {|cmd|
let cmd_result = (do {
^$provisioning_cli $cmd e>| complete
} | complete)
if $cmd_result.exit_code != 0 {
log error $"CLI command failed: ($cmd) - ($cmd_result.stderr)"
{
test: "cli_command"
command: $cmd
status: "failed"
error: $cmd_result.stderr
2025-10-07 11:12:02 +01:00
}
} else {
log info $"CLI command test passed: ($cmd)"
{
2025-10-07 11:12:02 +01:00
test: "cli_command"
command: $cmd
status: "success"
}
2025-10-07 11:12:02 +01:00
}
}
let errors = ($cmd_results | where status == "failed")
2025-10-07 11:12:02 +01:00
return {
status: (if ($errors | length) > 0 { "failed" } else { "success" })
tested_commands: ($test_commands | length)
errors: $errors
}
}
# Run integration tests
def run_integration_tests [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Running integration tests..."
let start_time = (date now)
let test_errors = []
2025-10-07 11:12:02 +01:00
# Integration tests would include:
# - End-to-end workflow testing
# - Multi-component interaction
# - External dependency integration
# Placeholder for now
log info "Integration tests not implemented yet"
{
category: "integration"
status: "success"
tests_total: 0
tests_passed: 0
success_rate: 100.0
duration: ((date now) - $start_time)
errors: []
}
}
# Run performance tests
def run_performance_tests [test_config: record] {
2025-10-07 11:12:02 +01:00
log info "Running performance tests..."
let start_time = (date now)
let test_errors = []
2025-10-07 11:12:02 +01:00
# Performance tests would include:
# - CLI response time benchmarks
# - Memory usage tests
# - Large configuration handling
# Placeholder for now
log info "Performance tests not implemented yet"
{
category: "performance"
status: "success"
tests_total: 0
tests_passed: 0
success_rate: 100.0
duration: ((date now) - $start_time)
errors: []
}
}
# Generate test report
def generate_test_report [results: list, test_config: record] {
2025-10-07 11:12:02 +01:00
let total_tests = ($results | get tests_total | math sum)
let total_passed = ($results | get tests_passed | math sum)
let overall_success_rate = if $total_tests > 0 {
(($total_passed | into float) / ($total_tests | into float) * 100)
} else {
100.0
}
let report = {
timestamp: (date now)
distribution_directory: $test_config.dist_dir
platform: $test_config.platform
total_categories: ($results | length)
total_tests: $total_tests
total_passed: $total_passed
overall_success_rate: $overall_success_rate
categories: $results
all_errors: ($results | get errors | flatten)
}
# Save report to file
let report_file = ($test_config.temp_workspace | path join "test-report.json")
$report | to json | save $report_file
log info $"Test report saved to: ($report_file)"
return $report
}
# Show distribution info for testing
def "main info" [dist_dir: string = "dist"] {
let dist_root = ($dist_dir | path expand)
if not ($dist_root | path exists) {
log error $"Distribution directory does not exist: ($dist_root)"
exit 1
}
let platform_dir = ($dist_root | path join "platform")
let core_dir = ($dist_root | path join "core")
let config_dir = ($dist_root | path join "config")
{
distribution_directory: $dist_root
platform: (detect_platform)
structure: {
platform: ($platform_dir | path exists)
core: ($core_dir | path exists)
config: ($config_dir | path exists)
}
platform_binaries: (if ($platform_dir | path exists) { ls $platform_dir | where type == file | get name } else { [] })
core_size: (if ($core_dir | path exists) { get_directory_size $core_dir } else { 0 })
config_files: (if ($config_dir | path exists) { ^find $config_dir -name "*.toml" | length } else { 0 })
2025-10-07 11:12:02 +01:00
}
}
# Get directory size helper
def get_directory_size [dir: string]: int -> int {
2025-10-07 11:12:02 +01:00
if not ($dir | path exists) {
return 0
}
let result = (do {
^find $dir -type f | each {|file| ls $file | get 0.size } | math sum
} | complete)
if $result.exit_code != 0 {
return 0
2025-10-07 11:12:02 +01:00
}
let total_size = $result.stdout
2025-10-07 11:12:02 +01:00
return ($total_size | if $in == null { 0 } else { $in })
}