em-pg-client-12 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,619 @@
1
+ NOTIFY_PAYLOAD = defined?(PG.library_version) && PG.library_version >= 90000
2
+ NOTIFY_PAYLOAD_QUERY = NOTIFY_PAYLOAD ? %q[NOTIFY "ruby-em-pg-client", 'foo'] : %q[NOTIFY "ruby-em-pg-client"]
3
+
4
+ module PGSpecMacros
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ def pg_exec_and_check(client, method, *args, &additional_checks)
10
+ client.__send__(method, *args) do |result|
11
+ result.should be_an_instance_of PG::Result
12
+ additional_checks.call(result) if additional_checks
13
+ EM.stop
14
+ end.should be_a_kind_of ::EM::Deferrable
15
+ end
16
+
17
+ def pg_exec_and_check_with_error(client, stop, err_class, err_message, method, *args, &additional_checks)
18
+ client.__send__(method, *args) do |exception|
19
+ exception.should be_an_instance_of err_class
20
+ exception.to_s.should include err_message if err_message
21
+ additional_checks.call(exception) if additional_checks
22
+ EM.next_tick { EM.stop } if stop
23
+ end.should be_a_kind_of ::EM::Deferrable
24
+ end
25
+
26
+ def ensure_em_stop
27
+ yield
28
+ ensure
29
+ EM.stop
30
+ end
31
+
32
+ module ClassMethods
33
+ def it_should_execute(text, method, *args)
34
+ it "should #{text}" do
35
+ pg_exec_and_check(@client, method, *args)
36
+ end
37
+ end
38
+
39
+ def it_should_execute_with_error(text, err_class, err_message, method, *args)
40
+ it "should #{text}" do
41
+ pg_exec_and_check_with_error(@client, true, err_class, err_message, method, *args)
42
+ end
43
+ end
44
+
45
+ def it_should_rollback
46
+ it_should_execute("rollback transaction", :query_defer, 'ROLLBACK')
47
+ end
48
+
49
+ def it_should_begin
50
+ it_should_execute("begin transaction", :query_defer, 'BEGIN TRANSACTION')
51
+ end
52
+ end
53
+ end
54
+
55
+ shared_context 'em-pg common before' do
56
+
57
+ around(:each) do |testcase|
58
+ EM.run do
59
+ EM.stop if testcase.call.is_a? Exception
60
+ end
61
+ end
62
+
63
+ before(:all) do
64
+ @cdates = []
65
+ @values = Array(('AA'..'ZZ').each_with_index)
66
+ ENV['PGCLIENTENCODING'] = nil
67
+ Encoding.default_internal = nil
68
+ @client = described_class.new
69
+ end
70
+
71
+ after(:all) do
72
+ @client.close
73
+ end
74
+
75
+ it "should be a client #{PG::VERSION}" do
76
+ ensure_em_stop do
77
+ @client.should be_an_instance_of described_class
78
+ end
79
+ end
80
+
81
+ it "should have disabled async_autoreconnect" do
82
+ ensure_em_stop do
83
+ @client.async_autoreconnect.should be_false
84
+ end
85
+ end
86
+
87
+ it "should enable async_autoreconnect" do
88
+ ensure_em_stop do
89
+ @client.async_autoreconnect = true
90
+ @client.async_autoreconnect.should be_true
91
+ end
92
+ end
93
+
94
+ it "should have same internal and external encoding" do
95
+ ensure_em_stop do
96
+ @client.external_encoding.should be @client.internal_encoding
97
+ end
98
+ end
99
+
100
+ it_should_begin
101
+
102
+ it_should_execute("drop table `foo` if exists",
103
+ :query_defer, 'DROP TABLE IF EXISTS foo')
104
+
105
+ it_should_execute("create simple table `foo`",
106
+ :query_defer, 'CREATE TABLE foo (id integer,cdate timestamp with time zone,data varchar)')
107
+
108
+ end
109
+
110
+ shared_context 'em-pg common after' do
111
+
112
+ if described_class.single_row_mode?
113
+
114
+ it "should get each result in single row mode" do
115
+ @client.single_row_mode?.should be_true
116
+ @client.get_result_defer do |result|
117
+ result.should be_nil
118
+ @client.send_query('SELECT data, id FROM foo order by id')
119
+ @client.set_single_row_mode
120
+ EM::Iterator.new(@values, 1).map(proc{ |(data, id), iter|
121
+ @client.get_result_defer do |result|
122
+ result.should be_an_instance_of PG::Result
123
+ result.check
124
+ result.result_status.should eq PG::PGRES_SINGLE_TUPLE
125
+ value = result.to_a
126
+ value.should eq [{'data' => data, 'id' => id.to_s}]
127
+ result.clear
128
+ iter.return value
129
+ end.should be_a_kind_of ::EM::Deferrable
130
+ }, proc{ |results|
131
+ results.length.should eq @values.length
132
+ @client.get_result_defer do |result|
133
+ result.should be_an_instance_of PG::Result
134
+ result.check
135
+ result.result_status.should eq PG::PGRES_TUPLES_OK
136
+ result.to_a.should eq []
137
+ result.clear
138
+ @client.get_result_defer do |result|
139
+ result.should be_nil
140
+ EM.stop
141
+ end.should be_a_kind_of ::EM::Deferrable
142
+ end.should be_a_kind_of ::EM::Deferrable
143
+ })
144
+ end.should be_a_kind_of ::EM::Deferrable
145
+ end
146
+
147
+ end
148
+
149
+ it_should_execute("create prepared statement",
150
+ :prepare_defer, 'get_foo', 'SELECT * FROM foo order by id')
151
+
152
+ it "should describe prepared statement" do
153
+ pg_exec_and_check(@client, :describe_prepared_defer, 'get_foo') do |result|
154
+ result.nfields.should eq 3
155
+ result.fname(0).should eq 'id'
156
+ result.values.should be_empty
157
+ end
158
+ end
159
+
160
+ it "should read foo table with prepared statement" do
161
+ pg_exec_and_check(@client, :exec_prepared_defer, 'get_foo') do |result|
162
+ result.each_with_index do |row, i|
163
+ row['id'].to_i.should == i
164
+ DateTime.parse(row['cdate']).should == @cdates[i]
165
+ row['data'].should == @values[i][0]
166
+ end
167
+ end
168
+ end
169
+
170
+ it_should_execute("declare cursor",
171
+ :query_defer, 'DECLARE foobar SCROLL CURSOR FOR SELECT * FROM foo')
172
+
173
+ it "should fetch two rows from table" do
174
+ pg_exec_and_check(@client, :query_defer, 'FETCH FORWARD 2 FROM foobar') do |result|
175
+ result.nfields.should eq 3
176
+ result.fname(0).should eq 'id'
177
+ result.values.length.should eq 2
178
+ end
179
+ end
180
+
181
+ it "should describe cursor with describe_portal" do
182
+ pg_exec_and_check(@client, :describe_portal_defer, 'foobar') do |result|
183
+ result.nfields.should eq 3
184
+ result.fname(0).should eq 'id'
185
+ end
186
+ end
187
+
188
+ it_should_execute("close cursor", :query_defer, 'CLOSE foobar')
189
+
190
+ it "should connect to database asynchronously" do
191
+ this = :first
192
+ Encoding.default_internal = Encoding::ISO_8859_1
193
+ described_class.connect_defer do |conn|
194
+ this = :second
195
+ Encoding.default_internal = nil
196
+ conn.should be_an_instance_of described_class
197
+ conn.external_encoding.should_not eq(conn.internal_encoding)
198
+ conn.internal_encoding.should be Encoding::ISO_8859_1
199
+ conn.get_client_encoding.should eq "LATIN1"
200
+ pg_exec_and_check(conn, :query_defer, 'SELECT pg_database_size(current_database());') do |result|
201
+ result[0]['pg_database_size'].to_i.should be > 0
202
+ end
203
+ end.should be_a_kind_of ::EM::Deferrable
204
+ this.should be :first
205
+ end
206
+
207
+ it "should connect without setting incompatible encoding" do
208
+ this = :first
209
+ Encoding.default_internal = Encoding::Emacs_Mule
210
+ described_class.connect_defer do |conn|
211
+ this = :second
212
+ Encoding.default_internal = nil
213
+ conn.should be_an_instance_of described_class
214
+ conn.external_encoding.should be conn.internal_encoding
215
+ EM.stop
216
+ end.should be_a_kind_of ::EM::Deferrable
217
+ this.should be :first
218
+ end
219
+
220
+ it_should_execute_with_error("raise syntax error in misspelled multiple statement",
221
+ PG::SyntaxError,
222
+ "syntax error",
223
+ :query_defer, 'SELECT * from pg_class; SRELECT CURRENT_TIMESTAMP; SELECT 42 number')
224
+
225
+ it_should_rollback
226
+
227
+ it "should return only last statement" do
228
+ pg_exec_and_check(@client, :query_defer,
229
+ 'SELECT * from pg_class; SELECT CURRENT_TIMESTAMP; SELECT 42 number') do |result|
230
+ result[0]['number'].should eq "42"
231
+ end
232
+ end
233
+
234
+ it "should timeout expire while executing query" do
235
+ @client.query_timeout.should eq 0
236
+ @client.query_timeout = 1.5
237
+ @client.query_timeout.should eq 1.5
238
+ start_time = Time.now
239
+ pg_exec_and_check_with_error(@client, false,
240
+ PG::ConnectionBad, "query timeout expired",
241
+ :query_defer, 'SELECT pg_sleep(2)') do
242
+ (Time.now - start_time).should be < 2
243
+ @client.async_command_aborted.should be_true
244
+ @client.status.should be PG::CONNECTION_BAD
245
+ @client.query_timeout = 0
246
+ @client.query_timeout.should eq 0
247
+ @client.async_autoreconnect = false
248
+ pg_exec_and_check_with_error(@client, true,
249
+ PG::ConnectionBad, "previous query expired",
250
+ :query_defer, 'SELECT 1') do
251
+ @client.async_autoreconnect = true
252
+ end
253
+ end
254
+ end
255
+
256
+ it "should timeout not expire while executing query with partial results" do
257
+ @client.query_timeout.should eq 0
258
+ @client.query_timeout = 1.1
259
+ @client.query_timeout.should eq 1.1
260
+ start_time = Time.now
261
+ pg_exec_and_check(@client, :query_defer,
262
+ 'SELECT * from pg_class;' +
263
+ 'SELECT pg_sleep(1);' +
264
+ 'SELECT * from pg_class;' +
265
+ 'SELECT pg_sleep(1);' +
266
+ 'SELECT 42 number') do |result|
267
+ (Time.now - start_time).should be > 2
268
+ result[0]['number'].should eq "42"
269
+ @client.query_timeout = 0
270
+ @client.query_timeout.should eq 0
271
+ @client.async_command_aborted.should be_false
272
+ @client.status.should be PG::CONNECTION_OK
273
+ end
274
+ end
275
+
276
+ it "should timeout expire while executing query with partial results" do
277
+ @client.query_timeout.should eq 0
278
+ @client.query_timeout = 1.1
279
+ @client.query_timeout.should eq 1.1
280
+ start_time = Time.now
281
+ pg_exec_and_check_with_error(@client, true,
282
+ PG::ConnectionBad, "query timeout expired",
283
+ :query_defer,
284
+ 'SELECT * from pg_class;' +
285
+ 'SELECT pg_sleep(1);' +
286
+ 'SELECT * from pg_class;' +
287
+ 'SELECT pg_sleep(2);' +
288
+ 'SELECT 42 number') do
289
+ (Time.now - start_time).should be > 2
290
+ @client.async_command_aborted.should be_true
291
+ @client.status.should be PG::CONNECTION_BAD
292
+ @client.query_timeout = 0
293
+ @client.query_timeout.should eq 0
294
+ end
295
+ end
296
+
297
+ it "should clear connection with blocking reset" do
298
+ ensure_em_stop do
299
+ @client.async_command_aborted.should be_true
300
+ @client.status.should be PG::CONNECTION_BAD
301
+ @client.reset
302
+ @client.async_command_aborted.should be_false
303
+ @client.status.should be PG::CONNECTION_OK
304
+ end
305
+ end
306
+
307
+ it "should not expire after executing erraneous query" do
308
+ @client.query_timeout.should eq 0
309
+ @client.query_timeout = 0.1
310
+ @client.query_timeout.should eq 0.1
311
+ start_time = Time.now
312
+ pg_exec_and_check_with_error(@client, false,
313
+ PG::SyntaxError, "syntax error",
314
+ :query_defer, 'SELLECT 1') do
315
+ @client.async_command_aborted.should be_false
316
+ ::EM.add_timer(0.11) do
317
+ @client.async_command_aborted.should be_false
318
+ @client.status.should be PG::CONNECTION_OK
319
+ @client.query_timeout = 0
320
+ @client.query_timeout.should eq 0
321
+ EM.stop
322
+ end
323
+ end
324
+ end
325
+
326
+ it "should get last result asynchronously" do
327
+ @client.get_last_result_defer do |result|
328
+ result.should be_nil
329
+ @client.send_query('SELECT 1; SELECT 2; SELECT 3')
330
+ @client.get_last_result_defer do |result|
331
+ result.should be_an_instance_of PG::Result
332
+ result.getvalue(0,0).should eq '3'
333
+ result.clear
334
+ @client.get_last_result_defer do |result|
335
+ result.should be_nil
336
+ EM.stop
337
+ end
338
+ end.should be_a_kind_of ::EM::Deferrable
339
+ end.should be_a_kind_of ::EM::Deferrable
340
+ end
341
+
342
+ it "should get each result asynchronously" do
343
+ @client.get_result_defer do |result|
344
+ result.should be_nil
345
+ @client.send_query('SELECT 4; SELECT 5; SELECT 6')
346
+ EM::Iterator.new(%w[4 5 6], 1).map(proc{ |value, iter|
347
+ @client.get_result_defer do |result|
348
+ result.should be_an_instance_of PG::Result
349
+ result.check
350
+ result.result_status.should eq PG::PGRES_TUPLES_OK
351
+ result.getvalue(0,0).should eq value
352
+ result.clear
353
+ iter.return value
354
+ end.should be_a_kind_of ::EM::Deferrable
355
+ }, proc{ |results|
356
+ results.should eq %w[4 5 6]
357
+ @client.get_result_defer do |result|
358
+ result.should be_nil
359
+ EM.stop
360
+ end.should be_a_kind_of ::EM::Deferrable
361
+ })
362
+ end.should be_a_kind_of ::EM::Deferrable
363
+ end
364
+
365
+ it "should raise connection reset on connection breakdown" do
366
+ client = described_class.new query_timeout: 0.1
367
+ client.send_query('SELECT pg_sleep(10)')
368
+ client.get_last_result_defer do |ex|
369
+ ex.should be_an_instance_of PG::ConnectionBad
370
+ ex.message.should match /connection reset/
371
+ EM.add_timer(0.2) do
372
+ client.async_command_aborted.should be_false
373
+ EM.stop
374
+ end
375
+ end
376
+ # simulate connection breakdown
377
+ client.finish
378
+ end
379
+
380
+ it "should return nil result after async reset began" do
381
+ checkpoint = 0
382
+ @client.send_query('SELECT 1')
383
+ @client.reset_defer do |conn|
384
+ conn.should be @client
385
+ EM.next_tick do
386
+ checkpoint.should eq 2
387
+ @client.send_query('SELECT 1')
388
+ @client.get_last_result_defer do |result|
389
+ result.should be_an_instance_of PG::Result
390
+ result.getvalue(0,0).should eq '1'
391
+ EM.stop
392
+ end
393
+ end
394
+ end
395
+ @client.get_result_defer do |result|
396
+ result.should be_nil
397
+ checkpoint += 1
398
+ end
399
+ @client.get_last_result_defer do |result|
400
+ result.should be_nil
401
+ checkpoint += 1
402
+ end
403
+ end
404
+
405
+ it "should receive notification while waiting for it" do
406
+ sender = described_class.new
407
+ sender_pid = nil
408
+ wait_over = false
409
+ @client.query_defer('LISTEN "ruby-em-pg-client"') do |result|
410
+ result.should be_an_instance_of PG::Result
411
+ @client.wait_for_notify_defer do |notification|
412
+ notification.should be_an_instance_of Hash
413
+ notification[:relname].should eq 'ruby-em-pg-client'
414
+ notification[:be_pid].should eq sender_pid
415
+ notification[:extra].should eq (NOTIFY_PAYLOAD ? 'foo' : '')
416
+ @client.query_defer('UNLISTEN *') do |result|
417
+ result.should be_an_instance_of PG::Result
418
+ EM.stop unless sender
419
+ wait_over = true
420
+ end
421
+ end.should be_a_kind_of ::EM::Deferrable
422
+ EM.next_tick do
423
+ sender.query_defer('SELECT pg_backend_pid()') do |result|
424
+ result.should be_an_instance_of PG::Result
425
+ sender_pid = result.getvalue(0,0).to_i
426
+ sender.query_defer(NOTIFY_PAYLOAD_QUERY) do |result|
427
+ result.should be_an_instance_of PG::Result
428
+ sender.finish
429
+ sender = nil
430
+ EM.stop if wait_over
431
+ end.should be_a_kind_of ::EM::Deferrable
432
+ end.should be_a_kind_of ::EM::Deferrable
433
+ end
434
+ end.should be_a_kind_of ::EM::Deferrable
435
+ end
436
+
437
+ it "should receive previously sent notification" do
438
+ @client.query_defer('LISTEN "ruby-em-pg-client"') do |result|
439
+ result.should be_an_instance_of PG::Result
440
+ @client.query_defer('SELECT pg_backend_pid()') do |result|
441
+ result.should be_an_instance_of PG::Result
442
+ sender_pid = result.getvalue(0,0).to_i
443
+ @client.query_defer(%q[NOTIFY "ruby-em-pg-client"]) do |result|
444
+ result.should be_an_instance_of PG::Result
445
+ @client.wait_for_notify_defer(1) do |notification|
446
+ notification.should be_an_instance_of Hash
447
+ notification[:relname].should eq 'ruby-em-pg-client'
448
+ notification[:be_pid].should eq sender_pid
449
+ notification[:extra].should eq ''
450
+ @client.query_defer('UNLISTEN *') do |result|
451
+ result.should be_an_instance_of PG::Result
452
+ EM.stop
453
+ end.should be_a_kind_of ::EM::Deferrable
454
+ end.should be_a_kind_of ::EM::Deferrable
455
+ end.should be_a_kind_of ::EM::Deferrable
456
+ end.should be_a_kind_of ::EM::Deferrable
457
+ end.should be_a_kind_of ::EM::Deferrable
458
+ end
459
+
460
+ it "should perform queries and receive own notification while waiting for it" do
461
+ sender_pid = nil
462
+ @client.query_defer('SELECT pg_backend_pid()') do |result|
463
+ sender_pid = result.getvalue(0,0).to_i
464
+ @client.query_defer('LISTEN "ruby-em-pg-client"') do |result|
465
+ result.should be_an_instance_of PG::Result
466
+ @client.query_defer(NOTIFY_PAYLOAD_QUERY) do |result|
467
+ result.should be_an_instance_of PG::Result
468
+ end.should be_a_kind_of ::EM::Deferrable
469
+ end.should be_a_kind_of ::EM::Deferrable
470
+ end.should be_a_kind_of ::EM::Deferrable
471
+ @client.wait_for_notify_defer do |notification|
472
+ notification.should be_an_instance_of Hash
473
+ notification[:relname].should eq 'ruby-em-pg-client'
474
+ notification[:be_pid].should eq sender_pid
475
+ notification[:extra].should eq (NOTIFY_PAYLOAD ? 'foo' : '')
476
+ @client.query_defer('UNLISTEN *') do |result|
477
+ result.should be_an_instance_of PG::Result
478
+ EM.stop
479
+ end.should be_a_kind_of ::EM::Deferrable
480
+ end.should be_a_kind_of ::EM::Deferrable
481
+ end
482
+
483
+ it "should reach timeout while waiting for notification" do
484
+ start_time = Time.now
485
+ async_flag = false
486
+ @client.wait_for_notify_defer(0.2) do |notification|
487
+ notification.should be_nil
488
+ (Time.now - start_time).should be >= 0.2
489
+ async_flag.should be_true
490
+ EM.stop
491
+ end.should be_a_kind_of ::EM::Deferrable
492
+ async_flag = true
493
+ end
494
+
495
+ it "should reach timeout while waiting for notification and executing query" do
496
+ start_time = Time.now
497
+ async_flag = false
498
+ @client.query_defer('SELECT pg_sleep(0.5)') do |result|
499
+ result.should be_an_instance_of PG::Result
500
+ (Time.now - start_time).should be >= 0.5
501
+ async_flag.should be_true
502
+ EM.stop
503
+ end
504
+ @client.wait_for_notify_defer(0.1) do |notification|
505
+ notification.should be_nil
506
+ (Time.now - start_time).should be_between(0.1, 0.5)
507
+ async_flag.should be_true
508
+ end.should be_a_kind_of ::EM::Deferrable
509
+ async_flag = true
510
+ end
511
+
512
+ it "should timeout expire while executing query and waiting for notification" do
513
+ @client.query_timeout.should eq 0
514
+ @client.query_timeout = 0.2
515
+ @client.query_timeout.should eq 0.2
516
+ visit_counter = 0
517
+ start_time = Time.now
518
+ pg_exec_and_check_with_error(@client, false,
519
+ PG::ConnectionBad, "query timeout expired (async)",
520
+ :wait_for_notify_defer) do
521
+ (Time.now - start_time).should be >= 0.2
522
+ (visit_counter+=1).should eq 2
523
+ @client.async_command_aborted.should be_true
524
+ @client.status.should be PG::CONNECTION_BAD
525
+ @client.query_timeout = 0
526
+ @client.query_timeout.should eq 0
527
+ @client.async_autoreconnect = false
528
+ pg_exec_and_check_with_error(@client, false,
529
+ PG::ConnectionBad, "previous query expired",
530
+ :wait_for_notify_defer) do
531
+ @client.reset_defer do |conn|
532
+ conn.should be @client
533
+ @client.async_autoreconnect = true
534
+ EM.stop
535
+ end
536
+ end
537
+ end
538
+ pg_exec_and_check_with_error(@client, false,
539
+ PG::ConnectionBad, "query timeout expired (async)",
540
+ :query_defer, 'SELECT pg_sleep(1)') do
541
+ (Time.now - start_time).should be_between(0.2, 1)
542
+ (visit_counter+=1).should eq 1
543
+ end
544
+ end
545
+
546
+ it "should fail wait_for_notify on connection reset" do
547
+ @client.status.should be PG::CONNECTION_OK
548
+ visit_counter = 0
549
+ pg_exec_and_check_with_error(@client, false,
550
+ PG::ConnectionBad, "connection reset",
551
+ :wait_for_notify_defer) do
552
+ pg_exec_and_check_with_error(@client, false,
553
+ PG::ConnectionBad, "connection reset",
554
+ :wait_for_notify_defer) do
555
+ (visit_counter+=1).should eq 2
556
+ end
557
+ @client.reset_defer do |conn|
558
+ conn.should be @client
559
+ (visit_counter+=1).should eq 3
560
+ EM.stop
561
+ end
562
+ end
563
+ @client.reset
564
+ (visit_counter+=1).should eq 1
565
+ end
566
+
567
+ it "should fail wait_for_notify and slow query on connection reset" do
568
+ @client.status.should be PG::CONNECTION_OK
569
+ visit_counter = 0
570
+ pg_exec_and_check_with_error(@client, false,
571
+ PG::ConnectionBad, "connection reset",
572
+ :query_defer, 'SELECT pg_sleep(10)') do
573
+ (visit_counter+=1).should eq 2
574
+ end
575
+ pg_exec_and_check_with_error(@client, false,
576
+ PG::ConnectionBad, "connection reset",
577
+ :wait_for_notify_defer) do
578
+ (visit_counter+=1).should eq 3
579
+ pg_exec_and_check_with_error(@client, false,
580
+ PG::ConnectionBad, "connection reset",
581
+ :wait_for_notify_defer) do
582
+ (visit_counter+=1).should eq 5
583
+ end
584
+ @client.reset_defer do |conn|
585
+ conn.should be @client
586
+ (visit_counter+=1).should eq 6
587
+ EM.stop
588
+ end
589
+ end
590
+ @client.reset
591
+ (visit_counter+=1).should eq 1
592
+ pg_exec_and_check_with_error(@client, false,
593
+ PG::ConnectionBad, "connection reset",
594
+ :query_defer, 'SELECT pg_sleep(10)') do
595
+ (visit_counter+=1).should eq 4
596
+ end
597
+ end
598
+
599
+ it "should fail wait_for_notify on another wait_for_notify" do
600
+ @client.status.should be PG::CONNECTION_OK
601
+ visit_counter = 0
602
+ @client.wait_for_notify_defer(0.5).errback do |ex|
603
+ ex.should be_nil
604
+ (visit_counter+=1).should eq 2
605
+ end.callback do
606
+ raise "This should never be called"
607
+ end.should be_a_kind_of ::EM::Deferrable
608
+ (visit_counter+=1).should eq 1
609
+ @client.wait_for_notify_defer(0.1).callback do |notification|
610
+ notification.should be_nil
611
+ (visit_counter+=1).should eq 4
612
+ EM.stop
613
+ end.errback do
614
+ raise "This should never be called"
615
+ end.should be_a_kind_of ::EM::Deferrable
616
+ (visit_counter+=1).should eq 3
617
+ end
618
+
619
+ end