diff --git a/scripts/README-migrate-test.md b/scripts/README-migrate-test.md new file mode 100644 index 000000000..9c60a06ce --- /dev/null +++ b/scripts/README-migrate-test.md @@ -0,0 +1,123 @@ +# Test Migration Script + +## Overview + +The `migrate-test.sh` script is designed to help migrate test files from the root directory to the `tests/` subdirectory in the kickstart-tests repository. This script maintains the improved test organization while preserving backward compatibility. + +## Location + +``` +scripts/migrate-test.sh +``` + +## Features + +- **Automatic Dependency Detection**: Finds and migrates library files referenced by `@KSINCLUDE@` directives +- **Batch Migration**: Can migrate multiple tests in a single command +- **Safety Checks**: Verifies files exist before migration and prompts for confirmation on overwrites +- **Detailed Feedback**: Provides colored output showing migration progress and results +- **List Functionality**: Can list all available tests in the root directory + +## Usage + +### Basic Commands + +```bash +# Show help +scripts/migrate-test.sh --help + +# List all tests available for migration +scripts/migrate-test.sh --list-root + +# Migrate a single test +scripts/migrate-test.sh hostname + +# Migrate multiple tests +scripts/migrate-test.sh hostname lang firewall + +# Migrate tests with dependencies +scripts/migrate-test.sh keyboard # Also migrates post-lib-keyboard.sh and post-nochroot-lib-keyboard.sh +``` + +### What Gets Migrated + +For each test, the script moves: +1. `testname.sh` - The test shell script +2. `testname.ks.in` - The kickstart template file +3. Any dependency files referenced by `@KSINCLUDE@` directives in the kickstart template + +### Example Migration + +```bash +$ scripts/migrate-test.sh hostname +[INFO] Starting test migration process... +[INFO] Root directory: /home/user/kickstart-tests +[INFO] Tests directory: /home/user/kickstart-tests/tests + +---------------------------------------- +[INFO] Migrating test: hostname +[INFO] Found dependencies for hostname: + - post-lib-network.sh +[SUCCESS] Moved shell script: hostname.sh +[SUCCESS] Moved kickstart template: hostname.ks.in +[SUCCESS] Moved dependency: post-lib-network.sh +[SUCCESS] Successfully migrated test: hostname + +======================================== +[INFO] Migration Summary: + Total tests processed: 1 + Successful migrations: 1 + Failed migrations: 0 + +[SUCCESS] Migration completed! You can now run tests using: + ./containers/runner/launch [test_name] + +[INFO] The test framework will automatically find tests in both +[INFO] the root directory and tests/ subdirectory for backward compatibility. +``` + +## Verification + +After migration, verify that the test works correctly: + +```bash +# Test the migrated test with dry-run +./containers/runner/launch hostname --dry-run + +# Run the actual test +./containers/runner/launch -p rhel10 hostname +``` + +## Backward Compatibility + +The test framework has been enhanced to search for tests in both: +1. Root directory (legacy location) +2. `tests/` subdirectory (new organized location) + +This means: +- Existing tests continue to work from the root directory +- Migrated tests work from the tests/ directory +- The `./containers/runner/launch` command automatically finds tests in either location + +## Safety Features + +- **Existence Verification**: Checks that both `.sh` and `.ks.in` files exist before migration +- **Overwrite Protection**: Prompts before overwriting existing files in the destination +- **Dependency Tracking**: Automatically finds and moves library dependencies +- **Error Handling**: Provides clear error messages for missing files or failed operations + +## Script Architecture + +The script consists of several key functions: +- `list_root_tests()`: Lists all available tests for migration +- `migrate_test()`: Migrates a single test with all dependencies +- `find_dependencies()`: Parses kickstart files for `@KSINCLUDE@` references +- `test_exists_in_root()` / `test_exists_in_tests()`: Validation functions + +## Future Enhancements + +Potential improvements could include: +- Reverse migration (from tests/ back to root) +- Batch migration with pattern matching +- Integration with git for automatic commit of migrations +- Validation of migrated tests before completion diff --git a/scripts/migrate-test.sh b/scripts/migrate-test.sh new file mode 100755 index 000000000..6ceffc1db --- /dev/null +++ b/scripts/migrate-test.sh @@ -0,0 +1,642 @@ +#!/bin/bash +# +# migrate-test.sh - Migrate tests from root directory to tests/ subdirectory +# +# This script moves test files (.sh and .ks.in) from the root directory to the tests/ +# subdirectory, along with any library files they depend on via @KSINCLUDE@ directives. +# +# Usage: migrate-test.sh [test1] [test2] [test3] ... +# +# Examples: +# migrate-test.sh hostname +# migrate-test.sh hostname lang firewall +# + +set -e + +SCRIPT_DIR="$(dirname "$(realpath "$0")")" +ROOT_DIR="$(dirname "$SCRIPT_DIR")" +TESTS_DIR="$ROOT_DIR/tests" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Print colored output +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Show usage information +usage() { + cat </dev/null || true + + return 0 + else + print_error "Failed to migrate test: $test_name" + return 1 + fi +} + +# Simple migration without dependency conflict checking (for batch operations) +migrate_test_simple() { + local test_name="$1" + local sh_file="$ROOT_DIR/${test_name}.sh" + local ks_file="$ROOT_DIR/${test_name}.ks.in" + + if ! test_exists_in_root "$test_name"; then + print_warning "Test '$test_name' not found in root directory - skipping" + return 1 + fi + + if test_exists_in_tests "$test_name"; then + print_info "Test '$test_name' already in tests/ directory - skipping" + return 0 + fi + + mkdir -p "$TESTS_DIR" + + local success=0 + + if move_file "$sh_file" "$TESTS_DIR/$(basename "$sh_file")" "shell script"; then + ((success++)) + fi + + if move_file "$ks_file" "$TESTS_DIR/$(basename "$ks_file")" "kickstart template"; then + ((success++)) + fi + + if [[ $success -gt 0 ]]; then + chmod +x "$TESTS_DIR/${test_name}.sh" 2>/dev/null || true + return 0 + fi + + return 1 +} + +# Analyze dependencies for a specific test +analyze_test_dependencies() { + local test_name="$1" + local ks_file="$ROOT_DIR/${test_name}.ks.in" + + if ! test_exists_in_root "$test_name"; then + print_error "Test '$test_name' not found in root directory" + return 1 + fi + + print_info "Dependency analysis for test: $test_name" + + local dependencies=($(find_dependencies "$ks_file")) + + if [[ ${#dependencies[@]} -eq 0 ]]; then + print_success "No dependencies found - safe to migrate" + return 0 + fi + + print_info "Dependencies found:" + + local has_conflicts=false + for dep in "${dependencies[@]}"; do + local usage_info=$(check_dependency_usage "$dep" "$test_name") + local count="${usage_info%%:*}" + local other_tests="${usage_info#*:}" + + if [[ $count -eq 0 ]]; then + echo " ✅ $dep (no conflicts)" + else + echo " ⚠️ $dep (shared with $count other test(s))" + for other_test in $other_tests; do + echo " - $other_test" + done + has_conflicts=true + fi + done + + echo + if [[ $has_conflicts == true ]]; then + print_warning "Migration will require handling shared dependencies" + else + print_success "All dependencies are safe to migrate" + fi +} + +# Analyze all shared dependencies in the repository +analyze_all_dependencies() { + print_info "Analyzing shared dependencies across all tests..." + + declare -A dep_usage + declare -A dep_tests + + # Build dependency usage map + for ks_file in "$ROOT_DIR"/*.ks.in; do + if [[ -f "$ks_file" ]]; then + local test_name=$(basename "$ks_file" .ks.in) + local dependencies=($(find_dependencies "$ks_file")) + + for dep in "${dependencies[@]}"; do + if [[ -z "${dep_usage[$dep]}" ]]; then + dep_usage[$dep]=0 + dep_tests[$dep]="" + fi + + dep_usage[$dep]=$((dep_usage[$dep] + 1)) + if [[ -n "${dep_tests[$dep]}" ]]; then + dep_tests[$dep]="${dep_tests[$dep]} $test_name" + else + dep_tests[$dep]="$test_name" + fi + done + fi + done + + # Display results + local shared_count=0 + local total_deps=0 + + print_info "Dependency usage summary:" + + for dep in "${!dep_usage[@]}"; do + local count=${dep_usage[$dep]} + total_deps=$((total_deps + 1)) + + if [[ $count -gt 1 ]]; then + shared_count=$((shared_count + 1)) + echo " ⚠️ $dep: used by $count tests" + + # Show first few tests + local tests_array=(${dep_tests[$dep]}) + local display_tests="${tests_array[@]:0:5}" + if [[ ${#tests_array[@]} -gt 5 ]]; then + display_tests="$display_tests ..." + fi + echo " Tests: $display_tests" + else + echo " ✅ $dep: used by 1 test (${dep_tests[$dep]})" + fi + done + + echo + print_info "Summary:" + echo " Total dependencies: $total_deps" + echo " Shared dependencies: $shared_count" + echo " Unique dependencies: $((total_deps - shared_count))" + + if [[ $shared_count -gt 0 ]]; then + echo + print_warning "Consider migrating tests with shared dependencies together" + print_info "Use --check-test to analyze specific tests" + fi +} + +# Main script +main() { + cd "$ROOT_DIR" + + # Handle special arguments + case "${1:-}" in + --help|-h) + usage + exit 0 + ;; + --list-root) + list_root_tests + exit 0 + ;; + --analyze-dependencies) + analyze_all_dependencies + exit 0 + ;; + --check-test) + if [[ -z "${2:-}" ]]; then + print_error "Test name required for --check-test option" + echo + usage + exit 1 + fi + analyze_test_dependencies "$2" + exit 0 + ;; + "") + print_error "No test names provided" + echo + usage + exit 1 + ;; + esac + + print_info "Starting test migration process..." + print_info "Root directory: $ROOT_DIR" + print_info "Tests directory: $TESTS_DIR" + echo + + local total_tests=$# + local successful_migrations=0 + local failed_migrations=0 + + # Process each test + for test_name in "$@"; do + echo "----------------------------------------" + if migrate_test "$test_name"; then + ((successful_migrations++)) + else + ((failed_migrations++)) + fi + echo + done + + # Summary + echo "========================================" + print_info "Migration Summary:" + echo " Total tests processed: $total_tests" + echo " Successful migrations: $successful_migrations" + echo " Failed migrations: $failed_migrations" + + if [[ $successful_migrations -gt 0 ]]; then + echo + print_success "Migration completed! You can now run tests using:" + echo " ./containers/runner/launch [test_name]" + echo + print_info "The test framework will automatically find tests in both" + print_info "the root directory and tests/ subdirectory for backward compatibility." + fi + + return $failed_migrations +} + +# Run main function with all arguments +main "$@" diff --git a/scripts/run_kickstart_tests.sh b/scripts/run_kickstart_tests.sh index e4624208e..ad88df0a7 100755 --- a/scripts/run_kickstart_tests.sh +++ b/scripts/run_kickstart_tests.sh @@ -211,14 +211,24 @@ function should_skip_test() { return 1 } -# Find all tests in the . folder. These tests will be filtered by TESTTYPE parameter -# if specified. +# Find all tests in both the root folder and tests/ subfolder for backward compatibility. +# These tests will be filtered by TESTTYPE parameter if specified. function find_tests() { - local tests=$(find . -maxdepth 1 -name '*.sh' -a -perm -o+x) + # Search in both root directory and tests/ subdirectory + local tests_root=$(find . -maxdepth 1 -name '*.sh' -a -perm -o+x) + local tests_subdir="" + if [[ -d tests ]]; then + tests_subdir=$(find tests -maxdepth 1 -name '*.sh' -a -perm -o+x) + fi + + local tests="${tests_root} ${tests_subdir}" local newtests="" local skipped_tests="" for f in ${tests}; do + # Skip empty entries from string concatenation + [[ -z "${f}" ]] && continue + if should_skip_test ${f}; then skipped_tests+="${f}" elif [[ "$TESTTYPE" != "" && "$(grep TESTTYPE= ${f})" =~ "${TESTTYPE}" ]]; then @@ -255,8 +265,19 @@ if [[ $# != 0 ]]; then else test="${t}.sh" fi - if ! should_skip_test ${test}; then - tests+="${test} " + + # Check for test in current directory first (backward compatibility) + if [[ -f "${test}" ]]; then + if ! should_skip_test ${test}; then + tests+="${test} " + fi + # Check for test in tests/ subdirectory + elif [[ -f "tests/${test}" ]]; then + if ! should_skip_test "tests/${test}"; then + tests+="tests/${test} " + fi + else + echo "Warning: Test ${test} not found in root directory or tests/ subdirectory" fi done elif [[ "${ghprbActualCommit}" != "" ]]; then @@ -264,25 +285,31 @@ elif [[ "${ghprbActualCommit}" != "" ]]; then tests="" candidates="$(for f in ${files}; do - # Only accept files that are .sh or .ks.in files in this top-level directory. + # Accept files that are .sh or .ks.in files in either the top-level directory or tests/ subdirectory. # Those are the tests. If either file for a particular test changed, we want # to run the test. The first step of figuring this out is stripping off - # the file extension. - if [[ ! "${f}" == */* && ("${f}" == *sh || "${f}" == *ks.in) ]]; then - echo "${f%%.*} " + # the file extension and directory path. + if [[ ! "${f}" == */*/* && ("${f}" == *sh || "${f}" == *ks.in) ]]; then + if [[ "${f}" == tests/* ]]; then + # Extract test name from tests/testname.ext + echo "${f#tests/}" | sed 's/\.[^.]*$//' | tr '\n' ' ' + else + # Extract test name from testname.ext in root directory + echo "${f%%.*} " + fi fi done | uniq)" # And then add the .sh suffix back on to everything in $candidates. That will # give us the list of tests to be run. for c in ${candidates}; do - - # Skip files that are not executable. - if [[ ! -x "${c}.sh" ]]; then - continue + # Check for test in current directory first (backward compatibility) + if [[ -x "${c}.sh" ]]; then + tests+="${c}.sh " + # Check for test in tests/ subdirectory + elif [[ -x "tests/${c}.sh" ]]; then + tests+="tests/${c}.sh " fi - - tests+="${c}.sh " done # Nothing find, find all tests and use TESTTYPE if specified. diff --git a/keyboard-convert-vc.ks.in b/tests/keyboard-convert-vc.ks.in similarity index 100% rename from keyboard-convert-vc.ks.in rename to tests/keyboard-convert-vc.ks.in diff --git a/keyboard-convert-vc.sh b/tests/keyboard-convert-vc.sh similarity index 100% rename from keyboard-convert-vc.sh rename to tests/keyboard-convert-vc.sh diff --git a/keyboard.ks.in b/tests/keyboard.ks.in similarity index 100% rename from keyboard.ks.in rename to tests/keyboard.ks.in diff --git a/keyboard.sh b/tests/keyboard.sh similarity index 100% rename from keyboard.sh rename to tests/keyboard.sh diff --git a/post-lib-keyboard.sh b/tests/post-lib-keyboard.sh similarity index 100% rename from post-lib-keyboard.sh rename to tests/post-lib-keyboard.sh diff --git a/post-nochroot-lib-keyboard.sh b/tests/post-nochroot-lib-keyboard.sh similarity index 100% rename from post-nochroot-lib-keyboard.sh rename to tests/post-nochroot-lib-keyboard.sh