rpush 1.0.0-java → 2.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +37 -22
  4. data/bin/rpush +13 -4
  5. data/lib/generators/rpush_generator.rb +2 -0
  6. data/lib/generators/templates/add_adm.rb +5 -5
  7. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +1 -1
  8. data/lib/generators/templates/add_app_to_rapns.rb +2 -2
  9. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +1 -1
  10. data/lib/generators/templates/add_gcm.rb +32 -32
  11. data/lib/generators/templates/add_rpush.rb +67 -67
  12. data/lib/generators/templates/add_wpns.rb +2 -2
  13. data/lib/generators/templates/create_rapns_apps.rb +5 -5
  14. data/lib/generators/templates/create_rapns_feedback.rb +2 -2
  15. data/lib/generators/templates/create_rapns_notifications.rb +15 -15
  16. data/lib/generators/templates/rpush.rb +28 -7
  17. data/lib/generators/templates/rpush_2_0_0_updates.rb +42 -0
  18. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  19. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  20. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  21. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  22. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  23. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  24. data/lib/rpush/client/active_model/apns/notification.rb +90 -0
  25. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  26. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  27. data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
  28. data/lib/rpush/client/active_model/notification.rb +26 -0
  29. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  30. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  31. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  32. data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
  33. data/lib/rpush/client/active_model.rb +21 -0
  34. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  35. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  36. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  37. data/lib/rpush/client/active_record/apns/feedback.rb +22 -0
  38. data/lib/rpush/client/active_record/apns/notification.rb +46 -0
  39. data/lib/rpush/client/active_record/app.rb +17 -0
  40. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  41. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  42. data/lib/rpush/client/active_record/notification.rb +38 -0
  43. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  44. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  45. data/lib/rpush/client/active_record.rb +19 -0
  46. data/lib/rpush/client/redis/adm/app.rb +14 -0
  47. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  48. data/lib/rpush/client/redis/apns/app.rb +11 -0
  49. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  50. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  51. data/lib/rpush/client/redis/app.rb +24 -0
  52. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  53. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  54. data/lib/rpush/client/redis/notification.rb +68 -0
  55. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  56. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  57. data/lib/rpush/client/redis.rb +35 -0
  58. data/lib/rpush/configuration.rb +27 -6
  59. data/lib/rpush/daemon/adm/delivery.rb +56 -55
  60. data/lib/rpush/daemon/apns/delivery.rb +20 -44
  61. data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
  62. data/lib/rpush/daemon/apns.rb +6 -5
  63. data/lib/rpush/daemon/app_runner.rb +103 -99
  64. data/lib/rpush/daemon/batch.rb +54 -40
  65. data/lib/rpush/daemon/delivery.rb +13 -3
  66. data/lib/rpush/daemon/delivery_error.rb +10 -2
  67. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +114 -0
  68. data/lib/rpush/daemon/dispatcher/http.rb +3 -3
  69. data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
  70. data/lib/rpush/daemon/dispatcher_loop.rb +37 -23
  71. data/lib/rpush/daemon/errors.rb +18 -0
  72. data/lib/rpush/daemon/feeder.rb +28 -39
  73. data/lib/rpush/daemon/gcm/delivery.rb +19 -20
  74. data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
  75. data/lib/rpush/daemon/loggable.rb +2 -4
  76. data/lib/rpush/daemon/proc_title.rb +16 -0
  77. data/lib/rpush/daemon/queue_payload.rb +12 -0
  78. data/lib/rpush/daemon/reflectable.rb +3 -5
  79. data/lib/rpush/daemon/retry_header_parser.rb +6 -6
  80. data/lib/rpush/daemon/retryable_error.rb +2 -0
  81. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  82. data/lib/rpush/daemon/service_config_methods.rb +23 -7
  83. data/lib/rpush/daemon/signal_handler.rb +56 -0
  84. data/lib/rpush/daemon/store/active_record/reconnectable.rb +21 -17
  85. data/lib/rpush/daemon/store/active_record.rb +71 -38
  86. data/lib/rpush/daemon/store/interface.rb +19 -0
  87. data/lib/rpush/daemon/store/redis.rb +149 -0
  88. data/lib/rpush/daemon/string_helpers.rb +15 -0
  89. data/lib/rpush/daemon/synchronizer.rb +60 -0
  90. data/lib/rpush/daemon/tcp_connection.rb +6 -11
  91. data/lib/rpush/daemon/wpns/delivery.rb +21 -30
  92. data/lib/rpush/daemon.rb +40 -60
  93. data/lib/rpush/deprecatable.rb +4 -3
  94. data/lib/rpush/deprecation.rb +7 -10
  95. data/lib/rpush/embed.rb +8 -3
  96. data/lib/rpush/logger.rb +11 -15
  97. data/lib/rpush/push.rb +1 -2
  98. data/lib/rpush/reflection.rb +8 -12
  99. data/lib/rpush/version.rb +1 -1
  100. data/lib/rpush.rb +5 -29
  101. data/lib/tasks/quality.rake +35 -0
  102. data/lib/tasks/test.rake +1 -5
  103. data/spec/.rubocop.yml +4 -0
  104. data/spec/functional/adm_spec.rb +3 -6
  105. data/spec/functional/apns_spec.rb +117 -24
  106. data/spec/functional/embed_spec.rb +20 -20
  107. data/spec/functional/gcm_spec.rb +4 -7
  108. data/spec/functional/new_app_spec.rb +59 -0
  109. data/spec/functional/retry_spec.rb +46 -0
  110. data/spec/functional/synchronization_spec.rb +68 -0
  111. data/spec/functional/wpns_spec.rb +3 -6
  112. data/spec/functional_spec_helper.rb +26 -0
  113. data/spec/integration/rpush_spec.rb +13 -0
  114. data/spec/integration/support/gcm_success_response.json +1 -0
  115. data/spec/spec_helper.rb +60 -0
  116. data/spec/support/active_record_setup.rb +48 -0
  117. data/{config → spec/support/config}/database.yml +0 -0
  118. data/spec/support/install.sh +43 -7
  119. data/spec/support/simplecov_helper.rb +9 -5
  120. data/spec/support/simplecov_quality_formatter.rb +10 -6
  121. data/spec/unit/apns_feedback_spec.rb +3 -3
  122. data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
  123. data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
  124. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  125. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  126. data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
  127. data/spec/unit/client/active_record/app_spec.rb +30 -0
  128. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  129. data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
  130. data/spec/unit/client/active_record/notification_spec.rb +21 -0
  131. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  132. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  133. data/spec/unit/configuration_spec.rb +12 -5
  134. data/spec/unit/daemon/adm/delivery_spec.rb +66 -55
  135. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
  136. data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
  137. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +22 -17
  138. data/spec/unit/daemon/app_runner_spec.rb +78 -186
  139. data/spec/unit/daemon/batch_spec.rb +52 -115
  140. data/spec/unit/daemon/delivery_spec.rb +15 -1
  141. data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
  142. data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
  143. data/spec/unit/daemon/dispatcher_loop_spec.rb +6 -24
  144. data/spec/unit/daemon/feeder_spec.rb +38 -39
  145. data/spec/unit/daemon/gcm/delivery_spec.rb +122 -101
  146. data/spec/unit/daemon/reflectable_spec.rb +2 -2
  147. data/spec/unit/daemon/retryable_error_spec.rb +1 -1
  148. data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
  149. data/spec/unit/daemon/signal_handler_spec.rb +95 -0
  150. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +48 -27
  151. data/spec/unit/daemon/store/active_record_spec.rb +38 -47
  152. data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
  153. data/spec/unit/daemon/wpns/delivery_spec.rb +58 -50
  154. data/spec/unit/daemon_spec.rb +48 -82
  155. data/spec/unit/embed_spec.rb +6 -4
  156. data/spec/unit/logger_spec.rb +35 -43
  157. data/spec/unit/notification_shared.rb +9 -79
  158. data/spec/unit/push_spec.rb +6 -10
  159. data/spec/unit/reflection_spec.rb +25 -25
  160. data/spec/unit/rpush_spec.rb +1 -2
  161. data/spec/unit_spec_helper.rb +33 -88
  162. metadata +126 -76
  163. data/lib/rpush/TODO +0 -3
  164. data/lib/rpush/adm/app.rb +0 -15
  165. data/lib/rpush/adm/data_validator.rb +0 -11
  166. data/lib/rpush/adm/notification.rb +0 -29
  167. data/lib/rpush/apns/app.rb +0 -29
  168. data/lib/rpush/apns/binary_notification_validator.rb +0 -12
  169. data/lib/rpush/apns/device_token_format_validator.rb +0 -12
  170. data/lib/rpush/apns/feedback.rb +0 -16
  171. data/lib/rpush/apns/notification.rb +0 -84
  172. data/lib/rpush/app.rb +0 -18
  173. data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
  174. data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
  175. data/lib/rpush/daemon/dispatcher_loop_collection.rb +0 -33
  176. data/lib/rpush/daemon/too_many_requests_error.rb +0 -20
  177. data/lib/rpush/gcm/app.rb +0 -11
  178. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
  179. data/lib/rpush/gcm/notification.rb +0 -30
  180. data/lib/rpush/notification.rb +0 -69
  181. data/lib/rpush/notifier.rb +0 -52
  182. data/lib/rpush/payload_data_size_validator.rb +0 -10
  183. data/lib/rpush/railtie.rb +0 -11
  184. data/lib/rpush/registration_ids_count_validator.rb +0 -10
  185. data/lib/rpush/wpns/app.rb +0 -9
  186. data/lib/rpush/wpns/notification.rb +0 -26
  187. data/lib/tasks/cane.rake +0 -18
  188. data/lib/tasks/rpush.rake +0 -16
  189. data/spec/unit/apns/app_spec.rb +0 -29
  190. data/spec/unit/apns/feedback_spec.rb +0 -9
  191. data/spec/unit/apns/notification_spec.rb +0 -208
  192. data/spec/unit/app_spec.rb +0 -30
  193. data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
  194. data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +0 -37
  195. data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
  196. data/spec/unit/daemon/too_many_requests_error_spec.rb +0 -14
  197. data/spec/unit/gcm/app_spec.rb +0 -4
  198. data/spec/unit/notification_spec.rb +0 -15
  199. data/spec/unit/notifier_spec.rb +0 -49
  200. data/spec/unit/wpns/app_spec.rb +0 -4
  201. data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -1,23 +1,21 @@
