ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-DBI/t/01_fake_mysql.t
Revision: 1.3
Committed: Tue Apr 2 02:13:13 2013 UTC (11 years, 2 months ago) by root
Content type: application/x-troff
Branch: MAIN
CVS Tags: rel-2_3
Changes since 1.2: +1 -6 lines
Log Message:
2.3

File Contents

# Content
1 #!/usr/bin/perl
2 BEGIN {
3 unless ($ENV{PERL_ANYEVENT_DBI_TESTS}) {
4 print "1..0 # SKIP env var PERL_ANYEVENT_DBI_TESTS not set\n"; exit;
5 }
6 eval {
7 require DBIx::MyServer;
8 require DBIx::MyServer::DBI;
9 };
10 if ($@) {
11 print "1..0 # SKIP these tests require DBIx::MyServer\n"; exit;
12 }
13 }
14
15 no warnings;
16 use List::Util qw(sum);
17 use Cwd qw(abs_path);
18 use File::Basename qw(dirname);
19
20 use AnyEvent::DBI;
21
22 my $topdir = dirname abs_path $0;
23
24 # fork off a child to be a mysql server
25 my $server_pid = fork;
26 unless ($server_pid) {
27 exec "$^X $topdir/fake-mysql --config $topdir/myserver.conf";
28 die 'exec failed';
29 }
30
31 # the parent is the test script
32 eval {
33 require Test::More;
34 #d#import Test::More tests => 34;
35 import Test::More tests => 33;
36 };
37 if ($@) {
38 print 'ok 1 # skip this test requires Test::More'."\n";
39 exit 0;
40 }
41
42 # wait for server
43 sleep 1;
44 my $cv = AnyEvent->condvar;
45 my $dbh = new AnyEvent::DBI(
46 "dbi:mysql:database=database;host=127.0.0.1;port=23306",'','',
47 PrintError => 0,
48 timeout => 2,
49 on_error => sub { },
50 on_connect => sub {
51 if (!$_[1]) {
52 $cv->send($@);
53 } else {
54 $cv->send();
55 }
56 },
57 );
58 my $connect_error = $cv->recv();
59 is($connect_error,undef,'on_connect() called without error, fake mysql server is connected');
60
61 # issue a query
62 $cv = AnyEvent->condvar;
63 $dbh->exec (
64 "select a,b,c from rows14 where num=?", 10, sub {
65 my ($dbh,$rows, $metadata) = @_;
66 if (! $dbh) {
67 $cv->send($@);
68 }
69 else {
70 $cv->send(undef,$rows);
71 }
72 }
73 );
74 my ($error, $rows) = $cv->recv();
75 #print "@$_\n" for @$rows;
76 is($error,undef,'query returns no errors');
77 is(scalar @$rows,14,'query found 14 rows');
78 is(scalar @{$$rows[0]},3,'first row has 3 data');
79
80 # issue a query that returns an error
81 $cv = AnyEvent->condvar;
82 $dbh->exec (
83 "select a,b,c from nosuchtable", sub {
84 my ($dbh, $rows, $metadata) = @_;
85 if (!$rows) {
86 $cv->send($@);
87 } else {
88 $cv->send(undef,$rows);
89 }
90 }
91 );
92 ($error, $rows) = $cv->recv();
93 is($error,qq{Table 'database.nosuchtable' doesn't exist},"SELECT on non-existant table returns NONFATAL error");
94
95 # good query after bad
96 $cv = AnyEvent->condvar;
97 $dbh->exec (
98 "select a,b,c from rows14 where num=?", 10, sub {
99 my ($dbh,$rows, $metadata) = @_;
100 if (!$rows) {
101 $cv->send($@);
102 } else {
103 $cv->send(undef,$rows);
104 }
105 }
106 );
107 ($error, $rows) = $cv->recv();
108 #print "@$_\n" for @$rows;
109 is($error,undef,'good query after bad returns no errors');
110 is(scalar @$rows,14,'query found 14 rows');
111 is(scalar @{$$rows[0]},3,'first row has 3 data');
112
113 ############################################################################
114 # enque a series of alternating good/bad queries
115 $cv = AnyEvent->condvar;
116 my @results = ();
117 my $num_qry = 0;
118 my $qrydone = sub {
119 my ($dbh,$rows,$metadata) = @_;
120 my $err = undef;
121 if (!$rows) {
122 $err = $@;
123 }
124 push @results , [$err,$rows];
125 if (scalar @results == $num_qry) {
126 $cv->send();
127 }
128 };
129
130 $dbh->exec ("select a,b,c from nosuchtable1", $qrydone); $num_qry++;
131 $dbh->exec ("select a,b,c from rows1" , $qrydone); $num_qry++;
132 $dbh->exec ("select a,b,c from nosuchtable2", $qrydone); $num_qry++;
133 $dbh->exec ("select a,b,c from rows2" , $qrydone); $num_qry++;
134 $dbh->exec ("select a,b,c from nosuchtable3", $qrydone); $num_qry++;
135 $dbh->exec ("select a,b,c from rows3" , $qrydone); $num_qry++;
136 $dbh->exec ("select a,b,c from nosuchtable4", $qrydone); $num_qry++;
137 $dbh->exec ("select a,b,c from rows4" , $qrydone); $num_qry++;
138
139 $cv->recv();
140 for my $r (0..$num_qry-1) {
141 my $offset = int($r / 2 )+1;
142 if ($r % 2) {
143 ok(! defined $results[$r]->[0],'Multi Query Queue: No error on good queries');
144 is(scalar @{$results[$r]->[1]},$offset,'Multi Query Queue: Good query got right number of rows');
145 } else {
146 is(
147 $results[$r]->[0],
148 qq{Table 'database.nosuchtable$offset' doesn't exist},'Multi Query Queue: Bad query gets correct error'
149 );
150 }
151 }
152
153 ############################################################################
154
155 # try to connect to a closed port
156 # NOTE tcp port 9 is 'discard', hopefully not running
157 $cv = AnyEvent->condvar;
158 my $dbh2 = new AnyEvent::DBI(
159 "dbi:mysql:database=test;host=127.0.0.1;port=9",'','',
160 PrintError => 0,
161 timeout => 3,
162 on_error => sub { },
163 on_connect => sub {
164 if (!$_[1]) {
165 $cv->send($@);
166 }
167 else {
168 $cv->send();
169 }
170 },
171 );
172 $connect_error = $cv->recv();
173 like($connect_error,qr{can't connect}i,'mysql connect to localhost:9 refused');
174
175 # try to connect to a firewalled port
176 $cv = AnyEvent->condvar;
177 $dbh2 = new AnyEvent::DBI(
178 "dbi:mysql:database=test;host=www.google.com;port=23306",'','',
179 timeout => 3,
180 on_error => sub { },
181 on_connect => sub {
182 if (!$_[1]) {
183 $cv->send($@);
184 }
185 else {
186 $cv->send();
187 }
188 },
189 );
190 $connect_error = $cv->recv();
191 is($connect_error,'timeout','mysql connect to google port 23306 times out');
192 undef $dbh2;
193
194 # issue a query which times out
195 $cv = AnyEvent->condvar;
196 $dbh->exec (
197 "select a,b,c from delay10 where num=?", 10, sub {
198 my ($dbh,$rows, $metadata) = @_;
199 if (! $rows) {
200 $cv->send($@);
201 }
202 else {
203 $cv->send(undef,$rows);
204 }
205 }
206 );
207 ($error,$rows) = $cv->recv();
208 is($error,'timeout','timeout fires during long-running query');
209
210 # issue a query after a fatal timeout error
211 $cv = AnyEvent->condvar;
212 my $start = AnyEvent->now;
213 my $run = 10;
214 my $ran = 0;
215 my $fin = 0;
216 my $errs = [];
217 while ($ran++ < $run) {
218 $dbh->exec (
219 "select d,e,f,g from rows5 where num=?", 10, sub {
220 my ($dbh,$rows, $metadata) = @_;
221 if (!$rows) {
222 push @$errs, $@;
223 }
224 if (++$fin == $run) {
225 $cv->send();
226 }
227 }
228 );
229 }
230 $cv->recv();
231 ok(AnyEvent->now -$start < 0.0001,'invalid db handle returns from multiple queries immediately');
232 is (scalar @$errs, 10, 'invalid db handle returned error for all enqueued queries');
233 is($errs->[0],'no database connection','invalid db handle returns correct error');
234 undef $dbh;
235
236 # check for server process leakage
237 eval {
238 require Proc::Exists;
239 import Proc::Exists qw(pexists);
240 };
241 my $has_pe = ! $@;
242 SKIP: {
243 skip ( 'This test requires Proc::Exists',4) unless $has_pe;
244 # connect three handles
245 $cv = AnyEvent->condvar;
246 my @handles;
247 my @handle_errors;
248 my $connected =0;
249 for (0..2) {
250 my $dbh3 = new AnyEvent::DBI(
251 "dbi:mysql:database=database;host=127.0.0.1;port=23306",'','',
252 PrintError => 0,
253 timeout => 2,
254 on_error => sub { },
255 on_connect => sub {
256 if (!$_[1]) {
257 push @handle_errors, $@;
258 }
259 if (++$connected == 3) {
260 $cv->send();
261 }
262 },
263 );
264 push @handles, $dbh3;
265 }
266 $cv->recv();
267 is(scalar @handles,3,'created three handles');
268 is(scalar @handle_errors,0,'no errors during handle creation');
269 my @pids = map {$_->_server_pid} @handles;
270 ok( defined pexists(@pids, {all=>1}),'Found three slave processes');
271 undef @handles;
272
273 $cv = AnyEvent->condvar;
274 my $cleanup = AnyEvent->timer(after=>0.5,cb=>sub {$cv->send()});
275 $cv->recv();
276 ok(!defined pexists(@pids, {any=>1}),'All slave processes exited');
277 }
278
279 # connect to the server again
280 $cv = AnyEvent->condvar;
281 $dbh = new AnyEvent::DBI(
282 "dbi:mysql:database=database;host=127.0.0.1;port=23306",'','',
283 PrintError => 0,
284 timeout => 2,
285 on_error => sub { },
286 on_connect => sub {
287 if (!$_[1]) {
288 $cv->send($@);
289 } else {
290 $cv->send();
291 }
292 },
293 );
294 $connect_error = $cv->recv();
295 is($connect_error,undef,'on_connect() called without error, fake mysql server is re-connected');
296
297 # End the server and reap it
298 $cv = AnyEvent->condvar;
299 my $server_process_watcher = AnyEvent->child(
300 pid => $server_pid,
301 cb => sub {
302 $cv->send(@_);
303 }
304 );
305 kill 2, $server_pid; # 2 is SIGINT, usually
306 my ($dead_pid,$dead_status)=$cv->recv();
307 is ($dead_pid,$server_pid,'MySQL Server processess exited');
308 is ($dead_status,2,'Server exited on our signal');
309
310 if (0) {
311 # does not seem tor eliably kill all children
312 sleep 2;
313
314 # try to make another query with a down MYSQL server
315 # issue a query
316 $cv = AnyEvent->condvar;
317 $dbh->exec (
318 "select x from rows1 where num=?", 10, sub {
319 my ($dbh, $rows, $metadata) = @_;
320 if (!$rows) {
321 $cv->send($@);
322 } else {
323 $cv->send(undef,$rows);
324 }
325 }
326 );
327
328 ($error, $rows) = $cv->recv();
329 is($error,'timeout','mysql query to dead server times out');
330 undef $dbh;
331 }
332
333 END {
334 if ($server_pid) {
335 # shut down the fake_mysql server
336 delete $SIG{CLD};
337 kill 15, $server_pid;
338 waitpid $server_pid,0;
339 }
340 exit 0;
341 }
342