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
data/lib/rpush/push.rb CHANGED
@@ -8,9 +8,8 @@ module Rpush
8
8
  Rpush.config.update(config)
9
9
 
10
10
  Rpush::Daemon.initialize_store
11
- Rpush::Daemon::AppRunner.sync
11
+ Rpush::Daemon::Synchronizer.sync
12
12
  Rpush::Daemon::Feeder.start
13
- Rpush::Daemon::AppRunner.wait
14
13
  Rpush::Daemon::AppRunner.stop
15
14
  end
16
15
  end
@@ -12,16 +12,14 @@ module Rpush
12
12
 
13
13
  REFLECTIONS = [
14
14
  :apns_feedback, :notification_enqueued, :notification_delivered,
15
- :notification_failed, :notification_will_retry, :apns_connection_lost,
16
- :gcm_delivered_to_recipient, :gcm_failed_to_recipient, :gcm_canonical_id,
17
- :gcm_invalid_registration_id, :error, :apns_certificate_will_expire,
18
- :adm_canonical_id, :tcp_connection_lost, :ssl_certificate_will_expire
15
+ :notification_failed, :notification_will_retry, :gcm_delivered_to_recipient,
16
+ :gcm_failed_to_recipient, :gcm_canonical_id, :gcm_invalid_registration_id,
17
+ :error, :adm_canonical_id, :adm_failed_to_recipient,
18
+ :tcp_connection_lost, :ssl_certificate_will_expire,
19
+ :notification_id_will_retry, :notification_id_failed
19
20
  ]
20
21
 
21
- DEPRECATIONS = {
22
- :apns_connection_lost => [:tcp_connection_lost, '4.1'],
23
- :apns_certificate_will_expire => [:ssl_certificate_will_expire, '4.1']
24
- }
22
+ DEPRECATIONS = {}
25
23
 
26
24
  REFLECTIONS.each do |reflection|
27
25
  class_eval(<<-RUBY, __FILE__, __LINE__)
@@ -36,7 +34,7 @@ module Rpush
36
34
  reflection = reflection.to_sym
37
35
 
38
36
  unless REFLECTIONS.include?(reflection)
39
- raise NoSuchReflectionError, reflection
37
+ fail NoSuchReflectionError, reflection
40
38
  end
41
39
 
42
40
  if DEPRECATIONS.key?(reflection)
@@ -44,9 +42,7 @@ module Rpush
44
42
  Rpush::Deprecation.warn("#{reflection} is deprecated and will be removed in version #{removal_version}. Use #{replacement} instead.")
45
43
  end
46
44
 
47
- if reflections[reflection]
48
- reflections[reflection].call(*args)
49
- end
45
+ reflections[reflection].call(*args) if reflections[reflection]
50
46
  end
51
47
 
52
48
  private
data/lib/rpush/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rpush
2
- VERSION = '1.0.0'
2
+ VERSION = '2.0.0'
3
3
  end
data/lib/rpush.rb CHANGED
@@ -1,13 +1,11 @@
1
- require 'active_record'
2
1
  require 'multi_json'
2
+ require 'active_support/all'
3
3
 
4
4
  module Rpush
5
5
  def self.attr_accessible_available?
6
6
  require 'rails'
7
- ::Rails::VERSION::STRING < '4'
7
+ ::Rails::VERSION::STRING < '4' || defined?(::ActiveRecord::MassAssignmentSecurity)
8
8
  end
9
-
10
- require 'rpush/railtie' if defined?(Rails)
11
9
  end
12
10
 
13
11
  require 'rpush/version'
@@ -15,33 +13,11 @@ require 'rpush/deprecation'
15
13
  require 'rpush/deprecatable'
16
14
  require 'rpush/logger'
17
15
  require 'rpush/multi_json_helper'
18
- require 'rpush/notification'
19
- require 'rpush/app'
20
16
  require 'rpush/configuration'
21
17
  require 'rpush/reflection'
22
18
  require 'rpush/embed'
23
19
  require 'rpush/push'
24
20
  require 'rpush/apns_feedback'
