App-SlimPacker
view release on metacpan or search on metacpan
1;
MOD
write_fixture("$td/bin/myapp", <<'BOOT');
#!/usr/bin/perl
use lib 'lib';
use App::MyMod;
# boot comment
print App::MyMod::greet('cli'), "\n";
BOOT
mkpath("$td/lib/App/Lab/Adapter");
write_fixture("$td/lib/App/Lab/Adapter/A.pm", "package App::Lab::Adapter::A;\n1;\n");
write_fixture("$td/lib/App/Lab/Adapter/B.pm", "package App::Lab::Adapter::B;\n1;\n");
write_fixture("$td/lib/App/Lab/Adapter/Sub/C.pm", "package App::Lab::Adapter::Sub::C;\n1;\n");
write_fixture("$td/bin/lab", <<'LAB');
use Module::Pluggable (
search_path => 'App::Lab::Adapter',
);
use strict; use warnings;
print join(',', sort plugins()), "\n";
LAB
write_fixture("$td/fatlib/Std.pm", <<'FAT');
package Std;
# fatlib comment kept by convention
use strict;
my $fat_long_name = 1;
sub fat { return $fat_long_name + 1 }
1;
FAT
# pack_string stress fixtures: one module whose minified source contains a
# quote and a q{...}-with-backslash, both still load and run byte-identically
# through deflate+base64 round-trip.
write_fixture("$td/lib/App/QuOt.pm", "package App::QuOt;\nsub once { return \"he said 'hi'\" }\n1;\n");
write_fixture("$td/lib/App/Back.pm", "package App::Back;\nsub twice { return \"a\\\\b\" }\n1;\n");
write_fixture("$td/bin/quback", <<'QBOOT');
#!/usr/bin/perl
use lib 'lib';
use App::QuOt;
use App::Back;
print App::QuOt::once(), "\n";
print App::Back::twice(), "\n";
QBOOT
my ($out, $rc, $c);
# -- plain bundle (compression is ON by default)
($out, $rc) = run_cli('-o', "$td/myapp_bundled", '--lib', "$td/lib", "$td/bin/myapp");
is $rc, 0, 'build script exits 0';
ok -f "$td/myapp_bundled", 'output file created';
ok -x "$td/myapp_bundled", 'output file is executable';
$c = file_content("$td/myapp_bundled");
like $c, qr/^#!\/usr\/bin\/perl\n/, 'shebang first line';
like $c, qr/SlimPacked::/, 'lazy @INC hook emitted';
like $c, qr/"App\/MyMod\.pm" =>/, 'bundled module source held in hook map';
unlike $c, qr/\$INC\{'App\/MyMod\.pm'\}=1;/, 'no eager %INC prefill';
unlike $c, qr/# keep me/, 'module comments minified (default)';
unlike $c, qr/# boot comment/, 'program comments minified (default)';
unlike $c, qr/\$who/, 'short variable renamed (strings with it would block, fixture avoids that)';
unlike $c, qr/use lib/, 'use lib stripped from program';
like $c, qr/BEGIN\{my%sl=\(/, 'compact loader: single BEGIN{my%sl=(...) block';
like $c, qr/bless\\%sl,\$class;/, 'compact loader: bless+unshift {$class} fragment';
unlike $c, qr/__SLPACK_ENTRIES__/, 'loader placeholder spliced away';
like $c, qr/use Compress::Raw::Zlib \(\);/, 'compressed loader: core zlib loaded';
like $c, qr/use MIME::Base64 qw\(decode_base64\);/, 'compressed loader: core base64 loaded';
my ($table) = $c =~ /BEGIN\{my%sl=\((.*?)\);my\$class=/s
or die "cannot locate module table in bundle";
unlike $table, qr/\\\$/, 'module table has no escaped sigils (all single-quoted)';
like $table, qr/"App\/MyMod\.pm" => '[A-Za-z0-9+\/=]+'/, 'module source deflate+base64 in table (default)';
unlike $table, qr/package App::MyMod;/, 'compressed source not embedded verbatim';
like $table, qr/"__MAIN__" => '[A-Za-z0-9+\/=]+'/, 'boot program deflate+base64 in table (default)';
unlike $c, qr/print App::MyMod::greet\('cli'\),/, 'boot program text not embedded verbatim (compressed)';
is `"$td/myapp_bundled"`, "hi cli\n", 'bundled script runs standalone';
{
local $ENV{PERL5LIB};
is `"$td/myapp_bundled"`, "hi cli\n", 'compressed bundle runs with @INC pruned';
}
# -- no-compress: identical behavior from visible, readable source literals
($out, $rc) = run_cli('-o', "$td/myapp_plain", '--no-compress', '--lib', "$td/lib", "$td/bin/myapp");
is $rc, 0, '--no-compress build exits 0';
$c = file_content("$td/myapp_plain");
unlike $c, qr/use Compress::Raw::Zlib/, '--no-compress omits zlib loader';
my ($table3) = $c =~ /BEGIN\{my%sl=\((.*?)\);my\$class=/s
or die "cannot locate module table in plain bundle";
like $table3, qr/"App\/MyMod\.pm" => 'package App::MyMod;/, 'plain: module code embedded as single-quoted literal (pack_string)';
is `"$td/myapp_plain"`, "hi cli\n", 'plain bundle runs standalone';
is `"$td/myapp_plain"`, `"$td/myapp_bundled"`, 'compressed and plain bundles behave identically';
# -- explicit --compress flag (default, but the switch must work)
($out, $rc) = run_cli('-o', "$td/myapp_comp", '--compress', '--lib', "$td/lib", "$td/bin/myapp");
is $rc, 0, '--compress flag build exits 0';
like file_content("$td/myapp_comp"), qr/use Compress::Raw::Zlib \(\);/, '--compress embeds compressed loader';
is `"$td/myapp_comp"`, "hi cli\n", '--compress bundle runs';
# -- a boot program with __DATA__/__END__ cannot be string-eval'd, so it is
# left uncompressed (with a warning) while modules stay compressed
write_fixture("$td/bin/dataapp", <<'DL');
#!/usr/bin/perl
use lib 'lib';
use App::MyMod;
print App::MyMod::greet('d'), "\n" . <DATA>;
__DATA__
data line
DL
($out, $rc) = run_cli('-o', "$td/dataapp_bundled", '--lib', "$td/lib", "$td/bin/dataapp");
is $rc, 0, 'data-section boot build exits 0';
like $out, qr/leaving the boot program uncompressed/, 'warns that boot program left uncompressed';
my $dc = file_content("$td/dataapp_bundled");
like $dc, qr/^__DATA__$/m, 'compressed build keeps __DATA__ at a line start';
like $dc, qr/print App::MyMod::greet\('d'\),"\\n"\.<DATA>;\n__DATA__\n/, 'boot program embedded verbatim despite --compress';
my ($dt) = $dc =~ /BEGIN\{my%sl=\((.*?)\);my\$class=/s
or die "cannot locate module table in data bundle";
like $dt, qr/"App\/MyMod\.pm" => '[A-Za-z0-9+\/=]+'/, 'modules still compressed when boot program is not';
unlike $dt, qr/__MAIN__/, 'no __MAIN__ entry when boot program left raw';
is `"$td/dataapp_bundled"`, "hi d\ndata line\n", 'data-section bundle runs (module + <DATA>)';
is `"$td/dataapp_bundled"`, `perl -I"$td/lib" "$td/bin/dataapp"`, 'data-section bundle matches running the raw script';
# -- pack_string endings under a real bundle: quote-rich module must land
# in a q<delim> literal, backslash module in an escaped single-quote,
# and both must still run against the embedded copies.
($out, $rc) = run_cli('-o', "$td/quback_plain", '--no-compress', '--lib', "$td/lib", "$td/bin/quback");
( run in 1.231 second using v1.01-cache-2.11-cpan-b16cb0d3907 )