Skip to content

Commit

Permalink
Merge pull request ddclient#742 from rhansen/strategy-dedup
Browse files Browse the repository at this point in the history
Improve deduplication of redundant `use*` queries
  • Loading branch information
rhansen authored Sep 6, 2024
2 parents 490dc16 + ad3cd11 commit 1c0ba9a
Show file tree
Hide file tree
Showing 6 changed files with 443 additions and 243 deletions.
457 changes: 254 additions & 203 deletions ddclient.in

Large diffs are not rendered by default.

153 changes: 121 additions & 32 deletions t/builtinfw_query.pl
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@
BEGIN { SKIP: { eval { require Test::Warnings; 1; } or skip($@, 1); } }
BEGIN { eval { require 'ddclient'; } or BAIL_OUT($@); }

my $got_host;
my $builtinfw = 't/builtinfw_query.pl';
$ddclient::builtinfw{$builtinfw} = {
name => 'dummy device for testing',
query => sub {
($got_host) = @_;
return '192.0.2.1 skip1 192.0.2.2 skip2 192.0.2.3';
},
queryv4 => sub {
($got_host) = @_;
return '192.0.2.4 skip1 192.0.2.5 skip3 192.0.2.6';
},
queryv6 => sub {
($got_host) = @_;
return '2001:db8::1 skip1 2001:db8::2 skip4 2001:db8::3';
},
};
%ddclient::builtinfw if 0; # suppress spurious warning "Name used only once: possible typo"
sub setbuiltinfw {
my ($fw) = @_;
no warnings 'once';
$ddclient::builtinfw{$fw->{name}} = $fw;
%ddclient::ip_strategies = ddclient::builtinfw_strategy($fw->{name});
%ddclient::ipv4_strategies = ddclient::builtinfwv4_strategy($fw->{name});
%ddclient::ipv6_strategies = ddclient::builtinfwv6_strategy($fw->{name});
}

my @gotcalls;

