Subversion Repositories zfs_utils

Rev

Rev 62 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#! /usr/bin/env perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/..";
use File::Temp qw(tempfile tempdir);
use File::Copy;
use File::Basename;

# Unit test for sneakernet script
# This test runs sneakernet in dry-run mode with maximum verbosity
# to validate configuration and command generation without making changes.

print "=" x 60 . "\n";
print "Sneakernet Unit Test\n";
print "=" x 60 . "\n\n";

my $sneakernet_script = "$FindBin::Bin/sneakernet";
my $config_file = "$sneakernet_script.conf.yaml";

# Verify files exist
unless (-f $sneakernet_script) {
    die "ERROR: sneakernet script not found at: $sneakernet_script\n";
}

unless (-f $config_file) {
    die "ERROR: Configuration file not found at: $config_file\n";
}

print "Test Configuration:\n";
print "  Script: $sneakernet_script\n";
print "  Config: $config_file\n";
print "  Mode: dry-run (--dryrun)\n";
print "  Verbosity: 3 (-vvv)\n";
print "\n";

# Test 1: Version check
print "-" x 60 . "\n";
print "Test 1: Version Check\n";
print "-" x 60 . "\n";
my $version_output = `perl $sneakernet_script --version 2>&1`;
my $version_exit = $? >> 8;
print "Output: $version_output";
print "Exit code: $version_exit\n";
if ($version_exit == 0 && $version_output =~ /sneakernet v\d+\.\d+/) {
    print "✓ PASS: Version check successful\n\n";
} else {
    print "✗ FAIL: Version check failed\n\n";
}

# Test 2: Help output
print "-" x 60 . "\n";
print "Test 2: Help Output\n";
print "-" x 60 . "\n";
my $help_output = `perl $sneakernet_script --help 2>&1`;
my $help_exit = $? >> 8;
print "Output:\n$help_output";
print "Exit code: $help_exit\n";
if ($help_exit == 0 && $help_output =~ /Usage:/) {
    print "✓ PASS: Help output successful\n\n";
} else {
    print "✗ FAIL: Help output failed\n\n";
}

# Test 3: Dry-run with maximum verbosity
print "-" x 60 . "\n";
print "Test 3: Dry-run Execution (High Verbosity)\n";
print "-" x 60 . "\n";
print "Running: perl $sneakernet_script --dryrun -vvv\n";
print "-" x 60 . "\n\n";

my $dryrun_output = `perl $sneakernet_script --dryrun -vvv 2>&1`;
my $dryrun_exit = $? >> 8;

print "Output:\n";
print $dryrun_output;
print "\n";
print "-" x 60 . "\n";
print "Exit code: $dryrun_exit\n";

# Analyze the output
my $has_config = $dryrun_output =~ /config|configuration/i;
my $has_dryrun = $dryrun_output =~ /dry[-\s]?run/i;
my $has_commands = $dryrun_output =~ /zfs send|command/i;

print "\nAnalysis:\n";
print "  Contains config info: " . ($has_config ? "Yes" : "No") . "\n";
print "  Dry-run mode active: " . ($has_dryrun ? "Yes" : "No") . "\n";
print "  Generated commands: " . ($has_commands ? "Yes" : "No") . "\n";

if ($dryrun_exit == 0) {
    print "\n✓ PASS: Dry-run completed successfully\n";
} else {
    print "\n✗ FAIL: Dry-run exited with error code $dryrun_exit\n";
}

# Test 4: Check log file creation
print "\n";
print "-" x 60 . "\n";
print "Test 4: Log File Check\n";
print "-" x 60 . "\n";

my $log_file = "$sneakernet_script.log";
if (-f $log_file) {
    print "Log file found: $log_file\n";
    my $log_size = -s $log_file;
    print "Log file size: $log_size bytes\n";
    
    if ($log_size > 0) {
        print "\nLast 20 lines of log file:\n";
        print "- " x 30 . "\n";
        my @log_lines = `tail -20 $log_file 2>/dev/null`;
        print @log_lines;
        print "- " x 30 . "\n";
        print "✓ PASS: Log file created and populated\n";
    } else {
        print "✗ FAIL: Log file is empty\n";
    }
} else {
    print "✗ FAIL: Log file not found at $log_file\n";
}

