user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
7d10c720d36ef2f68e4229fbecda9f49140dceea blob 3894 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
 
# Copyright (C) 2016-2019 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
#
# Ensure buffering behavior in -httpd doesn't cause runaway memory use
# or data corruption
use strict;
use warnings;
use Test::More;
use File::Temp qw/tempdir/;
use POSIX qw(setsid);

my $git_dir = $ENV{GIANT_GIT_DIR};
plan 'skip_all' => 'GIANT_GIT_DIR not defined' unless $git_dir;
foreach my $mod (qw(BSD::Resource
			Plack::Util Plack::Builder
			HTTP::Date HTTP::Status Net::HTTP)) {
	eval "require $mod";
	plan skip_all => "$mod missing for git-http-backend.t" if $@;
}
require './t/common.perl';
my $psgi = "./t/git-http-backend.psgi";
my $tmpdir = tempdir('pi-git-http-backend-XXXXXX', TMPDIR => 1, CLEANUP => 1);
my $err = "$tmpdir/stderr.log";
my $out = "$tmpdir/stdout.log";
my $httpd = 'blib/script/public-inbox-httpd';
my $sock = tcp_server();
my $host = $sock->sockhost;
my $port = $sock->sockport;
my $pid;
END { kill 'TERM', $pid if defined $pid };

my $get_maxrss = sub {
        my $http = Net::HTTP->new(Host => "$host:$port");
	ok($http, 'Net::HTTP object created for maxrss');
        $http->write_request(GET => '/');
        my ($code, $mess, %h) = $http->read_response_headers;
	is($code, 200, 'success reading maxrss');
	my $n = $http->read_entity_body(my $buf, 256);
	ok(defined $n, 'read response body');
	like($buf, qr/\A\d+\n\z/, 'got memory response');
	ok(int($buf) > 0, 'got non-zero memory response');
	int($buf);
};

{
	ok($sock, 'sock created');
	my $cmd = [ $httpd, '-W0', "--stdout=$out", "--stderr=$err", $psgi ];
	ok(defined($pid = spawn_listener(undef, $cmd, [$sock])),
	   'forked httpd process successfully');
}
my $mem_a = $get_maxrss->();

SKIP: {
	my $max = 0;
	my $pack;
	my $glob = "$git_dir/objects/pack/pack-*.pack";
	foreach my $f (glob($glob)) {
		my $n = -s $f;
		if ($n > $max) {
			$max = $n;
			$pack = $f;
		}
	}
	skip "no packs found in $git_dir" unless defined $pack;
	if ($pack !~ m!(/objects/pack/pack-[a-f0-9]{40}.pack)\z!) {
		skip "bad pack name: $pack";
	}
	my $url = $1;
	my $http = Net::HTTP->new(Host => "$host:$port");
	ok($http, 'Net::HTTP object created');
	$http->write_request(GET => $url);
	my ($code, $mess, %h) = $http->read_response_headers;
	is(200, $code, 'got 200 success for pack');
	is($max, $h{'Content-Length'}, 'got expected Content-Length for pack');

	# no $http->read_entity_body, here, since we want to force buffering
	foreach my $i (1..3) {
		sleep 1;
		my $diff = $get_maxrss->() - $mem_a;
		note "${diff}K memory increase after $i seconds";
		ok($diff < 1024, 'no bloating caused by slow dumb client');
	}
}

unless ($ENV{MANY_CLONE}) {
	my $c = fork;
	if ($c == 0) {
		setsid();
		exec qw(git clone -q --mirror), "http://$host:$port/",
			"$tmpdir/mirror.git";
		die "Failed start git clone: $!\n";
	}
	select(undef, undef, undef, 0.1);
	foreach my $i (1..10) {
		is(1, kill('STOP', -$c), 'signaled clone STOP');
		sleep 1;
		ok(kill('CONT', -$c), 'continued clone');
		my $diff = $get_maxrss->() - $mem_a;
		note "${diff}K memory increase after $i seconds";
		ok($diff < 2048, 'no bloating caused by slow smart client');
	}
	ok(kill('CONT', -$c), 'continued clone');
	is($c, waitpid($c, 0), 'reaped wayward slow clone');
	is($?, 0, 'clone did not error out');
	note 'clone done, fsck-ing clone result...';
	is(0, system("git", "--git-dir=$tmpdir/mirror.git",
			qw(fsck --no-progress)),
		'fsck did not report corruption');

	my $diff = $get_maxrss->() - $mem_a;
	note "${diff}K memory increase after smart clone";
	ok($diff < 2048, 'no bloating caused by slow smart client');
}

if ($ENV{MANY_CLONE}) {
	system(<<EOF);
	for i in a b c d
	do
		git clone --mirror http://$host:$port/ $tmpdir/dst-\$i &
	done
	wait
EOF

	my @lsof = `lsof -p $pid`;
	diag join('', @lsof);
}

{
	ok(kill('TERM', $pid), 'killed httpd');
	$pid = undef;
	waitpid(-1, 0);
}

done_testing();
debug log:

solving 7d10c720 ...
found 7d10c720 in http://public-inbox.org/meta/20190913085702.5jqrld5d6xajpxks@dcvr/
found d9b33bad in http://public-inbox.org/meta/20190913015043.17149-1-e@80x24.org/
found 1d9bb9f3 in public-inbox.git
preparing index
index prepared:
100644 1d9bb9f3230b0d70a3568c54f488e047e95c7599	t/git-http-backend.t

applying [1/2] http://public-inbox.org/meta/20190913015043.17149-1-e@80x24.org/
diff --git a/t/git-http-backend.t b/t/git-http-backend.t
index 1d9bb9f3..d9b33bad 100644


applying [2/2] http://public-inbox.org/meta/20190913085702.5jqrld5d6xajpxks@dcvr/
diff --git a/t/git-http-backend.t b/t/git-http-backend.t
index d9b33bad..7d10c720 100644

Checking patch t/git-http-backend.t...
Applied patch t/git-http-backend.t cleanly.
Checking patch t/git-http-backend.t...
Applied patch t/git-http-backend.t cleanly.

index at:
100644 7d10c720d36ef2f68e4229fbecda9f49140dceea	t/git-http-backend.t

Code repositories for project(s) associated with this inbox:

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).