rpush 1.0.0 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +12 -14
  4. data/bin/rpush +11 -2
  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 +10 -7
  17. data/lib/generators/templates/rpush_2_0_0_updates.rb +23 -0
  18. data/lib/rpush.rb +4 -28
  19. data/lib/rpush/client/active_model.rb +21 -0
  20. data/lib/rpush/client/active_model/adm/app.rb +23 -0
  21. data/lib/rpush/client/active_model/adm/data_validator.rb +14 -0
  22. data/lib/rpush/client/active_model/adm/notification.rb +28 -0
  23. data/lib/rpush/client/active_model/apns/app.rb +37 -0
  24. data/lib/rpush/client/active_model/apns/binary_notification_validator.rb +16 -0
  25. data/lib/rpush/client/active_model/apns/device_token_format_validator.rb +14 -0
  26. data/lib/rpush/client/active_model/apns/notification.rb +90 -0
  27. data/lib/rpush/client/active_model/gcm/app.rb +19 -0
  28. data/lib/rpush/client/active_model/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +14 -0
  29. data/lib/rpush/client/active_model/gcm/notification.rb +31 -0
  30. data/lib/rpush/client/active_model/notification.rb +26 -0
  31. data/lib/rpush/client/active_model/payload_data_size_validator.rb +13 -0
  32. data/lib/rpush/client/active_model/registration_ids_count_validator.rb +13 -0
  33. data/lib/rpush/client/active_model/wpns/app.rb +13 -0
  34. data/lib/rpush/client/active_model/wpns/notification.rb +17 -0
  35. data/lib/rpush/client/active_record.rb +19 -0
  36. data/lib/rpush/client/active_record/adm/app.rb +11 -0
  37. data/lib/rpush/client/active_record/adm/notification.rb +11 -0
  38. data/lib/rpush/client/active_record/apns/app.rb +11 -0
  39. data/lib/rpush/client/active_record/apns/feedback.rb +20 -0
  40. data/lib/rpush/client/active_record/apns/notification.rb +46 -0
  41. data/lib/rpush/client/active_record/app.rb +17 -0
  42. data/lib/rpush/client/active_record/gcm/app.rb +11 -0
  43. data/lib/rpush/client/active_record/gcm/notification.rb +11 -0
  44. data/lib/rpush/client/active_record/notification.rb +38 -0
  45. data/lib/rpush/client/active_record/wpns/app.rb +11 -0
  46. data/lib/rpush/client/active_record/wpns/notification.rb +11 -0
  47. data/lib/rpush/client/redis.rb +35 -0
  48. data/lib/rpush/client/redis/adm/app.rb +14 -0
  49. data/lib/rpush/client/redis/adm/notification.rb +11 -0
  50. data/lib/rpush/client/redis/apns/app.rb +11 -0
  51. data/lib/rpush/client/redis/apns/feedback.rb +20 -0
  52. data/lib/rpush/client/redis/apns/notification.rb +11 -0
  53. data/lib/rpush/client/redis/app.rb +22 -0
  54. data/lib/rpush/client/redis/gcm/app.rb +11 -0
  55. data/lib/rpush/client/redis/gcm/notification.rb +11 -0
  56. data/lib/rpush/client/redis/notification.rb +68 -0
  57. data/lib/rpush/client/redis/wpns/app.rb +11 -0
  58. data/lib/rpush/client/redis/wpns/notification.rb +11 -0
  59. data/lib/rpush/configuration.rb +27 -6
  60. data/lib/rpush/daemon.rb +36 -56
  61. data/lib/rpush/daemon/adm/delivery.rb +50 -52
  62. data/lib/rpush/daemon/apns.rb +6 -5
  63. data/lib/rpush/daemon/apns/delivery.rb +20 -44
  64. data/lib/rpush/daemon/apns/feedback_receiver.rb +11 -8
  65. data/lib/rpush/daemon/app_runner.rb +67 -60
  66. data/lib/rpush/daemon/batch.rb +54 -40
  67. data/lib/rpush/daemon/delivery.rb +13 -3
  68. data/lib/rpush/daemon/delivery_error.rb +10 -2
  69. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +106 -0
  70. data/lib/rpush/daemon/dispatcher/http.rb +3 -3
  71. data/lib/rpush/daemon/dispatcher/tcp.rb +3 -3
  72. data/lib/rpush/daemon/dispatcher_loop.rb +15 -6
  73. data/lib/rpush/daemon/errors.rb +18 -0
  74. data/lib/rpush/daemon/feeder.rb +28 -39
  75. data/lib/rpush/daemon/gcm/delivery.rb +19 -20
  76. data/lib/rpush/daemon/interruptible_sleep.rb +26 -45
  77. data/lib/rpush/daemon/loggable.rb +2 -4
  78. data/lib/rpush/daemon/proc_title.rb +16 -0
  79. data/lib/rpush/daemon/queue_payload.rb +12 -0
  80. data/lib/rpush/daemon/reflectable.rb +3 -5
  81. data/lib/rpush/daemon/retry_header_parser.rb +6 -6
  82. data/lib/rpush/daemon/ring_buffer.rb +16 -0
  83. data/lib/rpush/daemon/service_config_methods.rb +23 -7
  84. data/lib/rpush/daemon/signal_handler.rb +51 -0
  85. data/lib/rpush/daemon/store/active_record.rb +71 -38
  86. data/lib/rpush/daemon/store/active_record/reconnectable.rb +15 -15
  87. data/lib/rpush/daemon/store/interface.rb +19 -0
  88. data/lib/rpush/daemon/store/redis.rb +149 -0
  89. data/lib/rpush/daemon/tcp_connection.rb +6 -11
  90. data/lib/rpush/daemon/wpns/delivery.rb +21 -30
  91. data/lib/rpush/deprecatable.rb +4 -3
  92. data/lib/rpush/deprecation.rb +7 -10
  93. data/lib/rpush/embed.rb +7 -2
  94. data/lib/rpush/logger.rb +11 -15
  95. data/lib/rpush/push.rb +0 -1
  96. data/lib/rpush/reflection.rb +6 -12
  97. data/lib/rpush/version.rb +1 -1
  98. data/lib/tasks/quality.rake +34 -0
  99. data/spec/.rubocop.yml +4 -0
  100. data/spec/functional/adm_spec.rb +3 -6
  101. data/spec/functional/apns_spec.rb +118 -24
  102. data/spec/functional/embed_spec.rb +22 -20
  103. data/spec/functional/gcm_spec.rb +4 -7
  104. data/spec/functional/new_app_spec.rb +61 -0
  105. data/spec/functional/retry_spec.rb +46 -0
  106. data/spec/functional/wpns_spec.rb +3 -6
  107. data/spec/functional_spec_helper.rb +26 -0
  108. data/spec/integration/rpush_spec.rb +13 -0
  109. data/spec/integration/support/gcm_success_response.json +1 -0
  110. data/spec/spec_helper.rb +60 -0
  111. data/spec/support/active_record_setup.rb +48 -0
  112. data/{config → spec/support/config}/database.yml +0 -0
  113. data/spec/support/install.sh +43 -7
  114. data/spec/support/simplecov_helper.rb +9 -5
  115. data/spec/support/simplecov_quality_formatter.rb +10 -6
  116. data/spec/unit/apns_feedback_spec.rb +3 -3
  117. data/spec/unit/{adm → client/active_record/adm}/app_spec.rb +3 -3
  118. data/spec/unit/{adm → client/active_record/adm}/notification_spec.rb +5 -7
  119. data/spec/unit/client/active_record/apns/app_spec.rb +29 -0
  120. data/spec/unit/client/active_record/apns/feedback_spec.rb +9 -0
  121. data/spec/unit/client/active_record/apns/notification_spec.rb +231 -0
  122. data/spec/unit/client/active_record/app_spec.rb +30 -0
  123. data/spec/unit/client/active_record/gcm/app_spec.rb +4 -0
  124. data/spec/unit/{gcm → client/active_record/gcm}/notification_spec.rb +5 -7
  125. data/spec/unit/client/active_record/notification_spec.rb +15 -0
  126. data/spec/unit/client/active_record/wpns/app_spec.rb +4 -0
  127. data/spec/unit/client/active_record/wpns/notification_spec.rb +21 -0
  128. data/spec/unit/configuration_spec.rb +12 -5
  129. data/spec/unit/daemon/adm/delivery_spec.rb +57 -54
  130. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +3 -3
  131. data/spec/unit/daemon/apns/delivery_spec.rb +90 -83
  132. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +24 -17
  133. data/spec/unit/daemon/app_runner_spec.rb +66 -123
  134. data/spec/unit/daemon/batch_spec.rb +52 -115
  135. data/spec/unit/daemon/delivery_spec.rb +15 -1
  136. data/spec/unit/daemon/dispatcher/http_spec.rb +3 -2
  137. data/spec/unit/daemon/dispatcher/tcp_spec.rb +10 -9
  138. data/spec/unit/daemon/dispatcher_loop_spec.rb +7 -12
  139. data/spec/unit/daemon/feeder_spec.rb +40 -39
  140. data/spec/unit/daemon/gcm/delivery_spec.rb +108 -89
  141. data/spec/unit/daemon/reflectable_spec.rb +2 -2
  142. data/spec/unit/daemon/retryable_error_spec.rb +1 -1
  143. data/spec/unit/daemon/service_config_methods_spec.rb +6 -3
  144. data/spec/unit/daemon/signal_handler_spec.rb +72 -0
  145. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +9 -9
  146. data/spec/unit/daemon/store/active_record_spec.rb +38 -47
  147. data/spec/unit/daemon/tcp_connection_spec.rb +22 -34
  148. data/spec/unit/daemon/too_many_requests_error_spec.rb +1 -1
  149. data/spec/unit/daemon/wpns/delivery_spec.rb +61 -50
  150. data/spec/unit/daemon_spec.rb +46 -81
  151. data/spec/unit/embed_spec.rb +4 -2
  152. data/spec/unit/logger_spec.rb +30 -40
  153. data/spec/unit/notification_shared.rb +9 -79
  154. data/spec/unit/push_spec.rb +3 -8
  155. data/spec/unit/reflection_spec.rb +25 -25
  156. data/spec/unit/rpush_spec.rb +1 -2
  157. data/spec/unit_spec_helper.rb +33 -88
  158. metadata +119 -67
  159. data/lib/rpush/TODO +0 -3
  160. data/lib/rpush/adm/app.rb +0 -15
  161. data/lib/rpush/adm/data_validator.rb +0 -11
  162. data/lib/rpush/adm/notification.rb +0 -29
  163. data/lib/rpush/apns/app.rb +0 -29
  164. data/lib/rpush/apns/binary_notification_validator.rb +0 -12
  165. data/lib/rpush/apns/device_token_format_validator.rb +0 -12
  166. data/lib/rpush/apns/feedback.rb +0 -16
  167. data/lib/rpush/apns/notification.rb +0 -84
  168. data/lib/rpush/app.rb +0 -18
  169. data/lib/rpush/daemon/apns/certificate_expired_error.rb +0 -20
  170. data/lib/rpush/daemon/apns/disconnection_error.rb +0 -20
  171. data/lib/rpush/gcm/app.rb +0 -11
  172. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +0 -11
  173. data/lib/rpush/gcm/notification.rb +0 -30
  174. data/lib/rpush/notification.rb +0 -69
  175. data/lib/rpush/notifier.rb +0 -52
  176. data/lib/rpush/payload_data_size_validator.rb +0 -10
  177. data/lib/rpush/railtie.rb +0 -11
  178. data/lib/rpush/registration_ids_count_validator.rb +0 -10
  179. data/lib/rpush/wpns/app.rb +0 -9
  180. data/lib/rpush/wpns/notification.rb +0 -26
  181. data/lib/tasks/cane.rake +0 -18
  182. data/lib/tasks/rpush.rake +0 -16
  183. data/spec/unit/apns/app_spec.rb +0 -29
  184. data/spec/unit/apns/feedback_spec.rb +0 -9
  185. data/spec/unit/apns/notification_spec.rb +0 -208
  186. data/spec/unit/app_spec.rb +0 -30
  187. data/spec/unit/daemon/apns/disconnection_error_spec.rb +0 -18
  188. data/spec/unit/daemon/interruptible_sleep_spec.rb +0 -68
  189. data/spec/unit/gcm/app_spec.rb +0 -4
  190. data/spec/unit/notification_spec.rb +0 -15
  191. data/spec/unit/notifier_spec.rb +0 -49
  192. data/spec/unit/wpns/app_spec.rb +0 -4
  193. data/spec/unit/wpns/notification_spec.rb +0 -30
@@ -1,19 +1,15 @@
1
1
  module Rpush
2
2
  class Logger
3
- def initialize(options)
4
- @options = options
5
-
6
- begin
7
- log_dir = File.join(Rails.root, 'log')
8
- FileUtils.mkdir_p(log_dir)
9
- log = File.open(File.join(log_dir, 'rpush.log'), 'a')
10
- log.sync = true
11
- setup_logger(log)
12
- rescue Errno::ENOENT, Errno::EPERM => e
13
- @logger = nil
14
- error(e)
15
- error('Logging disabled.')
16
- end
3
+ def initialize
4
+ log_dir = File.join(Rpush.config.log_dir, 'log')
5
+ FileUtils.mkdir_p(log_dir)
6
+ log = File.open(File.join(log_dir, 'rpush.log'), 'a')
7
+ log.sync = true
8
+ setup_logger(log)
9
+ rescue Errno::ENOENT, Errno::EPERM => e
10
+ @logger = nil
11
+ error(e)
12
+ error('Logging disabled.')
17
13
  end
18
14
 
19
15
  def info(msg)
@@ -53,7 +49,7 @@ module Rpush
53
49
 
54
50
  if io == STDERR
55
51
  io.puts formatted_msg
56
- elsif @options[:foreground]
52
+ elsif Rpush.config.foreground
57
53
  io.puts formatted_msg
