]> Sergey Matveev's repositories - public-inbox.git/blobdiff - t/www_listing.t
wwwlisting: avoid lazy loading JSON module
[public-inbox.git] / t / www_listing.t
index 1f2929808f54c21ab1dd73ddda4a7f600608029a..39c1957756bb367c7618541abcb3d557fc168383 100644 (file)
@@ -1,58 +1,81 @@
-# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# Copyright (C) 2019-2020 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 # manifest.js.gz generation and grok-pull integration test
 use strict;
 use warnings;
 use Test::More;
 use PublicInbox::Spawn qw(which);
-use File::Temp qw/tempdir/;
-require './t/common.perl';
-my @mods = qw(URI::Escape Plack::Builder IPC::Run Digest::SHA HTTP::Tiny
-               IO::Compress::Gzip IO::Uncompress::Gunzip Net::HTTP);
-foreach my $mod (@mods) {
-       eval("require $mod") or plan skip_all => "$mod missing for $0";
-}
-use_ok 'PublicInbox::WwwListing';
+use PublicInbox::TestCommon;
+require_mods(qw(URI::Escape Plack::Builder Digest::SHA
+               IO::Compress::Gzip IO::Uncompress::Gunzip HTTP::Tiny));
+require PublicInbox::WwwListing;
+my $json = $PublicInbox::WwwListing::json or
+       plan skip_all => "JSON module missing";
+
 use_ok 'PublicInbox::Git';
 
-my $fi_data = './t/git.fast-import-data';
-my $tmpdir = tempdir('www_listing-tmp-XXXXXX', TMPDIR => 1, CLEANUP => 1);
+my ($tmpdir, $for_destroy) = tmpdir();
 my $bare = PublicInbox::Git->new("$tmpdir/bare.git");
 is(system(qw(git init -q --bare), $bare->{git_dir}), 0, 'git init --bare');
 is(PublicInbox::WwwListing::fingerprint($bare), undef,
        'empty repo has no fingerprint');
-
-my $cmd = [ 'git', "--git-dir=$bare->{git_dir}", qw(fast-import --quiet) ];
-ok(IPC::Run::run($cmd, '<', $fi_data), 'fast-import');
+{
+       my $fi_data = './t/git.fast-import-data';
+       local $ENV{GIT_DIR} = $bare->{git_dir};
+       is(system("git fast-import --quiet <$fi_data"), 0, 'fast-import');
+}
 
 like(PublicInbox::WwwListing::fingerprint($bare), qr/\A[a-f0-9]{40}\z/,
        'got fingerprint with non-empty repo');
 