1
1
  require 'unit_spec_helper'
2
2
  require 'unit/notification_shared.rb'
3
3
 
4
- describe Rpush::Gcm::Notification do
4
+ describe Rpush::Client::ActiveRecord::Gcm::Notification do
5
5
  it_should_behave_like 'an Notification subclass'
6
6
 
7
- let(:app) { Rpush::Gcm::App.create!(:name => 'test', :auth_key => 'abc') }
8
- let(:notification_class) { Rpush::Gcm::Notification }
7
+ let(:app) { Rpush::Client::ActiveRecord::Gcm::App.create!(name: 'test', auth_key: 'abc') }
8
+ let(:notification_class) { Rpush::Client::ActiveRecord::Gcm::Notification }
9
9
  let(:notification) { notification_class.new }
10
- let(:data_setter) { 'data=' }
11
- let(:data_getter) { 'data' }
12
10
 
13
11
  it "has a 'data' payload limit of 4096 bytes" do
14
- notification.data = { :key => "a" * 4096 }
12
+ notification.data = { key: "a" * 4096 }
15
13
  notification.valid?.should be_false
16
14
  notification.errors[:base].should eq ["Notification payload data cannot be larger than 4096 bytes."]
17
15
  end
18
16
 
19
17
  it 'limits the number of registration ids to 1000' do
