File: proxyms.t

package info (click to toggle)
memcached 1.6.39-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,320 kB
  • sloc: ansic: 62,281; perl: 12,500; sh: 4,569; makefile: 468; python: 402; xml: 59
file content (84 lines) | stat: -rw-r--r-- 2,408 bytes parent folder | download
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
#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;
use FindBin qw($Bin);
use lib "$Bin/lib";
use Carp qw(croak);
use MemcachedTest;
use IO::Socket qw(AF_INET SOCK_STREAM);
use IO::Select;
use Data::Dumper qw/Dumper/;

if (!supports_proxy()) {
    plan skip_all => 'proxy not enabled';
    exit 0;
}

my $p_srv = new_memcached('-o proxy_config=./t/proxyms.lua -t 1');
my $ps = $p_srv->sock;
$ps->autoflush(1);

my $w = $p_srv->new_sock;
print $w "watch proxyevents\r\n";
is(<$w>, "OK\r\n");

# Slow string generator.
sub rand_string {
    my $len = shift;
    my $val = '';
    my @chars = ("A".."Z");
    for (1 .. $len) {
        $val .= $chars[rand @chars];
    }
    return $val;
}

my $req_count = 3;
my @cmds = ();
for (1 .. $req_count) {
    my $key = rand_string(100);
    my $cmd = "ms $key 203 c T10 O$_\r\n";
    my $val = rand_string(203) . "\r\n";
    push(@cmds, $cmd, $val);
}
my $rendered = join('', @cmds);
# Add in one more command with a partial payload
$rendered .= "ms " . rand_string(100) . " 203 c T10 O999\r\n";
$rendered .= rand_string(103);
my $payload_final = rand_string(100) . "\r\n";

# Generate N set requests that fit into one network read (< 16kb)
# Add in a third which fails partway through a set payload
# With the pause, the first N requests will get processed, dispatched to the
# backend, and completed instantly since the backend is down.
# Then we send the rest of the payload. With the bug we'll end up with an out
# of sync state machine and different errors.
subtest 'batch ms with split requests' => sub {
    syswrite($ps, $rendered, length($rendered));
    # Ensure memcached picks up the initial partial buffer.
    sleep 0.5;
    syswrite($ps, $payload_final, length($payload_final));
    for my $n (1 .. $req_count+1) {
        my $resline = scalar <$ps>;
        is($resline, "SERVER_ERROR backend failure\r\n", "expected error");
    }
};

# With the bug, we resume the conn state machine and clobber the pending
# request that was waiting for a payload. Leaks the actvie request.
subtest 'batch ms with closed client' => sub {
    # Get a new client so we can close it.
    my $d = $p_srv->new_sock;
    $d->autoflush(1);
    syswrite($d, $rendered, length($rendered));
    # Wait for IO execution
    sleep 0.5;
    $d->close();

    my $stats = mem_stats($ps);
    is($stats->{proxy_req_active}, 0, "no leaked requests");
};

done_testing();