58
54
  end
59
55
 
@@ -10,7 +10,6 @@ module Rpush
10
10
  Rpush::Daemon.initialize_store
11
11
  Rpush::Daemon::AppRunner.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,12 @@ 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, :tcp_connection_lost, :ssl_certificate_will_expire
19
18
  ]
20
19
 
21
- DEPRECATIONS = {
22
- :apns_connection_lost => [:tcp_connection_lost, '4.1'],
23
- :apns_certificate_will_expire => [:ssl_certificate_will_expire, '4.1']
24
- }
20
+ DEPRECATIONS = {}
25
21
 
26
22
  REFLECTIONS.each do |reflection|
27
23
  class_eval(<<-RUBY, __FILE__, __LINE__)
@@ -36,7 +32,7 @@ module Rpush
36
32
  reflection = reflection.to_sym
37
33
 
38
34
  unless REFLECTIONS.include?(reflection)
39
- raise NoSuchReflectionError, reflection
35
+ fail NoSuchReflectionError, reflection
40
36
  end
41
37
 
42
38
  if DEPRECATIONS.key?(reflection)
@@ -44,9 +40,7 @@ module Rpush
44
40
  Rpush::Deprecation.warn("#{reflection} is deprecated and will be removed in version #{removal_version}. Use #{replacement} instead.")
