Config-Abstraction
view release on metacpan or search on metacpan
t/extended_tests.t view on Meta::CPAN
Test::Without::Module->unimport('XML::Simple');
};
# ===========================================================================
# AUTOLOAD croak when mid-path value is not a HASH (line 1351 false branch)
# ===========================================================================
# The condition `(ref($val) eq 'HASH') && exists $val->{$part}` in AUTOLOAD
# fires its else/croak when $val is NOT a hashref at some point in traversal.
# This covers the left-hand-side false branch: ref($val) ne 'HASH'.
subtest 'AUTOLOAD - croaks when intermediate key is a scalar (non-HASH)' => sub {
my $cfg = Config::Abstraction->new(
data => { foo => 'bar' },
config_dirs => [],
sep_char => $SEP_US,
);
# foo is a scalar; foo_baz tries to traverse fooâbaz but foo is not HASH
my $died = 0;
eval { $cfg->foo_baz() };
if($@) {
$died = 1;
like($@, qr/No such config key/i, 'AUTOLOAD croak message mentions key name');
}
ok($died, 'AUTOLOAD croaks when intermediate path value is not a HASH ref');
};
# ===========================================================================
# _parse_config_string() with logger set -- error path logs via $logger->warn
# ===========================================================================
# When _parse_config_string encounters a parse error AND a logger is attached,
# the ternary at line 1319 takes the logger->warn path instead of Carp::carp.
subtest '_parse_config_string() - parse error with logger emits logger->warn' => sub {
my ($logger, $log_ref) = _make_spy_logger();
# Create proxy with the spy logger already blessed (bypasses Log::Abstraction wrap)
my $proxy = Config::Abstraction::ExtTestProxy->new(
data => { dummy => 1 },
config_dirs => [],
);
$proxy->{'logger'} = $logger; # directly inject spy logger
# Malformed YAML: unclosed bracket causes YAML::XS::Load to throw
my $result;
_silenced(sub {
$result = $proxy->test_parse_string("{bad yaml: [unclosed", 'remote.yaml', 'test-label');
});
ok(!defined($result), '_parse_config_string returns undef on YAML parse error');
my @warns = grep { $_->[0] eq 'warn' && $_->[1] =~ /test-label/ } @{$log_ref};
ok(scalar(@warns) > 0, 'logger->warn called for parse error in _parse_config_string')
or diag('log: ' . join('; ', map { "$_->[0]: $_->[1]" } @{$log_ref}));
};
# ===========================================================================
# Access guard -- Illegal Operation croak (line 444-445)
# ===========================================================================
# Calling _load_config() (or _parse_config_string, _load_remote_dir) directly
# from a non-subclass caller should croak with 'Illegal Operation'.
# The UNIVERSAL::isa guard at line 444 checks (caller)[0] against __PACKAGE__.
subtest '_load_config() - illegal direct call from outside class croaks' => sub {
my $cfg = Config::Abstraction->new(
data => { dummy => 1 },
config_dirs => [],
);
# Direct call from package main (not a subclass) must croak
my $died = 0;
eval { $cfg->_load_config() };
if($@) {
$died = 1;
like($@, qr/Illegal Operation/i, 'croak message mentions Illegal Operation');
}
ok($died, '_load_config() croaks when called from outside the class hierarchy');
};
# ===========================================================================
# XML base file failure WITHOUT logger -- Carp::carp path (line 536)
# ===========================================================================
# When a base.xml file exists but is malformed AND no logger is set, the module
# falls through to Carp::carp (line 536) instead of calling $logger->notice.
# The `if($logger)` at line 533 is FALSE in this case.
subtest '_load_config() - malformed base.xml without logger emits carp' => sub {
my $dir = tempdir(CLEANUP => 1);
# Valid XML header but unclosed tag: XML::Simple/XML::PP will throw
_write_file($dir, 'base.xml', "<?xml version=\"1.0\"?><config><unclosed>\n");
my @carps;
local $SIG{__WARN__} = sub { push @carps, $_[0] };
my $cfg = Config::Abstraction->new(
data => { fallback => 'yes' },
config_dirs => [$dir],
# no logger: the if($logger) at line 533 is false â Carp::carp fires
);
ok(defined($cfg), 'object created despite malformed base.xml without logger');
pass('no crash when malformed base.xml without logger (Carp::carp path)');
};
# ===========================================================================
# _load_remote_dir() -- File::Slurp::Remote absent, logger set (line 1206)
# ===========================================================================
# When File::Slurp::Remote is not installed, _load_remote_dir emits a warning.
# With a logger set, the ternary `$logger ? $logger->warn(...) : Carp::carp(...)`
# at line 1206 must take the logger->warn path.
subtest '_load_remote_dir() - logger->warn when File::Slurp::Remote absent' => sub {
Test::Without::Module->import('File::Slurp::Remote');
my ($logger, $log_ref) = _make_spy_logger();
my $proxy = Config::Abstraction::ExtTestProxy->new(
data => { dummy => 1 },
config_dirs => [],
);
$proxy->{'logger'} = $logger; # inject spy logger
my %merged;
_silenced(sub {
$proxy->test_load_remote_dir('remotehost', '/etc/myapp', \%merged);
( run in 4.951 seconds using v1.01-cache-2.11-cpan-364913b4093 )