Chandra

 view release on metacpan or  search on metacpan

t/46_assets_edge.t  view on Meta::CPAN

#!/usr/bin/env perl
use strict;
use warnings;
use Test::More;

BEGIN {
    eval { require File::Raw };
    plan skip_all => 'File::Raw required for Chandra::Assets tests' if $@;
}

use File::Temp qw(tempdir);
use File::Path qw(mkpath);

use_ok('Chandra::Assets');

my $dir = tempdir(CLEANUP => 1);
mkpath("$dir/sub/deep");

sub _write {
    my ($path, $content) = @_;
    open my $fh, '>', $path or die "Cannot write $path: $!";
    print $fh $content;
    close $fh;
}

_write("$dir/file.txt",          "hello");
_write("$dir/empty.css",         "");
_write("$dir/sub/nested.js",     "var x = 1;");
_write("$dir/sub/deep/a.css",    "a {}");
_write("$dir/binary.bin",        "\x00\x01\x02\x03");
_write("$dir/has spaces.txt",    "spaced");
_write("$dir/UPPER.CSS",         "upper");

# ---- Path traversal attempts ----

{
    my $a = Chandra::Assets->new(root => $dir);

    my @bad_paths = (
        '../etc/passwd',
        '../../root/.ssh/id_rsa',
        'sub/../../etc/shadow',
        'sub/../../../outside',
    );

    for my $bad (@bad_paths) {
        eval { $a->read($bad) };
        like($@, qr/traversal/i, "blocked: $bad");
    }
}

# ---- Backslash rejection ----

{
    my $a = Chandra::Assets->new(root => $dir);

    eval { $a->read('sub\\nested.js') };
    like($@, qr/traversal/i, 'backslash path rejected');
}

# ---- Empty file ----

{
    my $a = Chandra::Assets->new(root => $dir);

    my $content = $a->read('empty.css');
    is($content, '', 'read empty file returns empty string');

    my $tag = $a->inline_css('empty.css');
    is($tag, '<style></style>', 'inline_css on empty file');
}

# ---- Binary file read ----

{
    my $a = Chandra::Assets->new(root => $dir);
    my $content = $a->read('binary.bin');
    ok(defined $content, 'read binary file');
    is(length($content), 4, 'binary content correct length');
}

# ---- Missing file ----

{
    my $a = Chandra::Assets->new(root => $dir);

    ok(!$a->exists('nonexistent.xyz'), 'missing file not found');

    eval { $a->inline_css('nonexistent.css') };
    like($@, qr/Cannot read/, 'inline_css on missing file croaks');

    eval { $a->inline_js('nonexistent.js') };
    like($@, qr/Cannot read/, 'inline_js on missing file croaks');

    eval { $a->inline_image('nonexistent.png') };
    like($@, qr/Cannot read/, 'inline_image on missing file croaks');
}

# ---- Unicode filename ----

{
    my $a = Chandra::Assets->new(root => $dir);
    my $uname = "caf\xc3\xa9.txt";  # UTF-8 bytes for café
    eval { _write("$dir/$uname", "unicode content") };

    SKIP: {
        skip "filesystem doesn't support unicode", 2 if $@ || !-f "$dir/$uname";
        ok($a->exists($uname), 'unicode filename exists');



( run in 0.688 second using v1.01-cache-2.11-cpan-5b529ec07f3 )