public-inbox.git  about / heads / tags
an "archives first" approach to mailing lists
blob ffe2b1a262ecee39c72ce92fcf0e9a989e2c727e 3619 bytes (raw)
name: t/git_async.t 	 # note: path name is non-authoritative(*)

  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
135
136
137
138
139
140
141
142
 
# Copyright (C) 2016 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
use strict;
use warnings;
use Test::More;
$SIG{PIPE} = 'IGNORE';
foreach my $mod (qw(Danga::Socket)) {
	eval "require $mod";
	plan skip_all => "$mod missing for git_async.t" if $@;
}
use File::Temp qw/tempdir/;
use Cwd qw/getcwd/;
my $tmpdir = tempdir('git_async-XXXXXX', TMPDIR => 1, CLEANUP => 1);
use_ok 'PublicInbox::Git';
my $dir = "$tmpdir/git.git";
{
	is(system(qw(git init -q --bare), $dir), 0, 'created git directory');
	my @cmd = ('git', "--git-dir=$dir", 'fast-import', '--quiet');
	my $fi_data = getcwd().'/t/git.fast-import-data';
	ok(-r $fi_data, "fast-import data readable (or run test at top level)");
	my $pid = fork;
	defined $pid or die "fork failed: $!\n";
	if ($pid == 0) {
		open STDIN, '<', $fi_data or die "open $fi_data: $!\n";
		exec @cmd;
		die "failed exec: ",join(' ', @cmd),": $!\n";
	}
	waitpid $pid, 0;
	is($?, 0, 'fast-import succeeded');
}

{
	my $f = 'HEAD:foo.txt';
	my @args;
	my $n = 0;
	my $git = PublicInbox::Git->new($dir);
	Danga::Socket->SetPostLoopCallback(sub {
		my ($fdmap) = @_;
		foreach (values %$fdmap) {
			return 1 if ref($_) =~ /::GitAsync/;
		}
		0
	});
	$git->check_async_ds($f, sub {
		$n++;
		@args = @_;
		$git = undef;
	});
	Danga::Socket->EventLoop;
	my @exp = PublicInbox::Git->new($dir)->check($f);
	my $exp = [ \@exp ];
	is_deeply(\@args, $exp, 'matches regular check');
	is($n, 1, 'callback only called once');
	$git = PublicInbox::Git->new($dir);
	$n = 0;
	my $max = 100;
	my $missing = 'm';
	my $m = 0;
	for my $i (0..$max) {
		my $k = "HEAD:m$i";
		$git->check_async_ds($k, sub {
			my ($info) = @_;
			++$n;
			++$m if $info->[1] eq 'missing' && $info->[0] eq $k;
		});
		if ($git->{async_c}->{wr}->{write_buf_size}) {
			diag("async_check capped at $i");
			$max = $i;
			last;
		}
	}
	is($m, $n, 'everything expected missing is missing');
	$git->check_async_ds($f, sub { $git = undef });
	Danga::Socket->EventLoop;

	$git = PublicInbox::Git->new($dir);
	my $info;
	my $str = '';
	my @missing;
	$git->cat_async_ds('HEAD:miss', sub {
		my ($miss) = @_;
		push @missing, $miss;
	});
	$git->cat_async_ds($f, sub {
		my $res = $_[0];
		if (ref($res) eq 'ARRAY') {
			is($info, undef, 'info unset, setting..');
			$info = $res;
		} elsif (ref($res) eq 'SCALAR') {
			$str .= $$res;
			if (length($str) >= $info->[2]) {
				is($info->[2], length($str), 'length match');
				$git = undef
			}
		}
	});
	Danga::Socket->EventLoop;
	is_deeply(\@missing, [['HEAD:miss', 'missing']], 'missing cat OK');
	is($git, undef, 'git undefined');
	$git = PublicInbox::Git->new($dir);
	my $sref = $git->cat_file($f);
	is($str, $$sref, 'matches synchronous version');
	$git = undef;
	Danga::Socket->RunTimers;
}

{
	my $git = PublicInbox::Git->new($dir);
	foreach my $s (qw(check_async_compat cat_async_compat)) {
		my @missing;
		$git->check_async_compat('HED:miss1ng', sub {
			my ($miss) = @_;
			push @missing, $miss;
		});
		is_deeply(\@missing, [['HED:miss1ng', 'missing']],
			"missing $s OK");
	}
	my @info;
	my $str = '';
	my $eof_seen = 0;
	$git->cat_async_compat('HEAD:foo.txt', sub {
		my $ref = $_[0];
		my $t = ref $ref;
		if ($t eq 'ARRAY') {
			push @info, $ref;
		} elsif ($t eq 'SCALAR') {
			$str .= $$ref;
		} elsif ($ref == 0) {
			$eof_seen++;
		} else {
			fail "fail type: $t";
		}
	});
	is($eof_seen, 1, 'EOF seen once');
	is_deeply(\@info, [ [ 'bf4f17855632367a160bef055fc8ba4675d10e6b',
			       'blob', 18 ]], 'info matches compat');
	is($str, "-----\nhello\nworld\n", 'data matches compat');
}

done_testing();

1;

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

git clone https://public-inbox.org/public-inbox.git
git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git