Dynamically compute default for use based on usev4, usev6
This is mostly to simplify tests, but it also improves readability.
The infrastructure changes in this commit also make it possible to
introduce a new `url` variable that defaults to `opt('server', $h)`
concatenated with `opt('script', $h)` so that we can start migrating
away from those user-unfriendly variables.
This commit is contained in:
parent
46bd2f1771
commit
f024bcce34
4 changed files with 84 additions and 19 deletions
|
|
@ -78,6 +78,7 @@ m4_foreach_w([_m], [
|
|||
File::Spec::Functions
|
||||
File::Temp
|
||||
List::Util
|
||||
re
|
||||
], [AX_PROG_PERL_MODULES([_m], [],
|
||||
[AC_MSG_WARN([some tests will fail due to missing module _m])])])
|
||||
|
||||
|
|
|
|||
22
ddclient.in
22
ddclient.in
|
|
@ -597,7 +597,13 @@ our %variables = (
|
|||
'password' => setv(T_PASSWD,1, 0, undef, undef),
|
||||
'host' => setv(T_STRING,1, 1, undef, undef),
|
||||
|
||||
'use' => setv(T_USE, 0, 0, 'ip', undef),
|
||||
'use' => setv(T_USE, 0, 0, sub {
|
||||
my ($h) = @_;
|
||||
return "'disabled' if '--usev4' or '--usev6' is enabled, otherwise 'ip'"
|
||||
if ($h // '') eq '<usage>';
|
||||
return 'disabled' if opt('usev4', $h) ne 'disabled' || opt('usev6', $h) ne 'disabled';
|
||||
return 'ip';
|
||||
}, undef),
|
||||
'usev4' => setv(T_USEV4, 0, 0, 'disabled', undef),
|
||||
'usev6' => setv(T_USEV6, 0, 0, 'disabled', undef),
|
||||
'if' => setv(T_IF, 0, 0, 'ppp0', undef),
|
||||
|
|
@ -1092,7 +1098,7 @@ $variables{'merged'} = {
|
|||
};
|
||||
|
||||
# This will hold the processed args.
|
||||
my %opt = ();
|
||||
our %opt;
|
||||
my $deprecated_handler = sub { warning("'-$_[0]' is deprecated and does nothing"); };
|
||||
$opt{'fw-banlocal'} = $deprecated_handler;
|
||||
$opt{'if-skip'} = $deprecated_handler;
|
||||
|
|
@ -1937,7 +1943,7 @@ sub usage {
|
|||
for (@_) {
|
||||
if (ref $_) {
|
||||
my ($key, $specifier, $arg_usage) = @$_;
|
||||
my $value = default($key);
|
||||
my $value = default($key, '<usage>');
|
||||
next unless $arg_usage;
|
||||
$usage .= " $arg_usage";
|
||||
if (defined($value) && $value ne '') {
|
||||
|
|
@ -2220,15 +2226,17 @@ sub split_by_comma {
|
|||
}
|
||||
sub default {
|
||||
my ($v, $h) = @_;
|
||||
my $var;
|
||||
if (defined($h) && $config{$h}) {
|
||||
my $proto = $protocols{opt('protocol', $v eq 'protocol' ? undef : $h)};
|
||||
my $var = $proto->{variables}{$v} if $proto;
|
||||
return $var->{default} if $var;
|
||||
$var = $proto->{variables}{$v} if $proto;
|
||||
}
|
||||
return undef if !defined($variables{'merged'}{$v});
|
||||
# TODO: This might grab an arbitrary protocol-specific variable definition, which could cause
|
||||
# surprising behavior.
|
||||
return $variables{'merged'}{$v}{'default'};
|
||||
$var //= $variables{'merged'}{$v};
|
||||
return undef if !defined($var);
|
||||
return $var->{'default'}($h) if ref($var->{default}) eq 'CODE';
|
||||
return $var->{'default'};
|
||||
}
|
||||
sub opt {
|
||||
my $v = shift;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ my @test_cases = (
|
|||
desc => "legacy, fresh, $desc",
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_update => 1,
|
||||
|
|
@ -136,7 +135,6 @@ my @test_cases = (
|
|||
ipv6 => 1,
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
'usev6' => 'webv6',
|
||||
},
|
||||
want_update => 1,
|
||||
|
|
@ -168,7 +166,6 @@ my @test_cases = (
|
|||
ipv6 => 1,
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
'usev4' => 'webv4',
|
||||
'usev6' => 'webv6',
|
||||
},
|
||||
|
|
@ -209,7 +206,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_cfg_changes => {
|
||||
|
|
@ -238,7 +234,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_cfg_changes => {
|
||||
|
|
@ -267,7 +262,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_recap_changes => {
|
||||
|
|
@ -299,7 +293,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_update => 1,
|
||||
|
|
@ -345,7 +338,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_recap_changes => {
|
||||
|
|
@ -374,7 +366,6 @@ my @test_cases = (
|
|||
},
|
||||
cfg => {
|
||||
'protocol' => 'legacy',
|
||||
'use' => 'disabled',
|
||||
%cfg,
|
||||
},
|
||||
want_update => 1,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use Test::More;
|
||||
use re qw(is_regexp);
|
||||
SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
|
||||
eval { require 'ddclient'; } or BAIL_OUT($@);
|
||||
|
||||
|
|
@ -23,14 +24,78 @@ for my $tc (@test_cases) {
|
|||
if ($tc->{def}{required}) {
|
||||
is($tc->{def}{default}, undef, "'$tc->{desc}' (required) has no default");
|
||||
} else {
|
||||
local %ddclient::variables = (merged => {var => $tc->{def}});
|
||||
# Preserve all existing variables in $variables{merged} so that variables with dynamic
|
||||
# defaults can reference them.
|
||||
local %ddclient::variables = (merged => {
|
||||
%{$ddclient::variables{merged}},
|
||||
'var for test' => $tc->{def},
|
||||
});
|
||||
# Variables with dynamic defaults will need their own unit tests, but we can still check the
|
||||
# clean-slate hostless default.
|
||||
local %ddclient::config;
|
||||
local %ddclient::opt;
|
||||
local %ddclient::globals;
|
||||
my $norm;
|
||||
my $default = ddclient::default('var');
|
||||
my $default = ddclient::default('var for test');
|
||||
diag("'$tc->{desc}' default: " . ($default // '<undefined>'));
|
||||
is($default, $tc->{def}{default}, "'$tc->{desc}' default() return value matches default");
|
||||
is($default, $tc->{def}{default}, "'$tc->{desc}' default() return value matches default")
|
||||
if ref($tc->{def}{default}) ne 'CODE';
|
||||
my $valid = eval { $norm = ddclient::check_value($default, $tc->{def}); 1; } or diag($@);
|
||||
ok($valid, "'$tc->{desc}' (optional) has a valid default");
|
||||
is($norm, $default, "'$tc->{desc}' default normalizes to itself") if $valid;
|
||||
}
|
||||
}
|
||||
|
||||
my @use_test_cases = (
|
||||
{
|
||||
desc => 'clean slate hostless default',
|
||||
want => 'ip',
|
||||
},
|
||||
{
|
||||
desc => 'usage string',
|
||||
host => '<usage>',
|
||||
want => qr/disabled.*ip|ip.*disabled/,
|
||||
},
|
||||
{
|
||||
desc => 'usev4 disables use by default',
|
||||
host => 'host',
|
||||
cfg => {usev4 => 'webv4'},
|
||||
want => 'disabled',
|
||||
},
|
||||
{
|
||||
desc => 'usev6 disables use by default',
|
||||
host => 'host',
|
||||
cfg => {usev4 => 'webv4'},
|
||||
want => 'disabled',
|
||||
},
|
||||
{
|
||||
desc => 'explicitly setting use re-enables it',
|
||||
host => 'host',
|
||||
cfg => {use => 'web', usev4 => 'webv4'},
|
||||
want => 'web',
|
||||
},
|
||||
);
|
||||
for my $tc (@use_test_cases) {
|
||||
my $desc = "'use' dynamic default: $tc->{desc}";
|
||||
local %ddclient::protocols =
|
||||
(protocol => {variables => $ddclient::variables{'protocol-common-defaults'}});
|
||||
local %ddclient::variables = (merged => {
|
||||
'protocol' => $ddclient::variables{'merged'}{'protocol'},
|
||||
'use' => $ddclient::variables{'protocol-common-defaults'}{'use'},
|
||||
'usev4' => $ddclient::variables{'merged'}{'usev4'},
|
||||
'usev6' => $ddclient::variables{'merged'}{'usev6'},
|
||||
});
|
||||
local %ddclient::config = (host => {protocol => 'protocol', %{$tc->{cfg} // {}}});
|
||||
local %ddclient::opt;
|
||||
local %ddclient::globals;
|
||||
|
||||
my $got = ddclient::opt('use', $tc->{host});
|
||||
|
||||
if (is_regexp($tc->{want})) {
|
||||
like($got, $tc->{want}, $desc);
|
||||
} else {
|
||||
is($got, $tc->{want}, $desc);
|
||||
}
|
||||
}
|
||||
|
||||
done_testing();
|
||||
|
|
|
|||
Loading…
Reference in a new issue