rpush 1.0.0-java → 2.0.0-java

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