Config-Abstraction
view release on metacpan or search on metacpan
t/edge_cases.t view on Meta::CPAN
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'base.toml', qq{host = "base_host"\nport = 5432\n});
_write_file($dir, 'local.toml', qq{host = "local_host"\n});
my $cfg = Config::Abstraction->new(
data => {},
config_dirs => [$dir],
env_prefix => $ENV_PREFIX,
);
is($cfg->get('host'), 'local_host', 'local.toml host overrides base.toml host');
is($cfg->get('port'), 5432, 'base.toml port survives when local.toml does not mention it');
};
subtest 'TOML: data constructor has lower precedence than base.toml' => sub {
plan skip_all => 'TOML::Tiny not installed' unless eval { require TOML::Tiny; 1 };
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'base.toml', qq{host = "toml_host"\n});
my $cfg = Config::Abstraction->new(
data => { host => 'data_host', extra => 'kept' },
config_dirs => [$dir],
env_prefix => $ENV_PREFIX,
);
is($cfg->get('host'), 'toml_host', 'base.toml overrides data constructor value');
is($cfg->get('extra'), 'kept', 'data key not in base.toml survives');
};
subtest 'TOML: TOML boolean and array types are loaded without corruption' => sub {
# TOML::Tiny returns Perl values: booleans as JSON::PP::Boolean objects,
# arrays as arrayrefs. Verify they arrive intact.
plan skip_all => 'TOML::Tiny not installed' unless eval { require TOML::Tiny; 1 };
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'base.toml', qq{debug = true\ntags = ["web", "api"]\n});
my $cfg = Config::Abstraction->new(
data => {},
config_dirs => [$dir],
env_prefix => $ENV_PREFIX,
);
ok($cfg->get('debug'), 'TOML boolean true is truthy');
my $tags = $cfg->get('tags');
ok(ref($tags) eq 'ARRAY', 'TOML array is loaded as arrayref');
is($tags->[0], 'web', 'first TOML array element is correct');
is($tags->[1], 'api', 'second TOML array element is correct');
};
subtest 'TOML: malformed TOML file is skipped with a carp warning' => sub {
# A TOML file with syntax errors should emit a carp and be skipped,
# not abort construction. data values must survive.
plan skip_all => 'TOML::Tiny not installed' unless eval { require TOML::Tiny; 1 };
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'base.toml', qq{host = "unclosed string\n});
my @warnings;
local $SIG{__WARN__} = sub { push @warnings, $_[0] };
my $cfg = Config::Abstraction->new(
data => { fallback => 'alive' },
config_dirs => [$dir],
env_prefix => $ENV_PREFIX,
);
ok(@warnings > 0, 'malformed TOML emits at least one carp warning');
ok(defined($cfg), 'construction succeeds despite malformed base.toml');
is($cfg->get('fallback'), 'alive', 'data values survive a malformed TOML file');
};
subtest 'TOML: config_file with .toml extension is loaded via extensionless chain' => sub {
# When config_file points to a .toml file, the all-parsers chain
# should try TOML::Tiny and succeed.
plan skip_all => 'TOML::Tiny not installed' unless eval { require TOML::Tiny; 1 };
my $dir = tempdir(CLEANUP => 1);
_write_file($dir, 'myapp.toml', qq{[server]\nhost = "explicit_host"\nport = 9000\n});
my $cfg = Config::Abstraction->new(
config_file => 'myapp.toml',
config_dirs => [$dir],
env_prefix => $ENV_PREFIX,
);
ok(defined($cfg), 'config_file pointing to a .toml file is loaded');
is($cfg->get('server.host'), 'explicit_host', 'TOML section key accessible via dotted notation from config_file');
is($cfg->get('server.port'), 9000, 'TOML section integer accessible from config_file');
};
# ---------------------------------------------------------------------------
# validators option - per-key value validation
# ---------------------------------------------------------------------------
subtest 'validators: type integer accepts valid integer strings' => sub {
my $cfg = Config::Abstraction->new(
data => { port => 8080 },
config_dirs => [],
env_prefix => $ENV_PREFIX,
validators => { 'port' => 'integer' },
);
ok(defined($cfg), 'construction succeeds for valid integer');
is($cfg->get('port'), 8080, 'value unchanged after integer validation');
};
subtest 'validators: type integer rejects non-integer string' => sub {
dies_ok {
Config::Abstraction->new(
data => { port => '80.5' },
config_dirs => [],
env_prefix => $ENV_PREFIX,
validators => { 'port' => 'integer' },
);
} 'construction croaks for float value failing integer type';
like($@, qr/must be an integer/, 'error message names the type');
};
subtest 'validators: type integer rejects undef' => sub {
dies_ok {
Config::Abstraction->new(
data => { port => undef },
config_dirs => [],
env_prefix => $ENV_PREFIX,
validators => { 'port' => 'integer' },
);
} 'undef value fails integer validation';
};
subtest 'validators: type number accepts integer and float' => sub {
for my $val (42, 3.14, -1, '0.001', '1e5') {
( run in 3.813 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )