right_agent 0.13.5 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/sender_spec.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright (c) 2009-2011 RightScale Inc
2
+ # Copyright (c) 2009-2012 RightScale Inc
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -58,7 +58,6 @@ describe RightScale::Sender do
58
58
 
59
59
  describe "when monitoring broker connectivity" do
60
60
  before(:each) do
61
- flexmock(EM).should_receive(:next_tick).and_yield.by_default
62
61
  @now = Time.at(1000000)
63
62
  flexmock(Time).should_receive(:now).and_return(@now).by_default
64
63
  @broker = flexmock("Broker", :subscribe => true, :publish => ["broker"], :connected? => true,
@@ -193,7 +192,135 @@ describe RightScale::Sender do
193
192
  end
194
193
  end
195
194
  end
196
-
195
+
196
+ describe "when validating a target" do
197
+ before(:each) do
198
+ @timer = flexmock("timer")
199
+ flexmock(EM::Timer).should_receive(:new).and_return(@timer)
200
+ flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
201
+ @broker = flexmock("Broker", :subscribe => true, :publish => true).by_default
202
+ @agent = flexmock("Agent", :identity => "agent", :broker => @broker).by_default
203
+ @agent.should_receive(:options).and_return({}).by_default
204
+ RightScale::Sender.new(@agent)
205
+ @instance = RightScale::Sender.instance
206
+ @instance.initialize_offline_queue
207
+ end
208
+
209
+ it "should accept nil target" do
210
+ @instance.__send__(:validate_target, nil, true).should be_true
211
+ end
212
+
213
+ it "should accept named target" do
214
+ @instance.__send__(:validate_target, "name", true).should be_true
215
+ end
216
+
217
+ describe "and target is a hash" do
218
+
219
+ describe "and selector is allowed" do
220
+
221
+ it "should accept :all or :any selector" do
222
+ @instance.__send__(:validate_target, {:selector => :all}, true).should be_true
223
+ @instance.__send__(:validate_target, {"selector" => "any"}, true).should be_true
224
+ end
225
+
226
+ it "should reject values other than :all or :any" do
227
+ lambda { @instance.__send__(:validate_target, {:selector => :other}, true) }.
228
+ should raise_error(ArgumentError, /Invalid target selector/)
229
+ end
230
+
231
+ end
232
+
233
+ describe "and selector is not allowed" do
234
+
235
+ it "should reject selector" do
236
+ lambda { @instance.__send__(:validate_target, {:selector => :all}, false) }.
237
+ should raise_error(ArgumentError, /Invalid target hash/)
238
+ end
239
+
240
+ end
241
+
242
+ describe "and tags is specified" do
243
+
244
+ it "should accept tags" do
245
+ @instance.__send__(:validate_target, {:tags => []}, true).should be_true
246
+ @instance.__send__(:validate_target, {"tags" => ["tag"]}, true).should be_true
247
+ end
248
+
249
+ it "should reject non-array" do
250
+ lambda { @instance.__send__(:validate_target, {:tags => {}}, true) }.
251
+ should raise_error(ArgumentError, /Invalid target tags/)
252
+ end
253
+
254
+ end
255
+
256
+ describe "and scope is specified" do
257
+
258
+ it "should accept account" do
259
+ @instance.__send__(:validate_target, {:scope => {:account => 1}}, true).should be_true
260
+ @instance.__send__(:validate_target, {"scope" => {"account" => 1}}, true).should be_true
261
+ end
262
+
263
+ it "should accept shard" do
264
+ @instance.__send__(:validate_target, {:scope => {:shard => 1}}, true).should be_true
265
+ @instance.__send__(:validate_target, {"scope" => {"shard" => 1}}, true).should be_true
266
+ end
267
+
268
+ it "should accept account and shard" do
269
+ @instance.__send__(:validate_target, {"scope" => {:shard => 1, "account" => 1}}, true).should be_true
270
+ end
271
+
272
+ it "should reject keys other than account and shard" do
273
+ target = {"scope" => {:shard => 1, "account" => 1, :other => 2}}
274
+ lambda { @instance.__send__(:validate_target, target, true) }.
275
+ should raise_error(ArgumentError, /Invalid target scope/)
276
+ end
277
+
278
+ it "should reject empty hash" do
279
+ lambda { @instance.__send__(:validate_target, {:scope => {}}, true) }.
280
+ should raise_error(ArgumentError, /Invalid target scope/)
281
+ end
282
+
283
+ end
284
+
285
+ describe "and multiple are specified" do
286
+
287
+ it "should accept scope and tags" do
288
+ @instance.__send__(:validate_target, {:scope => {:shard => 1}, :tags => []}, true).should be_true
289
+ end
290
+
291
+ it "should accept scope, tags, and selector" do
292
+ target = {:scope => {:shard => 1}, :tags => ["tag"], :selector => :all}
293
+ @instance.__send__(:validate_target, target, true).should be_true
294
+ end
295
+
296
+ it "should reject selector if not allowed" do
297
+ target = {:scope => {:shard => 1}, :tags => ["tag"], :selector => :all}
298
+ lambda { @instance.__send__(:validate_target, target, false) }.
299
+ should raise_error(ArgumentError, /Invalid target hash/)
300
+ end
301
+
302
+ end
303
+
304
+ it "should reject keys other than selector, scope, and tags" do
305
+ target = {:scope => {:shard => 1}, :tags => [], :selector => :all, :other => 2}
306
+ lambda { @instance.__send__(:validate_target, target, true) }.
307
+ should raise_error(ArgumentError, /Invalid target hash/)
308
+ end
309
+
310
+ it "should reject empty hash" do
311
+ lambda { @instance.__send__(:validate_target, {}, true) }.
312
+ should raise_error(ArgumentError, /Invalid target hash/)
313
+ end
314
+
315
+ it "should reject value that is not nil, string, or hash" do
316
+ lambda { @instance.__send__(:validate_target, [], true) }.
317
+ should raise_error(ArgumentError, /Invalid target/)
318
+ end
319
+
320
+ end
321
+
322
+ end
323
+
197
324
  describe "when making a push request" do
198
325
  before(:each) do
199
326
  @timer = flexmock("timer")
@@ -209,22 +336,8 @@ describe RightScale::Sender do
209
336
 
210
337
  it "should validate target" do
211
338
  @broker.should_receive(:publish)
212
- lambda { @instance.send_push('/foo/bar', nil) }.should be_true
213
- lambda { @instance.send_push('/foo/bar', nil, "target") }.should be_true
214
- lambda { @instance.send_push('/foo/bar', nil, {}) }.should be_true
215
- lambda { @instance.send_push('/foo/bar', nil, :tags => "tags") }.should be_true
216
- lambda { @instance.send_push('/foo/bar', nil, "tags" => "tags") }.should be_true
217
- lambda { @instance.send_push('/foo/bar', nil, :tags => "tags", :scope => {:shard => 1}) }.should be_true
218
- lambda { @instance.send_push('/foo/bar', nil, "scope" => {:shard => 1, "account" => 1}) }.should be_true
219
- lambda { @instance.send_push('/foo/bar', nil, :scope => {}) }.should be_true
220
- lambda { @instance.send_push('/foo/bar', nil, :selector => :all) }.should be_true
221
- lambda { @instance.send_push('/foo/bar', nil, "selector" => "any") }.should be_true
222
- lambda { @instance.send_push('/foo/bar', nil, 1) }.should raise_error(ArgumentError)
223
- lambda { @instance.send_push('/foo/bar', nil, []) }.should raise_error(ArgumentError)
224
- lambda { @instance.send_push('/foo/bar', nil, :bogus => 1) }.should raise_error(ArgumentError)
225
- lambda { @instance.send_push('/foo/bar', nil, :scope => 1) }.should raise_error(ArgumentError)
226
- lambda { @instance.send_push('/foo/bar', nil, :scope => {:bogus => 1}) }.should raise_error(ArgumentError)
227
- lambda { @instance.send_push('/foo/bar', nil, :selector => :bogus) }.should raise_error(ArgumentError)
339
+ flexmock(@instance).should_receive(:validate_target).with("target", true).once
340
+ @instance.send_push('/foo/bar', nil, "target").should be_true
228
341
  end
229
342
 
230
343
  it "should create a Push object" do
@@ -283,6 +396,15 @@ describe RightScale::Sender do
283
396
  @instance.offline_handler.queue.size.should == 1
284
397
  end
285
398
 
399
+ it 'should raise exception if not connected to any brokers and :offline_queueing disabled' do
400
+ @log.should_receive(:error).with(/Failed to publish request/, RightAMQP::HABrokerClient::NoConnectedBrokers).once
401
+ @broker.should_receive(:publish).and_raise(RightAMQP::HABrokerClient::NoConnectedBrokers)
402
+ @agent.should_receive(:options).and_return({:offline_queueing => false})
403
+ RightScale::Sender.new(@agent)
404
+ @instance = RightScale::Sender.instance
405
+ lambda { @instance.send_push('/welcome/aboard', 'iZac') }.should raise_error(RightScale::Sender::TemporarilyOffline)
406
+ end
407
+
286
408
  it "should store the response handler if given" do
287
409
  response_handler = lambda {}
288
410
  flexmock(RightScale::AgentIdentity).should_receive(:generate).and_return('abc').once
@@ -313,6 +435,12 @@ describe RightScale::Sender do
313
435
  @instance.pending_requests['xyz'].should_not be_nil
314
436
  @instance.pending_requests['abc'].should be_nil
315
437
  end
438
+
439
+ it "should log exceptions and re-raise them" do
440
+ @log.should_receive(:error).with(/Failed to publish request/, Exception, :trace).once
441
+ @broker.should_receive(:publish).and_raise(Exception)
442
+ lambda { @instance.send_push('/welcome/aboard', 'iZac') }.should raise_error(RightScale::Sender::SendFailure)
443
+ end
316
444
  end
317
445
 
318
446
  describe "when making a send_persistent_push request" do
@@ -380,7 +508,6 @@ describe RightScale::Sender do
380
508
  before(:each) do
381
509
  @timer = flexmock("timer")
382
510
  flexmock(EM::Timer).should_receive(:new).and_return(@timer).by_default
383
- flexmock(EM).should_receive(:next_tick).and_yield.by_default
384
511
  @broker_id = "broker"
385
512
  @broker_ids = [@broker_id]
386
513
  @broker = flexmock("Broker", :subscribe => true, :publish => @broker_ids, :connected? => true,
@@ -394,33 +521,15 @@ describe RightScale::Sender do
394
521
 
395
522
  it "should validate target" do
396
523
  @broker.should_receive(:publish)
397
- lambda { @instance.send_retryable_request('/foo/bar', nil) }.should be_true
398
- lambda { @instance.send_retryable_request('/foo/bar', nil, "target") }.should be_true
399
- lambda { @instance.send_retryable_request('/foo/bar', nil, {}) }.should be_true
400
- lambda { @instance.send_retryable_request('/foo/bar', nil, :tags => "tags") }.should be_true
401
- lambda { @instance.send_retryable_request('/foo/bar', nil, "tags" => "tags") }.should be_true
402
- lambda { @instance.send_retryable_request('/foo/bar', nil, :tags => "tags", :scope => {:shard => 1}) }.should be_true
403
- lambda { @instance.send_retryable_request('/foo/bar', nil, "scope" => {:shard => 1, "account" => 1}) }.should be_true
404
- lambda { @instance.send_retryable_request('/foo/bar', nil, :scope => {}) }.should be_true
405
- lambda { @instance.send_retryable_request('/foo/bar', nil, :selector => :all) }.should raise_error(ArgumentError)
406
- lambda { @instance.send_retryable_request('/foo/bar', nil, 1) }.should raise_error(ArgumentError)
407
- lambda { @instance.send_retryable_request('/foo/bar', nil, []) }.should raise_error(ArgumentError)
408
- lambda { @instance.send_retryable_request('/foo/bar', nil, :bogus => 1) }.should raise_error(ArgumentError)
409
- lambda { @instance.send_retryable_request('/foo/bar', nil, :scope => 1) }.should raise_error(ArgumentError)
410
- lambda { @instance.send_retryable_request('/foo/bar', nil, :scope => {:bogus => 1}) }.should raise_error(ArgumentError)
411
- lambda { @instance.send_retryable_request('/foo/bar', nil, :selector => :bogus) }.should raise_error(ArgumentError)
524
+ flexmock(@instance).should_receive(:validate_target).with("target", false).once
525
+ @instance.send_retryable_request('/foo/bar', nil, "target") {_}.should be_true
412
526
  end
413
527
 
414
528
  it "should create a Request object" do
415
529
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
416
530
  request.class.should == RightScale::Request
417
531
  end, hsh(:persistent => false, :mandatory => true)).once
418
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
419
- end
420
-
421
- it "should process request in next tick to preserve pending request data integrity" do
422
- flexmock(EM).should_receive(:next_tick).and_yield.once
423
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
532
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
424
533
  end
425
534
 
426
535
  it "should set correct attributes on the request message" do
@@ -433,7 +542,7 @@ describe RightScale::Sender do
433
542
  request.target.should be_nil
434
543
  request.expires_at.should == 1000100
435
544
  end, hsh(:persistent => false, :mandatory => true)).once
