ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-DBI/t/01_fake_mysql.t
Revision: 1.4
Committed: Tue Aug 15 07:28:55 2017 UTC (6 years, 9 months ago) by root
Content type: application/x-troff
Branch: MAIN
Changes since 1.3: +1 -0 lines
Log Message:
*** empty log message ***

File Contents

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