rpush 1.0.0 → 2.0.0.beta1

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