436
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
545
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
437
546
  end
438
547
 
439
548
  it "should disable time-to-live if disabled in configuration" do
@@ -445,14 +554,14 @@ describe RightScale::Sender do
445
554
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
446
555
  request.expires_at.should == 0
447
556
  end, hsh(:persistent => false, :mandatory => true)).once
448
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
557
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
449
558
  end
450
559
 
451
560
  it "should set the correct target if specified" do
452
561
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
453
562
  request.target.should == 'my-target'
454
563
  end, hsh(:persistent => false, :mandatory => true)).once
455
- @instance.send_retryable_request('/welcome/aboard', 'iZac', 'my-target') {|response|}
564
+ @instance.send_retryable_request('/welcome/aboard', 'iZac', 'my-target') {|_|}
456
565
  end
457
566
 
458
567
  it "should set the correct target selectors if specified" do
@@ -461,12 +570,12 @@ describe RightScale::Sender do
461
570
  request.selector.should == :any
462
571
  request.scope.should == {:account => 123}
463
572
  end, hsh(:persistent => false, :mandatory => true)).once
464
- @instance.send_retryable_request('/welcome/aboard', 'iZac', :tags => ['tag'], :scope => {:account => 123})
573
+ @instance.send_retryable_request('/welcome/aboard', 'iZac', :tags => ['tag'], :scope => {:account => 123}) {|_|}
465
574
  end
