about summary refs log tree commit homepage
path: root/t/perf-nntpd.t
blob: 4987f98109b1c9e284bd6052daafbb69099f28db (plain)
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
# Copyright (C) 2018 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;
use Benchmark qw(:all);
use PublicInbox::Inbox;
use File::Temp qw/tempdir/;
use POSIX qw(dup2);
use Fcntl qw(FD_CLOEXEC F_SETFD F_GETFD);
use Net::NNTP;
my $pi_dir = $ENV{GIANT_PI_DIR};
plan skip_all => "GIANT_PI_DIR not defined for $0" unless $pi_dir;
eval { require PublicInbox::Search };
my ($host_port, $group, %opts, $s, $pid);
END {
	if ($s) {
		$s->print("QUIT\r\n");
		$s->getline;
		$s = undef;
	}
	kill 'TERM', $pid if defined $pid;
};

if (($ENV{NNTP_TEST_URL} || '') =~ m!\Anntp://([^/]+)/([^/]+)\z!) {
	($host_port, $group) = ($1, $2);
	$host_port .= ":119" unless index($host_port, ':') > 0;
} else {
	$group = 'inbox.test.perf.nntpd';
	my $ibx = { mainrepo => $pi_dir, newsgroup => $group };
	$ibx = PublicInbox::Inbox->new($ibx);
	my $nntpd = 'blib/script/public-inbox-nntpd';
	my $tmpdir = tempdir('perf-nntpd-XXXXXX', TMPDIR => 1, CLEANUP => 1);

	my $pi_config = "$tmpdir/config";
	{
		open my $fh, '>', $pi_config or die "open($pi_config): $!";
		print $fh <<"" or die "print $pi_config: $!";
[publicinbox "test"]
	newsgroup = $group
	mainrepo = $pi_dir
	address = test\@example.com

		close $fh or die "close($pi_config): $!";
	}

	%opts = (
		LocalAddr => '127.0.0.1',
		ReuseAddr => 1,
		Proto => 'tcp',
		Listen => 1024,
	);
	my $sock = IO::Socket::INET->new(%opts);

	ok($sock, 'sock created');
	$! = 0;
	$pid = fork;
	if ($pid == 0) {
		# pretend to be systemd
		my $fl = fcntl($sock, F_GETFD, 0);
		dup2(fileno($sock), 3) or die "dup2 failed: $!\n";
		dup2(1, 2) or die "dup2 failed: $!\n";
		fcntl($sock, F_SETFD, $fl &= ~FD_CLOEXEC);
		$ENV{LISTEN_PID} = $$;
		$ENV{LISTEN_FDS} = 1;
		$ENV{PI_CONFIG} = $pi_config;
		exec $nntpd, '-W0';
		die "FAIL: $!\n";
	}
	ok(defined $pid, 'forked nntpd process successfully');
	$host_port = $sock->sockhost . ':' . $sock->sockport;
}
%opts = (
	PeerAddr => $host_port,
	Proto => 'tcp',
	Timeout => 1,
);
$s = IO::Socket::INET->new(%opts);
$s->autoflush(1);
my $buf = $s->getline;
is($buf, "201 server ready - post via email\r\n", 'got greeting');
ok($s->print("GROUP $group\r\n"), 'changed group');
$buf = $s->getline;
my ($tot, $min, $max) = ($buf =~ /\A211 (\d+) (\d+) (\d+) /);
ok($tot && $min && $max, 'got GROUP response');
my $nr = $max - $min;
my $nmax = 50000;
my $nmin = $max - $nmax;
$nmin = $min if $nmin < $min;
my $res;
my $spec = "$nmin-$max";
my $n;

sub read_until_dot ($) {
	my $n = 0;
	do {
		$buf = $s->getline;
		++$n
	} until $buf eq ".\r\n";
	$n;
}

my $t = timeit(1, sub {
	$s->print("XOVER $spec\r\n");
	$n = read_until_dot($s);
});
diag 'xover took: ' . timestr($t) . " for $n";

$t = timeit(1, sub {
	$s->print("HDR From $spec\r\n");
	$n = read_until_dot($s);

});
diag "XHDR From ". timestr($t) . " for $n";

my $date = $ENV{NEWNEWS_DATE};
unless ($date) {
	my (undef, undef, undef, $d, $m, $y) = gmtime(time - 30 * 86400);
	$date = sprintf('%04u%02u%02u', $y + 1900, $m, $d);
	diag "NEWNEWS_DATE undefined, using $date";
}
$t = timeit(1, sub {
	$s->print("NEWNEWS * $date 000000 GMT\r\n");
	$n = read_until_dot($s);
});
diag 'newnews took: ' . timestr($t) . " for $n";

done_testing();

1;