rapns 2.0.5 → 3.0.0.beta.1

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.
Files changed (82) hide show
  1. data/lib/generators/rapns_generator.rb +1 -0
  2. data/lib/generators/templates/add_gcm.rb +86 -0
  3. data/lib/generators/templates/create_rapns_notifications.rb +1 -1
  4. data/lib/rapns/apns/app.rb +8 -0
  5. data/lib/rapns/apns/binary_notification_validator.rb +12 -0
  6. data/lib/rapns/apns/device_token_format_validator.rb +12 -0
  7. data/lib/rapns/apns/feedback.rb +14 -0
  8. data/lib/rapns/apns/notification.rb +84 -0
  9. data/lib/rapns/app.rb +5 -6
  10. data/lib/rapns/{config.rb → configuration.rb} +5 -5
  11. data/lib/rapns/daemon/apns/app_runner.rb +36 -0
  12. data/lib/rapns/daemon/apns/connection.rb +113 -0
  13. data/lib/rapns/daemon/apns/delivery.rb +63 -0
  14. data/lib/rapns/daemon/apns/delivery_handler.rb +21 -0
  15. data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
  16. data/lib/rapns/daemon/apns/feedback_receiver.rb +74 -0
  17. data/lib/rapns/daemon/app_runner.rb +76 -77
  18. data/lib/rapns/daemon/database_reconnectable.rb +3 -3
  19. data/lib/rapns/daemon/delivery.rb +43 -0
  20. data/lib/rapns/daemon/delivery_error.rb +6 -2
  21. data/lib/rapns/daemon/delivery_handler.rb +13 -79
  22. data/lib/rapns/daemon/delivery_queue_18.rb +2 -2
  23. data/lib/rapns/daemon/delivery_queue_19.rb +3 -3
  24. data/lib/rapns/daemon/feeder.rb +5 -5
  25. data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
  26. data/lib/rapns/daemon/gcm/delivery.rb +206 -0
  27. data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
  28. data/lib/rapns/daemon.rb +31 -20
  29. data/lib/rapns/gcm/app.rb +7 -0
  30. data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
  31. data/lib/rapns/gcm/notification.rb +31 -0
  32. data/lib/rapns/gcm/payload_size_validator.rb +13 -0
  33. data/lib/rapns/multi_json_helper.rb +16 -0
  34. data/lib/rapns/notification.rb +28 -95
  35. data/lib/rapns/version.rb +1 -1
  36. data/lib/rapns.rb +14 -4
  37. data/lib/tasks/cane.rake +19 -0
  38. data/lib/tasks/test.rake +34 -0
  39. data/spec/acceptance/gcm_upgrade_spec.rb +34 -0
  40. data/spec/acceptance_spec_helper.rb +85 -0
  41. data/spec/support/simplecov_helper.rb +13 -0
  42. data/spec/support/simplecov_quality_formatter.rb +8 -0
  43. data/spec/unit/apns/app_spec.rb +15 -0
  44. data/spec/unit/apns/feedback_spec.rb +12 -0
  45. data/spec/{rapns → unit/apns}/notification_spec.rb +44 -72
  46. data/spec/unit/app_spec.rb +18 -0
  47. data/spec/unit/daemon/apns/app_runner_spec.rb +37 -0
  48. data/spec/{rapns/daemon → unit/daemon/apns}/connection_spec.rb +9 -9
  49. data/spec/unit/daemon/apns/delivery_handler_spec.rb +48 -0
  50. data/spec/unit/daemon/apns/delivery_spec.rb +154 -0
  51. data/spec/{rapns/daemon → unit/daemon/apns}/feedback_receiver_spec.rb +14 -14
  52. data/spec/unit/daemon/app_runner_shared.rb +66 -0
  53. data/spec/unit/daemon/app_runner_spec.rb +78 -0
  54. data/spec/{rapns → unit}/daemon/database_reconnectable_spec.rb +4 -5
  55. data/spec/{rapns → unit}/daemon/delivery_error_spec.rb +2 -2
  56. data/spec/unit/daemon/delivery_handler_shared.rb +19 -0
  57. data/spec/{rapns → unit}/daemon/delivery_queue_spec.rb +1 -1
  58. data/spec/{rapns → unit}/daemon/feeder_spec.rb +33 -33
  59. data/spec/unit/daemon/gcm/app_runner_spec.rb +15 -0
  60. data/spec/unit/daemon/gcm/delivery_handler_spec.rb +36 -0
  61. data/spec/unit/daemon/gcm/delivery_spec.rb +236 -0
  62. data/spec/{rapns → unit}/daemon/interruptible_sleep_spec.rb +1 -1
  63. data/spec/{rapns → unit}/daemon/logger_spec.rb +1 -1
  64. data/spec/{rapns → unit}/daemon_spec.rb +1 -1
  65. data/spec/unit/gcm/app_spec.rb +5 -0
  66. data/spec/unit/gcm/notification_spec.rb +55 -0
  67. data/spec/unit/notification_shared.rb +38 -0
  68. data/spec/unit/notification_spec.rb +6 -0
  69. data/spec/{rapns/app_spec.rb → unit_spec_helper.rb} +76 -16
  70. metadata +107 -45
  71. data/lib/rapns/binary_notification_validator.rb +0 -10
  72. data/lib/rapns/daemon/connection.rb +0 -114
  73. data/lib/rapns/daemon/delivery_handler_pool.rb +0 -18
  74. data/lib/rapns/daemon/disconnection_error.rb +0 -14
  75. data/lib/rapns/daemon/feedback_receiver.rb +0 -82
  76. data/lib/rapns/device_token_format_validator.rb +0 -10
  77. data/lib/rapns/feedback.rb +0 -12
  78. data/spec/rapns/daemon/app_runner_spec.rb +0 -193
  79. data/spec/rapns/daemon/delivery_handler_pool_spec.rb +0 -17
  80. data/spec/rapns/daemon/delivery_handler_spec.rb +0 -206
  81. data/spec/rapns/feedback_spec.rb +0 -12
  82. data/spec/spec_helper.rb +0 -78