466
575
 
467
576
  it "should set up for retrying the request if necessary by default" do
468
577
  flexmock(@instance).should_receive(:publish_with_timeout_retry).once
469
- @instance.send_retryable_request('/welcome/aboard', 'iZac', 'my-target') {|response|}
578
+ @instance.send_retryable_request('/welcome/aboard', 'iZac', 'my-target') {|_|}
470
579
  end
471
580
 
472
581
  it "should store the response handler" do
@@ -480,7 +589,7 @@ describe RightScale::Sender do
480
589
  flexmock(RightScale::AgentIdentity).should_receive(:generate).and_return('abc').once
481
590
  flexmock(Time).should_receive(:now).and_return(Time.at(1000000)).by_default
482
591
  @instance.pending_requests.kind(RightScale::Sender::PendingRequests::REQUEST_KINDS).youngest_age.should be_nil
483
- @instance.send_retryable_request('/welcome/aboard', 'iZac')
592
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
484
593
  @instance.pending_requests['abc'].receive_time.should == Time.at(1000000)
485
594
  flexmock(Time).should_receive(:now).and_return(Time.at(1000100))
486
595
  @instance.pending_requests.kind(RightScale::Sender::PendingRequests::REQUEST_KINDS).youngest_age.should == 100
@@ -494,17 +603,40 @@ describe RightScale::Sender do
494
603
  @broker.should_receive(:publish).never
495
604
  @instance.enable_offline_mode
496
605
  @instance.offline_handler.mode.should == :offline
497
- @instance.send_retryable_request('/welcome/aboard', 'iZac')
606
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
498
607
  @instance.offline_handler.queue.size.should == 1
499
608
  end
500
609
 
610
+ it 'should raise exception if not connected to any brokers and :offline_queueing disabled' do
611
+ @log.should_receive(:error).with(/Failed to publish request/, RightAMQP::HABrokerClient::NoConnectedBrokers).once
612
+ @broker.should_receive(:publish).and_raise(RightAMQP::HABrokerClient::NoConnectedBrokers)
613
+ @agent.should_receive(:options).and_return({:offline_queueing => false})
614
+ RightScale::Sender.new(@agent)
615
+ @instance = RightScale::Sender.instance
616
+ lambda { @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|} }.should raise_error(RightScale::Sender::TemporarilyOffline)
617
+ end
618
+
501
619
  it "should dump the pending requests" do
502
620
  flexmock(RightScale::AgentIdentity).should_receive(:generate).and_return('abc').once
503
621
  flexmock(Time).should_receive(:now).and_return(Time.at(1000000))
504
- @instance.send_retryable_request('/welcome/aboard', 'iZac')
622
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
505
623
  @instance.dump_requests.should == ["#{Time.at(1000000).localtime} <abc>"]
506
624
  end
507
625
 
626
+ it "should not allow a selector target" do
627
+ lambda { @instance.send_retryable_request('/welcome/aboard', 'iZac', :selector => :all) }.should raise_error(ArgumentError)
628
+ end
629
+
630
+ it "should raise error if there is no callback block" do
631
+ lambda { @instance.send_retryable_request('/welcome/aboard', 'iZac') }.should raise_error(ArgumentError)
632
+ end
633
+
634
+ it "should log exceptions and re-raise them" do
635
+ @log.should_receive(:error).with(/Failed to publish request/, Exception, :trace).once
636
+ @broker.should_receive(:publish).and_raise(Exception)
637
+ lambda { @instance.send_retryable_request('/welcome/aboard', 'iZac') {|r|} }.should raise_error(RightScale::Sender::SendFailure)
638
+ end
639
+
508
640
  describe "with retry" do
509
641
  it "should not setup for retry if retry_timeout nil" do
510
642
  flexmock(EM).should_receive(:add_timer).never
@@ -512,7 +644,7 @@ describe RightScale::Sender do
512
644
  RightScale::Sender.new(@agent)
513
645
  @instance = RightScale::Sender.instance
514
646
  @broker.should_receive(:publish).once
515
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
647
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
516
648
  end
517
649
 
518
650
  it "should not setup for retry if retry_interval nil" do
@@ -521,7 +653,7 @@ describe RightScale::Sender do
521
653
  RightScale::Sender.new(@agent)
522
654
  @instance = RightScale::Sender.instance
523
655
  @broker.should_receive(:publish).once
524
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
656
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
525
657
  end
526
658
 
527
659
  it "should not setup for retry if publish failed" do
@@ -530,7 +662,7 @@ describe RightScale::Sender do
530
662
  RightScale::Sender.new(@agent)
531
663
  @instance = RightScale::Sender.instance
532
664
  @broker.should_receive(:publish).and_return([]).once
533
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
665
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
534
666
  end
535
667
 
536
668
  it "should setup for retry if retry_timeout and retry_interval not nil and publish successful" do
@@ -539,7 +671,7 @@ describe RightScale::Sender do
539
671
  RightScale::Sender.new(@agent)
540
672
  @instance = RightScale::Sender.instance
541
673
  @broker.should_receive(:publish).and_return(@broker_ids).once
542
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
674
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
543
675
  end
544
676
 
545
677
  it "should adjust retry interval by recent request duration" do
@@ -559,12 +691,10 @@ describe RightScale::Sender do
559
691
  @instance.send_retryable_request('/welcome/aboard', 'iZac') do |response|
560
692
  result = RightScale::OperationResult.from_results(response)
561
693
  end
562
- header = flexmock("amqp header")
563
- header.should_receive(:ack).once
564
694
  EM.add_timer(0.15) do
565
695
  @instance.pending_requests.empty?.should be_false
566
696
  result = RightScale::Result.new(token, nil, {'from' => RightScale::OperationResult.success}, nil)
567
- @instance.handle_response(result, header)
697
+ @instance.handle_response(result)
568
698
  end
569
699
  EM.add_timer(0.3) do
570
700
  EM.stop
@@ -609,7 +739,7 @@ describe RightScale::Sender do
609
739
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
610
740
  request.expires_at.should == (expires_at ||= request.expires_at)
611
741
  end, hsh(:persistent => false, :mandatory => true)).and_return(@broker_ids).twice
612
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response|}
742
+ @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
613
743
  EM.add_timer(0.2) { EM.stop }
614
744
  end
615
745
  end
@@ -675,7 +805,6 @@ describe RightScale::Sender do
675
805
  before(:each) do
676
806
  @timer = flexmock("timer")
677
807
  flexmock(EM::Timer).should_receive(:new).and_return(@timer).by_default
678
- flexmock(EM).should_receive(:next_tick).and_yield.by_default
679
808
  @broker_id = "broker"
680
809
  @broker_ids = [@broker_id]
681
810
  @broker = flexmock("Broker", :subscribe => true, :publish => @broker_ids, :connected? => true,
@@ -691,7 +820,7 @@ describe RightScale::Sender do
691
820
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
692
821
  request.class.should == RightScale::Request
693
822
  end, hsh(:persistent => true, :mandatory => true)).once