25
- require 'rpush/notifier'
26
- require 'rpush/payload_data_size_validator'
27
- require 'rpush/registration_ids_count_validator'
28
-
29
- require 'rpush/apns/binary_notification_validator'
30
- require 'rpush/apns/device_token_format_validator'
31
- require 'rpush/apns/notification'
32
- require 'rpush/apns/feedback'
33
- require 'rpush/apns/app'
34
-
35
- require 'rpush/gcm/expiry_collapse_key_mutual_inclusion_validator'
36
- require 'rpush/gcm/notification'
37
- require 'rpush/gcm/app'
38
-
39
- require 'rpush/wpns/notification'
40
- require 'rpush/wpns/app'
41
-
42
- require 'rpush/adm/data_validator'
43
- require 'rpush/adm/notification'
44
- require 'rpush/adm/app'
45
21
 
46
22
  module Rpush
47
23
  def self.jruby?
@@ -53,10 +29,10 @@ module Rpush
53
29
  end
54
30
 
55
31
  def self.logger
56
- @logger ||= Logger.new(:foreground => Rpush.config.foreground)
32
+ @logger ||= Logger.new
57
33
  end
58
34
 
59
- def self.logger=(logger)
60
- @logger = logger
35
+ class << self
36
+ attr_writer :logger
61
37
  end
62
38
  end
@@ -0,0 +1,35 @@
1
+ begin
2
+ require 'cane/rake_task'
3
+
4
+ desc 'Run cane to check quality metrics'
5
+ Cane::RakeTask.new(:cane_quality) do |cane|
6
+ cane.add_threshold 'coverage/covered_percent', :>=, 95
7
+ cane.no_style = false
8
+ cane.style_measure = 1000
9
+ cane.no_doc = true
10
+ cane.abc_max = 20
11
+ end
12
+
13
+ namespace :spec do
14
+ task cane: %w(spec cane_quality)
15
+ end
16
+ rescue LoadError
17
+ warn "cane not available."
18
+
19
+ namespace :spec do
20
+ task cane: ['spec']
21
+ end
22
+ end
23
+
24
+ begin
25
+ require 'rubocop/rake_task'
26
+ t = RuboCop::RakeTask.new
27
+ t.options << '-D'
28
+ rescue LoadError
29
+ warn 'rubocop not available.'
30
+ task rubocop: ['spec']
31
+ end
32
+
33
+ namespace :spec do
34
+ task quality: %w(cane rubocop)
35
+ end
data/lib/tasks/test.rake CHANGED
@@ -4,11 +4,7 @@ namespace :test do
4
4
 
5
5
  def cmd(str, clean_env = true)
6
6
  puts "* #{str}"
7
- retval = if clean_env
8
- Bundler.with_clean_env { `#{str}` }
9
- else
10
- `#{str}`
11
- end
7
+ retval = clean_env ? Bundler.with_clean_env { `#{str}` } : `#{str}`
12
8
  puts retval.strip
13
9
  retval
14
10
  end
data/spec/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ inherit_from: ../.rubocop.yml
2
+
3
+ RescueModifier:
4
+ Enabled: false
@@ -1,4 +1,4 @@
1
- require 'unit_spec_helper'
1
+ require 'functional_spec_helper'
2
2
 
3
3
  describe 'ADM' do
4
4
  let(:app) { Rpush::Adm::App.new }
@@ -17,14 +17,11 @@ describe 'ADM' do
17
17
  notification.data = { message: 'test' }
18
18
  notification.save!
19
19
 
20
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
21
- Rpush.config.logger = ::Logger.new(STDOUT)
22
-
23
20
  Net::HTTP::Persistent.stub(new: http)
24
21
  end
25
22
 
26
23
  it 'delivers a notification successfully' do
27
- response.stub(body: JSON.dump({registrationID: notification.registration_ids.first.to_s}))
24
+ response.stub(body: JSON.dump(registrationID: notification.registration_ids.first.to_s))
28
25
 
29
26
  expect do
30
27
  Rpush.push
