Crypt-SecretBuffer
view release on metacpan or search on metacpan
t/20-console.t view on Meta::CPAN
$buf->{stringify_mask} = undef;
is("$buf", "password", 'Buffer contains expected password');
is($buf->length, 8, 'Buffer length matches password length');
};
# Test with empty line
subtest 'append_console_line with empty line' => sub {
my ($r, $w)= pipe_with_data("\n");
$w->close;
my $buf = Crypt::SecretBuffer->new;
my $result = $buf->append_console_line($r);
ok($result, 'append_console_line returns true with empty line');
is($buf->length, 0, 'Buffer length is zero for empty line');
};
# Test with no newline
subtest 'append_console_line with no newline' => sub {
skip_all "Nonblocking doesn't work on Win32"
if $^O eq 'MSWin32';
my ($r, $w)= pipe_with_data("incomplete");
$r->blocking(0);
my $buf = Crypt::SecretBuffer->new;
$buf->{stringify_mask} = undef;
my $result = $buf->append_console_line($r);
is($result, undef, 'append_console_line returns undef on nonblocking incomplete line');
is("$buf", "incomplete", 'Buffer contains partial data');
is($buf->length, 10, 'Buffer length matches input length');
};
subtest 'parent/child pipe communication' => sub {
my ($read_fh, $write_fh)= pipe_with_data();
my $pid = fork();
die "Cannot fork: $!" unless defined $pid;
if ($pid == 0) {
# Child process
print $write_fh "secret from child process\n";
exit(0);
}
# Parent process
my $buf = Crypt::SecretBuffer->new();
my $result = $buf->append_console_line($read_fh);
is($result, T, 'append_console_line returns true when reading from child process pipe');
is($buf->length, 25, 'buffer contains correct number of characters from child process');
$buf->{stringify_mask} = undef;
is("$buf", 'secret from child process', 'content from child process is correct');
waitpid($pid, 0);
close($read_fh);
};
subtest unicode => sub {
my ($read_fh, $write_fh)= pipe_with_data();
my $pid = fork();
die "Cannot fork: $!" unless defined $pid;
if ($pid == 0) {
# Child process
binmode($write_fh, ':encoding(utf-8)');
print $write_fh "unicode \x{100} \x{1000}\n";
exit(0);
}
# Parent process
my $buf = Crypt::SecretBuffer->new();
my $result = $buf->append_console_line($read_fh, utf8 => 1);
is($result, T, 'append_console_line returns true when reading from child process pipe');
note 'contents: "'.$buf->unmask_to(\&escape_nonprintable).'"';
is($buf->span(encoding => 'UTF-8')->cmp("unicode \x{100} \x{1000}"), 0,
'buffer contains correct utf8 data from child process');
waitpid($pid, 0);
close($read_fh);
};
use Socket qw(AF_UNIX SOCK_STREAM PF_UNSPEC );
subtest 'timeout loop' => sub {
pipe(my $input_r, my $input_w) or die "Cannot create pipe: $!";
# Use socketpair for control because it is select()able on Win32
socketpair(my $parent, my $child, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
or die "socketpair: $!";
$_->autoflush(1) for $input_w, $parent, $child;
my $ppid= $$;
my $pid = fork();
die "Cannot fork: $!" unless defined $pid;
if ($pid == 0) {
# Child process (or thread on Win32)
$input_w->print("secret ");
sleep 1;
$input_w->print("from child process\n");
# Wait up to 10 seconds for message from main thread
# that the test is done, else kill parent process.
my $rfd= '';
vec($rfd, fileno($child), 1)= 1;
my $n= select($rfd, undef, undef, 10);
if ($n <= 0) {
# timeout. stop parent from hanging forever.
note "child killing parent";
kill TERM => $ppid;
}
note "child exits cleanly";
exit 0;
}
# Parent process
pipe(my $prompt_r, my $prompt_w) or die "Cannot create pipe: $!";
my $buf = Crypt::SecretBuffer->new();
my $timeouts= 0;
my $result;
my %state;
while (1) {
my $start_t= time;
$!= 0;
$result = $buf->append_console_line(
input_fh => $input_r, prompt_fh => $prompt_w,
prompt => 'password: ',
timeout => .2, state => \%state
);
note sprintf("append_console_line = %s, errno = %s, chars = %d, elapsed %.3f",
(defined $result? $result : '<undef>'), $!, $buf->length, (time - $start_t));
last if defined $result or !$!{EINTR};
++$timeouts;
}
is($result, T, 'append_console_line returns true when reading from child process pipe');
ok($timeouts > 0, 'more than one timeout');
is($buf->length, 25, 'buffer contains correct number of characters from child process');
$prompt_w->close;
my $prompt_buf= do { local $/; <$prompt_r> };
( run in 1.209 second using v1.01-cache-2.11-cpan-5837b0d9d2c )