File: optional_http-server-restart.t

package info (click to toggle)
libcatalyst-perl 5.7014-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 1,276 kB
  • ctags: 874
  • sloc: perl: 11,270; makefile: 48
file content (244 lines) | stat: -rw-r--r-- 6,737 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
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#!perl

# This test tests the standalone server's auto-restart feature.

use strict;
use warnings;

use File::Path;
use FindBin;
use LWP::Simple;
use IO::Socket;
use Test::More;
use Time::HiRes qw/sleep/;
eval "use Catalyst::Devel 1.0;";

plan skip_all => 'set TEST_HTTP to enable this test' unless $ENV{TEST_HTTP};
plan skip_all => 'Catalyst::Devel required' if $@;
plan skip_all => 'Catalyst::Devel >= 1.04 required' if $Catalyst::Devel::VERSION <= 1.03;
eval "use File::Copy::Recursive";
plan skip_all => 'File::Copy::Recursive required' if $@;

plan tests => 120;

# clean up
rmtree "$FindBin::Bin/../t/tmp" if -d "$FindBin::Bin/../t/tmp";

# create a TestApp and copy the test libs into it
mkdir "$FindBin::Bin/../t/tmp";
chdir "$FindBin::Bin/../t/tmp";
system
  "perl -I$FindBin::Bin/../lib $FindBin::Bin/../script/catalyst.pl TestApp";
chdir "$FindBin::Bin/..";
File::Copy::Recursive::dircopy( 't/lib', 't/tmp/TestApp/lib' );

# remove TestApp's tests
rmtree 't/tmp/TestApp/t';

# spawn the standalone HTTP server
my $port = 30000 + int rand( 1 + 10000 );

my $pid  = open my $server,
"perl -I$FindBin::Bin/../lib $FindBin::Bin/../t/tmp/TestApp/script/testapp_server.pl -port $port -restart 2>&1 |"
  or die "Unable to spawn standalone HTTP server: $!";

# switch to non-blocking reads so we can fail
# gracefully instead of just hanging forever

$server->blocking( 0 );

# wait for it to start
print "Waiting for server to start...\n";
while ( check_port( 'localhost', $port ) != 1 ) {
    sleep 1;
}

# change various files
my @files = (
    "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp.pm",
    "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Action/Begin.pm",
"$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Engine/Request/URI.pm",
);

# change some files and make sure the server restarts itself
NON_ERROR_RESTART:
for ( 1 .. 20 ) {
    my $index = rand @files;
    open my $pm, '>>', $files[$index]
      or die "Unable to open $files[$index] for writing: $!";
    print $pm "\n";
    close $pm;

    # give the server time to notice the change and restart
    my $count = 0;
    my $line;

    while ( ( $line || '' ) !~ /can connect/ ) {
        # wait for restart message
        $line = $server->getline;
        sleep 0.1;
        if ( $count++ > 100 ) {
            fail "Server restarted";
            SKIP: {
                skip "Server didn't restart, no sense in checking response", 1;
            }
            next NON_ERROR_RESTART;
        }
    };
    pass "Server restarted";

    $count = 0;
    while ( check_port( 'localhost', $port ) != 1 ) {
        # wait for it to restart
        sleep 0.1;
        die "Server appears to have died" if $count++ > 100;
    }
    my $response = get("http://localhost:$port/action/default");
    like( $response, qr/Catalyst::Request/, 'Non-error restart, request OK' );

    # give the server some time to reindex its files
    sleep 1;
}

# add errors to the file and make sure server does not die or restart
NO_RESTART_ON_ERROR:
for ( 1 .. 20 ) {
    my $index = rand @files;
    open my $pm, '>>', $files[$index]
      or die "Unable to open $files[$index] for writing: $!";
    print $pm "bleh";
    close $pm;

    my $count = 0;
    my $line;

    while ( ( $line || '' ) !~ /failed/ ) {
        # wait for restart message
        $line = $server->getline;
        sleep 0.1;
        if ( $count++ > 100 ) {
            fail "Server restarted";
            SKIP: {
                skip "Server didn't restart, no sense in checking response", 1;
            }
            next NO_RESTART_ON_ERROR;
        }
    };

    pass "Server refused to restart";

    if ( check_port( 'localhost', $port ) != 1 ) {
        die "Server appears to have died";
    }
    my $response = get("http://localhost:$port/action/default");
    like( $response, qr/Catalyst::Request/,
        'Syntax error, no restart, request OK' );

    # give the server some time to reindex its files
    sleep 1;

}

# multiple restart directories

# we need different options so we have to rebuild most
# of the testing environment

kill 'KILL', $pid;
close $server;

# pick next port because the last one might still be blocked from
# previous server. This might fail if this port is unavailable
# but picking the first one has the same problem so this is acceptable

$port += 1;

{ no warnings 'once'; $File::Copy::Recursive::RMTrgFil = 1; }
File::Copy::Recursive::dircopy( 't/lib', 't/tmp/TestApp/lib' );

# change various files
@files = (
  "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Action/Begin.pm",
  "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Engine/Request/URI.pm",
);

my $app_root = "$FindBin::Bin/../t/tmp/TestApp";
my $restartdirs = join ' ', map{
    "-restartdirectory $app_root/lib/TestApp/Controller/$_"
} qw/Action Engine/;

$pid  = open $server,
"perl -I$FindBin::Bin/../lib $FindBin::Bin/../t/tmp/TestApp/script/testapp_server.pl -port $port -restart $restartdirs 2>&1 |"
  or die "Unable to spawn standalone HTTP server: $!";
$server->blocking( 0 );


# wait for it to start
print "Waiting for server to start...\n";
while ( check_port( 'localhost', $port ) != 1 ) {
    sleep 1;
}

MULTI_DIR_RESTART:
for ( 1 .. 20 ) {
    my $index = rand @files;
    open my $pm, '>>', $files[$index]
      or die "Unable to open $files[$index] for writing: $!";
    print $pm "\n";
    close $pm;

    # give the server time to notice the change and restart
    my $count = 0;
    my $line;

    while ( ( $line || '' ) !~ /can connect/ ) {
        # wait for restart message
        $line = $server->getline;
        sleep 0.1;
        if ( $count++ > 100 ) {
            fail "Server restarted";
            SKIP_NO_RESTART_2: {
                skip "Server didn't restart, no sense in checking response", 1;
            }
            next MULTI_DIR_RESTART;
        }
    };
    pass "Server restarted with multiple restartdirs";

    $count = 0;
    while ( check_port( 'localhost', $port ) != 1 ) {
        # wait for it to restart
        sleep 0.1;
        die "Server appears to have died" if $count++ > 100;
    }
    my $response = get("http://localhost:$port/action/default");
    like( $response, qr/Catalyst::Request/, 'Non-error restart, request OK' );

    # give the server some time to reindex its files
    sleep 1;
}

# shut it down again

kill 'KILL', $pid;
close $server;

# clean up
rmtree "$FindBin::Bin/../t/tmp" if -d "$FindBin::Bin/../t/tmp";

sub check_port {
    my ( $host, $port ) = @_;

    my $remote = IO::Socket::INET->new(
        Proto    => "tcp",
        PeerAddr => $host,
        PeerPort => $port
    );
    if ($remote) {
        close $remote;
        return 1;
    }
    else {
        return 0;
    }
}