-my $pid;
-END { kill 'TERM', $pid if defined $pid };
+sub tiny_test {
+       my ($json, $host, $port) = @_;
+       my $http = HTTP::Tiny->new;
+       my $res = $http->get("http://$host:$port/");
+       is($res->{status}, 200, 'got HTML listing');
+       like($res->{content}, qr!</html>!si, 'listing looks like HTML');
+       $res = $http->get("http://$host:$port/manifest.js.gz");
+       is($res->{status}, 200, 'got manifest');
+       my $tmp;
+       IO::Uncompress::Gunzip::gunzip(\(delete $res->{content}) => \$tmp);
+       unlike($tmp, qr/"modified":\s*"/, 'modified is an integer');
+       my $manifest = $json->decode($tmp);
+       ok(my $clone = $manifest->{'/alt'}, '/alt in manifest');
+       is($clone->{owner}, 'lorelei', 'owner set');
+       is($clone->{reference}, '/bare', 'reference detected');
+       is($clone->{description}, "we're all clones", 'description read');
+       ok(my $bare = $manifest->{'/bare'}, '/bare in manifest');
+       is($bare->{description}, 'Unnamed repository',
+               'missing $GIT_DIR/description fallback');
+
+       like($bare->{fingerprint}, qr/\A[a-f0-9]{40}\z/, 'fingerprint');
+       is($clone->{fingerprint}, $bare->{fingerprint}, 'fingerprint matches');
+       is(HTTP::Date::time2str($bare->{modified}),
+               $res->{headers}->{'last-modified'},
+               'modified field and Last-Modified header match');
+
+       ok(my $v2epoch0 = $manifest->{'/v2/git/0.git'}, 'v2 epoch 0 appeared');
+       like($v2epoch0->{description}, qr/ \[epoch 0\]\z/,
+               'epoch 0 in description');
+       ok(my $v2epoch1 = $manifest->{'/v2/git/1.git'}, 'v2 epoch 1 appeared');
+       like($v2epoch1->{description}, qr/ \[epoch 1\]\z/,
+               'epoch 1 in description');
+}
+
+my $td;
 SKIP: {
-       my $json = eval { PublicInbox::WwwListing::_json() };
-       skip "JSON module missing: $@", 1 if $@;
        my $err = "$tmpdir/stderr.log";
        my $out = "$tmpdir/stdout.log";
        my $alt = "$tmpdir/alt.git";
        my $cfgfile = "$tmpdir/config";
        my $v2 = "$tmpdir/v2";
-       my $httpd = 'blib/script/public-inbox-httpd';
-       use IO::Socket::INET;
-       my %opts = (
-               LocalAddr => '127.0.0.1',
-               ReuseAddr => 1,
-               Proto => 'tcp',
-               Type => SOCK_STREAM,
-               Listen => 1024,
-       );
-       my $sock = IO::Socket::INET->new(%opts);
+       my $sock = tcp_server();
        ok($sock, 'sock created');
        my ($host, $port) = ($sock->sockhost, $sock->sockport);
        my @clone = qw(git clone -q -s --bare);
        is(system(@clone, $bare->{git_dir}, $alt), 0, 'clone shared repo');
 
+       system(qw(git init --bare -q), "$v2/all.git") == 0 or die;
        for my $i (0..2) {
                is(system(@clone, $alt, "$v2/git/$i.git"), 0, "clone epoch $i");
        }
@@ -65,54 +88,28 @@ SKIP: {
        ok(unlink("$bare->{git_dir}/description"), 'removed bare/description');
        open $fh, '>', $cfgfile or die;
        print $fh <<"" or die;
+[publicinbox]
+       wwwlisting = all
 [publicinbox "bare"]
-       mainrepo = $bare->{git_dir}
+       inboxdir = $bare->{git_dir}
        url = http://$host/bare
        address = bare\@example.com
 [publicinbox "alt"]
-       mainrepo = $alt
+       inboxdir = $alt
        url = http://$host/alt
        address = alt\@example.com
 [publicinbox "v2"]
-       mainrepo = $v2
+       inboxdir = $v2
        url = http://$host/v2
        address = v2\@example.com
 
        close $fh or die;
        my $env = { PI_CONFIG => $cfgfile };
-       my $cmd = [ $httpd, "--stdout=$out", "--stderr=$err" ];
-       $pid = spawn_listener($env, $cmd, [$sock]);
+       my $cmd = [ '-httpd', '-W0', "--stdout=$out", "--stderr=$err" ];
+       $td = start_script($cmd, $env, { 3 => $sock });
        $sock = undef;
-       my $http = Net::HTTP->new(Host => "$host:$port");
-       $http->write_request(GET => '/manifest.js.gz');
-       my ($code, undef, %h) = $http->read_response_headers;
-       is($code, 200, 'got manifest');
-       my $tmp;
-       my $body = '';
-       while (1) {
-               my $n = $http->read_entity_body(my $buf, 65536);
-               die unless defined $n;
-               last if $n == 0;
-               $body .= $buf;
-       }
-       IO::Uncompress::Gunzip::gunzip(\$body => \$tmp);
-       unlike($tmp, qr/"modified":\s*"/, 'modified is an integer');
-       my $manifest = $json->decode($tmp);
-       ok(my $clone = $manifest->{'/alt'}, '/alt in manifest');
-       is($clone->{owner}, 'lorelei', 'owner set');
-       is($clone->{reference}, '/bare', 'reference detected');
-       is($clone->{description}, "we're all clones", 'description read');
-       ok(my $bare = $manifest->{'/bare'}, '/bare in manifest');
-       is($bare->{description}, 'Unnamed repository',
-               'missing $GIT_DIR/description fallback');
-
-       like($bare->{fingerprint}, qr/\A[a-f0-9]{40}\z/, 'fingerprint');
-       is($clone->{fingerprint}, $bare->{fingerprint}, 'fingerprint matches');
-
-       is(HTTP::Date::time2str($bare->{modified}), $h{'Last-Modified'},
-               'modified field and Last-Modified header match');
 
-       ok($manifest->{'/v2/git/0.git'}, 'v2 epoch appeared');
+       tiny_test($json, $host, $port);
 
        skip 'skipping grok-pull integration test', 2 if !which('grok-pull');