my @test_cases = (
my $skip_test_fw = 't/builtinfw_query.pl skip test';
setbuiltinfw({
name => $skip_test_fw,
query => sub { return '192.0.2.1 skip1 192.0.2.2 skip2 192.0.2.3'; },
queryv4 => sub { return '192.0.2.4 skip1 192.0.2.5 skip3 192.0.2.6'; },
queryv6 => sub { return '2001:db8::1 skip1 2001:db8::2 skip4 2001:db8::3'; },
});

my @skip_test_cases = (
{
desc => 'query',
getip => \&ddclient::get_ip,
Expand Down Expand Up @@ -61,20 +61,109 @@
},
);

for my $tc (@test_cases) {
subtest $tc->{desc} => sub {
my $h = "t/builtinfw_query.pl $tc->{desc}";
$ddclient::config{$h} = {
$tc->{useopt} => $builtinfw,
'fw-skip' => 'skip1',
%{$tc->{cfgxtra}},
};
%ddclient::config if 0; # suppress spurious warning "Name used only once: possible typo"
undef($got_host);
my $got = $tc->{getip}($builtinfw, $h);
is($got_host, $h, "host is passed through");
is($got, $tc->{want}, "returned IP matches");
for my $tc (@skip_test_cases) {
my $h = "t/builtinfw_query.pl $tc->{desc}";
$ddclient::config{$h} = {
$tc->{useopt} => $skip_test_fw,
'fw-skip' => 'skip1',
%{$tc->{cfgxtra}},
};
my $got = $tc->{getip}(ddclient::strategy_inputs($tc->{useopt}, $h));
is($got, $tc->{want}, $tc->{desc});
}

my $default_inputs_fw = 't/builtinfw_query.pl default inputs';
setbuiltinfw({
name => $default_inputs_fw,
query => sub { my %p = @_; push(@gotcalls, \%p); return '192.0.2.1'; },
queryv4 => sub { my %p = @_; push(@gotcalls, \%p); return '192.0.2.2'; },
queryv6 => sub { my %p = @_; push(@gotcalls, \%p); return '2001:db8::1'; },
});
my @default_inputs_test_cases = (
{
desc => 'use with default inputs',
getip => \&ddclient::get_ip,
useopt => 'use',
want => {use => $default_inputs_fw, fw => 'server', 'fw-skip' => 'skip',
'fw-login' => 'login', 'fw-password' => 'password', 'fw-ssl-validate' => 1},
},
{
desc => 'usev4 with default inputs',
getip => \&ddclient::get_ipv4,
useopt => 'usev4',
want => {usev4 => $default_inputs_fw, fwv4 => 'serverv4', fw => 'server',
'fwv4-skip' => 'skipv4', 'fw-skip' => 'skip', 'fw-login' => 'login',
'fw-password' => 'password', 'fw-ssl-validate' => 1},
},
{
desc => 'usev6 with default inputs',
getip => \&ddclient::get_ipv6,
useopt => 'usev6',
want => {usev6 => $default_inputs_fw, fwv6 => 'serverv6', 'fwv6-skip' => 'skipv6'},
},
);
for my $tc (@default_inputs_test_cases) {
my $h = "t/builtinfw_query.pl $tc->{desc}";
$ddclient::config{$h} = {
$tc->{useopt} => $default_inputs_fw,
'fw' => 'server',
'fwv4' => 'serverv4',
'fwv6' => 'serverv6',
'fw-login' => 'login',
'fw-password' => 'password',
'fw-ssl-validate' => 1,
'fw-skip' => 'skip',
'fwv4-skip' => 'skipv4',
'fwv6-skip' => 'skipv6',
};
@gotcalls = ();
$tc->{getip}(ddclient::strategy_inputs($tc->{useopt}, $h));
is_deeply(\@gotcalls, [$tc->{want}], $tc->{desc});
}

my $custom_inputs_fw = 't/builtinfw_query.pl custom inputs';
setbuiltinfw({
name => $custom_inputs_fw,
query => sub { my %p = @_; push(@gotcalls, \%p); return '192.0.2.1'; },
inputs => ['if'],
queryv4 => sub { my %p = @_; push(@gotcalls, \%p); return '192.0.2.2'; },
inputsv4 => ['ifv4'],
queryv6 => sub { my %p = @_; push(@gotcalls, \%p); return '2001:db8::1'; },
inputsv6 => ['ifv6'],
});

my @custom_inputs_test_cases = (
{
desc => 'use with custom inputs',
getip => \&ddclient::get_ip,
useopt => 'use',
want => {use => $custom_inputs_fw, if => 'eth0'},
},
{
desc => 'usev4 with custom inputs',
getip => \&ddclient::get_ipv4,
useopt => 'usev4',
want => {usev4 => $custom_inputs_fw, ifv4 => 'eth4'},
},
{
desc => 'usev6 with custom inputs',
getip => \&ddclient::get_ipv6,
useopt => 'usev6',
want => {usev6 => $custom_inputs_fw, ifv6 => 'eth6'},
},
);

for my $tc (@custom_inputs_test_cases) {
my $h = "t/builtinfw_query.pl $tc->{desc}";
$ddclient::config{$h} = {
$tc->{useopt} => $custom_inputs_fw,
'if' => 'eth0',
'ifv4' => 'eth4',
'ifv6' => 'eth6',
};
@gotcalls = ();
$tc->{getip}(ddclient::strategy_inputs($tc->{useopt}, $h));
is_deeply(\@gotcalls, [$tc->{want}], $tc->{desc});
}

done_testing();
14 changes: 11 additions & 3 deletions t/skip.pl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ BEGIN
if httpd('6');
$ddclient::builtinfw{$builtinfw} = {name => 'test', skip => 'skip'};
%ddclient::builtinfw if 0; # suppress spurious warning "Name used only once: possible typo"
%ddclient::ip_strategies = (%ddclient::ip_strategies, ddclient::builtinfw_strategy($builtinfw));
%ddclient::ipv4_strategies =
(%ddclient::ipv4_strategies, ddclient::builtinfwv4_strategy($builtinfw));
%ddclient::ipv6_strategies =
(%ddclient::ipv6_strategies, ddclient::builtinfwv6_strategy($builtinfw));

sub run_test_case {
my %tc = @_;
Expand All @@ -31,9 +36,12 @@ sub run_test_case {
my $h = 't/skip.pl';
$ddclient::config{$h} = $tc{cfg};
%ddclient::config if 0; # suppress spurious warning "Name used only once: possible typo"
is(ddclient::get_ip($tc{cfg}{use}, $h), $tc{want}, $tc{desc}) if ($tc{cfg}{use});
is(ddclient::get_ipv4($tc{cfg}{usev4}, $h), $tc{want}, $tc{desc}) if ($tc{cfg}{usev4});
is(ddclient::get_ipv6($tc{cfg}{usev6}, $h), $tc{want}, $tc{desc}) if ($tc{cfg}{usev6});
is(ddclient::get_ip(ddclient::strategy_inputs('use', $h)), $tc{want}, $tc{desc})
if ($tc{cfg}{use});
is(ddclient::get_ipv4(ddclient::strategy_inputs('usev4', $h)), $tc{want}, $tc{desc})
if ($tc{cfg}{usev4});
is(ddclient::get_ipv6(ddclient::strategy_inputs('usev6', $h)), $tc{want}, $tc{desc})
if ($tc{cfg}{usev6});
}
}

Expand Down
4 changes: 2 additions & 2 deletions t/ssl-validate.pl
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ BEGIN
skip("HTTP::Daemon too old for IPv6 support", 1) if $tc->{ipv6} && !$httpd_ipv6_supported;
$ddclient::config{$h} = $tc->{cfg};
%ddclient::config if 0; # suppress spurious warning "Name used only once: possible typo"
is(ddclient::get_ipv4($tc->{cfg}{usev4}, $h), $tc->{want}, $tc->{desc})
is(ddclient::get_ipv4(ddclient::strategy_inputs('usev4', $h)), $tc->{want}, $tc->{desc})
if ($tc->{cfg}{usev4});
is(ddclient::get_ipv6($tc->{cfg}{usev6}, $h), $tc->{want}, $tc->{desc})
is(ddclient::get_ipv6(ddclient::strategy_inputs('usev6', $h)), $tc->{want}, $tc->{desc})
if ($tc->{cfg}{usev6});
}
}
Expand Down
52 changes: 52 additions & 0 deletions t/update_nics.pl
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,58 @@ sub mergecfg {
%$_,
};
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
map({
my %cfg = %{delete($_->{cfg})};
my $desc = join(' ', map("$_=$cfg{$_}", sort(keys(%cfg))));
{
desc => "deduplicates identical IP discovery, $desc",
cfg => {
hosta => {protocol => 'legacy', %cfg},
hostb => {protocol => 'legacy', %cfg},
},
want_reqs_webv4 => 1,
want_updates => [['hosta', 'hostb']],
want_recap_changes => {
hosta => {
'atime' => $ddclient::now,
'ipv4' => '192.0.2.1',
'mtime' => $ddclient::now,
'status-ipv4' => 'good',
},
hostb => {
'atime' => $ddclient::now,
'ipv4' => '192.0.2.1',
'mtime' => $ddclient::now,
'status-ipv4' => 'good',
},
},
%$_,
};
} {cfg => {use => 'web'}}, {cfg => {usev4 => 'webv4'}}),
{
desc => "deduplicates identical IP discovery, usev6=webv6",
ipv6 => 1,
cfg => {
hosta => {protocol => 'legacy', usev6 => 'webv6'},
hostb => {protocol => 'legacy', usev6 => 'webv6'},
},
want_reqs_webv6 => 1,
want_updates => [['hosta', 'hostb']],
want_recap_changes => {
hosta => {
'atime' => $ddclient::now,
'ipv6' => '2001:db8::1',
'mtime' => $ddclient::now,
'status-ipv6' => 'good',
},
hostb => {
'atime' => $ddclient::now,
'ipv6' => '2001:db8::1',
'mtime' => $ddclient::now,
'status-ipv6' => 'good',
},
},
},
);