694
- @instance.send_persistent_request('/welcome/aboard', 'iZac') {|response|}
823
+ @instance.send_persistent_request('/welcome/aboard', 'iZac') {|_|}
695
824
  end
696
825
 
697
826
  it "should set correct attributes on the request message" do
@@ -704,14 +833,14 @@ describe RightScale::Sender do
704
833
  request.target.should be_nil
705
834
  request.expires_at.should == 0
706
835
  end, hsh(:persistent => true, :mandatory => true)).once
707
- @instance.send_persistent_request('/welcome/aboard', 'iZac') {|response|}
836
+ @instance.send_persistent_request('/welcome/aboard', 'iZac') {|_|}
708
837
  end
709
838
 
710
839
  it "should set the correct target if specified" do
711
840
  @broker.should_receive(:publish).with(hsh(:name => "request"), on do |request|
712
841
  request.target.should == 'my-target'
713
842
  end, hsh(:persistent => true, :mandatory => true)).once
714
- @instance.send_persistent_request('/welcome/aboard', 'iZac', 'my-target') {|response|}
843
+ @instance.send_persistent_request('/welcome/aboard', 'iZac', 'my-target') {|_|}
715
844
  end
716
845
 
717
846
  it "should set the correct target selectors if specified" do
@@ -720,18 +849,25 @@ describe RightScale::Sender do
720
849
  request.selector.should == :any
721
850
  request.scope.should == {:account => 123}
722
851
  end, hsh(:persistent => true, :mandatory => true)).once
723
- @instance.send_persistent_request('/welcome/aboard', 'iZac', :tags => ['tag'], :scope => {:account => 123})
852
+ @instance.send_persistent_request('/welcome/aboard', 'iZac', :tags => ['tag'], :scope => {:account => 123}) {|_|}
724
853
  end
725
854
 
726
855
  it "should not set up for retrying the request" do
727
856
  flexmock(@instance).should_receive(:publish_with_timeout_retry).never
728
- @instance.send_persistent_request('/welcome/aboard', 'iZac', 'my-target') {|response|}
857
+ @instance.send_persistent_request('/welcome/aboard', 'iZac', 'my-target') {|_|}
858
+ end
859
+
860
+ it "should not allow a selector target" do
861
+ lambda { @instance.send_retryable_request('/welcome/aboard', 'iZac', :selector => :all) }.should raise_error(ArgumentError)
862
+ end
863
+
864
+ it "should raise error if there is no callback block" do
865
+ lambda { @instance.send_persistent_request('/welcome/aboard', 'iZac') }.should raise_error(ArgumentError)
729
866
  end
730
867
  end
731
868
 
732
869
  describe "when handling a response" do
733
870
  before(:each) do
734
- flexmock(EM).should_receive(:next_tick).and_yield.by_default
735
871
  flexmock(EM).should_receive(:defer).and_yield.by_default
736
872
  @broker = flexmock("Broker", :subscribe => true, :publish => ["broker"], :connected? => true,
737
873
  :identity_parts => ["host", 123, 0, 0]).by_default
@@ -739,92 +875,61 @@ describe RightScale::Sender do
739
875
  RightScale::Sender.new(@agent)
740
876
  @instance = RightScale::Sender.instance
741
877
  flexmock(RightScale::AgentIdentity, :generate => 'token1')
742
- @header = flexmock("amqp header")
743
878
  end
744
879
 
745
880
  it "should deliver the response for a Request" do
746
881
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
747
882
  response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
748
- flexmock(@instance).should_receive(:deliver).with(response, RightScale::Sender::PendingRequest, @header).once
749
- @instance.handle_response(response, @header)
883
+ flexmock(@instance).should_receive(:deliver).with(response, RightScale::Sender::PendingRequest).once
884
+ @instance.handle_response(response)
750
885
  end
751
886
 
752
887
  it "should deliver the response for a Push" do
753
888
  @instance.send_push('/welcome/aboard', 'iZac') {|_|}
754
889
  response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
755
- flexmock(@instance).should_receive(:deliver).with(response, RightScale::Sender::PendingRequest, @header).once
756
- @instance.handle_response(response, @header)
890
+ flexmock(@instance).should_receive(:deliver).with(response, RightScale::Sender::PendingRequest).once
891
+ @instance.handle_response(response)
757
892
  end
758
893
 
