App-makefilepl2cpanfile
view release on metacpan or search on metacpan
use Path::Tiny;
BEGIN { use_ok('App::makefilepl2cpanfile') }
my $dir = tempdir(CLEANUP => 1);
chdir $dir;
path('Makefile.PL')->spew_utf8(<<'END_MF');
WriteMakefile(
MIN_PERL_VERSION => '5.010',
PREREQ_PM => { 'Try::Tiny' => 0 },
);
END_MF
my $out = App::makefilepl2cpanfile::generate(makefile => 'Makefile.PL');
like $out, qr/requires 'Try::Tiny'/, 'runtime dep is present';
like $out, qr/'perl', '5.010'/, 'MIN_PERL_VERSION is emitted';
like $out, qr/^# Generated from/m, 'header comment is present';
# A versioned dependency must include the version constraint.
path('Makefile.PL')->spew_utf8(<<'END_MF');
WriteMakefile(
PREREQ_PM => { 'Foo::Bar' => '1.23' },
);
END_MF
t/function.t view on Meta::CPAN
# Private helpers are called via their fully-qualified names. No strict-refs
# trick is needed because these are compile-time-known symbol names.
# The leading underscore is a convention; Sub::Private is not enforced.
Readonly my $PKG => 'App::makefilepl2cpanfile';
# Shared fixture: a realistic Makefile.PL string exercising the common cases.
Readonly my $MF_SIMPLE => <<'END_MF';
WriteMakefile(
PREREQ_PM => {
'Try::Tiny' => 0,
'Moo' => '2.000', # object system
},
TEST_REQUIRES => {
'Test::More' => 0,
},
MIN_PERL_VERSION => '5.010',
);
END_MF
# A minimal deps hashref used to drive _emit without going through parse_prereqs.
t/function.t view on Meta::CPAN
# Strategy: test comment capture, blank/comment line skipping, first-
# occurrence-wins across a single call and across multiple calls, return
# value, and in-place mutation semantics.
# -----------------------------------------------------------------------
subtest '_extract_pairs â block parser' => sub {
# Basic: one module with version zero, one with an explicit version.
{
my %deps;
App::makefilepl2cpanfile::_extract_pairs(
" 'Try::Tiny' => 0,\n 'Moo' => '2.000',\n",
\%deps, 'runtime', 'requires',
);
ok exists $deps{runtime}{requires}{'Try::Tiny'}, 'Try::Tiny extracted';
is $deps{runtime}{requires}{'Try::Tiny'}{version}, 0, 'version 0 stored';
is $deps{runtime}{requires}{'Try::Tiny'}{comment}, undef, 'no comment stored as undef';
ok exists $deps{runtime}{requires}{'Moo'}, 'Moo extracted';
is $deps{runtime}{requires}{'Moo'}{version}, '2.000', 'explicit version stored';
}
# Inline comment must be captured before the comment text is stripped.
{
my %deps;
App::makefilepl2cpanfile::_extract_pairs(
" 'Foo::Bar' => 0, # used in bin/ scripts\n",
t/function.t view on Meta::CPAN
subtest 'generate â integration: parse, merge, format' => sub {
# Redirect config loading to an empty home so default develop tools are
# injected whenever with_develop => 1 is in effect. The guard is held for
# the entire subtest; it restores File::HomeDir when the sub returns.
my $empty_home = tempdir( CLEANUP => 1 );
my $g = mock_scoped 'File::HomeDir::my_home' => sub { $empty_home };
my $dir = tempdir( CLEANUP => 1 );
my $mf = path($dir)->child('Makefile.PL');
$mf->spew_utf8("WriteMakefile(PREREQ_PM => { 'Try::Tiny' => 0 });\n");
# ---- Guard: croak on missing file ----
throws_ok {
App::makefilepl2cpanfile::generate( makefile => "$dir/nonexistent.pl" )
}
qr/Cannot read/,
'croaks with "Cannot read" for missing makefile';
# ---- Guard: croak when path is a directory, not a file ----
throws_ok {
App::makefilepl2cpanfile::generate( makefile => $dir )
}
qr/Cannot read/,
'croaks when path is a directory';
# ---- Minimal valid Makefile.PL ----
{
my $out;
lives_ok { $out = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 ) }
'lives with a valid minimal Makefile.PL';
like $out, qr/requires 'Try::Tiny'/, 'module appears in output';
like $out, qr/\n$/, 'output ends with a newline';
}
# ---- Flat-hash calling style ----
{
my $r = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 );
like $r, qr/requires 'Try::Tiny'/, 'flat hash calling style works';
}
# ---- Hashref calling style ----
{
my $r = App::makefilepl2cpanfile::generate(
{ makefile => "$mf", with_develop => 0 }
);
like $r, qr/requires 'Try::Tiny'/, 'hashref calling style works';
}
# ---- with_develop defaults to 1 when the argument is omitted ----
{
my $r = App::makefilepl2cpanfile::generate( makefile => "$mf" );
like $r, qr/Perl::Critic/, 'with_develop defaults to 1 â develop block present';
}
# ---- with_develop => 0 suppresses the develop block entirely ----
{
t/integration.t view on Meta::CPAN
# -----------------------------------------------------------------------
# Fixture constants â shared across all subtests.
# -----------------------------------------------------------------------
# Makefile.PL with only PREREQ_PM entries; no version constraints, no comments.
Readonly my $MF_SIMPLE => <<'END';
use ExtUtils::MakeMaker;
WriteMakefile(
PREREQ_PM => {
'Moo' => 0,
'Try::Tiny' => 0,
},
);
END
# Makefile.PL with all four simple key types.
Readonly my $MF_ALL_PHASES => <<'END';
use ExtUtils::MakeMaker;
WriteMakefile(
CONFIGURE_REQUIRES => { 'ExtUtils::MakeMaker' => '6.64' },
BUILD_REQUIRES => { 'Module::Build' => '0.42' },
t/integration.t view on Meta::CPAN
#
# Strategy: call generate() with two different Makefile.PLs (A and B),
# then call generate() for A again. The first and third outputs must be
# identical, and A must differ from B. This confirms no shared mutable
# state exists between calls.
# -----------------------------------------------------------------------
subtest 'statelessness: independent generate() calls do not interfere' => sub {
my $g = empty_home();
my $mf_a = make_mf($MF_SIMPLE); # Moo + Try::Tiny
my $mf_b = make_mf($MF_ALL_PHASES); # completely different modules
my $out_a1 = App::makefilepl2cpanfile::generate(
makefile => "$mf_a", with_develop => 0
);
my $out_b = App::makefilepl2cpanfile::generate(
makefile => "$mf_b", with_develop => 0
);
my $out_a2 = App::makefilepl2cpanfile::generate(
makefile => "$mf_a", with_develop => 0
t/parse_prereqs.t view on Meta::CPAN
use App::makefilepl2cpanfile;
# -----------------------------------------------------------------------
# Basic extraction â simple PREREQ_PM / TEST_REQUIRES / etc. form
# -----------------------------------------------------------------------
my $content = <<'END_MF';
WriteMakefile(
PREREQ_PM => {
'Moo' => '2.000',
'Try::Tiny' => 0,
},
TEST_REQUIRES => {
'Test::More' => 0,
},
CONFIGURE_REQUIRES => {
'ExtUtils::MakeMaker' => '6.64',
},
BUILD_REQUIRES => {
'Module::Build' => '0.42',
},
t/parse_prereqs.t view on Meta::CPAN
END_MF
my $deps = App::makefilepl2cpanfile::parse_prereqs($content);
isa_ok $deps, 'HASH', 'parse_prereqs returns a hashref';
# The simple keys all map to the 'requires' relationship.
ok exists $deps->{runtime}{requires}{'Moo'}, 'Moo is in runtime/requires';
is $deps->{runtime}{requires}{'Moo'}{version}, '2.000', 'Moo carries its version';
ok exists $deps->{runtime}{requires}{'Try::Tiny'}, 'Try::Tiny is in runtime/requires';
is $deps->{runtime}{requires}{'Try::Tiny'}{version}, 0, 'Try::Tiny version is 0';
ok exists $deps->{test}{requires}{'Test::More'}, 'Test::More in test/requires';
ok exists $deps->{configure}{requires}{'ExtUtils::MakeMaker'}, 'EMM in configure/requires';
is $deps->{configure}{requires}{'ExtUtils::MakeMaker'}{version}, '6.64',
'ExtUtils::MakeMaker version correct';
ok exists $deps->{build}{requires}{'Module::Build'}, 'Module::Build in build/requires';
is $deps->{build}{requires}{'Module::Build'}{version}, '0.42',
'Module::Build version correct';
# Write a Makefile.PL into a tempdir and return its path object.
sub make_mf {
my ($content) = @_;
my $dir = tempdir( CLEANUP => 1 );
my $mf = path($dir)->child('Makefile.PL');
$mf->spew_utf8($content);
return $mf;
}
Readonly my $MF_SIMPLE =>
"WriteMakefile(PREREQ_PM => { 'Try::Tiny' => 0 });\n";
Readonly my $MF_VERSIONED =>
"WriteMakefile(PREREQ_PM => { 'Moo' => '2.000' });\n";
# -----------------------------------------------------------------------
# generate() â error / message paths
# -----------------------------------------------------------------------
subtest 'generate() â croak on unreadable makefile' => sub {
my $g = empty_home();
my $dir = tempdir( CLEANUP => 1 );
path($dir)->child('Makefile.PL')->spew_utf8($MF_SIMPLE);
my $orig = Path::Tiny->cwd;
chdir $dir;
my $out;
lives_ok {
$out = App::makefilepl2cpanfile::generate( with_develop => 0 )
} 'generate() reads Makefile.PL from cwd when no makefile arg given';
like $out, qr/Try::Tiny/, 'content from default Makefile.PL appears in output';
chdir "$orig";
covered('generate.arg.default_makefile');
};
subtest 'generate() â default argument: existing is empty string' => sub {
my $g = empty_home();
# When 'existing' is omitted, no pre-existing develop entries should be
# merged (there are none to merge from an empty string).
my $out;
lives_ok {
$out = App::makefilepl2cpanfile::generate(
makefile => "$mf",
with_develop => 0,
)
} 'generate() with no existing arg lives';
# The output must contain the parsed module but no phantom develop entries
# from a non-existent pre-existing cpanfile.
like $out, qr/Try::Tiny/, 'parsed module present';
unlike $out, qr/on 'develop' => sub/, 'no develop block from empty existing';
covered('generate.arg.default_existing_empty');
};
subtest 'generate() â default argument: with_develop is 1 (true)' => sub {
my $g = empty_home(); # no config file -> uses DEFAULT_DEVELOP
my $mf = make_mf($MF_SIMPLE);
my $out = App::makefilepl2cpanfile::generate( makefile => "$mf" );
};
# -----------------------------------------------------------------------
# generate() â calling style variants
# -----------------------------------------------------------------------
subtest 'generate() â flat hash calling style' => sub {
my $g = empty_home();
my $mf = make_mf($MF_SIMPLE);
my $out = App::makefilepl2cpanfile::generate( makefile => "$mf", with_develop => 0 );
like $out, qr/Try::Tiny/, 'flat hash calling style works';
covered('generate.calling.flat_hash');
};
subtest 'generate() â hashref calling style' => sub {
my $g = empty_home();
my $mf = make_mf($MF_SIMPLE);
my $out = App::makefilepl2cpanfile::generate(
{ makefile => "$mf", with_develop => 0 }
);
like $out, qr/Try::Tiny/, 'single hashref calling style works';
covered('generate.calling.hashref');
};
# -----------------------------------------------------------------------
# generate() â with_develop behaviour
# -----------------------------------------------------------------------
subtest 'generate() â develop block injected when with_develop => 1' => sub {
# Use an empty home so default tools (Perl::Critic etc.) are injected.
my $g = empty_home();
( run in 2.117 seconds using v1.01-cache-2.11-cpan-6de40a662fe )