App-Ariza.git | t/ | 01-resources.rakutest


use v6.d;
use Test;
use JSON::Fast;

use App::Ariza::Resources;

plan 4;

subtest 'checkout-root', {
    plan 4;
    my $root = checkout-root();
    ok $root.defined, 'found the distribution root';
    ok $root.add('META6.json').f, 'it has a META6.json';
    ok $root.add('resources').d, 'it has a resources directory';

    # The distribution this test file belongs to, and not some parent of
    # it. Compared as a path rather than by name: a checkout is not
    # obliged to be called App-Ariza, and one that has been copied
    # somewhere else — a container, a build directory — is still this
    # distribution.
    is $root.absolute, $?FILE.IO.resolve.parent(2).absolute,
        'it is this distribution, not a directory above it';
};

subtest 'resource() finds every shipped file', {
    plan 8;

    my $versions = resource('versions.toml');
    ok $versions.f, 'versions.toml';
    ok $versions.slurp.contains('sqlcipher'), 'versions.toml has its content';

    ok resource('templates/launcher-posix.sh.j2').f, 'a top-level template';
    ok resource('templates/ci/release.yml.j2').f, 'a nested template';
    ok resource('templates/installer-common-posix.sh').f, 'the POSIX partial';
    ok resource('templates/installer-common-windows.ps1').f,
       'the Windows partial';

    # The two halves of the packaging invariant, checked against the
    # working tree rather than against a number that has to be edited
    # every time a resource is added:
    #
    #   * every entry in META6 resolves — one that does not is a file
    #     that will simply be missing from the installed distribution;
    #   * every file in resources/ is declared — one that is not is a
    #     file that works in a checkout and vanishes once installed,
    #     which is the harder bug to find.
    my $root = checkout-root().add('resources');
    my @declared = from-json(checkout-root().add('META6.json').slurp)<resources>.list;
    my @unresolvable = @declared.grep({ !(try resource($_).f) });
    is-deeply @unresolvable.List, (), 'every declared resource resolves';

    # `.absolute` speaks the native separator — backslashes on Windows —
    # while META6 `resources` keys are forward-slash by spec. Normalise
    # here, at the one seam, so the prefix strip and every comparison
    # against the declared list stay portable.
    my @on-disk = gather {
        my @queue = $root;
        while @queue {
            my $d = @queue.shift;
            for $d.dir -> $e { $e.d ?? @queue.push($e) !! take $e }
        }
    }.map({ .absolute.substr($root.absolute.chars + 1).subst('\\', '/', :g) }).sort;
    is-deeply @on-disk.grep({ !@declared.first($_) }).List, (),
        'and every file in resources/ is declared in META6';
};

subtest 'a missing resource is loud', {
    plan 3;
    throws-like { resource('no/such/resource.txt') }, Exception,
        message => /'missing resource'/,
        'dies naming the resource it could not find';

    # A directory is not a resource. Installed, Distribution::Resources
    # answers any key at all with a path that degrades to the resource
    # store directory, so a prefix that happens to exist must still fail
    # here rather than surfacing later as "malformed TOML in .../resources".
    throws-like { resource('templates/ci') }, Exception,
        message => /'missing resource'/,
        'a directory prefix is not a resource';
    throws-like { resource('templates') }, Exception,
        message => /'missing resource'/,
        'nor is a top-level resource directory';
};

subtest 'resource-list', {
    plan 4;
    is-deeply resource-list('templates/ci'),
       ('templates/ci/lane-linux-x86_64-glibc.yml.j2',
        'templates/ci/lane-macos-arm64.yml.j2',
        'templates/ci/lane-windows-x86_64.yml.j2',
        'templates/ci/release.yml.j2',
        'templates/ci/smoke-installer-linux-x86_64-glibc.yml.j2',
        'templates/ci/smoke-installer-macos-arm64.yml.j2',
        'templates/ci/smoke-installer-windows-x86_64.yml.j2',
        'templates/ci/test.yml.j2'),
       'returns sorted distribution-relative paths';

    my @templates = resource-list('templates');
    ok @templates.grep('templates/launcher-posix.sh.j2'),
       'finds the templates directly under a prefix';
    nok @templates.grep(*.contains('/ci/')),
       'does not descend into subdirectories';

    is-deeply resource-list('templates/nothing-here'), (),
       'an empty prefix is an empty list, not a failure';
};