759
894
  it "should not deliver TARGET_NOT_CONNECTED and TTL_EXPIRATION responses for send_retryable_request" do
760
- @header.should_receive(:ack).twice
761
895
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
762
896
  flexmock(@instance).should_receive(:deliver).never
763
897
  non_delivery = RightScale::OperationResult.non_delivery(RightScale::OperationResult::TARGET_NOT_CONNECTED)
764
898
  response = RightScale::Result.new('token1', 'to', non_delivery, 'target1')
765
- @instance.handle_response(response, @header)
899
+ @instance.handle_response(response)
766
900
  non_delivery = RightScale::OperationResult.non_delivery(RightScale::OperationResult::TTL_EXPIRATION)
767
901
  response = RightScale::Result.new('token1', 'to', non_delivery, 'target1')
768
- @instance.handle_response(response, @header)
902
+ @instance.handle_response(response)
769
903
  end
770
904
 
771
905
  it "should record non-delivery regardless of whether there is a response handler" do
772
- @header.should_receive(:ack).once
773
906
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
774
907
  non_delivery = RightScale::OperationResult.non_delivery(RightScale::OperationResult::NO_ROUTE_TO_TARGET)
775
908
  response = RightScale::Result.new('token1', 'to', non_delivery, 'target1')
776
- @instance.handle_response(response, @header)
909
+ @instance.handle_response(response)
777
910
  @instance.instance_variable_get(:@non_delivery_stats).total.should == 1
778
911
  end
779
912
 
780
913
  it "should log non-delivery if there is no response handler" do
781
- @header.should_receive(:ack).once
782
914
  @log.should_receive(:info).with(/Non-delivery of/).once
783
915
  @instance.send_push('/welcome/aboard', 'iZac')
784
916
  non_delivery = RightScale::OperationResult.non_delivery(RightScale::OperationResult::NO_ROUTE_TO_TARGET)
785
917
  response = RightScale::Result.new('token1', 'to', non_delivery, 'target1')
786
- @instance.handle_response(response, @header)
918
+ @instance.handle_response(response)
787
919
  end
788
920
 
789
921
  it "should log a debug message if request no longer pending" do
790
- @header.should_receive(:ack).once
791
922
  @log.should_receive(:debug).with(/No pending request for response/).once
792
923
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
793
924
  @instance.pending_requests['token1'].should_not be_nil
794
925
  @instance.pending_requests['token2'].should be_nil
795
926
  response = RightScale::Result.new('token2', 'to', RightScale::OperationResult.success, 'target1')
796
- @instance.handle_response(response, @header)
797
- end
798
-
799
- it "should ack response even if fail while handling it" do
800
- @header.should_receive(:ack).once
801
- @instance.send_push('/welcome/aboard', 'iZac') {|_|}
802
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
803
- flexmock(response).should_receive(:token).and_raise(Exception).once
804
- flexmock(@instance).should_receive(:deliver).never
805
- lambda { @instance.handle_response(response, @header) }.should raise_error(Exception)
806
- end
807
-
808
- it "should not attempt to ack response if fail while handling it and there is no header" do
809
- @instance.send_push('/welcome/aboard', 'iZac') {|_|}
810
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
811
- exception = Exception.new("test")
812
- flexmock(response).should_receive(:token).and_raise(exception).once
813
- flexmock(@instance).should_receive(:deliver).never
814
- lambda { @instance.handle_response(response, nil) }.should raise_error(Exception, "test")
815
- end
816
-
817
- it "should not attempt to ack response if there is no header" do
818
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
819
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
820
- flexmock(@instance).should_receive(:deliver).with(response, RightScale::Sender::PendingRequest, nil).once
821
927
  @instance.handle_response(response)
822
928
  end
823
929
  end
824
930
 
825
931
  describe "when delivering a response" do
826
932
  before(:each) do
827
- flexmock(EM).should_receive(:next_tick).and_yield.by_default
828
933
  flexmock(EM).should_receive(:defer).and_yield.by_default
829
934
  @broker = flexmock("Broker", :subscribe => true, :publish => ["broker"], :connected? => true,
830
935
  :identity_parts => ["host", 123, 0, 0]).by_default
@@ -832,15 +937,13 @@ describe RightScale::Sender do
832
937
  RightScale::Sender.new(@agent)
833
938
  @instance = RightScale::Sender.instance
834
939
  flexmock(RightScale::AgentIdentity, :generate => 'token1')