@@ -33,7 +30,7 @@ describe 'ADM' do
33
30
  end
34
31
 
35
32
  it 'fails to deliver a notification successfully' do
36
- response.stub(code: 400, body: JSON.dump({reason: 'error', registrationID: notification.registration_ids.first.to_s}))
33
+ response.stub(code: 400, body: JSON.dump(reason: 'error', registrationID: notification.registration_ids.first.to_s))
37
34
 
38
35
  expect do
39
36
  Rpush.push
@@ -1,58 +1,151 @@
1
- require 'unit_spec_helper'
1
+ require 'functional_spec_helper'
2
2
 
3
3
  describe 'APNs' do
4
- let(:app) { Rpush::Apns::App.new }
5
- let(:notification) { Rpush::Apns::Notification.new }
4
+ let(:timeout) { 10 }
5
+ let(:app) { create_app }
6
+ let!(:notification) { create_notification }
6
7
  let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
7
- let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
8
- write: nil, flush: nil, read: nil, close: nil) }
8
+ let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
9
+ let(:io_double) { double(select: nil) }
9
10
 
10
11
  before do
12
+ stub_tcp_connection
13
+ end
14
+
15
+ def create_app
16
+ app = Rpush::Apns::App.new
11
17
  app.certificate = TEST_CERT
12
18
  app.name = 'test'
13
19
  app.environment = 'sandbox'
14
20
  app.save!
21
+ app
22
+ end
15
23
 
24
+ def create_notification
25
+ notification = Rpush::Apns::Notification.new
16
26
  notification.app = app
17
27
  notification.alert = 'test'
18
28
  notification.device_token = 'a' * 64
19
29
  notification.save!
30
+ notification
31
+ end
20
32
 
21
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
22
- Rpush.config.logger = ::Logger.new(STDOUT)
33
+ def stub_tcp_connection
34
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
35
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
36
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
37
+ end
23
38
 
24
- stub_tcp_connection
39
+ def wait_for_notification_to_deliver(notification)
40
+ Timeout.timeout(timeout) do
41
+ until notification.delivered
42
+ sleep 0.1
43
+ notification.reload
44
+ end
45
+ end
25
46
  end
26
47
 
27
- def stub_tcp_connection
28
- TCPSocket.stub(:new => tcp_socket)
29
- OpenSSL::SSL::SSLSocket.stub(:new => ssl_socket)
30
- IO.stub(:select => nil)
48
+ def wait_for_notification_to_fail(notification)
49
+ Timeout.timeout(timeout) do
50
+ while notification.delivered
51
+ sleep 0.1
52
+ notification.reload
53
+ end
54
+ end
31
55
  end
32
56
 
33
- it 'delivers a notification successfully' do
34
- expect do
35
- Rpush.push
36
- notification.reload
37
- end.to change(notification, :delivered).to(true)
57
+ def wait_for_notification_to_retry(notification)
58
+ Timeout.timeout(timeout) do
59
+ until !notification.delivered && !notification.failed && !notification.deliver_after.nil?
60
+ sleep 0.1
61
+ notification.reload
62
+ end
63
+ end
38
64
  end
39
65
 
40
- it 'fails to deliver a notification successfully' do
41
- IO.stub(:select => true)
42
- ssl_socket.stub(:read => [8, 4, 69].pack('ccN'))
66
+ def fail_notification(notification)
67
+ ssl_socket.stub(read: [8, 4, notification.id].pack('ccN'))
68
+ enable_io_select
69
+ end
43
70
 
71
+ def enable_io_select
72
+ called = false
73
+ io_double.stub(:select) do
74
+ if called
75
+ nil
76
+ else
77
+ called = true
78
+ end
79
+ end
80
+ end
81
+
82
+ it 'delivers a notification successfully' do
44
83
  expect do
45
84
  Rpush.push
46
85
  notification.reload
47
- end.to_not change(notification, :delivered).to(true)
86
+ end.to change(notification, :delivered).to(true)
48
87
  end
49
88
 
50
89
  it 'receives feedback' do