20
- notification.registration_ids = ['a']*(1000+1)
18
+ notification.registration_ids = ['a'] * (1000 + 1)
21
19
  notification.valid?.should be_false
22
20
  notification.errors[:base].should eq ["Number of registration_ids cannot be larger than 1000."]
23
21
  end
@@ -0,0 +1,21 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Notification do
4
+ let(:notification) { Rpush::Client::ActiveRecord::Notification.new }
5
+
6
+ it 'allows assignment of many registration IDs' do
7
+ notification.registration_ids = %w(a b)
8
+ notification.registration_ids.should eq %w(a b)
9
+ end
10
+
11
+ it 'allows assignment of a single registration ID' do
12
+ notification.registration_ids = 'a'
13
+ notification.registration_ids.should eq ['a']
14
+ end
15
+
16
+ it 'saves its parent App if required' do
17
+ notification.app = Rpush::Client::ActiveRecord::App.new(name: "aname")
18
+ expect(notification.app).to be_valid
19
+ expect(notification).to be_valid
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Client::ActiveRecord::Wpns::App do
4
+ end
@@ -0,0 +1,21 @@
1
+ require 'unit_spec_helper'
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rpush::Client::ActiveRecord::Wpns::Notification do
5
+ it_should_behave_like 'an Notification subclass'
6
+ let(:app) { Rpush::Client::ActiveRecord::Wpns::App.create!(name: 'test', auth_key: 'abc') }
7
+ let(:notification_class) { Rpush::Client::ActiveRecord::Wpns::Notification }
8
+ let(:notification) { notification_class.new }
9
+
10
+ it "should have an url in the uri parameter" do
11
+ notification = Rpush::Client::ActiveRecord::Wpns::Notification.new(uri: "somthing")
12
+ notification.valid?
13
+ notification.errors[:uri].include?("is invalid").should be_true
14
+ end
15
+
16
+ it "should be invalid if there's no message" do
17
+ notification = Rpush::Client::ActiveRecord::Wpns::Notification.new(alert: "")
18
+ notification.valid?
19
+ notification.errors[:alert].include?("can't be blank").should be_true
20
+ end
21
+ end
@@ -1,11 +1,14 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Rpush do
4
- let(:config) { double }
4
+ let(:config) { Rpush.config }
5
5
 
6
- before { Rpush.stub(:config => config) }
6
+ before do
7
+ Rpush.stub(require: nil)
8
+ Rpush.stub(config: config)
9
+ end
7
10
 
8
- it 'can yields a config block' do
11
+ it 'yields a configure block' do
9
12
  expect { |b| Rpush.configure(&b) }.to yield_with_args(config)
10
13
  end
11
14
  end
@@ -26,9 +29,8 @@ describe Rpush::Configuration do
26
29
  end
27
30
 
28
31
  it 'sets the pid_file relative if not absolute' do
29
- Rails.stub(:root => '/rails')
30
32
  config.pid_file = 'tmp/rpush.pid'
31
- config.pid_file.should eq '/rails/tmp/rpush.pid'
33
+ config.pid_file.should eq '/tmp/rails_root/tmp/rpush.pid'
32
34
  end
33
35
 
34
36
  it 'does not alter an absolute pid_file path' do
@@ -42,4 +44,9 @@ describe Rpush::Configuration do
42
44
  config.foreground = false
43
45
  config.foreground.should be_true
44
46
  end
47
+
48
+ it 'delegate redis_options to Modis' do
49
+ Rpush.config.redis_options = { hi: :mom }
50
+ Modis.redis_options.should eq(hi: :mom)
51
+ end
45
52
  end
@@ -1,15 +1,15 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Rpush::Daemon::Adm::Delivery do
4
- let(:app) { Rpush::Adm::App.new(:name => 'MyApp', :client_id => 'CLIENT_ID', :client_secret => 'CLIENT_SECRET') }
5
- let(:notification) { Rpush::Adm::Notification.create!(:app => app, :registration_ids => ['xyz'], :deliver_after => Time.now, :data => {'message' => 'test'}) }
6
- let(:logger) { double(:error => nil, :info => nil, :warn => nil) }
7
- let(:response) { double(:code => 200, :header => {}) }
8
- let(:http) { double(:shutdown => nil, :request => response)}
4
+ let(:app) { Rpush::Adm::App.create!(name: 'MyApp', client_id: 'CLIENT_ID', client_secret: 'CLIENT_SECRET') }
5
+ let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: ['xyz'], deliver_after: Time.now, data: { 'message' => 'test' }) }
6
+ let(:logger) { double(error: nil, info: nil, warn: nil) }
7
+ let(:response) { double(code: 200, header: {}) }
8
+ let(:http) { double(shutdown: nil, request: response) }
9
9
  let(:now) { Time.parse('2012-10-14 00:00:00') }
10
- let(:batch) { double(:mark_failed => nil, :mark_delivered => nil, :mark_retryable => nil) }
10
+ let(:batch) { double(mark_failed: nil, mark_delivered: nil, mark_retryable: nil, notification_processed: nil) }
11
11
  let(:delivery) { Rpush::Daemon::Adm::Delivery.new(app, http, notification, batch) }
12
- let(:store) { double(:create_adm_notification => double(:id => 2)) }
12
+ let(:store) { double(create_adm_notification: double(id: 2)) }
13
13
 
14
14
  def perform
15
15
  delivery.perform
@@ -19,44 +19,45 @@ describe Rpush::Daemon::Adm::Delivery do
19
19
  app.access_token = 'ACCESS_TOKEN'
20
20
  app.access_token_expiration = Time.now + 1.month
21
21
 
22
- delivery.stub(:reflect => nil)
23
- Rpush::Daemon.stub(:store => store)
24
- Time.stub(:now => now)
25
- Rpush.stub(:logger => logger)
22
+ delivery.stub(reflect: nil)
23
+ Rpush::Daemon.stub(store: store)
24
+ Time.stub(now: now)
25
+ Rpush.stub(logger: logger)
26
26
  end
27
27
 
28
28
  describe 'unknown error response' do
29
29
  before do
30
- response.stub(:code => 408)
30
+ response.stub(code: 408)
31
31
  end
32
32
 
33
33
  it 'marks the notification as failed because no successful delivery was made' do
34
- response.stub(:body => JSON.dump({ 'reason' => 'InvalidData' }))
35
- delivery.should_receive(:mark_failed).with(408, 'Request Timeout')
34
+ response.stub(body: JSON.dump('reason' => 'InvalidData'))
35
+ error = Rpush::DeliveryError.new(408, notification.id, 'Request Timeout')
36
+ delivery.should_receive(:mark_failed).with(error)
36
37
  expect { perform }.to raise_error(Rpush::DeliveryError)
37
38
  end
38
39
  end
39
40
 
40
41
  describe 'a 200 (Ok) response' do
41
42
  before do
42
- response.stub(:code => 200)
43
+ response.stub(code: 200)
43
44
  end
44
45
 
45
46
  it 'marks the notification as delivered if delivered successfully to all devices' do
