#!/usr/bin/env perl

# Test script to check for uninitialized variable access in sneakernet target mode
#
# This script tests various configuration scenarios where optional fields might be
# undefined, checking if the code handles missing values gracefully without warnings
# or errors.

use strict;
use warnings;
use Data::Dumper;
use FindBin;
use lib "$FindBin::Bin/..";

# Capture warnings for analysis
my @warnings;
local $SIG{__WARN__} = sub { push @warnings, shift };

print "=" x 70 . "\n";
print "Testing sneakernet target mode for uninitialized variable issues\n";
print "=" x 70 . "\n\n";

# Test 1: Minimal config (required keys only)
print "Test 1: Minimal target configuration\n";
print "-" x 70 . "\n";
my $minimal_config = {
   runningAs => 'target',
   dryrun => 1,
   verbosity => 0,
   datasets => {
      dataset1 => {
         source => 'pool',
         target => 'backup',
         dataset => 'dataset1'
      }
   },
   transport => {
      label => 'sneakernet',
      mount_point => '/tmp/test_mount',
      serial_file => 'serial.txt',
      dataset_dir => 'datasets'
   },
   source => {
      hostname => 'source-server',
      poolname => 'pool'
   },
   target => {
      hostname => 'target-server',
      poolname => 'backup'
      # Deliberately omitting optional fields:
      # - geli
      # - stateFile  
      # - report
      # - cleanUpScriptsDir
      # - shutdown_after_replication
   }
};

test_config_access($minimal_config, "Minimal config");

# Test 2: Config with empty geli hash
print "\nTest 2: Target with empty geli configuration\n";
print "-" x 70 . "\n";
my $empty_geli_config = {
   %$minimal_config,
   target => {
      %{$minimal_config->{target}},
      geli => {}  # Empty hash - should not crash
   }
};

test_config_access($empty_geli_config, "Empty geli hash");

# Test 3: Config with partial geli (missing secureKey)
print "\nTest 3: Target with partial geli (missing secureKey)\n";
print "-" x 70 . "\n";
my $partial_geli_config = {
   %$minimal_config,
   target => {
      %{$minimal_config->{target}},
      geli => {
         poolname => 'backup',
         localKey => 'abc123',
         target => '/tmp/geli.key'
         # Missing secureKey hash
      }
   }
};

test_config_access($partial_geli_config, "Partial geli config");

# Test 4: Config with partial report (missing targetDrive)
print "\nTest 4: Target with partial report (missing targetDrive)\n";
print "-" x 70 . "\n";
my $partial_report_config = {
   %$minimal_config,
   target => {
      %{$minimal_config->{target}},
      report => {
         email => 'test@example.com',
         subject => 'Test Report'
         # Missing targetDrive hash
      }
   }
};

test_config_access($partial_report_config, "Partial report config");

# Test 5: Config with nested undefined values
print "\nTest 5: Target with deeply nested undefined access\n";
print "-" x 70 . "\n";
my $nested_undef_config = {
   %$minimal_config,
   target => {
      %{$minimal_config->{target}},
      geli => {
         secureKey => {
            # label is undefined
            fstype => 'ufs'
         }
      },
      report => {
         targetDrive => {
            # label is undefined
            fstype => 'msdos'
        }
      }
   }
};

test_config_access($nested_undef_config, "Nested undefined values");

# Print summary
print "\n" . "=" x 70 . "\n";
print "Test Summary\n";
print "=" x 70 . "\n";
if (@warnings) {
   print "⚠ WARNINGS DETECTED (" . scalar(@warnings) . "):\n";
   print "  This indicates potential uninitialized variable access issues.\n\n";
   foreach my $warning (@warnings) {
      print "  • $warning";
   }
   print "\n✗ FAIL: Code accesses uninitialized variables\n";
} else {
   print "✓ PASS: No uninitialized variable warnings detected\n";
}
print "\n";

sub test_config_access {
   my ($config, $test_name) = @_;
   
   my $warning_count = scalar(@warnings);
   
   # Simulate the key access patterns from target mode (lines 1106-1145)
   eval {
      # Line 1110: Check mount_point access
      my $serialFile = "$config->{transport}->{mount_point}/" . 
                       ($config->{transport}->{serial_file} // 'serial.txt');
      
      # Line 1118: Check geli access
      if (defined $config->{target}->{geli}) {
         # Line 1121: Access secureKey->label with //= default
         $config->{target}->{geli}->{secureKey}->{label} //= '';
         
         # Line 1122-1123: Access in unmountDriveByLabel call
         my $geli_label = $config->{target}->{geli}->{secureKey}->{label};
         my $transport_label = $config->{transport}->{label};
         
         # Simulate the comparison without calling unmountDriveByLabel
         unless ($geli_label eq $transport_label) {
            # Would call unmountDriveByLabel here
         }
      }
      
      # Line 1125: Check stateFile and poolname access
      my $stateFile = $config->{target}->{stateFile};
      my $poolname = $config->{target}->{poolname};
      
      # Line 1126-1128: Check report->targetDrive->label access
      $config->{target}->{report}->{targetDrive}->{label} //= '';
      if ($config->{target}->{report}->{targetDrive}->{label}) {
         my $label = $config->{target}->{report}->{targetDrive}->{label};
      }
      
      # Line 1142: Check cleanUpScriptsDir access
      if ($config->{target}->{cleanUpScriptsDir}) {
         # Would run cleanup scripts
      }
   };
   
   if ($@) {
      print "✗ ERROR: $@\n";
   } else {
      my $new_warnings = scalar(@warnings) - $warning_count;
      if ($new_warnings > 0) {
         print "⚠ Detected $new_warnings new warning(s)\n";
      } else {
         print "✓ No warnings for $test_name\n";
      }
   }
}

1;