# Test 5: Status file check
print "\n";
print "-" x 60 . "\n";
print "Test 5: Status File Check\n";
print "-" x 60 . "\n";

my $status_file = "$sneakernet_script.status";
if (-f $status_file) {
    print "Status file found: $status_file\n";
    my $status_size = -s $status_file;
    print "Status file size: $status_size bytes\n";
    
    if ($status_size > 0) {
        print "\nStatus file contents:\n";
        print "- " x 30 . "\n";
        open my $fh, '<', $status_file or die "Can't open status file: $!\n";
        print while <$fh>;
        close $fh;
        print "- " x 30 . "\n";
        print "✓ INFO: Status file exists (may be from previous run)\n";
    } else {
        print "✓ INFO: Status file is empty (expected in dry-run)\n";
    }
} else {
    print "✓ INFO: Status file not found (expected in dry-run)\n";
}

# Summary
print "\n";
print "=" x 60 . "\n";
print "Test Summary\n";
print "=" x 60 . "\n";
print "All basic tests completed. Review output above for details.\n";
print "Note: Dry-run mode ensures no actual writes were performed.\n";
print "\n";

# Test 6: Target mode simulation
print "=" x 60 . "\n";
print "Test 6: Target Mode Simulation\n";
print "=" x 60 . "\n";
print "Note: This test simulates running on the target server\n";
print "      by temporarily overriding the hostname.\n\n";

# Read the config to get the target hostname
my $target_hostname;
if (open my $cfg_fh, '<', $config_file) {
    while (my $line = <$cfg_fh>) {
        if ($line =~ /^\s*hostname:\s*['"]?([^'"]+)['"]?\s*$/) {
            # This is a bit crude, but we need to find target.hostname
            # We'll look for it after we see 'target:' section
            my $in_target = 0;
            seek($cfg_fh, 0, 0);  # Reset to beginning
            while (my $l2 = <$cfg_fh>) {
                if ($l2 =~ /^target:/) {
                    $in_target = 1;
                    next;
                }
                if ($in_target && $l2 =~ /^\s*hostname:\s*['"]?([^'"]+)['"]?\s*$/) {
                    $target_hostname = $1;
                    last;
                }
                if ($in_target && $l2 =~ /^[a-z]+:/ && $l2 !~ /^\s/) {
                    $in_target = 0;  # Exited target section
                }
            }
            last;
        }
    }
    close $cfg_fh;
}

if ($target_hostname) {
    print "Target hostname from config: $target_hostname\n";
    print "Running sneakernet with HOSTNAME=$target_hostname\n";
    print "-" x 60 . "\n\n";
    
    # Set environment variable to simulate target hostname
    local $ENV{HOSTNAME} = $target_hostname;
    
    my $target_output = `HOSTNAME=$target_hostname perl $sneakernet_script --dryrun -vvv 2>&1`;
    my $target_exit = $? >> 8;
    
    print "Output:\n";
    print $target_output;
    print "\n";
    print "-" x 60 . "\n";
    print "Exit code: $target_exit\n";
    
    # Analyze the output for target-specific behavior
    my $detected_target = $target_output =~ /target|receiving|import/i;
    my $has_receive = $target_output =~ /zfs receive/i;
    my $has_geli = $target_output =~ /geli|decrypt|mount/i;
    
    print "\nTarget Mode Analysis:\n";
    print "  Running as target: " . ($detected_target ? "Yes" : "No") . "\n";
    print "  Contains zfs receive: " . ($has_receive ? "Yes" : "No") . "\n";
    print "  Contains GELI operations: " . ($has_geli ? "Yes" : "No") . "\n";
    
    if ($target_exit == 0) {
        print "\n✓ PASS: Target mode dry-run completed successfully\n";
    } else {
        print "\n✗ FAIL: Target mode dry-run exited with error code $target_exit\n";
    }
} else {
    print "⚠ SKIP: Could not determine target hostname from config\n";
    print "        Target mode test skipped.\n";
}

print "\n";
print "=" x 60 . "\n";
print "All Tests Complete\n";
print "=" x 60 . "\n";
print "\n";

1;