tests: Add some unit tests for read_recap
This commit is contained in:
parent
0a9ee106e4
commit
c943d7c0d9
4 changed files with 210 additions and 2 deletions
|
@ -78,6 +78,7 @@ handwritten_tests = \
|
||||||
t/protocol_directnic.pl \
|
t/protocol_directnic.pl \
|
||||||
t/protocol_dnsexit2.pl \
|
t/protocol_dnsexit2.pl \
|
||||||
t/protocol_dyndns2.pl \
|
t/protocol_dyndns2.pl \
|
||||||
|
t/read_recap.pl \
|
||||||
t/skip.pl \
|
t/skip.pl \
|
||||||
t/ssl-validate.pl \
|
t/ssl-validate.pl \
|
||||||
t/update_nics.pl \
|
t/update_nics.pl \
|
||||||
|
|
|
@ -78,6 +78,7 @@ m4_foreach_w([_m], [
|
||||||
File::Spec::Functions
|
File::Spec::Functions
|
||||||
File::Temp
|
File::Temp
|
||||||
List::Util
|
List::Util
|
||||||
|
Scalar::Util
|
||||||
re
|
re
|
||||||
], [AX_PROG_PERL_MODULES([_m], [],
|
], [AX_PROG_PERL_MODULES([_m], [],
|
||||||
[AC_MSG_WARN([some tests will fail due to missing module _m])])])
|
[AC_MSG_WARN([some tests will fail due to missing module _m])])])
|
||||||
|
@ -95,7 +96,6 @@ m4_foreach_w([_m], [
|
||||||
HTTP::Response
|
HTTP::Response
|
||||||
JSON::PP
|
JSON::PP
|
||||||
LWP::UserAgent
|
LWP::UserAgent
|
||||||
Scalar::Util
|
|
||||||
Test::MockModule
|
Test::MockModule
|
||||||
Test::TCP
|
Test::TCP
|
||||||
Test::Warnings
|
Test::Warnings
|
||||||
|
|
|
@ -103,7 +103,7 @@ our $version = humanize_version($VERSION);
|
||||||
|
|
||||||
my $programd = $0;
|
my $programd = $0;
|
||||||
$programd =~ s%^.*/%%;
|
$programd =~ s%^.*/%%;
|
||||||
my $program = $programd;
|
our $program = $programd;
|
||||||
$program =~ s/d$//;
|
$program =~ s/d$//;
|
||||||
our $now = time;
|
our $now = time;
|
||||||
my $hostname = hostname();
|
my $hostname = hostname();
|
||||||
|
|
207
t/read_recap.pl
Normal file
207
t/read_recap.pl
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
use Test::More;
|
||||||
|
use File::Temp;
|
||||||
|
use Scalar::Util qw(refaddr);
|
||||||
|
SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
|
||||||
|
eval { require 'ddclient'; } or BAIL_OUT($@);
|
||||||
|
|
||||||
|
local $ddclient::globals{debug} = 1;
|
||||||
|
local $ddclient::globals{verbose} = 1;
|
||||||
|
local %ddclient::protocols = (
|
||||||
|
protocol_a => {
|
||||||
|
variables => {
|
||||||
|
'host' => {type => ddclient::T_STRING(), recap => 1},
|
||||||
|
'mtime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||||
|
'atime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||||
|
'wtime' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||||
|
'ip' => {type => ddclient::T_IP(), recap => 1},
|
||||||
|
'ipv4' => {type => ddclient::T_IPV4(), recap => 1},
|
||||||
|
'ipv6' => {type => ddclient::T_IPV6(), recap => 1},
|
||||||
|
'status' => {type => ddclient::T_ANY(), recap => 1},
|
||||||
|
'status-ipv4' => {type => ddclient::T_ANY(), recap => 1},
|
||||||
|
'status-ipv6' => {type => ddclient::T_ANY(), recap => 1},
|
||||||
|
'warned-min-error-interval' => {type => ddclient::T_ANY(), recap => 1},
|
||||||
|
'warned-min-interval' => {type => ddclient::T_ANY(), recap => 1},
|
||||||
|
|
||||||
|
'var_a' => {type => ddclient::T_BOOL(), recap => 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
protocol_b => {
|
||||||
|
variables => {
|
||||||
|
'host' => {type => ddclient::T_STRING(), recap => 1},
|
||||||
|
'mtime' => {type => ddclient::T_NUMBER()}, # Intentionally not a recap var.
|
||||||
|
'var_b' => {type => ddclient::T_NUMBER(), recap => 1},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
local %ddclient::variables =
|
||||||
|
(merged => {map({ %{$ddclient::protocols{$_}{variables}}; } sort(keys(%ddclient::protocols)))});
|
||||||
|
|
||||||
|
# Sentinel value that means "this hash entry should be deleted."
|
||||||
|
my $DOES_NOT_EXIST = [];
|
||||||
|
|
||||||
|
my @test_cases = (
|
||||||
|
{
|
||||||
|
desc => "ok value",
|
||||||
|
cachefile_lines => ["var_a=yes host_a"],
|
||||||
|
want => {host_a => {host => 'host_a', var_a => 1}},
|
||||||
|
# No config changes are expected because `var_a` is not a "status" recap var.
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unknown host",
|
||||||
|
cachefile_lines => ["var_a=yes host_c"],
|
||||||
|
want => {},
|
||||||
|
want_TODO => "longstanding minor issue, doesn't affect functionality",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unknown var",
|
||||||
|
cachefile_lines => ["var_b=123 host_a"],
|
||||||
|
want => {host_a => {host => 'host_a'}},
|
||||||
|
want_TODO => "longstanding minor issue, doesn't affect functionality",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "invalid value",
|
||||||
|
cachefile_lines => ["var_a=wat host_a"],
|
||||||
|
want => {host_a => {host => 'host_a'}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "multiple entries",
|
||||||
|
cachefile_lines => [
|
||||||
|
"var_a=yes host_a",
|
||||||
|
"var_b=123 host_b",
|
||||||
|
],
|
||||||
|
want => {
|
||||||
|
host_a => {host => 'host_a', var_a => 1},
|
||||||
|
host_b => {host => 'host_b', var_b => 123},
|
||||||
|
},
|
||||||
|
# No config changes are expected because `var_a` and `var_b` are not "status" recap vars.
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "used to be status vars",
|
||||||
|
cachefile_lines => ["ip=192.0.2.1,status=good host_a"],
|
||||||
|
want => {host_a => {host => 'host_a', ip => '192.0.2.1', status => 'good'}},
|
||||||
|
# No config changes are expected because `ip` and `status` are no longer "status" recap
|
||||||
|
# vars.
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "status vars",
|
||||||
|
cachefile_lines => ["mtime=1234567890,atime=1234567891,wtime=1234567892,ipv4=192.0.2.1,ipv6=2001:db8::1,status-ipv4=good,status-ipv6=bad,warned-min-interval=1234567893,warned-min-error-interval=1234567894 host_a"],
|
||||||
|
want => {host_a => {
|
||||||
|
'host' => 'host_a',
|
||||||
|
'mtime' => 1234567890,
|
||||||
|
'atime' => 1234567891,
|
||||||
|
'wtime' => 1234567892,
|
||||||
|
'ipv4' => '192.0.2.1',
|
||||||
|
'ipv6' => '2001:db8::1',
|
||||||
|
'status-ipv4' => 'good',
|
||||||
|
'status-ipv6' => 'bad',
|
||||||
|
'warned-min-interval' => 1234567893,
|
||||||
|
'warned-min-error-interval' => 1234567894,
|
||||||
|
}},
|
||||||
|
want_config_changes => {host_a => {
|
||||||
|
'mtime' => 1234567890,
|
||||||
|
'atime' => 1234567891,
|
||||||
|
'wtime' => 1234567892,
|
||||||
|
'ipv4' => '192.0.2.1',
|
||||||
|
'ipv6' => '2001:db8::1',
|
||||||
|
'status-ipv4' => 'good',
|
||||||
|
'status-ipv6' => 'bad',
|
||||||
|
'warned-min-interval' => 1234567893,
|
||||||
|
'warned-min-error-interval' => 1234567894,
|
||||||
|
}},
|
||||||
|
want_config_changes_TODO => "longstanding bug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unset status var clears config",
|
||||||
|
cachefile_lines => ["host_a"],
|
||||||
|
config => {host_a => {
|
||||||
|
'mtime' => 1234567890,
|
||||||
|
'atime' => 1234567891,
|
||||||
|
'wtime' => 1234567892,
|
||||||
|
'ipv4' => '192.0.2.1',
|
||||||
|
'ipv6' => '2001:db8::1',
|
||||||
|
'status-ipv4' => 'good',
|
||||||
|
'status-ipv6' => 'bad',
|
||||||
|
'warned-min-interval' => 1234567893,
|
||||||
|
'warned-min-error-interval' => 1234567894,
|
||||||
|
'var_a' => 1,
|
||||||
|
}},
|
||||||
|
want => {host_a => {host => 'host_a'}},
|
||||||
|
want_config_changes => {host_a => {
|
||||||
|
'mtime' => $DOES_NOT_EXIST,
|
||||||
|
'atime' => $DOES_NOT_EXIST,
|
||||||
|
'wtime' => $DOES_NOT_EXIST,
|
||||||
|
'ipv4' => $DOES_NOT_EXIST,
|
||||||
|
'ipv6' => $DOES_NOT_EXIST,
|
||||||
|
'status-ipv4' => $DOES_NOT_EXIST,
|
||||||
|
'status-ipv6' => $DOES_NOT_EXIST,
|
||||||
|
'warned-min-interval' => $DOES_NOT_EXIST,
|
||||||
|
'warned-min-error-interval' => $DOES_NOT_EXIST,
|
||||||
|
# `var_a` should remain untouched.
|
||||||
|
}},
|
||||||
|
want_config_changes_TODO => "longstanding bug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "non-recap vars are not loaded to %recap or copied to %config",
|
||||||
|
cachefile_lines => ["mtime=1234567890 host_b"],
|
||||||
|
want => {host_b => {host => 'host_b'}},
|
||||||
|
want_TODO => "longstanding minor issue, doesn't affect functionality",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "non-recap vars are scrubbed from %recap",
|
||||||
|
cachefile_lines => ["mtime=1234567890 host_b"],
|
||||||
|
recap => {host_b => {host => 'host_b', mtime => 1234567891}},
|
||||||
|
want => {host_b => {host => 'host_b'}},
|
||||||
|
want_TODO => "longstanding minor issue, doesn't affect functionality",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unknown hosts are scrubbed from %recap",
|
||||||
|
cachefile_lines => ["host_a", "host_c"],
|
||||||
|
recap => {host_a => {host => 'host_a'}, host_c => {host => 'host_c'}},
|
||||||
|
want => {host_a => {host => 'host_a'}},
|
||||||
|
want_TODO => "longstanding minor issue, doesn't affect functionality",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
for my $tc (@test_cases) {
|
||||||
|
my $cachef = File::Temp->new();
|
||||||
|
print($cachef join('', map("$_\n", "## $ddclient::program-$ddclient::version",
|
||||||
|
@{$tc->{cachefile_lines}})));
|
||||||
|
$cachef->close();
|
||||||
|
local $ddclient::globals{cache} = "$cachef";
|
||||||
|
local %ddclient::recap = %{$tc->{recap} // {}};
|
||||||
|
my %want_config = (
|
||||||
|
host_a => {protocol => 'protocol_a'},
|
||||||
|
host_b => {protocol => 'protocol_b'},
|
||||||
|
);
|
||||||
|
$tc->{config} //= {};
|
||||||
|
$want_config{$_} = {%{$want_config{$_} // {}}, %{$tc->{config}{$_}}} for keys(%{$tc->{config}});
|
||||||
|
# Deep clone %want_config so we can check for changes.
|
||||||
|
local %ddclient::config;
|
||||||
|
$ddclient::config{$_} = {%{$want_config{$_}}} for keys(%want_config);
|
||||||
|
|
||||||
|
ddclient::read_recap($cachef->filename(), \%ddclient::recap);
|
||||||
|
|
||||||
|
TODO: {
|
||||||
|
local $TODO = $tc->{want_TODO};
|
||||||
|
is_deeply(\%ddclient::recap, $tc->{want}, "$tc->{desc}: %recap")
|
||||||
|
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{want}],
|
||||||
|
Names => ['*got', '*want']));
|
||||||
|
}
|
||||||
|
TODO: {
|
||||||
|
local $TODO = $tc->{want_config_changes_TODO};
|
||||||
|
$tc->{want_config_changes} //= {};
|
||||||
|
$want_config{$_} = {%{$want_config{$_} // {}}, %{$tc->{want_config_changes}{$_}}}
|
||||||
|
for keys(%{$tc->{want_config_changes}});
|
||||||
|
for my $h (keys(%want_config)) {
|
||||||
|
for my $k (keys(%{$want_config{$h}})) {
|
||||||
|
my $a = refaddr($want_config{$h}{$k});
|
||||||
|
delete($want_config{$h}{$k}) if defined($a) && $a == refaddr($DOES_NOT_EXIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_deeply(\%ddclient::config, \%want_config, "$tc->{desc}: %config")
|
||||||
|
or diag(ddclient::repr(Values => [\%ddclient::config, \%want_config],
|
||||||
|
Names => ['*got', '*want']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing();
|
Loading…
Reference in a new issue