App-SlimPacker

 view release on metacpan or  search on metacpan

t/bundle.t  view on Meta::CPAN

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 )