for my $tc (@test_cases) {
Expand Down
6 changes: 3 additions & 3 deletions t/use_web.pl
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ BEGIN
SKIP: {
skip("IPv6 not supported on this system", 1) if $tc->{ipv6} && !$ipv6_supported;
skip("HTTP::Daemon too old for IPv6 support", 1) if $tc->{ipv6} && !$httpd_ipv6_supported;
is(ddclient::get_ip($tc->{cfg}{use}, $h), $tc->{want}, $tc->{desc})
is(ddclient::get_ip(ddclient::strategy_inputs('use', $h)), $tc->{want}, $tc->{desc})
if $tc->{cfg}{use};
is(ddclient::get_ipv4($tc->{cfg}{usev4}, $h), $tc->{want}, $tc->{desc})
is(ddclient::get_ipv4(ddclient::strategy_inputs('usev4', $h)), $tc->{want}, $tc->{desc})
if $tc->{cfg}{usev4};
is(ddclient::get_ipv6($tc->{cfg}{usev6}, $h), $tc->{want}, $tc->{desc})
is(ddclient::get_ipv6(ddclient::strategy_inputs('usev6', $h)), $tc->{want}, $tc->{desc})
if $tc->{cfg}{usev6};
}
}
Expand Down

0 comments on commit 1c0ba9a

Please sign in to comment.