51
90
  tuple = "N\xE3\x84\r\x00 \x83OxfU\xEB\x9F\x84aJ\x05\xAD}\x00\xAF1\xE5\xCF\xE9:\xC3\xEA\a\x8F\x1D\xA4M*N\xB0\xCE\x17"
52
91
  allow(ssl_socket).to receive(:read).and_return(tuple, nil)
92
+ Rpush.apns_feedback
93
+ feedback = Rpush::Apns::Feedback.all.first
94
+ feedback.should_not be_nil
95
+ feedback.app_id.should eq(app.id)
96
+ feedback.device_token.should eq('834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17')
97
+ end
53
98
 
54
- expect do
55
- Rpush.apns_feedback
56
- end.to change(Rpush::Apns::Feedback, :count).to(1)
99
+ describe 'delivery failures' do
100
+ before { Rpush.embed }
101
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
102
+
103
+ it 'fails to deliver a notification' do
104
+ wait_for_notification_to_deliver(notification)
105
+ fail_notification(notification)
106
+ wait_for_notification_to_fail(notification)
107
+ end
108
+
109
+ describe 'with multiple notifications' do
110
+ let(:notification1) { create_notification }
111
+ let(:notification2) { create_notification }
112
+ let(:notification3) { create_notification }
113
+ let(:notification4) { create_notification }
114
+ let!(:notifications) { [notification1, notification2, notification3, notification4] }
115
+
116
+ it 'marks the correct notification as failed' do
117
+ notifications.each { |n| wait_for_notification_to_deliver(n) }
118
+ fail_notification(notification2)
119
+ wait_for_notification_to_fail(notification2)
120
+ end
121
+
122
+ it 'does not mark prior notifications as failed' do
123
+ notifications.each { |n| wait_for_notification_to_deliver(n) }
124
+ fail_notification(notification2)
125
+ sleep 1
126
+ notification1.reload
127
+ notification1.delivered.should be_true
128
+ end
129
+
130
+ it 'marks notifications following the failed one as retryable' do
131
+ Rpush.config.push_poll = 1_000_000
132
+
133
+ notifications.each { |n| wait_for_notification_to_deliver(n) }
134
+ fail_notification(notification2)
135
+
136
+ [notification3, notification4].each do |n|
137
+ wait_for_notification_to_retry(n)
138
+ end
139
+ end
140
+
141
+ describe 'without an error response' do
142
+ it 'marks all notifications as failed' do
143
+ notifications.each { |n| wait_for_notification_to_deliver(n) }
144
+ ssl_socket.stub(read: nil)
145
+ enable_io_select
146
+ notifications.each { |n| wait_for_notification_to_fail(n) }
147
+ end
148
+ end
149
+ end
57
150
  end
58
151
  end
@@ -1,11 +1,12 @@
1
- require 'unit_spec_helper'
1
+ require 'functional_spec_helper'
2
2
 
3
3
  describe 'embedding' do
4
+ let(:timeout) { 10 }
4
5
  let(:app) { Rpush::Apns::App.new }
5
6
  let(:notification) { Rpush::Apns::Notification.new }
6
7
  let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
7
- let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
8
- write: nil, flush: nil, read: nil, close: nil) }
8
+ let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
9
+ let(:io_double) { double(select: nil) }
9
10
 
10
11
  before do
11
12
  app.certificate = TEST_CERT
@@ -18,32 +19,31 @@ describe 'embedding' do
18
19
  notification.device_token = 'a' * 64
19
20
  notification.save!
20
21
 
21
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
22
- Rpush.config.logger = ::Logger.new(STDOUT)
23
-
24
22
  stub_tcp_connection
25
23
  end
26
24
 
27
25
  def stub_tcp_connection
28
- TCPSocket.stub(:new => tcp_socket)
29
- OpenSSL::SSL::SSLSocket.stub(:new => ssl_socket)
30
- IO.stub(:select => nil)
31
- Rpush::Daemon::Apns::FeedbackReceiver.stub(:new => double.as_null_object)
26
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
27
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
28
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
29
+ Rpush::Daemon::Apns::FeedbackReceiver.stub(new: double.as_null_object)
30
+ end
31
+
32
+ before do
33
+ Rpush.config.push_poll = 5
34
+ Rpush.embed
32
35
  end
