#!/usr/bin/env perl

# Regression tests for redactSecrets(), added in ZFS_Utils.pm as part of
# sneakernet/allowKeyRotation.md Part 1 (log/report redaction of transport.encryptionKey).
#
# No live ZFS or network required. Run with no arguments.

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/..";
use ZFS_Utils qw(redactSecrets);

$ZFS_Utils::displayLogsOnConsole = 0;
$ZFS_Utils::logFileName = '/tmp/test_redactSecrets.log';
unlink $ZFS_Utils::logFileName if -f $ZFS_Utils::logFileName;

my $passed = 0;
my $failed = 0;

sub ok {
   my ($cond, $desc) = @_;
   if ($cond) { print "  PASS: $desc\n"; $passed++; }
   else       { print "  FAIL: $desc\n"; $failed++; }
}

my $key64 = 'a71f77ad7de4e50f579901221c6d161cec46c55e66a126011a03fe678e03d7e3';

print "=" x 70 . "\n";
print "redactSecrets()\n";
print "=" x 70 . "\n";

{
   my $in  = "openssl enc -aes-256-cbc -K $key64 -iv abcdef0123456789";
   my $out = redactSecrets($in);
   ok( $out =~ /-K \[REDACTED\]/,       "encrypt pipeline: -K value is redacted" );
   ok( $out !~ /\Q$key64\E/,            "encrypt pipeline: raw key no longer present" );
   ok( $out =~ /-iv abcdef0123456789/,  "encrypt pipeline: IV is left untouched (public by design)" );
}

{
   my $in  = "openssl enc -aes-256-cbc -d -K $key64 -iv abcdef0123456789 -in '/mnt/sneakernet/datasets/x'";
   my $out = redactSecrets($in);
   ok( $out =~ /-K \[REDACTED\]/, "decrypt pipeline: -K value is redacted" );
   ok( $out !~ /\Q$key64\E/,      "decrypt pipeline: raw key no longer present" );
}

{
   my $in  = "openssl enc -aes-256-cbc -d -K $key64 -iv abcdef0123456789 -in '/x' 2>/dev/null";
   my $out = redactSecrets($in);
   ok( $out =~ /-K \[REDACTED\]/, "verifyTransportFile-style command: -K value is redacted" );
}

{
   # Multiple occurrences in one string (e.g. logMsg concatenating several commands) must all redact.
   my $in  = "cmd1 -K $key64 -iv aaa ; cmd2 -K $key64 -iv bbb";
   my $out = redactSecrets($in);
   my $count = () = $out =~ /\[REDACTED\]/g;
   ok( $count == 2, "multiple -K occurrences in one string are all redacted ($count found)" );
}

# --- Negative cases: things that must NOT be touched ---

{
   my $in  = "sha256sum reported: $key64";
   my $out = redactSecrets($in);
   ok( $out eq $in, "a bare 64-hex checksum with no '-K' prefix is left untouched" );
}

{
   my $in  = "geli attach -p -k /media/geli.key da0";
   my $out = redactSecrets($in);
   ok( $out eq $in, "geli's lowercase '-k <path>' is left untouched (not a hex key, not -K)" );
}

{
   my $in  = "some -K 5 unrelated flag";
   my $out = redactSecrets($in);
   ok( $out eq $in, "a short/non-hex value after -K is left untouched (below the 16-hex-char floor)" );
}

{
   my $out = redactSecrets('');
   ok( $out eq '', "empty string returned unchanged" );
}

{
   my $out = redactSecrets(undef);
   ok( !defined $out, "undef returned unchanged (not '' - callers should not see a type change)" );
}

print "\n" . "=" x 70 . "\n";
print "Test Summary: $passed passed, $failed failed\n";
print "=" x 70 . "\n";

exit( $failed == 0 ? 0 : 1 );