45
41
  end
46
42
 
47
- if reflections[reflection]
48
- reflections[reflection].call(*args)
49
- end
43
+ reflections[reflection].call(*args) if reflections[reflection]
50
44
  end
51
45
 
52
46
  private
@@ -1,3 +1,3 @@
1
1
  module Rpush
2
- VERSION = '1.0.0'
2
+ VERSION = '2.0.0.beta1'
3
3
  end
@@ -0,0 +1,34 @@
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 => ['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
+ RuboCop::RakeTask.new
27
+ rescue LoadError
28
+ warn 'rubocop not available.'
29
+ task :rubocop => ['spec']
30
+ end
31
+
32
+ namespace :spec do
33
+ task quality: ['cane', 'rubocop']
34
+ end
@@ -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,152 @@
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) do double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
9
+ write: nil, flush: nil, read: nil, close: nil)
10
+ end
11
+ let(:io_double) { double(select: nil) }
9
12
 
10
13
  before do
14
+ stub_tcp_connection
15
+ end
16
+
17
+ def create_app
18
+ app = Rpush::Apns::App.new
11
19
  app.certificate = TEST_CERT
12
20
  app.name = 'test'
13
21
  app.environment = 'sandbox'
14
22
  app.save!
23
+ app
24
+ end
15
25
 