33
36
 
34
37
  it 'delivers a notification successfully' do
35
38
  expect do
36
- ::ActiveRecord::Base.clear_all_connections!
37
-
38
- pid = fork do
39
- Rpush.embed
40
- sleep 0.5
41
- Rpush.shutdown
42
- Kernel.at_exit { exit! } # Don't run any at_exit hooks.
39
+ Timeout.timeout(timeout) do
40
+ until notification.delivered
41
+ notification.reload
42
+ sleep 0.1
43
+ end
43
44
  end
44
-
45
- Process.waitpid(pid)
46
- notification.reload
47
45
  end.to change(notification, :delivered).to(true)
48
46
  end
47
+
48
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
49
49
  end
@@ -1,4 +1,4 @@
1
- require 'unit_spec_helper'
1
+ require 'functional_spec_helper'
2
2
 
3
3
  describe 'GCM' do
4
4
  let(:app) { Rpush::Gcm::App.new }
@@ -11,19 +11,16 @@ describe 'GCM' do
11
11
  app.auth_key = 'abc123'
12
12
  app.save!
13
13
 
14
- notification.app = app
14
+ notification.app_id = app.id
15
15
  notification.registration_ids = ['foo']
16
16
  notification.data = { message: 'test' }
17
17
  notification.save!
18
18
 
19
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
20
- Rpush.config.logger = ::Logger.new(STDOUT)
21
-
22
19
  Net::HTTP::Persistent.stub(new: http)
23
20
  end
24
21
 
25
22
  it 'delivers a notification successfully' do
26
- response.stub(body: JSON.dump({results: [{message_id: notification.registration_ids.first.to_s}]}))
23
+ response.stub(body: JSON.dump(results: [{ message_id: notification.registration_ids.first.to_s }]))
27
24
 
28
25
  expect do
29
26
  Rpush.push
@@ -32,7 +29,7 @@ describe 'GCM' do
32
29
  end
33
30
 
34
31
  it 'fails to deliver a notification successfully' do
35
- response.stub(body: JSON.dump({results: [{error: 'Err'}]}))
32
+ response.stub(body: JSON.dump(results: [{ error: 'Err' }]))
36
33
 
37
34
  expect do
38
35
  Rpush.push