46
- response.stub(:body => JSON.dump({ 'registrationID' => 'xyz' }))
47
+ response.stub(body: JSON.dump('registrationID' => 'xyz'))
47
48
  delivery.should_receive(:mark_delivered)
48
49
  perform
49
50
  end
50
51
 
51
52
  it 'logs that the notification was delivered' do
52
- response.stub(:body => JSON.dump({ 'registrationID' => 'xyz' }))
53
+ response.stub(body: JSON.dump('registrationID' => 'xyz'))
53
54
  logger.should_receive(:info).with("[MyApp] #{notification.id} sent to xyz")
54
55
  perform
55
56
  end
56
57
 
57
58
  it 'reflects on canonical IDs' do
58
- response.stub(:body => JSON.dump({'registrationID' => 'canonical123' }))
59
- notification.stub(:registration_ids => ['1'])
59
+ response.stub(body: JSON.dump('registrationID' => 'canonical123'))
60
+ notification.stub(registration_ids: ['1'])
60
61
  delivery.should_receive(:reflect).with(:adm_canonical_id, '1', 'canonical123')
61
62
  perform
62
63
  end
@@ -64,31 +65,40 @@ describe Rpush::Daemon::Adm::Delivery do
64
65
 
65
66
  describe 'a 400 (Bad Request) response' do
66
67
  before do
67
- response.stub(:code => 400)
68
+ response.stub(code: 400)
68
69
  end
69
70
 
70
71
  it 'marks the notification as failed because no successful delivery was made' do
71
- response.stub(:body => JSON.dump({ 'reason' => 'InvalidData' }))
72
- delivery.should_receive(:mark_failed).with(nil, 'Failed to deliver to all recipients.')
73
- expect { perform }.to raise_error(Rpush::DeliveryError)
72
+ response.stub(body: JSON.dump('reason' => 'InvalidData'))
73
+ error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients.')
74
+ delivery.should_receive(:mark_failed).with(error)
75
+ expect { perform }.to raise_error(error)
74
76
  end
75
77
 
76
78
  it 'logs that the notification was not delivered' do
77
- response.stub(:body => JSON.dump({ 'reason' => 'InvalidRegistrationId' }))
79
+ response.stub(body: JSON.dump('reason' => 'InvalidRegistrationId'))
78
80
  logger.should_receive(:warn).with("[MyApp] bad_request: xyz (InvalidRegistrationId)")
79
- expect { perform }.to raise_error(Rpush::DeliveryError)
81
+ expect { perform }.to raise_error
80
82
  end
83
+
84
+ it 'reflects' do
85
+ response.stub(body: JSON.dump('registrationID' => 'canonical123', 'reason' => 'Unregistered'))
86
+ notification.stub(registration_ids: ['1'])
87
+ delivery.should_receive(:reflect).with(:adm_failed_to_recipient, notification, '1', 'Unregistered')
88
+ expect { perform }.to raise_error
89
+ end
90
+
81
91
  end
82
92
 
83
93
  describe 'a 401 (Unauthorized) response' do
84
- let(:http) { double(:shutdown => nil)}
85
- let(:token_response) { double(:code => 200, :header => {}, :body => JSON.dump({'access_token' => 'ACCESS_TOKEN', 'expires_in' => 60})) }
94
+ let(:http) { double(shutdown: nil) }
95
+ let(:token_response) { double(code: 200, header: {}, body: JSON.dump('access_token' => 'ACCESS_TOKEN', 'expires_in' => 60)) }
86
96
 
87
97
  before do
88
- response.stub(:code => 401, :header => { 'retry-after' => 10 })
98
+ response.stub(code: 401, header: { 'retry-after' => 10 })
89
99
 
90
100
  # first request to deliver message that returns unauthorized response
91
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % [notification.registration_ids.first])
101
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
92
102
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
93
103
  end
94
104
 
@@ -116,7 +126,7 @@ describe Rpush::Daemon::Adm::Delivery do
116
126
  end
117
127
 
118
128
  it 'should log the error and stop retrying if new access token can\'t be retrieved' do
119
- token_response.stub(:code => 404, :body => "test")
129
+ token_response.stub(code: 404, body: "test")
120
130
  # request for access token
121
131
  http.should_receive(:request).with(Rpush::Daemon::Adm::Delivery::AMAZON_TOKEN_URI, instance_of(Net::HTTP::Post)).and_return(token_response)
122
132
 
@@ -130,15 +140,15 @@ describe Rpush::Daemon::Adm::Delivery do
130
140
  end
131
141
 
132
142
  describe 'a 429 (Too Many Request) response' do