@@ -0,0 +1,154 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rapns::Daemon::Apns::Delivery do
4
+ let(:app) { stub(:name => 'MyApp') }
5
+ let(:notification) { stub.as_null_object }
6
+ let(:logger) { stub(:error => nil, :info => nil) }
7
+ let(:config) { stub(:check_for_errors => true) }
8
+ let(:connection) { stub(:select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
9
+ let(:delivery) { Rapns::Daemon::Apns::Delivery.new(app, connection, notification) }
10
+
11
+ def perform
12
+ begin
13
+ delivery.perform
14
+ rescue Rapns::DeliveryError, Rapns::Apns::DisconnectionError
15
+ end
16
+ end
17
+
18
+ before do
19
+ Rapns::Daemon.stub(:logger => logger, :config => config)
20
+ end
21
+
22
+ it "sends the binary version of the notification" do
23
+ notification.stub(:to_binary => "hi mom")
24
+ connection.should_receive(:write).with("hi mom")
25
+ perform
26
+ end
27
+
28
+ it "logs the notification delivery" do
29
+ notification.stub(:id => 666, :device_token => 'abc123')
30
+ logger.should_receive(:info).with("[MyApp] 666 sent to abc123")
31
+ perform
32
+ end
33
+
34
+ it "marks the notification as delivered" do
35
+ notification.should_receive(:delivered=).with(true)
36
+ perform
37
+ end
38
+
39
+ it "sets the time the notification was delivered" do
40
+ now = Time.now
41
+ Time.stub(:now).and_return(now)
42
+ notification.should_receive(:delivered_at=).with(now)
43
+ perform
44
+ end
45
+
46
+ it "does not trigger validations when saving the notification" do
47
+ notification.should_receive(:save!).with(:validate => false)
48
+ perform
49
+ end
50
+
51
+ it "updates notification with the ability to reconnect the database" do
52
+ delivery.should_receive(:with_database_reconnect_and_retry)
53
+ perform
54
+ end
55
+
56
+ it 'does not check for errors if check_for_errors config option is false' do
57
+ config.stub(:check_for_errors => false)
58
+ delivery.should_not_receive(:check_for_error)
59
+ perform
60
+ end
61
+
62
+ describe "when delivery fails" do
63
+ before { connection.stub(:select => true, :read => [8, 4, 69].pack("ccN")) }
64
+
65
+ it "updates notification with the ability to reconnect the database" do
66
+ delivery.should_receive(:with_database_reconnect_and_retry)
67
+ perform
68
+ end
69
+
70
+ it "sets the notification as not delivered" do
71
+ notification.should_receive(:delivered=).with(false)
72
+ perform
73
+ end
74
+
75
+ it "sets the notification delivered_at timestamp to nil" do
76
+ notification.should_receive(:delivered_at=).with(nil)
77
+ perform
78
+ end
79
+
80
+ it "sets the notification as failed" do
81
+ notification.should_receive(:failed=).with(true)
82
+ perform
83
+ end
84
+
85
+ it "sets the notification failed_at timestamp" do
86
+ now = Time.now
87
+ Time.stub(:now).and_return(now)
88
+ notification.should_receive(:failed_at=).with(now)
89
+ perform
90
+ end
91
+
92
+ it "sets the notification error code" do
93
+ notification.should_receive(:error_code=).with(4)
94
+ perform
95
+ end
96
+
97
+ it "logs the delivery error" do
98
+ error = Rapns::DeliveryError.new(4, 12, "Missing payload")
99
+ Rapns::DeliveryError.stub(:new => error)
100
+ expect { delivery.perform }.to raise_error(error)
101
+ end
102
+
103
+ it "sets the notification error description" do
104
+ notification.should_receive(:error_description=).with("Missing payload")
105
+ perform
106
+ end
107
+
108
+ it "skips validation when saving the notification" do
109
+ notification.should_receive(:save!).with(:validate => false)
110
+ perform
111
+ end
112
+
113
+ it "reads 6 bytes from the socket" do
114
+ connection.should_receive(:read).with(6).and_return(nil)
115
+ perform
116
+ end
117
+
118
+ it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
119
+ connection.stub(:select => nil)
120
+ connection.should_not_receive(:read)
121
+ perform
122
+ end
123
+
124
+ it "reconnects the socket" do
125
+ connection.should_receive(:reconnect)
126
+ perform
127
+ end
128
+
129
+ it "logs that the connection is being reconnected" do
130
+ Rapns::Daemon.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
131
+ perform
132
+ end
133
+
134
+ context "when the APNs disconnects without returning an error" do
135
+ before do
136
+ connection.stub(:read => nil)
137
+ end
138
+
139
+ it 'raises a DisconnectError error if the connection is closed without an error being returned' do
140
+ expect { delivery.perform }.to raise_error(Rapns::Apns::DisconnectionError)
141
+ end
142
+
143
+ it 'does not set the error code on the notification' do
144
+ notification.should_receive(:error_code=).with(nil)
145
+ perform
146
+ end
147
+
148
+ it 'sets the error description on the notification' do
149
+ notification.should_receive(:error_description=).with("APNs disconnected without returning an error.")
150
+ perform
151
+ end
152
+ end
153
+ end
154
+ end
@@ -1,21 +1,21 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
- describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
3
+ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
4
4
  let(:host) { 'feedback.push.apple.com' }
5
5
  let(:port) { 2196 }
6
6
  let(:poll) { 60 }
7
7
  let(:certificate) { stub }
8
8
  let(:password) { stub }
9
- let(:app) { 'my_app' }
9
+ let(:app) { stub(:name => 'my_app', :password => password, :certificate => certificate) }
10
10
  let(:connection) { stub(:connect => nil, :read => nil, :close => nil) }
11
11
  let(:logger) { stub(:error => nil, :info => nil) }
12
- let(:receiver) { Rapns::Daemon::FeedbackReceiver.new(app, host, port, poll, certificate, password) }
12
+ let(:receiver) { Rapns::Daemon::Apns::FeedbackReceiver.new(app, host, port, poll) }
13
13
 
14
14
  before do
15
15
  receiver.stub(:interruptible_sleep)
16
16
  Rapns::Daemon.logger = logger
17
- Rapns::Daemon::Connection.stub(:new => connection)
18
- Rapns::Feedback.stub(:create!)
17
+ Rapns::Daemon::Apns::Connection.stub(:new => connection)
18
+ Rapns::Apns::Feedback.stub(:create!)
19
19
  receiver.instance_variable_set("@stop", false)
20
20
  end
21
21
 
@@ -30,8 +30,8 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
30
30
  end
31
31
  end
32
32
 
33
- it 'instantiates a new connection' do
34
- Rapns::Daemon::Connection.should_receive(:new).with("FeedbackReceiver:#{app}", host, port, certificate, password)
33
+ it 'instantiates a new connection' do
34
+ Rapns::Daemon::Apns::Connection.should_receive(:new).with("FeedbackReceiver:#{app.name}", host, port, certificate, password)
35
35
  receiver.check_for_feedback
36
36
  end
37
37
 
@@ -58,7 +58,7 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
58
58
 
59
59
  it 'creates the feedback' do
60
60
  stub_connection_read_with_tuple
61
- Rapns::Feedback.should_receive(:create!).with(:failed_at => Time.at(1323533325), :device_token => '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', :app => 'my_app')
61
+ Rapns::Apns::Feedback.should_receive(:create!).with(:failed_at => Time.at(1323533325), :device_token => '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', :app => app)
62
62
  receiver.check_for_feedback
63
63
  end
64
64
 
@@ -66,7 +66,7 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
66
66
  error = StandardError.new('bork!')
67
67
  connection.stub(:read).and_raise(error)
68
68
  Rapns::Daemon.logger.should_receive(:error).with(error)
69
- lambda { receiver.check_for_feedback }.should raise_error
69
+ receiver.check_for_feedback
70
70
  end
71
71
 
72
72
  it 'sleeps for the feedback poll period' do
@@ -92,10 +92,10 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
92
92
 
93
93
  it 'calls the configuration feedback_callback when feedback is received and the callback is set' do
94
94
  stub_connection_read_with_tuple
95
- Rapns::configuration.feedback_callback = Proc.new {}
95
+ Rapns.configuration.feedback_callback = Proc.new {}
96
96
  feedback = Object.new
97
- Rapns::Feedback.stub(:create! => feedback)
98
- Rapns::configuration.feedback_callback.should_receive(:call).with(feedback)
97
+ Rapns::Apns::Feedback.stub(:create! => feedback)
98
+ Rapns.configuration.feedback_callback.should_receive(:call).with(feedback)
99
99
  receiver.check_for_feedback
100
100
  end
101
101
 
@@ -115,4 +115,4 @@ describe Rapns::Daemon::FeedbackReceiver, 'check_for_feedback' do
115
115
  Rapns::configuration.feedback_callback = callback
116
116
  receiver.check_for_feedback
117
117
  end
118
- end
118
+ end
@@ -0,0 +1,66 @@
1
+ shared_examples_for "an AppRunner subclass" do
2
+ let(:queue) { stub(:notifications_processed? => true, :push => nil) }
3
+
4
+ before { Rapns::Daemon::DeliveryQueue.stub(:new => queue) }
5
+ after { Rapns::Daemon::AppRunner.runners.clear }
6
+
7
+ describe 'start' do
8
+ it 'starts a delivery handler for each connection' do
9
+ handler.should_receive(:start)
10
+ runner.start
11
+ end
12
+
13
+ it 'assigns the queue to the handler' do
14
+ handler.should_receive(:queue=).with(queue)
15
+ runner.start
16
+ end
17
+ end
18
+
19
+ describe 'enqueue' do
20
+ let(:notification) { stub }
21
+
22
+ it 'enqueues the notification' do
23
+ queue.should_receive(:push).with(notification)
24
+ runner.enqueue(notification)
25
+ end
26
+ end
27
+
28
+ describe 'stop' do
29
+ before { runner.start }
30
+
31
+ it 'stops the delivery handlers' do
32
+ handler.should_receive(:stop)
33
+ runner.stop
34
+ end
35
+ end
36
+
37
+ describe 'idle?' do
38
+ it 'is idle if all notifications have been processed' do
39
+ queue.stub(:notifications_processed? => true)
40
+ runner.idle?.should be_true
41
+ end
42
+
43
+ it 'is not idle if not all notifications have been processed' do
44
+ queue.stub(:notifications_processed? => false)
45
+ runner.idle?.should be_false
46
+ end
47
+ end
48
+
49
+ describe 'sync' do
50
+ before { runner.start }
51
+
52
+ it 'reduces the number of handlers if needed' do
53
+ handler.should_receive(:stop)
54
+ new_app = app_class.new
55
+ new_app.stub(:connections => app.connections - 1)
56
+ runner.sync(new_app)
57
+ end
58
+
59
+ it 'increases the number of handlers if needed' do
60
+ runner.should_receive(:start_handler).and_return(handler)
61
+ new_app = app_class.new
62
+ new_app.stub(:connections => app.connections + 1)
63
+ runner.sync(new_app)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,78 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rapns::Daemon::AppRunner, 'stop' do
4
+ let(:runner) { stub }
5
+ before { Rapns::Daemon::AppRunner.runners['app'] = runner }
6
+ after { Rapns::Daemon::AppRunner.runners.clear }
7
+
8
+ it 'stops all runners' do
9
+ runner.should_receive(:stop)
10
+ Rapns::Daemon::AppRunner.stop
11
+ end
12
+ end
13
+
14
+ describe Rapns::Daemon::AppRunner, 'deliver' do
15
+ let(:runner) { stub }
16
+ let(:notification) { stub(:app_id => 1) }
17
+ let(:logger) { stub(:error => nil) }
18
+
19
+ before do
20
+ Rapns::Daemon.stub(:logger => logger)
21
+ Rapns::Daemon::AppRunner.runners[1] = runner
22
+ end
23
+
24
+ after { Rapns::Daemon::AppRunner.runners.clear }
25
+
26
+ it 'enqueues the notification' do
27
+ runner.should_receive(:enqueue).with(notification)
28
+ Rapns::Daemon::AppRunner.enqueue(notification)
29
+ end
30
+
31
+ it 'logs an error if there is no runner to deliver the notification' do
32
+ notification.stub(:app_id => 2, :id => 123)
33
+ logger.should_receive(:error).with("No such app '#{notification.app_id}' for notification #{notification.id}.")
34
+ Rapns::Daemon::AppRunner.enqueue(notification)
35
+ end
36
+ end
37
+
38
+ describe Rapns::Daemon::AppRunner, 'sync' do
39
+ let(:app) { Rapns::Apns::App.new }
40
+ let(:new_app) { Rapns::Apns::App.new }
41
+ let(:runner) { stub(:sync => nil, :stop => nil, :start => nil) }
42
+ let(:logger) { stub(:error => nil) }
43
+ let(:queue) { Rapns::Daemon::DeliveryQueue.new }
44
+
45
+ before do
46
+ app.stub(:id => 1)
47
+ new_app.stub(:id => 2)
48
+ Rapns::Daemon::DeliveryQueue.stub(:new => queue)
49
+ Rapns::Daemon::AppRunner.runners[app.id] = runner
50
+ Rapns::App.stub(:all => [app])
51
+ end
52
+
53
+ after { Rapns::Daemon::AppRunner.runners.clear }
54
+
55
+ it 'loads all apps' do
56
+ Rapns::App.should_receive(:all)
57
+ Rapns::Daemon::AppRunner.sync
58
+ end
59
+
60
+ it 'instructs existing runners to sync' do
61
+ runner.should_receive(:sync).with(app)
62
+ Rapns::Daemon::AppRunner.sync
63
+ end
64
+
65
+ it 'starts a runner for a new app' do
66
+ Rapns::App.stub(:all => [app, new_app])
67
+ new_runner = stub
68
+ Rapns::Daemon::Apns::AppRunner.should_receive(:new).with(new_app).and_return(new_runner)
69
+ new_runner.should_receive(:start)
70
+ Rapns::Daemon::AppRunner.sync
71
+ end
72
+
73
+ it 'deletes old apps' do
74
+ Rapns::App.stub(:all => [])
75
+ runner.should_receive(:stop)
76
+ Rapns::Daemon::AppRunner.sync
77
+ end
78
+ end
@@ -1,4 +1,4 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::DatabaseReconnectable do
4
4
  class TestDouble
@@ -7,7 +7,6 @@ describe Rapns::Daemon::DatabaseReconnectable do
7
7
  attr_reader :name
8
8
 
9
9
  def initialize(error, max_calls)
10
- @name = 'TestDouble'
11
10
  @error = error
12
11
  @max_calls = max_calls
13
12
  @calls = 0
@@ -53,12 +52,12 @@ describe Rapns::Daemon::DatabaseReconnectable do
53
52
  end
54
53
 
55
54
  it "should log that the database is being reconnected" do
56
- Rapns::Daemon.logger.should_receive(:warn).with("[TestDouble] Lost connection to database, reconnecting...")
55
+ Rapns::Daemon.logger.should_receive(:warn).with("Lost connection to database, reconnecting...")
57
56
  test_double.perform
58
57
  end
59
58
 
60
59
  it "should log the reconnection attempt" do
61
- Rapns::Daemon.logger.should_receive(:warn).with("[TestDouble] Attempt 1")
60
+ Rapns::Daemon.logger.should_receive(:warn).with("Attempt 1")
62
61
  test_double.perform
63
62
  end
64
63
 
@@ -91,7 +90,7 @@ describe Rapns::Daemon::DatabaseReconnectable do
91
90
  end
92
91
 
93
92
  it "should log the 2nd attempt" do
94
- Rapns::Daemon.logger.should_receive(:warn).with("[TestDouble] Attempt 2")
93
+ Rapns::Daemon.logger.should_receive(:warn).with("Attempt 2")
95
94
  test_double.perform
96
95
  end
97
96
 
@@ -1,10 +1,10 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
3
  describe Rapns::DeliveryError do
4
4
  let(:error) { Rapns::DeliveryError.new(4, 12, "Missing payload") }
5
5
 
6
6
  it "returns an informative message" do
7
- error.message.should == "Unable to deliver notification 12, received APN error 4 (Missing payload)"
7
+ error.message.should == "Unable to deliver notification 12, received error 4 (Missing payload)"
8
8
  end
9
9
 
10
10
  it "returns the error code" do
@@ -0,0 +1,19 @@
1
+ shared_examples_for 'an DeliveryHandler subclass' do
2
+ it "instructs the queue to wakeup the thread when told to stop" do
3
+ thread = stub(:join => nil)
4
+ Thread.stub(:new => thread)
5
+ queue.should_receive(:wakeup).with(thread)
6
+ delivery_handler.start
7
+ delivery_handler.stop
8
+ end
9
+
10
+ describe "when being stopped" do
11
+ before { queue.pop }
12
+
13
+ it "does not attempt to deliver a notification when a DeliveryQueue::::WakeupError is raised" do
14
+ queue.stub(:pop).and_raise(Rapns::Daemon::DeliveryQueue::WakeupError)
15
+ delivery_handler.should_not_receive(:deliver)
16
+ delivery_handler.send(:handle_next_notification)
17
+ end
18
+ end
19
+ end
@@ -1,4 +1,4 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::DeliveryQueue do
4
4
  let(:queue) { Rapns::Daemon::DeliveryQueue.new }
@@ -1,79 +1,79 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
3
  describe Rapns::Daemon::Feeder do
4
- let(:poll) { 2 }
5
4
  let(:config) { stub(:batch_size => 5000) }
6
- let(:notification) { Rapns::Notification.create!(:device_token => "a" * 64, :app => 'my_app') }
5
+ let!(:app) { Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
6
+ let(:notification) { Rapns::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
7
7
  let(:logger) { stub }
8
8
 
9
9
  before do
10
- Rapns::Daemon::Feeder.stub(:sleep)
11
- Rapns::Daemon::Feeder.stub(:interruptible_sleep)
12
10
  Rapns::Daemon.stub(:logger => logger, :config => config)
13
- Rapns::Daemon::Feeder.instance_variable_set("@stop", false)
14
- Rapns::Daemon::AppRunner.stub(:ready => ['my_app'])
15
- Rapns::Daemon::AppRunner.stub(:ready => ['my_app'])
11
+ Rapns::Daemon::Feeder.instance_variable_set("@stop", true)
12
+ Rapns::Daemon::AppRunner.stub(:idle => [stub(:app => app)])
13
+ end
14
+
15
+ def start
16
+ Rapns::Daemon::Feeder.start(0)
16
17
  end
17
18
 
18
19
  it "checks for new notifications with the ability to reconnect the database" do
19
20
  Rapns::Daemon::Feeder.should_receive(:with_database_reconnect_and_retry)
20
- Rapns::Daemon::Feeder.enqueue_notifications
21
+ start
21
22
  end
22
23
 
23
24
  it 'loads notifications in batches' do
24
- relation = stub
25
- relation.should_receive(:find_each).with(:batch_size => 5000)
25
+ relation = stub.as_null_object
26
+ relation.should_receive(:limit).with(5000)
26
27
  Rapns::Notification.stub(:ready_for_delivery => relation)
27
- Rapns::Daemon::Feeder.enqueue_notifications
28
+ start
28
29
  end
29
30
 
30
- it "delivers the notification" do
31
+ it "enqueue the notification" do
31
32
  notification.update_attributes!(:delivered => false)
32
- Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
33
- Rapns::Daemon::Feeder.enqueue_notifications
33
+ Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
34
+ start
34
35
  end
35
36
 
36
37
  it 'does not enqueue the notification if the app runner is still processing the previous batch' do
37
- Rapns::Daemon::AppRunner.stub(:ready => [])
38
- Rapns::Daemon::AppRunner.should_not_receive(:deliver)
39
- Rapns::Daemon::Feeder.enqueue_notifications
38
+ Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
39
+ start
40
40
  end
41
41
 
42
42
  it "enqueues an undelivered notification without deliver_after set" do
43
43
  notification.update_attributes!(:delivered => false, :deliver_after => nil)
44
- Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
45
- Rapns::Daemon::Feeder.enqueue_notifications
44
+ Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
45
+ start
46
46
  end
47
47
 
48
48
  it "enqueues a notification with a deliver_after time in the past" do
49
49
  notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.ago)
50
- Rapns::Daemon::AppRunner.should_receive(:deliver).with(notification)
51
- Rapns::Daemon::Feeder.enqueue_notifications
50
+ Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
51
+ start
52
52
  end
53
53
 
54
54
  it "does not enqueue a notification with a deliver_after time in the future" do
55
55
  notification.update_attributes!(:delivered => false, :deliver_after => 1.hour.from_now)
56
- Rapns::Daemon::AppRunner.should_not_receive(:deliver)
57
- Rapns::Daemon::Feeder.enqueue_notifications
56
+ Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
57
+ start
58
58
  end
59
59
 
60
60
  it "does not enqueue a previously delivered notification" do
61
61
  notification.update_attributes!(:delivered => true, :delivered_at => Time.now)
62
- Rapns::Daemon::AppRunner.should_not_receive(:deliver)
63
- Rapns::Daemon::Feeder.enqueue_notifications
62
+ Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
63
+ start
64
64
  end
65
65
 
66
66
  it "does not enqueue a notification that has previously failed delivery" do
67
67
  notification.update_attributes!(:delivered => false, :failed => true)
68
- Rapns::Daemon::AppRunner.should_not_receive(:deliver)
69
- Rapns::Daemon::Feeder.enqueue_notifications
68
+ Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
69
+ start
70
70
  end
71
71
 
72
72
  it "logs errors" do
73
73
  e = StandardError.new("bork")
74
74
  Rapns::Notification.stub(:ready_for_delivery).and_raise(e)
75
75
  Rapns::Daemon.logger.should_receive(:error).with(e)
76
- Rapns::Daemon::Feeder.enqueue_notifications
76
+ start
77
77
  end
78
78
 
79
79
  it "interrupts sleep when stopped" do
@@ -84,12 +84,12 @@ describe Rapns::Daemon::Feeder do
84
84
  it "enqueues notifications when started" do
85
85
  Rapns::Daemon::Feeder.should_receive(:enqueue_notifications).at_least(:once)
86
86
  Rapns::Daemon::Feeder.stub(:loop).and_yield
87
- Rapns::Daemon::Feeder.start(poll)
87
+ start
88
88
  end
89
89
 
90
90
  it "sleeps for the given period" do
91
- Rapns::Daemon::Feeder.should_receive(:interruptible_sleep).with(poll)
91
+ Rapns::Daemon::Feeder.should_receive(:interruptible_sleep).with(2)
92
92
  Rapns::Daemon::Feeder.stub(:loop).and_yield
93
- Rapns::Daemon::Feeder.start(poll)
93
+ Rapns::Daemon::Feeder.start(2)
94
94
  end
95
- end
95
+ end
@@ -0,0 +1,15 @@
1
+ require 'unit_spec_helper'
2
+ require File.dirname(__FILE__) + '/../app_runner_shared.rb'
3
+
4
+ describe Rapns::Daemon::Gcm::AppRunner do
5
+ it_behaves_like 'an AppRunner subclass'
6
+
7
+ let(:app_class) { Rapns::Gcm::App }
8
+ let(:app) { app_class.new }
9
+ let(:runner) { Rapns::Daemon::Gcm::AppRunner.new(app) }
10
+ let(:handler) { stub(:start => nil, :stop => nil, :queue= => nil) }
11
+
12
+ before do
13
+ Rapns::Daemon::Gcm::DeliveryHandler.stub(:new => handler)
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ require "unit_spec_helper"
2
+ require File.dirname(__FILE__) + '/../delivery_handler_shared.rb'
3
+
4
+ describe Rapns::Daemon::Gcm::DeliveryHandler do
5
+ it_should_behave_like 'an DeliveryHandler subclass'
6
+
7
+ let(:app) { stub }
8
+ let(:delivery_handler) { Rapns::Daemon::Gcm::DeliveryHandler.new(app) }
9
+ let(:notification) { stub }
10
+ let(:http) { stub(:shutdown => nil)}
11
+ let(:queue) { Rapns::Daemon::DeliveryQueue.new }
12
+
13
+ before do
14
+ Net::HTTP::Persistent.stub(:new => http)
15
+ Rapns::Daemon::Gcm::Delivery.stub(:perform)
16
+ delivery_handler.queue = queue
17
+ queue.push(notification)
18
+ end
19
+
20
+ it 'performs delivery of an notification' do
21
+ Rapns::Daemon::Gcm::Delivery.should_receive(:perform).with(app, http, notification)
22
+ delivery_handler.start
23
+ delivery_handler.stop
24
+ end
25
+
26
+ it 'initiates a persistent connection object' do
27
+ Net::HTTP::Persistent.should_receive(:new).with('rapns')
28
+ Rapns::Daemon::Gcm::DeliveryHandler.new(app)
29
+ end
30
+
31
+ it 'shuts down the http connection stopped' do
32
+ http.should_receive(:shutdown)
33
+ delivery_handler.start
34
+ delivery_handler.stop
35
+ end
36
+ end