Config-Abstraction
view release on metacpan or search on metacpan
t/extended_tests.t view on Meta::CPAN
);
ok(defined($cfg), 'object created with SCRIPT_NAME set (line 596 A=TRUE)');
diag('script_name from SCRIPT_NAME: ' . ($cfg ? 'ok' : 'n/a')) if $ENV{TEST_VERBOSE};
pass('line 596 A=TRUE covered: SCRIPT_NAME used instead of $0');
};
# ===========================================================================
# Pass both config_file AND file alias: the //= at line 359 sees LHS already
# defined, so it does NOT overwrite config_file. This covers the //= B=FALSE
# (defined LHS) condition path.
# ===========================================================================
subtest 'new() - explicit config_file not clobbered by file alias (line 359 //= defined)' => sub {
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'real.yaml', "result: correct\n");
_write_file($dir, 'alias.yaml', "result: wrong\n");
my $cfg = Config::Abstraction->new(
config_file => 'real.yaml',
file => 'alias.yaml', # alias: ignored because config_file already set
config_dirs => [$dir],
);
ok(defined($cfg), 'object created when both config_file and file are supplied');
is($cfg->get('result'), 'correct',
'config_file wins over file alias (line 359 //= B=FALSE: LHS already defined)');
};
# ===========================================================================
# AUTOLOAD resolves from config when $self->{data} is undef (line 1339 A=FALSE)
# All existing AUTOLOAD tests use data=>{...}, so $self->{data} is always truthy
# (A=TRUE path). Creating an object without data=> makes $self->{data} undef,
# forcing the || to fall through to $self->{'config'} (A=FALSE, B=TRUE).
# ===========================================================================
subtest 'AUTOLOAD - uses config hash when data attribute is undef (line 1339 A=FALSE)' => sub {
my $dir = tempdir(CLEANUP => 1);
# No data=> arg: $self->{data} will be undef after construction
_write_file($dir, 'base.yaml', "mykey: autoload_val\n");
my $cfg = Config::Abstraction->new(
config_dirs => [$dir],
sep_char => '_',
);
ok(defined($cfg), 'object created from yaml without data arg');
# AUTOLOAD: $self->{data} is undef â falls through to $self->{"config"}
my $val;
eval { $val = $cfg->mykey() };
ok(!$@, 'AUTOLOAD call succeeds on object without data attribute') or diag("error: $@");
is($val, 'autoload_val', 'AUTOLOAD resolves from config (line 1339 A=FALSE, B=TRUE)');
};
# ===========================================================================
# Config::Abstract hidden via local %INC + Test::Without::Module:
# - line 701 FALSE: _load_driver('Config::Abstract') returns 0
# - line 719 condition A=FALSE,B=TRUE: $data is truthy (scalar from YAML) but
# NOT a HASH ref, which is the one sub-condition path not yet covered.
#
# Content "just a plain string" is parsed by YAML::XS as a truthy scalar.
# XMLin at line 697 fails (not XML) so $data stays as that truthy scalar.
# With Config::Abstract blocked, line 701 is FALSE â $data unchanged â line 719:
# !$data = FALSE (data truthy)
# ref ne HASH = TRUE (ref is "")
# This is the previously-uncovered A=FALSE,B=TRUE condition path.
# ===========================================================================
subtest '_load_config() - 701 FALSE + 719 A=FALSE,B=TRUE via Config::Abstract hidden' => sub {
# Remove Config::Abstract from the %INC cache so that the eval "require"
# inside _load_driver will search @INC (where Test::Without::Module blocks it).
# 'local %INC' restores the cache after the subtest exits.
local %INC = %INC;
delete $INC{'Config/Abstract.pm'};
Test::Without::Module->import('Config::Abstract');
my $dir = tempdir(CLEANUP => 1);
# "just a plain string" â YAML returns a truthy scalar (not HASH).
# XMLin at line 697 throws on non-XML â eval catches it, $data unchanged.
# Config::Abstract hidden â line 701 FALSE â $data stays truthy scalar.
_write_file($dir, 'plain.cfg', "just a plain string\n");
my $cfg;
_silenced(sub {
$cfg = Config::Abstraction->new(
config_file => 'plain.cfg',
config_dirs => [$dir],
data => { fallback => 'ca_hidden' },
);
});
# $cfg is defined because the data=> fallback provides config keys.
ok(defined($cfg), 'object created: data fallback present when Config::Abstract hidden');
is($cfg->get('fallback'), 'ca_hidden',
'fallback data intact: Config::Abstract was skipped (line 701 FALSE)');
pass('line 719 condition A=FALSE B=TRUE covered: data was truthy non-HASH scalar');
Test::Without::Module->unimport('Config::Abstract');
};
# ===========================================================================
# Config::Abstract->new throws: line 708 TRUE + line 709
# The inner eval at line 705 catches the die, setting $err. Line 708 TRUE
# fires, line 709 undef-s $data. Normally Config::Abstract never throws on
# an existing readable file, so we monkey-patch its constructor to force it.
# ===========================================================================
subtest '_load_config() - line 708 TRUE: Config::Abstract->new throws in inner eval' => sub {
my $dir = tempdir(CLEANUP => 1);
# Content that falls through to the Config::Abstract block:
# YAML parses as scalar (non-HASH), XMLin fails (not XML), INI fails (no sections).
_write_file($dir, 'throws.cfg', "just a plain string\n");
my $cfg;
_silenced(sub {
no warnings 'redefine', 'once';
local *Config::Abstract::new = sub { die "forced Config::Abstract error\n" };
$cfg = Config::Abstraction->new(
config_file => 'throws.cfg',
config_dirs => [$dir],
data => { fallback => 'throws_test' },
);
});
ok(defined($cfg), 'object survives when Config::Abstract->new throws (708 TRUE)');
( run in 1.297 second using v1.01-cache-2.11-cpan-800906f7e73 )