133
- let(:http) { double(:shutdown => nil) }
134
- let(:notification) { Rpush::Adm::Notification.create!(:app => app, :registration_ids => ['abc','xyz'], :deliver_after => Time.now, :collapse_key => 'sync', :data => {'message' => 'test'}) }
135
- let(:too_many_request_response) { double(:code => 429, :header => { 'retry-after' => 3600 }) }
143
+ let(:http) { double(shutdown: nil) }
144
+ let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: %w(abc xyz), deliver_after: Time.now, collapse_key: 'sync', data: { 'message' => 'test' }) }
145
+ let(:rate_limited_response) { double(code: 429, header: { 'retry-after' => 3600 }) }
136
146
 
137
147
  it 'should retry the entire notification respecting the Retry-After header if none sent out yet' do
138
- response.stub(:code => 429, :header => { 'retry-after' => 3600 })
148
+ response.stub(code: 429, header: { 'retry-after' => 3600 })
139
149
 
140
150
  # first request to deliver message that returns too many request response
141
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % [notification.registration_ids.first])
151
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
142
152
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
143
153
 
144
154
  delivery.should_receive(:mark_retryable).with(notification, now + 1.hour)
@@ -146,36 +156,36 @@ describe Rpush::Daemon::Adm::Delivery do
146
156
  end
147
157
 
148
158
  it 'should retry the entire notification using exponential backoff' do
149
- response.stub(:code => 429, :header => {})
159
+ response.stub(code: 429, header: {})
150
160
 
151
161
  # first request to deliver message that returns too many request response
152
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % [notification.registration_ids.first])
162
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, notification.registration_ids.first))
153
163
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
154
164
 
155
- delivery.should_receive(:mark_retryable).with(notification, Time.now + 2 ** (notification.retries + 1))
165
+ delivery.should_receive(:mark_retryable).with(notification, Time.now + 2**(notification.retries + 1))
156
166
  perform
157
167
  end
158
168
 
159
169
  it 'should keep sent reg ids in original notification and create new notification with remaining reg ids for retry' do
160
- response.stub(:code => 200, :body => JSON.dump({ 'registrationID' => 'abc' }))
170
+ response.stub(code: 200, body: JSON.dump('registrationID' => 'abc'))
161
171
 
162
172
  # first request to deliver message succeeds
163
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % ['abc'])
173
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'abc'))
164
174
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
165
175
 
166
176
  # first request to deliver message that returns too many request response
167
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % ['xyz'])
168
- http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(too_many_request_response)
177
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'xyz'))
178
+ http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(rate_limited_response)
169
179
 
170
180
  store.should_receive(:update_notification).with do |notif|
171
181
  notif.registration_ids.include?('abc').should be_true
172
182
  notif.registration_ids.include?('xyz').should be_false
173
183
  end
174
184
 
175
- store.should_receive(:create_adm_notification).with do |attrs, notification_data, reg_ids, deliver_after, notification_app|
176
- attrs.has_key?('collapse_key').should be_true
177
- attrs.has_key?('delay_while_idle').should be_true
178
- attrs.has_key?('app_id').should be_true
185
+ store.should_receive(:create_adm_notification).with do |attrs, _notification_data, reg_ids, deliver_after, notification_app|
186
+ attrs.key?('collapse_key').should be_true
187
+ attrs.key?('delay_while_idle').should be_true
188
+ attrs.key?('app_id').should be_true
179
189
 
180
190
  reg_ids.should eq ['xyz']
181
191
  deliver_after.should eq now + 1.hour
@@ -190,11 +200,12 @@ describe Rpush::Daemon::Adm::Delivery do
190
200
 
191
201
  describe 'a 500 (Internal Server Error) response' do
192
202
  before do
193
- response.stub(:code => 500)
203
+ response.stub(code: 500)
194
204
  end
195
205
 
196
206
  it 'marks the notification as failed because no successful delivery was made' do
197
- delivery.should_receive(:mark_failed).with(nil, 'Failed to deliver to all recipients.')
207
+ error = Rpush::DeliveryError.new(nil, notification.id, 'Failed to deliver to all recipients.')
208
+ delivery.should_receive(:mark_failed).with(error)
198
209
  expect { perform }.to raise_error(Rpush::DeliveryError)
199
210
  end
200
211
 
@@ -206,7 +217,7 @@ describe Rpush::Daemon::Adm::Delivery do
206
217
 
207
218
  describe 'a 503 (Service Unavailable) response' do
208
219
  before do
209
- response.stub(:code => 503, :header => { 'retry-after' => 10 })
220
+ response.stub(code: 503, header: { 'retry-after' => 10 })
210
221
  end
211
222
 
212
223
  it 'should retry the notification respecting the Retry-After header' do
@@ -216,19 +227,19 @@ describe Rpush::Daemon::Adm::Delivery do
216
227
  end
217
228
 
218
229
  describe 'some registration ids succeeding and some failing' do
