commit
a7abfcb715
10 changed files with 1068 additions and 837 deletions
|
@ -100,6 +100,8 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
|
* Fixed numerous bugs in cache file (recap) handling.
|
||||||
|
[#740](https://github.com/ddclient/ddclient/pull/740)
|
||||||
* Fixed numerous bugs in command-line option and configuration file
|
* Fixed numerous bugs in command-line option and configuration file
|
||||||
processing. [#733](https://github.com/ddclient/ddclient/pull/733)
|
processing. [#733](https://github.com/ddclient/ddclient/pull/733)
|
||||||
* `noip`: Fixed failure to honor IP discovery settings in some circumstances.
|
* `noip`: Fixed failure to honor IP discovery settings in some circumstances.
|
||||||
|
|
|
@ -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
|
||||||
|
|
1617
ddclient.in
1617
ddclient.in
File diff suppressed because it is too large
Load diff
|
@ -52,7 +52,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv4, good',
|
desc => 'IPv4, good',
|
||||||
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/abc/", wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/abc/", wantipv4 => '192.0.2.1'}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -62,7 +62,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv4, failed',
|
desc => 'IPv4, failed',
|
||||||
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/bad_token/", wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {urlv4 => "$hostname/dns/gateway/bad_token/", wantipv4 => '192.0.2.1'}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'failed'},
|
h1 => {'status-ipv4' => 'failed'},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -72,7 +72,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv4, bad',
|
desc => 'IPv4, bad',
|
||||||
cfg => {h1 => {urlv4 => "$hostname/bad/path/", wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {urlv4 => "$hostname/bad/path/", wantipv4 => '192.0.2.1'}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'bad'},
|
h1 => {'status-ipv4' => 'bad'},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -82,7 +82,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv4, unexpected response',
|
desc => 'IPv4, unexpected response',
|
||||||
cfg => {h1 => {urlv4 => "$hostname/unexpected/path/", wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {urlv4 => "$hostname/unexpected/path/", wantipv4 => '192.0.2.1'}},
|
||||||
wantstatus => {h1 => {}},
|
wantrecap => {},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
{label => 'FAILED', ctx => ['h1'], msg => qr/400 Bad Request/},
|
{label => 'FAILED', ctx => ['h1'], msg => qr/400 Bad Request/},
|
||||||
],
|
],
|
||||||
|
@ -90,7 +90,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv4, no urlv4',
|
desc => 'IPv4, no urlv4',
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||||
wantstatus => {h1 => {}},
|
wantrecap => {},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
{label => 'FAILED', ctx => ['h1'], msg => qr/missing urlv4 option/},
|
{label => 'FAILED', ctx => ['h1'], msg => qr/missing urlv4 option/},
|
||||||
],
|
],
|
||||||
|
@ -98,7 +98,7 @@ my @test_cases = (
|
||||||
{
|
{
|
||||||
desc => 'IPv6, good',
|
desc => 'IPv6, good',
|
||||||
cfg => {h1 => {urlv6 => "$hostname/dns/gateway/abc/", wantipv6 => '2001:db8::1'}},
|
cfg => {h1 => {urlv6 => "$hostname/dns/gateway/abc/", wantipv6 => '2001:db8::1'}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -113,7 +113,7 @@ my @test_cases = (
|
||||||
wantipv4 => '192.0.2.1',
|
wantipv4 => '192.0.2.1',
|
||||||
wantipv6 => '2001:db8::1',
|
wantipv6 => '2001:db8::1',
|
||||||
}},
|
}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
||||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||||
'mtime' => $ddclient::now},
|
'mtime' => $ddclient::now},
|
||||||
|
@ -132,7 +132,7 @@ my @test_cases = (
|
||||||
wantipv6 => '2001:db8::1',
|
wantipv6 => '2001:db8::1',
|
||||||
}},
|
}},
|
||||||
wantips => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
wantips => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'failed',
|
h1 => {'status-ipv4' => 'failed',
|
||||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||||
'mtime' => $ddclient::now},
|
'mtime' => $ddclient::now},
|
||||||
|
@ -152,20 +152,14 @@ for my $tc (@test_cases) {
|
||||||
local $ddclient::globals{verbose} = 1;
|
local $ddclient::globals{verbose} = 1;
|
||||||
my $l = Logger->new($ddclient::_l);
|
my $l = Logger->new($ddclient::_l);
|
||||||
local %ddclient::config = %{$tc->{cfg}};
|
local %ddclient::config = %{$tc->{cfg}};
|
||||||
|
local %ddclient::recap;
|
||||||
{
|
{
|
||||||
local $ddclient::_l = $l;
|
local $ddclient::_l = $l;
|
||||||
ddclient::nic_directnic_update(sort(keys(%{$tc->{cfg}})));
|
ddclient::nic_directnic_update(undef, sort(keys(%{$tc->{cfg}})));
|
||||||
}
|
}
|
||||||
# These are the properties in %ddclient::config to check against $tc->{wantstatus}.
|
is_deeply(\%ddclient::recap, $tc->{wantrecap}, "$tc->{desc}: recap")
|
||||||
my %statuskeys = map(($_ => undef), qw(atime ip ipv4 ipv6 mtime status status-ipv4 status-ipv6
|
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{wantrecap}],
|
||||||
wantip wantipv4 wantipv6 wtime));
|
Names => ['*got', '*want']));
|
||||||
my %gotstatus;
|
|
||||||
for my $h (keys(%ddclient::config)) {
|
|
||||||
$gotstatus{$h} = {map(($_ => $ddclient::config{$h}{$_}),
|
|
||||||
grep(exists($statuskeys{$_}), keys(%{$ddclient::config{$h}})))};
|
|
||||||
}
|
|
||||||
is_deeply(\%gotstatus, $tc->{wantstatus}, "$tc->{desc}: status")
|
|
||||||
or diag(ddclient::repr(\%ddclient::config, Names => ['*ddclient::config']));
|
|
||||||
$tc->{wantlogs} //= [];
|
$tc->{wantlogs} //= [];
|
||||||
subtest("$tc->{desc}: logs" => sub {
|
subtest("$tc->{desc}: logs" => sub {
|
||||||
my @got = @{$l->{logs}};
|
my @got = @{$l->{logs}};
|
||||||
|
|
|
@ -41,7 +41,7 @@ my $ua = LWP::UserAgent->new;
|
||||||
sub test_nic_dnsexit2_update {
|
sub test_nic_dnsexit2_update {
|
||||||
my ($config, @hostnames) = @_;
|
my ($config, @hostnames) = @_;
|
||||||
%ddclient::config = %$config;
|
%ddclient::config = %$config;
|
||||||
ddclient::nic_dnsexit2_update(@hostnames);
|
ddclient::nic_dnsexit2_update(undef, @hostnames);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub decode_and_sort_array {
|
sub decode_and_sort_array {
|
||||||
|
|
|
@ -45,7 +45,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||||
resp => ['good'],
|
resp => ['good'],
|
||||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -57,7 +57,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||||
resp => ['nochg'],
|
resp => ['nochg'],
|
||||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -70,7 +70,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||||
resp => ['nohost'],
|
resp => ['nohost'],
|
||||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'nohost'},
|
h1 => {'status-ipv4' => 'nohost'},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -82,7 +82,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1'}},
|
||||||
resp => ['WAT'],
|
resp => ['WAT'],
|
||||||
wantquery => 'hostname=h1&myip=192.0.2.1',
|
wantquery => 'hostname=h1&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'WAT'},
|
h1 => {'status-ipv4' => 'WAT'},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -100,7 +100,7 @@ my @test_cases = (
|
||||||
'good',
|
'good',
|
||||||
],
|
],
|
||||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
|
@ -122,7 +122,7 @@ my @test_cases = (
|
||||||
'dnserr',
|
'dnserr',
|
||||||
],
|
],
|
||||||
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h3 => {'status-ipv4' => 'dnserr'},
|
h3 => {'status-ipv4' => 'dnserr'},
|
||||||
|
@ -139,7 +139,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv6 => '2001:db8::1'}},
|
cfg => {h1 => {wantipv6 => '2001:db8::1'}},
|
||||||
resp => ['good'],
|
resp => ['good'],
|
||||||
wantquery => 'hostname=h1&myip=2001:db8::1',
|
wantquery => 'hostname=h1&myip=2001:db8::1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv6' => 'good', 'ipv6' => '2001:db8::1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
wantlogs => [
|
wantlogs => [
|
||||||
|
@ -151,7 +151,7 @@ my @test_cases = (
|
||||||
cfg => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
cfg => {h1 => {wantipv4 => '192.0.2.1', wantipv6 => '2001:db8::1'}},
|
||||||
resp => ['good'],
|
resp => ['good'],
|
||||||
wantquery => 'hostname=h1&myip=192.0.2.1,2001:db8::1',
|
wantquery => 'hostname=h1&myip=192.0.2.1,2001:db8::1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1',
|
||||||
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
'status-ipv6' => 'good', 'ipv6' => '2001:db8::1',
|
||||||
'mtime' => $ddclient::now},
|
'mtime' => $ddclient::now},
|
||||||
|
@ -173,7 +173,7 @@ my @test_cases = (
|
||||||
'WAT',
|
'WAT',
|
||||||
],
|
],
|
||||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
|
@ -191,7 +191,7 @@ my @test_cases = (
|
||||||
},
|
},
|
||||||
resp => ['abuse'],
|
resp => ['abuse'],
|
||||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'abuse'},
|
h1 => {'status-ipv4' => 'abuse'},
|
||||||
h2 => {'status-ipv4' => 'abuse'},
|
h2 => {'status-ipv4' => 'abuse'},
|
||||||
},
|
},
|
||||||
|
@ -208,7 +208,7 @@ my @test_cases = (
|
||||||
},
|
},
|
||||||
resp => ['good'],
|
resp => ['good'],
|
||||||
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
},
|
},
|
||||||
|
@ -230,7 +230,7 @@ my @test_cases = (
|
||||||
'nochg',
|
'nochg',
|
||||||
],
|
],
|
||||||
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
wantquery => 'hostname=h1,h2,h3&myip=192.0.2.1',
|
||||||
wantstatus => {
|
wantrecap => {
|
||||||
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h1 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
h2 => {'status-ipv4' => 'good', 'ipv4' => '192.0.2.1', 'mtime' => $ddclient::now},
|
||||||
h3 => {'status-ipv4' => 'unknown'},
|
h3 => {'status-ipv4' => 'unknown'},
|
||||||
|
@ -252,6 +252,7 @@ for my $tc (@test_cases) {
|
||||||
local $ddclient::globals{verbose} = 1;
|
local $ddclient::globals{verbose} = 1;
|
||||||
my $l = Logger->new($ddclient::_l);
|
my $l = Logger->new($ddclient::_l);
|
||||||
local %ddclient::config;
|
local %ddclient::config;
|
||||||
|
local %ddclient::recap;
|
||||||
$ddclient::config{$_} = {
|
$ddclient::config{$_} = {
|
||||||
login => 'username',
|
login => 'username',
|
||||||
password => 'password',
|
password => 'password',
|
||||||
|
@ -265,20 +266,11 @@ for my $tc (@test_cases) {
|
||||||
map("line: $_", @{$tc->{resp}}),
|
map("line: $_", @{$tc->{resp}}),
|
||||||
);
|
);
|
||||||
local $ddclient::_l = $l;
|
local $ddclient::_l = $l;
|
||||||
ddclient::nic_dyndns2_update(sort(keys(%{$tc->{cfg}})));
|
ddclient::nic_dyndns2_update(undef, sort(keys(%{$tc->{cfg}})));
|
||||||
}
|
}
|
||||||
# These are the properties in %ddclient::config to check against $tc->{wantstatus}. Keys are
|
is_deeply(\%ddclient::recap, $tc->{wantrecap}, "$tc->{desc}: recap")
|
||||||
# explicitly listed here rather than read from $tc->{wantstatus} to ensure that entries that
|
or diag(ddclient::repr(Values => [\%ddclient::recap, $tc->{wantrecap}],
|
||||||
# should not exist (e.g., wantipv4 and friends) are deleted (or never set).
|
Names => ['*got', '*want']));
|
||||||
my %statuskeys = map(($_ => undef), qw(atime ip ipv4 ipv6 mtime status status-ipv4 status-ipv6
|
|
||||||
wantip wantipv4 wantipv6 wtime));
|
|
||||||
my %gotstatus;
|
|
||||||
for my $h (keys(%ddclient::config)) {
|
|
||||||
$gotstatus{$h} = {map(($_ => $ddclient::config{$h}{$_}),
|
|
||||||
grep(exists($statuskeys{$_}), keys(%{$ddclient::config{$h}})))};
|
|
||||||
}
|
|
||||||
is_deeply(\%gotstatus, $tc->{wantstatus}, "$tc->{desc}: status")
|
|
||||||
or diag(ddclient::repr(\%ddclient::config, Names => ['*ddclient::config']));
|
|
||||||
$tc->{wantlogs} //= [];
|
$tc->{wantlogs} //= [];
|
||||||
subtest("$tc->{desc}: logs" => sub {
|
subtest("$tc->{desc}: logs" => sub {
|
||||||
my @got = @{$l->{logs}};
|
my @got = @{$l->{logs}};
|
||||||
|
|
107
t/read_recap.pl
Normal file
107
t/read_recap.pl
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
use Test::More;
|
||||||
|
use File::Temp;
|
||||||
|
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 => ddclient::Protocol->new(
|
||||||
|
recapvars => {
|
||||||
|
host => ddclient::T_STRING(),
|
||||||
|
var_a => ddclient::T_BOOL(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
protocol_b => ddclient::Protocol->new(
|
||||||
|
recapvars => {
|
||||||
|
host => ddclient::T_STRING(),
|
||||||
|
var_b => ddclient::T_NUMBER(),
|
||||||
|
},
|
||||||
|
cfgvars => {
|
||||||
|
var_b_non_recap => {type => ddclient::T_ANY()},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
local %ddclient::cfgvars = (merged => {map({ %{$ddclient::protocols{$_}{cfgvars} // {}}; }
|
||||||
|
sort(keys(%ddclient::protocols)))});
|
||||||
|
|
||||||
|
my @test_cases = (
|
||||||
|
{
|
||||||
|
desc => "ok value",
|
||||||
|
cachefile_lines => ["var_a=yes host_a"],
|
||||||
|
want => {host_a => {host => 'host_a', var_a => 1}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unknown host",
|
||||||
|
cachefile_lines => ["var_a=yes host_c"],
|
||||||
|
want => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "unknown var",
|
||||||
|
cachefile_lines => ["var_b=123 host_a"],
|
||||||
|
want => {host_a => {host => 'host_a'}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "non-recap vars are not loaded to %recap",
|
||||||
|
cachefile_lines => ["var_b_non_recap=foo host_b"],
|
||||||
|
want => {host_b => {host => 'host_b'}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc => "non-recap vars are scrubbed from %recap",
|
||||||
|
cachefile_lines => ["var_b_non_recap=foo host_b"],
|
||||||
|
recap => {host_b => {host => 'host_b', var_b_non_recap => 'foo'}},
|
||||||
|
want => {host_b => {host => 'host_b'}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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'}},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
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'},
|
||||||
|
);
|
||||||
|
# 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());
|
||||||
|
|
||||||
|
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']));
|
||||||
|
}
|
||||||
|
is_deeply(\%ddclient::config, \%want_config, "$tc->{desc}: %config")
|
||||||
|
or diag(ddclient::repr(Values => [\%ddclient::config, \%want_config],
|
||||||
|
Names => ['*got', '*want']));
|
||||||
|
}
|
||||||
|
|
||||||
|
done_testing();
|
|
@ -47,19 +47,21 @@ local %ddclient::protocols = (
|
||||||
# The `legacy` protocol reads the legacy `wantip` property and sets the legacy `ip` and `status`
|
# The `legacy` protocol reads the legacy `wantip` property and sets the legacy `ip` and `status`
|
||||||
# properties. (Modern protocol implementations read `wantipv4` and `wantipv6` and set `ipv4`,
|
# properties. (Modern protocol implementations read `wantipv4` and `wantipv6` and set `ipv4`,
|
||||||
# `ipv6`, `status-ipv4`, and `status-ipv6`.) It always succeeds.
|
# `ipv6`, `status-ipv4`, and `status-ipv6`.) It always succeeds.
|
||||||
legacy => {
|
legacy => ddclient::LegacyProtocol->new(
|
||||||
update => sub {
|
update => sub {
|
||||||
|
my $self = shift;
|
||||||
|
ddclient::debug('in update');
|
||||||
for my $h (@_) {
|
for my $h (@_) {
|
||||||
|
local $ddclient::_l = ddclient::pushlogctx($h);
|
||||||
|
ddclient::debug('updating host');
|
||||||
push(@updates, [@_]);
|
push(@updates, [@_]);
|
||||||
$ddclient::config{$h}{status} = 'good';
|
$ddclient::recap{$h}{status} = 'good';
|
||||||
$ddclient::config{$h}{ip} = delete($ddclient::config{$h}{wantip});
|
$ddclient::recap{$h}{ip} = delete($ddclient::config{$h}{wantip});
|
||||||
$ddclient::config{$h}{mtime} = $ddclient::now;
|
$ddclient::recap{$h}{mtime} = $ddclient::now;
|
||||||
}
|
}
|
||||||
|
ddclient::debug('returning from update');
|
||||||
},
|
},
|
||||||
variables => {
|
),
|
||||||
%{$ddclient::variables{'protocol-common-defaults'}},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
my @test_cases = (
|
my @test_cases = (
|
||||||
|
@ -79,12 +81,6 @@ my @test_cases = (
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
'status-ipv4' => 'good',
|
'status-ipv4' => 'good',
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv4' => '192.0.2.1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
'status-ipv4' => 'good',
|
|
||||||
},
|
|
||||||
%$_,
|
%$_,
|
||||||
};
|
};
|
||||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||||
|
@ -103,12 +99,6 @@ my @test_cases = (
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
'status-ipv6' => 'good',
|
'status-ipv6' => 'good',
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv6' => '2001:db8::1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
'status-ipv6' => 'good',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc => 'legacy, fresh, usev6=webv6',
|
desc => 'legacy, fresh, usev6=webv6',
|
||||||
|
@ -124,12 +114,6 @@ my @test_cases = (
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
'status-ipv6' => 'good',
|
'status-ipv6' => 'good',
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv6' => '2001:db8::1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
'status-ipv6' => 'good',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc => 'legacy, fresh, usev4=webv4 usev6=webv6',
|
desc => 'legacy, fresh, usev4=webv4 usev6=webv6',
|
||||||
|
@ -146,12 +130,6 @@ my @test_cases = (
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
'status-ipv4' => 'good',
|
'status-ipv4' => 'good',
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv4' => '192.0.2.1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
'status-ipv4' => 'good',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
map({
|
map({
|
||||||
my %cfg = %{delete($_->{cfg})};
|
my %cfg = %{delete($_->{cfg})};
|
||||||
|
@ -231,11 +209,6 @@ my @test_cases = (
|
||||||
'ipv4' => '192.0.2.1',
|
'ipv4' => '192.0.2.1',
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv4' => '192.0.2.1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
},
|
|
||||||
%$_,
|
%$_,
|
||||||
};
|
};
|
||||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||||
|
@ -283,12 +256,6 @@ my @test_cases = (
|
||||||
'mtime' => $ddclient::now,
|
'mtime' => $ddclient::now,
|
||||||
'status-ipv4' => 'good',
|
'status-ipv4' => 'good',
|
||||||
},
|
},
|
||||||
want_cfg_changes => {
|
|
||||||
'atime' => $ddclient::now,
|
|
||||||
'ipv4' => '192.0.2.1',
|
|
||||||
'mtime' => $ddclient::now,
|
|
||||||
'status-ipv4' => 'good',
|
|
||||||
},
|
|
||||||
%$_,
|
%$_,
|
||||||
};
|
};
|
||||||
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
|
||||||
|
@ -307,7 +274,6 @@ for my $tc (@test_cases) {
|
||||||
# $cachef is an object that stringifies to a filename.
|
# $cachef is an object that stringifies to a filename.
|
||||||
local $ddclient::globals{cache} = "$cachef";
|
local $ddclient::globals{cache} = "$cachef";
|
||||||
my %cfg = (
|
my %cfg = (
|
||||||
%{$tc->{recap} // {}}, # Simulate a previous update.
|
|
||||||
web => 'v4',
|
web => 'v4',
|
||||||
webv4 => 'v4',
|
webv4 => 'v4',
|
||||||
webv6 => 'v6',
|
webv6 => 'v6',
|
||||||
|
@ -335,7 +301,6 @@ for my $tc (@test_cases) {
|
||||||
Names => ['*got', '*want']));
|
Names => ['*got', '*want']));
|
||||||
}
|
}
|
||||||
my %want_cfg = (host => {
|
my %want_cfg = (host => {
|
||||||
$tc->{want_update} ? (update => 1) : (),
|
|
||||||
%cfg,
|
%cfg,
|
||||||
%{$tc->{want_cfg_changes} // {}},
|
%{$tc->{want_cfg_changes} // {}},
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,8 @@ SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
|
||||||
eval { require 'ddclient'; } or BAIL_OUT($@);
|
eval { require 'ddclient'; } or BAIL_OUT($@);
|
||||||
|
|
||||||
my %variable_collections = (
|
my %variable_collections = (
|
||||||
map({ ($_ => $ddclient::variables{$_}) } grep($_ ne 'merged', keys(%ddclient::variables))),
|
map({ ($_ => $ddclient::cfgvars{$_}) } grep($_ ne 'merged', keys(%ddclient::cfgvars))),
|
||||||
map({ ("protocol=$_" => $ddclient::protocols{$_}{variables}); } keys(%ddclient::protocols)),
|
map({ ("protocol=$_" => $ddclient::protocols{$_}{cfgvars}); } keys(%ddclient::protocols)),
|
||||||
);
|
);
|
||||||
my %seen;
|
my %seen;
|
||||||
my @test_cases = (
|
my @test_cases = (
|
||||||
|
@ -24,10 +24,10 @@ for my $tc (@test_cases) {
|
||||||
if ($tc->{def}{required}) {
|
if ($tc->{def}{required}) {
|
||||||
is($tc->{def}{default}, undef, "'$tc->{desc}' (required) has no default");
|
is($tc->{def}{default}, undef, "'$tc->{desc}' (required) has no default");
|
||||||
} else {
|
} else {
|
||||||
# Preserve all existing variables in $variables{merged} so that variables with dynamic
|
# Preserve all existing variables in $cfgvars{merged} so that variables with dynamic
|
||||||
# defaults can reference them.
|
# defaults can reference them.
|
||||||
local %ddclient::variables = (merged => {
|
local %ddclient::cfgvars = (merged => {
|
||||||
%{$ddclient::variables{merged}},
|
%{$ddclient::cfgvars{merged}},
|
||||||
'var for test' => $tc->{def},
|
'var for test' => $tc->{def},
|
||||||
});
|
});
|
||||||
# Variables with dynamic defaults will need their own unit tests, but we can still check the
|
# Variables with dynamic defaults will need their own unit tests, but we can still check the
|
||||||
|
@ -77,13 +77,12 @@ my @use_test_cases = (
|
||||||
);
|
);
|
||||||
for my $tc (@use_test_cases) {
|
for my $tc (@use_test_cases) {
|
||||||
my $desc = "'use' dynamic default: $tc->{desc}";
|
my $desc = "'use' dynamic default: $tc->{desc}";
|
||||||
local %ddclient::protocols =
|
local %ddclient::protocols = (protocol => ddclient::Protocol->new());
|
||||||
(protocol => {variables => $ddclient::variables{'protocol-common-defaults'}});
|
local %ddclient::cfgvars = (merged => {
|
||||||
local %ddclient::variables = (merged => {
|
'protocol' => $ddclient::cfgvars{'merged'}{'protocol'},
|
||||||
'protocol' => $ddclient::variables{'merged'}{'protocol'},
|
'use' => $ddclient::cfgvars{'protocol-common-defaults'}{'use'},
|
||||||
'use' => $ddclient::variables{'protocol-common-defaults'}{'use'},
|
'usev4' => $ddclient::cfgvars{'merged'}{'usev4'},
|
||||||
'usev4' => $ddclient::variables{'merged'}{'usev4'},
|
'usev6' => $ddclient::cfgvars{'merged'}{'usev6'},
|
||||||
'usev6' => $ddclient::variables{'merged'}{'usev6'},
|
|
||||||
});
|
});
|
||||||
local %ddclient::config = (host => {protocol => 'protocol', %{$tc->{cfg} // {}}});
|
local %ddclient::config = (host => {protocol => 'protocol', %{$tc->{cfg} // {}}});
|
||||||
local %ddclient::opt;
|
local %ddclient::opt;
|
||||||
|
|
Loading…
Reference in a new issue