+sub tiny_test {
+ my ($json, $host, $port, $html) = @_;
+ my ($tmp, $res);
+ my $http = HTTP::Tiny->new;
+ if ($html) {
+ $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/",
+ {'Accept-Encoding'=>'gzip'});
+ is($res->{status}, 200, 'got gzipped HTML listing');
+ gunzip(\(delete $res->{content}) => \$tmp);
+ like($tmp, qr!</html>!si, 'unzipped listing looks like HTML');
+ }
+ $res = $http->get("http://$host:$port/manifest.js.gz");
+ is($res->{status}, 200, 'got manifest');
+ 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 \x{100}", 'owner set');
+ is($clone->{reference}, '/bare', 'reference detected');
+ is($clone->{description}, "we're \x{100}ll 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');
+
+ $res = $http->get("http://$host:$port/alt/description");
+ is($res->{content}, "we're \xc4\x80ll clones\n", 'UTF-8 description')
+ or diag explain($res);
+}
+
+my $td;