1#!/usr/bin/perl
2
3# Test connection reuse.  Allocates a connection, frees it, and
4# allocates another.  The second allocation should return right away
5# because it is honored from the keep-alive pool.
6
7use warnings;
8use strict;
9use lib qw(./mylib ../mylib);
10use Test::More tests => 6;
11
12sub POE::Kernel::ASSERT_DEFAULT () { 1 }
13
14use POE;
15use POE::Component::Client::Keepalive;
16use POE::Component::Resolver;
17use Socket qw(AF_INET);
18
19use TestServer;
20my $server_port = TestServer->spawn(0);
21
22my $test_server_use_count = 0;
23
24POE::Session->create(
25  inline_states => {
26    _child   => sub { },
27    _start   => \&start_with,
28    _stop    => sub { },
29    got_conn => \&got_conn,
30  }
31);
32
33POE::Session->create(
34  inline_states => {
35    _child   => sub { },
36    _start   => \&start_without,
37    _stop    => sub { },
38    got_conn => \&got_conn,
39  }
40);
41
42sub start_with {
43  my $heap = $_[HEAP];
44
45  $_[KERNEL]->alias_set ('WITH');
46  $heap->{cm} = POE::Component::Client::Keepalive->new(
47    resolver => POE::Component::Resolver->new(af_order => [ AF_INET ]),
48  );
49
50  $heap->{cm}->allocate(
51    scheme  => "http",
52    addr    => "localhost",
53    port    => $server_port,
54    event   => "got_conn",
55    context => "first",
56  );
57
58  ++$test_server_use_count;
59}
60
61sub start_without {
62  my $heap = $_[HEAP];
63
64  $_[KERNEL]->alias_set ('WITHOUT');
65  $heap->{cm} = POE::Component::Client::Keepalive->new(
66    resolver => POE::Component::Resolver->new(af_order => [ AF_INET ]),
67  );
68
69  $heap->{cm}->allocate(
70    scheme  => "http",
71    addr    => "localhost",
72    port    => $server_port,
73    event   => "got_conn",
74    context => "second",
75  );
76
77  ++$test_server_use_count;
78}
79
80# TODO - I think this callback is polymorphic (first vs. second)
81# bcause it has common code.  It's probably cleaner to implement two
82# separate callbacks and some helpers to handle their commonalities.
83
84sub got_conn{
85  my ($kernel, $heap, $response) = @_[KERNEL, HEAP, ARG0];
86
87  # The delete() ensures only one copy of the connection exists.
88  my $connection = delete $response->{connection};
89  my $which = $response->{context};
90
91  if (defined $connection) {
92    pass "$which request honored asynchronously";
93  }
94  else {
95    fail(
96      "$which request $response->{function} error $response->{error_num}: " .
97      $response->{error_str}
98    );
99  }
100
101  ok(
102    (not defined $response->{'from_cache'}),
103    "$which request not from cache"
104  );
105
106  if ($which eq 'first') {
107    ok(1, "$which request from internal resolver");
108  } elsif ($which eq 'second') {
109    ok(1, "$which request from external resolver");
110  }
111
112  TestServer->shutdown() unless --$test_server_use_count;
113
114  # need this so we don't get trace output about our session having
115  # already died
116  $connection = undef;
117  # and this so we can terminate without having to go through the
118  # idle polling period
119  $heap->{cm}->shutdown;
120  # and this so we terminate at all
121  delete $heap->{cm};
122}
123
124POE::Kernel->run();
125exit;
126