diff --git a/MANIFEST b/MANIFEST index 7def16c..ec9eda7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -18,6 +18,7 @@ lib/Net/OpenSSH/ShellQuoter/MSCmd.pm lib/Net/OpenSSH/ShellQuoter/Chain.pm lib/Net/OpenSSH/ObjectRemote.pm t/common.pm +t/connection-cache.t t/test_server_key t/test_server_key.pub t/test_user_key diff --git a/lib/Net/OpenSSH/ConnectionCache.pm b/lib/Net/OpenSSH/ConnectionCache.pm index e6130f0..551a379 100644 --- a/lib/Net/OpenSSH/ConnectionCache.pm +++ b/lib/Net/OpenSSH/ConnectionCache.pm @@ -29,10 +29,10 @@ sub _factory { if ($MAX_SIZE <= keys %cache) { for (keys %cache) { $ssh = $cache{$_}; - $ssh or $ssh->error != OSSH_MASTER_FAILED or delete $cache{$_} + delete $cache{$_} unless $ssh and $ssh->error != OSSH_MASTER_FAILED; } for (keys %cache) { - last if ($MAX_SIZE <= keys %cache); + last if (keys %cache < $MAX_SIZE); weaken $cache{$_}; if (defined $cache{$_}) { $cache{$_} = $cache{$_}; # unweaken diff --git a/t/connection-cache.t b/t/connection-cache.t new file mode 100644 index 0000000..52b5360 --- /dev/null +++ b/t/connection-cache.t @@ -0,0 +1,46 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 7; +use Net::OpenSSH::Constants qw(OSSH_MASTER_FAILED); +use Net::OpenSSH::ConnectionCache; + +{ + package Test::Net::OpenSSH::ConnectionCache::SSH; + + sub new { + my $class = shift; + return bless { @_ }, $class; + } + + sub error { shift->{error} || 0 } + sub wait_for_master { 1 } +} + +local $Net::OpenSSH::ConnectionCache::MAX_SIZE = 2; +local %Net::OpenSSH::ConnectionCache::cache = ( + live => Test::Net::OpenSSH::ConnectionCache::SSH->new(error => 0), + failed => Test::Net::OpenSSH::ConnectionCache::SSH->new(error => OSSH_MASTER_FAILED), + empty => undef, +); + +my $ssh; +eval { + $ssh = Net::OpenSSH::ConnectionCache::_factory( + 'Test::Net::OpenSSH::ConnectionCache::SSH', + host => 'cache-test-host' + ); +}; + +is($@, '', 'cache cleanup does not die on empty entries'); +ok($ssh, 'factory returns a new object'); +ok(!exists $Net::OpenSSH::ConnectionCache::cache{failed}, 'failed master entry is removed'); +ok(!exists $Net::OpenSSH::ConnectionCache::cache{empty}, 'empty cache entry is removed'); +ok(exists $Net::OpenSSH::ConnectionCache::cache{live}, 'live cache entry is retained'); +ok((keys %Net::OpenSSH::ConnectionCache::cache) <= $Net::OpenSSH::ConnectionCache::MAX_SIZE, + 'cache is reduced to the configured maximum or below'); + +Net::OpenSSH::ConnectionCache::clean_cache(); +is(scalar keys %Net::OpenSSH::ConnectionCache::cache, 0, 'clean_cache clears cache');