26
+ def create_notification
27
+ notification = Rpush::Apns::Notification.new
16
28
  notification.app = app
17
29
  notification.alert = 'test'
18
30
  notification.device_token = 'a' * 64
19
31
  notification.save!
32
+ notification
33
+ end
20
34
 
21
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
22
- Rpush.config.logger = ::Logger.new(STDOUT)
35
+ def stub_tcp_connection
36
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
37
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
38
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
39
+ end
23
40
 
24
- stub_tcp_connection
41
+ def wait_for_notification_to_deliver(notification)
42
+ Timeout.timeout(timeout) do
43
+ until notification.delivered
44
+ sleep 0.1
45
+ notification.reload
46
+ end
47
+ end
25
48
  end
26
49
 
27
- def stub_tcp_connection
28
- TCPSocket.stub(:new => tcp_socket)
29
- OpenSSL::SSL::SSLSocket.stub(:new => ssl_socket)
30
- IO.stub(:select => nil)
50
+ def wait_for_notification_to_fail(notification)
51
+ Timeout.timeout(timeout) do
52
+ while notification.delivered
53
+ sleep 0.1
54
+ notification.reload
55
+ end
56
+ end
31
57
  end
32
58
 
33
- it 'delivers a notification successfully' do
34
- expect do
35
- Rpush.push
36
- notification.reload
37
- end.to change(notification, :delivered).to(true)
59
+ def wait_for_notification_to_retry(notification)
60
+ Timeout.timeout(timeout) do
61
+ until !notification.delivered && !notification.failed && !notification.deliver_after.nil?
62
+ sleep 0.1
63
+ notification.reload
64
+ end
65
+ end
66
+ end
67
+
68
+ def fail_notification(notification)
69
+ ssl_socket.stub(read: [8, 4, notification.id].pack('ccN'))
70
+ enable_io_select
38
71
  end
39
72
 
40
- it 'fails to deliver a notification successfully' do
41
- IO.stub(:select => true)
42
- ssl_socket.stub(:read => [8, 4, 69].pack('ccN'))
73
+ def enable_io_select
74
+ called = false
75
+ io_double.stub(:select) do
76
+ if called
77
+ nil
78
+ else
79
+ called = true
80
+ end
81
+ end
82
+ end
43
83
 
84
+ it 'delivers a notification successfully' do
44
85
  expect do
45
86
  Rpush.push
46
87
  notification.reload
47
- end.to_not change(notification, :delivered).to(true)
88
+ end.to change(notification, :delivered).to(true)
48
89
  end
49
90
 
50
91
  it 'receives feedback' do
51
92
  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
93
  allow(ssl_socket).to receive(:read).and_return(tuple, nil)