835
- @header = flexmock("amqp header")
836
- @header.should_receive(:ack).once.by_default
837
940
  end
838
941
 
839
942
  it "should delete all associated pending Request requests" do
840
943
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
841
944
  @instance.pending_requests['token1'].should_not be_nil
842
945
  response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
843
- @instance.handle_response(response, @header)
946
+ @instance.handle_response(response)
844
947
  @instance.pending_requests['token1'].should be_nil
845
948
  end
846
949
 
@@ -848,7 +951,7 @@ describe RightScale::Sender do
848
951
  @instance.send_push('/welcome/aboard', 'iZac') {|_|}
849
952
  @instance.pending_requests['token1'].should_not be_nil
850
953
  response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
851
- @instance.handle_response(response, @header)
954
+ @instance.handle_response(response)
852
955
  @instance.pending_requests['token1'].should_not be_nil
853
956
  end
854
957
 
@@ -858,7 +961,7 @@ describe RightScale::Sender do
858
961
  @instance.pending_requests['token2'] = @instance.pending_requests['token1'].dup
859
962
  @instance.pending_requests['token2'].retry_parent = 'token1'
860
963
  response = RightScale::Result.new('token2', 'to', RightScale::OperationResult.success, 'target1')
861
- @instance.handle_response(response, @header)
964
+ @instance.handle_response(response)
862
965
  @instance.pending_requests['token1'].should be_nil
863
966
  @instance.pending_requests['token2'].should be_nil
864
967
  end
@@ -867,67 +970,8 @@ describe RightScale::Sender do
867
970
  called = 0
868
971
  @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response| called += 1}
869
972
  response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
870
- @instance.handle_response(response, @header)
871
- called.should == 1
872
- end
873
-
874
- it "should defer the response handler call if not single threaded" do
875
- @agent.should_receive(:options).and_return({:single_threaded => false})
876
- RightScale::Sender.new(@agent)
877
- @instance = RightScale::Sender.instance
878
- called = 0
879
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response| called += 1}
880
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
881
- flexmock(EM).should_receive(:defer).and_yield.once
882
- flexmock(EM).should_receive(:next_tick).never
883
- @instance.handle_response(response, @header)
884
- called.should == 1
885
- end
886
-
887
- it "should not defer the response handler call if single threaded" do
888
- @agent.should_receive(:options).and_return({:single_threaded => true})
889
- RightScale::Sender.new(@agent)
890
- @instance = RightScale::Sender.instance
891
- called = 0
892
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|response| called += 1}
893
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
894
- flexmock(EM).should_receive(:next_tick).and_yield.once
895
- flexmock(EM).should_receive(:defer).never
896
- @instance.handle_response(response, @header)
897
- called.should == 1
898
- end
899
-
900
- it "should log an error if the response handler raises an exception but still delete pending request" do
901
- @agent.should_receive(:options).and_return({:single_threaded => true})
902
- @log.should_receive(:error).with(/Failed processing response/, Exception, :trace).once
903
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_| raise Exception}
904
- @instance.pending_requests['token1'].should_not be_nil
905
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
906
- @instance.handle_response(response, @header)
907
- @instance.pending_requests['token1'].should be_nil
908
- end
909
-
910
- it "should ack response even if fail while delivering it" do
911
- flexmock(EM).should_receive(:defer).and_raise(Exception).once
912
- @instance.send_push('/welcome/aboard', 'iZac') {|_|}
913
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
914
- lambda { @instance.handle_response(response, @header) }.should raise_error(Exception)
915
- end
916
-
917
- it "should not attempt to ack response if fail while delivering it and there is no header" do
918
- @header.should_receive(:ack).never
919
- exception = Exception.new("test")
920
- flexmock(EM).should_receive(:defer).and_raise(exception).once
921
- @instance.send_push('/welcome/aboard', 'iZac') {|_|}
922
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
923
- lambda { @instance.handle_response(response, nil) }.should raise_error(Exception, "test")
924
- end
925
-
926
- it "should not attempt to ack response if there is no header" do
927
- @header.should_receive(:ack).never
928
- @instance.send_retryable_request('/welcome/aboard', 'iZac') {|_|}
929
- response = RightScale::Result.new('token1', 'to', RightScale::OperationResult.success, 'target1')
930
973
  @instance.handle_response(response)
974
+ called.should == 1
931
975
  end
932
976
  end
933
977