219
- let(:http) { double(:shutdown => nil) }
220
- let(:notification) { Rpush::Adm::Notification.create!(:app => app, :registration_ids => ['abc','xyz'], :deliver_after => Time.now, :collapse_key => 'sync', :data => {'message' => 'test'}) }
221
- let(:bad_request_response) { double(:code => 400, :body => JSON.dump({ 'reason' => 'InvalidData' })) }
230
+ let(:http) { double(shutdown: nil) }
231
+ let(:notification) { Rpush::Adm::Notification.create!(app: app, registration_ids: %w(abc xyz), deliver_after: Time.now, collapse_key: 'sync', data: { 'message' => 'test' }) }
232
+ let(:bad_request_response) { double(code: 400, body: JSON.dump('reason' => 'InvalidData')) }
222
233
 
223
234
  it 'should keep sent reg ids in original notification and create new notification with remaining reg ids for retry' do
224
- response.stub(:code => 200, :body => JSON.dump({ 'registrationID' => 'abc' }))
235
+ response.stub(code: 200, body: JSON.dump('registrationID' => 'abc'))
225
236
 
226
237
  # first request to deliver message succeeds
227
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % ['abc'])
238
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'abc'))
228
239
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(response)
229
240
 
230
241
  # first request to deliver message that returns too many request response
231
- adm_uri = URI.parse(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL % ['xyz'])
242
+ adm_uri = URI.parse(format(Rpush::Daemon::Adm::Delivery::AMAZON_ADM_URL, 'xyz'))
232
243
  http.should_receive(:request).with(adm_uri, instance_of(Net::HTTP::Post)).and_return(bad_request_response)
233
244
 
234
245
  store.should_receive(:update_notification).with do |notif|
@@ -1,8 +1,8 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
- describe Rpush::Apns::CertificateExpiredError do
4
- let(:app) { double(:name => 'test') }
5
- let(:error) { Rpush::Apns::CertificateExpiredError.new(app, Time.now) }
3
+ describe Rpush::CertificateExpiredError do
4
+ let(:app) { double(name: 'test') }
5
+ let(:error) { Rpush::CertificateExpiredError.new(app, Time.now) }
6
6
 
7
7
  it 'returns a message' do
8
8
  error.message
@@ -1,101 +1,108 @@
1
1
  require 'unit_spec_helper'
2
2
 
3
3
  describe Rpush::Daemon::Apns::Delivery do
4
- let(:app) { double(:name => 'MyApp') }
5
- let(:notification) { double.as_null_object }
6
- let(:batch) { double(:mark_failed => nil, :mark_delivered => nil) }
7
- let(:logger) { double(:error => nil, :info => nil) }
8
- let(:config) { double(:check_for_errors => true) }
9
- let(:connection) { double(:select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
10
- let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection, notification, batch) }
11
-
12
- def perform
13
- begin
14
- delivery.perform
15
- rescue Rpush::DeliveryError, Rpush::Apns::DisconnectionError
16
- end
17
- end
4
+ let(:app) { double(name: 'MyApp') }
5
+ let(:notification1) { double.as_null_object }
6
+ let(:notification2) { double.as_null_object }
7
+ let(:batch) { double(mark_all_failed: nil, mark_all_delivered: nil, all_processed: nil) }
8
+ let(:logger) { double(error: nil, info: nil) }
9
+ let(:connection) { double(select: false, write: nil, reconnect: nil, close: nil, connect: nil) }
10
+ let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection, batch) }
18
11
 
19
12
  before do
20
- Rpush.stub(:config => config, :logger => logger)
13
+ batch.stub(:each_notification) do |&blk|
14
+ [notification1, notification2].each(&blk)
15
+ end
16
+ Rpush.stub(logger: logger)
21
17
  end
22
18
 
23
- it "sends the binary version of the notification" do
24
- notification.stub(:to_binary => "hi mom")
25
- connection.should_receive(:write).with("hi mom")
26
- perform
19
+ it 'writes the binary batch' do
20
+ notification1.stub(to_binary: 'binary1')
21
+ notification2.stub(to_binary: 'binary2')
22
+ connection.should_receive(:write).with('binary1binary2')
23
+ delivery.perform
27
24
  end
28
25
 
29
- it "logs the notification delivery" do
30
- notification.stub(:id => 666, :device_token => 'abc123')
31
- logger.should_receive(:info).with("[MyApp] 666 sent to abc123")
32
- perform
26
+ it 'logs the notification deliveries' do
27
+ notification1.stub(id: 666, device_token: 'abc123')
28
+ notification2.stub(id: 42, device_token: 'abc456')
29
+ logger.should_receive(:info).with('[MyApp] 666 sent to abc123')
30
+ logger.should_receive(:info).with('[MyApp] 42 sent to abc456')
31
+ delivery.perform
33
32
  end
34
33
 