@@ -0,0 +1,59 @@
1
+ require 'functional_spec_helper'
2
+
3
+ describe 'New app loading' do
4
+ let(:timeout) { 10 }
5
+ let(:app) { create_app }
6
+ let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
7
+ let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
8
+ let(:io_double) { double(select: nil) }
9
+
10
+ before do
11
+ stub_tcp_connection
12
+ end
13
+
14
+ def create_app
15
+ app = Rpush::Apns::App.new
16
+ app.certificate = TEST_CERT
17
+ app.name = 'test'
18
+ app.environment = 'sandbox'
19
+ app.save!
20
+ app
21
+ end
22
+
23
+ def create_notification
24
+ notification = Rpush::Apns::Notification.new
25
+ notification.app = app
26
+ notification.alert = 'test'
27
+ notification.device_token = 'a' * 64
28
+ notification.save!
29
+ notification
30
+ end
31
+
32
+ def stub_tcp_connection
33
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
34
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
35
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
36
+ end
37
+
38
+ def wait_for_notification_to_deliver(notification)
39
+ Timeout.timeout(timeout) do
40
+ until notification.delivered
41
+ sleep 0.1
42
+ notification.reload
43
+ end
44
+ end
45
+ end
46
+
47
+ before do
48
+ Rpush.config.push_poll = 0
49
+ Rpush.embed
50
+ end
51
+
52
+ it 'delivers a notification successfully' do
53
+ sleep 1 # TODO: Need a better way to detect when the Feeder is running.
54
+ notification = create_notification
55
+ wait_for_notification_to_deliver(notification)
56
+ end
57
+
58
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
59
+ end
@@ -0,0 +1,46 @@
1
+ require 'functional_spec_helper'
2
+
3
+ describe 'Retries' do
4
+ let(:app) { Rpush::Gcm::App.new }
5
+ let(:notification) { Rpush::Gcm::Notification.new }
6
+ let(:response) { double(Net::HTTPResponse, code: 200) }
7
+ let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
8
+
9
+ before do
10
+ Rpush::Daemon.initialize_store
11
+
12
+ app.name = 'test'
13
+ app.auth_key = 'abc123'
14
+ app.save!
15
+
16
+ notification.app_id = app.id
17
+ notification.registration_ids = ['foo']
18
+ notification.data = { message: 'test' }
19
+ notification.save!
20
+
21
+ Modis.with_connection do |redis|
22
+ redis.del(Rpush::Client::Redis::Notification.absolute_pending_namespace)
23
+ end
24
+
25
+ Net::HTTP::Persistent.stub(new: http)
26
+ response.stub(body: JSON.dump(results: [{ message_id: notification.registration_ids.first.to_s }]))
27
+ end
28
+
29
+ it 'delivers a notification due to be retried' do
30
+ Rpush::Daemon.store.mark_retryable(notification, Time.now - 1.minute)
31
+
32
+ expect do
33
+ Rpush.push
34
+ notification.reload
35
+ end.to change(notification, :delivered).to(true)
36
+ end
37
+
38
+ it 'does not deliver a notification not due to be retried' do
39
+ Rpush::Daemon.store.mark_retryable(notification, Time.now + 1.minute)
40
+
41
+ expect do
42
+ Rpush.push
43
+ notification.reload
44
+ end.to_not change(notification, :delivered).to(true)
45
+ end
46
+ end
@@ -0,0 +1,68 @@
1
+ require 'functional_spec_helper'
2
+
3
+ describe 'Synchronization' do
4
+ let(:timeout) { 10 }
5
+ let(:app) { Rpush::Gcm::App.new }
6
+
7
+ def wait_for_num_dispatchers(num)
8
+ Timeout.timeout(timeout) do
9
+ until Rpush::Daemon::AppRunner.num_dispatchers_for_app(app) == num
10
+ sleep 0.1
11
+ end
12
+ end
13
+ end
14
+
15
+ before do
16
+ app.name = 'test'
17
+ app.auth_key = 'abc123'
18
+ app.connections = 2
19
+ app.certificate = TEST_CERT_WITH_PASSWORD
20
+ app.password = 'fubar'
21
+ app.environment = 'sandbox'
22
+ app.save!
23
+
24
+ Rpush.embed
25
+ wait_for_num_dispatchers(app.connections)
26
+ end
27
+
28
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
29
+
30
+ it 'increments the number of dispatchers' do
31
+ app.connections += 1
32
+ app.save!
33
+ Rpush.sync
34
+ wait_for_num_dispatchers(app.connections)
35
+ end
36
+
37
+ it 'decrements the number of dispatchers' do
38
+ app.connections -= 1
39
+ app.save!
40
+ Rpush.sync
41
+ wait_for_num_dispatchers(app.connections)
42
+ end
43
+
44
+ it 'stops a deleted app' do
45
+ app.destroy
46
+ Rpush.sync
47
+ Rpush::Daemon::AppRunner.app_running?(app).should be_false
48
+ end
49
+
50
+ it 'restarts an app when the certificate is changed' do
51
+ app.certificate = TEST_CERT
52
+ app.password = nil
53
+ app.save!
54
+ Rpush.sync
55
+
56
+ running_app = Rpush::Daemon::AppRunner.app_with_id(app.id)
57
+ expect(running_app.certificate).to eql(TEST_CERT)
58
+ end
59
+
60
+ it 'restarts an app when the environment is changed' do
61
+ app.environment = 'production'
62
+ app.save!
63
+ Rpush.sync
64
+
65
+ running_app = Rpush::Daemon::AppRunner.app_with_id(app.id)
66
+ expect(running_app.environment).to eql('production')
67
+ end
68
+ end