94
+ Rpush.apns_feedback
95
+ feedback = Rpush::Apns::Feedback.all
96
+ feedback.should_not be_empty
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
+ # # Such hacks. Set the poll frequency high enough that we'll only ever feed once.
132
+ # Rpush.config.push_poll = 1_000_000
133
+ #
134
+ # notifications.each { |n| wait_for_notification_to_deliver(n) }
135
+ # fail_notification(notification2)
136
+ #
137
+ # [notification3, notification4].each do |n|
138
+ # wait_for_notification_to_retry(n)
139
+ # end
140
+ # end
141
+
142
+ describe 'without an error response' do
143
+ it 'marks all notifications as failed' do
144
+ notifications.each { |n| wait_for_notification_to_deliver(n) }
145
+ ssl_socket.stub(read: nil)
146
+ enable_io_select
147
+ notifications.each { |n| wait_for_notification_to_fail(n) }
148
+ end
149
+ end
150
+ end
57
151
  end
58
152
  end
@@ -1,11 +1,14 @@
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) do double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
9
+ write: nil, flush: nil, read: nil, close: nil)
10
+ end
11
+ let(:io_double) { double(select: nil) }
9
12
 
10
13
  before do
11
14
  app.certificate = TEST_CERT
@@ -18,32 +21,31 @@ describe 'embedding' do
18
21
  notification.device_token = 'a' * 64
19
22
  notification.save!
20
23
 
21
- Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
22
- Rpush.config.logger = ::Logger.new(STDOUT)
23
-
24
24
  stub_tcp_connection
25
25
  end
26
26
 
27
27
  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)
28
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
29
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
30
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
31
+ Rpush::Daemon::Apns::FeedbackReceiver.stub(new: double.as_null_object)
32
+ end
33
+
34
+ before do
35
+ Rpush.config.push_poll = 5
36
+ Rpush.embed
32
37
  end
33
38
 
34
39
  it 'delivers a notification successfully' do
35
40
  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.
41
+ Timeout.timeout(timeout) do
42
+ until notification.delivered
43
+ notification.reload
44
+ sleep 0.1
45
+ end
43
46
  end
44
-
45
- Process.waitpid(pid)
46
- notification.reload
47
47
  end.to change(notification, :delivered).to(true)
48
48
  end
49
+
50
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
49
51
  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,61 @@
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) do double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
8
+ write: nil, flush: nil, read: nil, close: nil)
9
+ end
10
+ let(:io_double) { double(select: nil) }
11
+
12
+ before do
13
+ stub_tcp_connection
14
+ end
15
+
16
+ def create_app
17
+ app = Rpush::Apns::App.new
18
+ app.certificate = TEST_CERT
19
+ app.name = 'test'
20
+ app.environment = 'sandbox'
21
+ app.save!
22
+ app
23
+ end
24
+
25
+ def create_notification
26
+ notification = Rpush::Apns::Notification.new
27
+ notification.app = app
28
+ notification.alert = 'test'
29
+ notification.device_token = 'a' * 64
30
+ notification.save!
31
+ notification
32
+ end
33
+
34
+ def stub_tcp_connection
35
+ Rpush::Daemon::TcpConnection.any_instance.stub(connect_socket: [tcp_socket, ssl_socket])
36
+ Rpush::Daemon::TcpConnection.any_instance.stub(setup_ssl_context: double.as_null_object)
37
+ stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
38
+ end
39
+
40
+ def wait_for_notification_to_deliver(notification)
41
+ Timeout.timeout(timeout) do
42
+ until notification.delivered
43
+ sleep 0.1
44
+ notification.reload
45
+ end
46
+ end
47
+ end
48
+
49
+ before do
50
+ Rpush.config.push_poll = 0
51
+ Rpush.embed
52
+ end
53
+
54
+ it 'delivers a notification successfully' do
55
+ sleep 1 # TODO: Need a better way to detect when the Feeder is running.
56
+ notification = create_notification
57
+ wait_for_notification_to_deliver(notification)
58
+ end
59
+
60
+ after { Timeout.timeout(timeout) { Rpush.shutdown } }
61
+ end