35
- it "marks the notification as delivered" do
36
- delivery.should_receive(:mark_delivered)
37
- perform
34
+ it 'marks all notifications as delivered' do
35
+ delivery.should_receive(:mark_batch_delivered)
36
+ delivery.perform
38
37
  end
39
38
 
40
- it 'does not check for errors if check_for_errors config option is false' do
41
- config.stub(:check_for_errors => false)
42
- delivery.should_not_receive(:check_for_error)
43
- perform
39
+ it 'notifies the batch all notifications have been processed' do
40
+ batch.should_receive(:all_processed)
41
+ delivery.perform
44
42
  end
45
43
 
46
- describe "when delivery fails" do
47
- before { connection.stub(:select => true, :read => [8, 4, 69].pack("ccN")) }
48
-
49
- it "marks the notification as failed" do
50
- delivery.should_receive(:mark_failed).with(4, "Missing payload")
51
- perform
52
- end
53
-
54
- it "logs the delivery error" do
55
- # checking for the doublebed error doesn't work in jruby, but checking
56
- # for the exception by class does.
57
-
58
- #error = Rpush::DeliveryError.new(4, 12, "Missing payload")
59
- #Rpush::DeliveryError.stub(:new => error)
60
- #expect { delivery.perform }.to raise_error(error)
61
-
62
- expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
63
- end
64
-
65
- it "reads 6 bytes from the socket" do
66
- connection.should_receive(:read).with(6).and_return(nil)
67
- perform
68
- end
69
-
70
- it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
71
- connection.stub(:select => nil)
72
- connection.should_not_receive(:read)
73
- perform
74
- end
75
-
76
- it "reconnects the socket" do
77
- connection.should_receive(:reconnect)
78
- perform
79
- end
80
-
81
- it "logs that the connection is being reconnected" do
82
- Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
83
- perform
84
- end
85
-
86
- context "when the APNs disconnects without returning an error" do
87
- before do
88
- connection.stub(:read => nil)
89
- end
90
-
91
- it 'raises a DisconnectError error if the connection is closed without an error being returned' do
92
- expect { delivery.perform }.to raise_error(Rpush::Apns::DisconnectionError)
93
- end
94
-
95
- it 'marks the notification as failed' do
96
- delivery.should_receive(:mark_failed).with(nil, "APNs disconnected without returning an error.")
97
- perform
98
- end
44
+ describe 'when an error is raised' do
45
+ it 'marks all notifications as failed' do
46
+ error = StandardError.new
47
+ connection.stub(:write).and_raise(error)
48
+ delivery.should_receive(:mark_batch_failed).with(error)
49
+ expect { delivery.perform }.to raise_error(error)
99
50
  end
100
51
  end
52
+
53
+ # describe "when delivery fails" do
54
+ # before { connection.stub(select: true, read: [8, 4, 69].pack("ccN")) }
55
+ #
56
+ # it "marks the notification as failed" do
57
+ # delivery.should_receive(:mark_failed).with(4, "Unable to deliver notification 69, received error 4 (Missing payload)")
58
+ # perform
59
+ # end
60
+ #
61
+ # it "logs the delivery error" do
62
+ # # checking for the doublebed error doesn't work in jruby, but checking
63
+ # # for the exception by class does.
64
+ #
65
+ # # error = Rpush::DeliveryError.new(4, 12, "Missing payload")
66
+ # # Rpush::DeliveryError.stub(new: error)
67
+ # # expect { delivery.perform }.to raise_error(error)
68
+ #
69
+ # expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
70
+ # end
71
+ #
72
+ # it "reads 6 bytes from the socket" do
73
+ # connection.should_receive(:read).with(6).and_return(nil)
74
+ # perform
75
+ # end
76
+ #
77
+ # it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
78
+ # connection.stub(select: nil)
79
+ # connection.should_not_receive(:read)
80
+ # perform
81
+ # end
82
+ #
83
+ # it "reconnects the socket" do
84
+ # connection.should_receive(:reconnect)
85
+ # perform
86
+ # end
87
+ #
88
+ # it "logs that the connection is being reconnected" do
89
+ # Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
90
+ # perform
91
+ # end
92
+ #
93
+ # context "when the APNs disconnects without returning an error" do
94
+ # before do
95
+ # connection.stub(read: nil)
96
+ # end
97
+ #
98
+ # it 'raises a DisconnectError error if the connection is closed without an error being returned' do
99
+ # expect { delivery.perform }.to raise_error(Rpush::DisconnectionError)
100
+ # end
101
+ #
102
+ # it 'marks the notification as failed' do
103
+ # delivery.should_receive(:mark_failed).with(nil, "The APNs disconnected without returning an error. This may indicate you are using an invalid certificate for the host.")
104
+ # perform
105
+ # end
106
+ # end
107
+ # end
101
108
  end