right_agent 0.13.5 → 0.14.0

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.
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