rpush 7.0.1 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -4
  3. data/README.md +24 -44
  4. data/lib/generators/rpush_migration_generator.rb +1 -0
  5. data/lib/generators/templates/rpush.rb +23 -13
  6. data/lib/generators/templates/rpush_7_1_0_updates.rb +12 -0
  7. data/lib/rpush/client/active_model/apns/notification.rb +0 -4
  8. data/lib/rpush/client/active_model/{gcm → fcm}/app.rb +4 -3
  9. data/lib/rpush/client/active_model/{gcm → fcm}/expiry_collapse_key_mutual_inclusion_validator.rb +1 -1
  10. data/lib/rpush/client/active_model/fcm/notification.rb +129 -0
  11. data/lib/rpush/client/active_model/fcm/notification_keys_in_allowed_list_validator.rb +20 -0
  12. data/lib/rpush/client/active_model.rb +4 -3
  13. data/lib/rpush/client/active_record/{gcm → fcm}/app.rb +2 -2
  14. data/lib/rpush/client/active_record/{gcm → fcm}/notification.rb +2 -2
  15. data/lib/rpush/client/active_record.rb +2 -2
  16. data/lib/rpush/client/redis/app.rb +2 -0
  17. data/lib/rpush/client/redis/{gcm → fcm}/app.rb +2 -2
  18. data/lib/rpush/client/redis/{gcm → fcm}/notification.rb +2 -2
  19. data/lib/rpush/client/redis.rb +2 -2
  20. data/lib/rpush/configuration.rb +2 -19
  21. data/lib/rpush/daemon/apns2/delivery.rb +0 -1
  22. data/lib/rpush/daemon/apnsp8/delivery.rb +0 -1
  23. data/lib/rpush/daemon/fcm/delivery.rb +162 -0
  24. data/lib/rpush/daemon/{gcm.rb → fcm.rb} +1 -1
  25. data/lib/rpush/daemon/google_credential_cache.rb +41 -0
  26. data/lib/rpush/daemon/service_config_methods.rb +0 -2
  27. data/lib/rpush/daemon/store/active_record.rb +15 -12
  28. data/lib/rpush/daemon/store/interface.rb +3 -3
  29. data/lib/rpush/daemon/store/redis.rb +13 -9
  30. data/lib/rpush/daemon/webpush/delivery.rb +2 -2
  31. data/lib/rpush/daemon.rb +3 -9
  32. data/lib/rpush/reflection_collection.rb +3 -3
  33. data/lib/rpush/version.rb +2 -2
  34. data/lib/rpush.rb +1 -1
  35. data/spec/functional/apns2_spec.rb +2 -6
  36. data/spec/functional/cli_spec.rb +41 -15
  37. data/spec/functional/embed_spec.rb +57 -26
  38. data/spec/functional/{gcm_priority_spec.rb → fcm_priority_spec.rb} +13 -7
  39. data/spec/functional/fcm_spec.rb +77 -0
  40. data/spec/functional/retry_spec.rb +21 -4
  41. data/spec/functional/synchronization_spec.rb +1 -1
  42. data/spec/functional_spec_helper.rb +1 -7
  43. data/spec/spec_helper.rb +4 -1
  44. data/spec/support/active_record_setup.rb +3 -1
  45. data/spec/unit/client/active_record/{gcm → fcm}/app_spec.rb +2 -2
  46. data/spec/unit/client/active_record/fcm/notification_spec.rb +10 -0
  47. data/spec/unit/client/active_record/shared/app.rb +1 -1
  48. data/spec/unit/client/redis/fcm/app_spec.rb +5 -0
  49. data/spec/unit/client/redis/fcm/notification_spec.rb +5 -0
  50. data/spec/unit/client/shared/apns/notification.rb +0 -15
  51. data/spec/unit/client/shared/fcm/app.rb +4 -0
  52. data/spec/unit/client/shared/fcm/notification.rb +92 -0
  53. data/spec/unit/configuration_spec.rb +1 -1
  54. data/spec/unit/daemon/apnsp8/delivery_spec.rb +1 -1
  55. data/spec/unit/daemon/fcm/delivery_spec.rb +127 -0
  56. data/spec/unit/daemon/service_config_methods_spec.rb +1 -1
  57. data/spec/unit/daemon/shared/store.rb +0 -42
  58. data/spec/unit/daemon/wns/delivery_spec.rb +1 -1
  59. data/spec/unit/logger_spec.rb +1 -1
  60. data/spec/unit_spec_helper.rb +1 -1
  61. metadata +127 -69
  62. data/lib/rpush/apns_feedback.rb +0 -18
  63. data/lib/rpush/client/active_model/gcm/notification.rb +0 -62
  64. data/lib/rpush/daemon/apns/delivery.rb +0 -43
  65. data/lib/rpush/daemon/apns/feedback_receiver.rb +0 -91
  66. data/lib/rpush/daemon/apns.rb +0 -17
  67. data/lib/rpush/daemon/dispatcher/apns_tcp.rb +0 -152
  68. data/lib/rpush/daemon/dispatcher/tcp.rb +0 -22
  69. data/lib/rpush/daemon/gcm/delivery.rb +0 -241
  70. data/lib/rpush/daemon/tcp_connection.rb +0 -190
  71. data/spec/functional/apns_spec.rb +0 -162
  72. data/spec/functional/gcm_spec.rb +0 -46
  73. data/spec/functional/new_app_spec.rb +0 -44
  74. data/spec/unit/apns_feedback_spec.rb +0 -39
  75. data/spec/unit/client/active_record/gcm/notification_spec.rb +0 -14
  76. data/spec/unit/client/redis/gcm/app_spec.rb +0 -5
  77. data/spec/unit/client/redis/gcm/notification_spec.rb +0 -5
  78. data/spec/unit/client/shared/gcm/app.rb +0 -4
  79. data/spec/unit/client/shared/gcm/notification.rb +0 -77
  80. data/spec/unit/daemon/apns/delivery_spec.rb +0 -108
  81. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +0 -137
  82. data/spec/unit/daemon/dispatcher/tcp_spec.rb +0 -32
  83. data/spec/unit/daemon/gcm/delivery_spec.rb +0 -387
  84. data/spec/unit/daemon/tcp_connection_spec.rb +0 -292
@@ -1,162 +0,0 @@
1
- require 'functional_spec_helper'
2
-
3
- describe 'APNs' do
4
- let(:app) { create_app }
5
- let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
6
- let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil, write: nil, flush: nil, read: nil, close: nil) }
7
- let(:io_double) { double(select: nil) }
8
- let(:delivered_ids) { [] }
9
- let(:failed_ids) { [] }
10
- let(:retry_ids) { [] }
11
-
12
- before do
13
- Rpush.config.push_poll = 0.5
14
- stub_tcp_connection(tcp_socket, ssl_socket, io_double)
15
- end
16
-
17
- def create_app
18
- app = Rpush::Apns::App.new
19
- app.certificate = TEST_CERT
20
- app.name = 'test'
21
- app.environment = 'sandbox'
22
- app.save!
23
- app
24
- end
25
-
26
- def create_notification
27
- notification = Rpush::Apns::Notification.new
28
- notification.app = app
29
- notification.alert = 'test'
30
- notification.device_token = 'a' * 108
31
- notification.save!
32
- notification
33
- end
34
-
35
- def wait
36
- sleep 0.1
37
- end
38
-
39
- def wait_for_notification_to_deliver(notification)
40
- timeout { wait until delivered_ids.include?(notification.id) }
41
- end
42
-
43
- def wait_for_notification_to_fail(notification)
44
- timeout { wait until failed_ids.include?(notification.id) }
45
- end
46
-
47
- def wait_for_notification_to_retry(notification)
48
- timeout { wait until retry_ids.include?(notification.id) }
49
- end
50
-
51
- def fail_notification(notification)
52
- allow(ssl_socket).to receive_messages(read: [8, 4, notification.id].pack('ccN'))
53
- enable_io_select
54
- end
55
-
56
- def enable_io_select
57
- called = false
58
- allow(io_double).to receive(:select) do
59
- if called
60
- nil
61
- else
62
- called = true
63
- end
64
- end
65
- end
66
-
67
- it 'delivers a notification successfully' do
68
- notification = create_notification
69
- expect do
70
- Rpush.push
71
- notification.reload
72
- end.to change(notification, :delivered).to(true)
73
- end
74
-
75
- it 'receives feedback' do
76
- app
77
- 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"
78
- allow(ssl_socket).to receive(:read).and_return(tuple, nil)
79
- Rpush.apns_feedback
80
- feedback = Rpush::Apns::Feedback.all.first
81
- expect(feedback).not_to be_nil
82
- expect(feedback.app_id).to eq(app.id)
83
- expect(feedback.device_token).to eq('834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17')
84
- end
85
-
86
- describe 'delivery failures' do
87
- before do
88
- Rpush.reflect do |on|
89
- on.notification_delivered do |n|
90
- delivered_ids << n.id
91
- end
92
-
93
- on.notification_id_failed do |_, n_id|
94
- failed_ids << n_id
95
- end
96
-
97
- on.notification_id_will_retry do |_, n_id|
98
- retry_ids << n_id
99
- end
100
-
101
- on.notification_will_retry do |n|
102
- retry_ids << n.id
103
- end
104
- end
105
-
106
- Rpush.embed
107
- end
108
-
109
- after do
110
- Rpush.reflection_stack.clear
111
- Rpush.reflection_stack.push(Rpush::ReflectionCollection.new)
112
-
113
- timeout { Rpush.shutdown }
114
- end
115
-
116
- it 'fails to deliver a notification' do
117
- notification = create_notification
118
- wait_for_notification_to_deliver(notification)
119
- fail_notification(notification)
120
- wait_for_notification_to_fail(notification)
121
- end
122
-
123
- describe 'with a failed connection' do
124
- it 'retries all notifications' do
125
- allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(sleep: nil)
126
- expect(ssl_socket).to receive(:write).at_least(1).times.and_raise(Errno::EPIPE)
127
- notifications = 2.times.map { create_notification }
128
- notifications.each { |n| wait_for_notification_to_retry(n) }
129
- end
130
- end
131
-
132
- describe 'with multiple notifications' do
133
- let(:notification1) { create_notification }
134
- let(:notification2) { create_notification }
135
- let(:notification3) { create_notification }
136
- let(:notification4) { create_notification }
137
- let(:notifications) { [notification1, notification2, notification3, notification4] }
138
-
139
- it 'marks the correct notification as failed' do
140
- notifications.each { |n| wait_for_notification_to_deliver(n) }
141
- fail_notification(notification2)
142
- wait_for_notification_to_fail(notification2)
143
- end
144
-
145
- it 'does not mark prior notifications as failed' do
146
- notifications.each { |n| wait_for_notification_to_deliver(n) }
147
- fail_notification(notification2)
148
- wait_for_notification_to_fail(notification2)
149
-
150
- expect(failed_ids).to_not include(notification1.id)
151
- notification1.reload
152
- expect(notification1.delivered).to eq(true)
153
- end
154
-
155
- it 'marks notifications following the failed one as retryable' do
156
- notifications.each { |n| wait_for_notification_to_deliver(n) }
157
- fail_notification(notification2)
158
- [notification3, notification4].each { |n| wait_for_notification_to_retry(n) }
159
- end
160
- end
161
- end
162
- end
@@ -1,46 +0,0 @@
1
- require 'functional_spec_helper'
2
-
3
- describe 'GCM' 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
- app.name = 'test'
11
- app.auth_key = 'abc123'
12
- app.save!
13
-
14
- notification.app_id = app.id
15
- notification.registration_ids = ['foo']
16
- notification.data = { message: 'test' }
17
- notification.save!
18
-
19
- allow(Net::HTTP::Persistent).to receive_messages(new: http)
20
- end
21
-
22
- it 'delivers a notification successfully' do
23
- allow(response).to receive_messages(body: JSON.dump(results: [{ message_id: notification.registration_ids.first.to_s }]))
24
-
25
- expect do
26
- Rpush.push
27
- notification.reload
28
- end.to change(notification, :delivered).to(true)
29
- end
30
-
31
- it 'fails to deliver a notification successfully' do
32
- allow(response).to receive_messages(body: JSON.dump(results: [{ error: 'Err' }]))
33
- Rpush.push
34
- notification.reload
35
- expect(notification.delivered).to eq(false)
36
- end
37
-
38
- it 'retries notification that fail due to a SocketError' do
39
- expect(http).to receive(:request).and_raise(SocketError.new)
40
- expect(notification.deliver_after).to be_nil
41
- expect do
42
- Rpush.push
43
- notification.reload
44
- end.to change(notification, :deliver_after).to(kind_of(Time))
45
- end
46
- end
@@ -1,44 +0,0 @@
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' * 108
28
- notification.save!
29
- notification
30
- end
31
-
32
- def stub_tcp_connection
33
- allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(connect_socket: [tcp_socket, ssl_socket])
34
- allow_any_instance_of(Rpush::Daemon::TcpConnection).to receive_messages(setup_ssl_context: double.as_null_object)
35
- stub_const('Rpush::Daemon::TcpConnection::IO', io_double)
36
- end
37
-
38
- it 'delivers a notification successfully' do
39
- notification = create_notification
40
- Rpush.push
41
- notification.reload
42
- expect(notification.delivered).to eq(true)
43
- end
44
- end
@@ -1,39 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush, 'apns_feedback' do
4
- let!(:apns_app) { Rpush::Apns::App.create!(apns_app_params) }
5
- let(:apns_app_params) do
6
- {
7
- name: 'test',
8
- environment: 'production',
9
- certificate: TEST_CERT
10
- }
11
- end
12
- let!(:gcm_app) { Rpush::Gcm::App.create!(name: 'MyApp', auth_key: 'abc123') }
13
-
14
- let(:receiver) { double(check_for_feedback: nil) }
15
-
16
- before do
17
- allow(Rpush::Daemon::Apns::FeedbackReceiver).to receive(:new) { receiver }
18
- end
19
-
20
- it 'initializes the daemon' do
21
- expect(Rpush::Daemon).to receive(:common_init)
22
- Rpush.apns_feedback
23
- end
24
-
25
- it 'checks feedback for each app' do
26
- expect(Rpush::Daemon::Apns::FeedbackReceiver).to receive(:new).with(apns_app).and_return(receiver)
27
- expect(receiver).to receive(:check_for_feedback)
28
- Rpush.apns_feedback
29
- end
30
-
31
- context 'feedback disabled' do
32
- let(:apns_app_params) { super().merge(feedback_enabled: false) }
33
-
34
- it 'does not initialize feedback receiver' do
35
- expect(Rpush::Daemon::Apns::FeedbackReceiver).not_to receive(:new)
36
- Rpush.apns_feedback
37
- end
38
- end
39
- end
@@ -1,14 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::ActiveRecord::Gcm::Notification do
4
- it_behaves_like 'Rpush::Client::Gcm::Notification'
5
- it_behaves_like 'Rpush::Client::ActiveRecord::Notification'
6
-
7
- subject(:notification) { described_class.new }
8
- let(:app) { Rpush::Gcm::App.create!(name: 'test', auth_key: 'abc') }
9
-
10
- it 'accepts non-booleans as a truthy value' do
11
- notification.dry_run = 'Not a boolean'
12
- expect(notification.as_json['dry_run']).to eq true
13
- end
14
- end if active_record?
@@ -1,5 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::Redis::Gcm::App do
4
- it_behaves_like 'Rpush::Client::Gcm::App'
5
- end if redis?
@@ -1,5 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Client::Redis::Gcm::Notification do
4
- it_behaves_like 'Rpush::Client::Gcm::Notification'
5
- end if redis?
@@ -1,4 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- shared_examples 'Rpush::Client::Gcm::App' do
4
- end
@@ -1,77 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- shared_examples 'Rpush::Client::Gcm::Notification' do
4
- let(:app) { Rpush::Gcm::App.create!(name: 'test', auth_key: 'abc') }
5
- let(:notification) { described_class.new }
6
-
7
- it "has a 'data' payload limit of 4096 bytes" do
8
- notification.data = { key: "a" * 4096 }
9
- expect(notification.valid?).to be_falsey
10
- expect(notification.errors[:base]).to eq ["Notification payload data cannot be larger than 4096 bytes."]
11
- end
12
-
13
- it 'limits the number of registration ids to 1000' do
14
- notification.registration_ids = ['a'] * (1000 + 1)
15
- expect(notification.valid?).to be_falsey
16
- expect(notification.errors[:base]).to eq ["Number of registration_ids cannot be larger than 1000."]
17
- end
18
-
19
- it 'validates expiry is present if collapse_key is set' do
20
- notification.collapse_key = 'test'
21
- notification.expiry = nil
22
- expect(notification.valid?).to be_falsey
23
- expect(notification.errors[:expiry]).to eq ['must be set when using a collapse_key']
24
- end
25
-
26
- it 'includes time_to_live in the payload' do
27
- notification.expiry = 100
28
- expect(notification.as_json['time_to_live']).to eq 100
29
- end
30
-
31
- it 'includes content_available in the payload' do
32
- notification.content_available = true
33
- expect(notification.as_json['content_available']).to eq true
34
- end
35
-
36
- it 'includes mutable_content in the payload' do
37
- notification.mutable_content = true
38
- expect(notification.as_json['mutable_content']).to eq true
39
- end
40
-
41
- it 'sets the priority to high when set to high' do
42
- notification.priority = 'high'
43
- expect(notification.as_json['priority']).to eq 'high'
44
- end
45
-
46
- it 'sets the priority to normal when set to normal' do
47
- notification.priority = 'normal'
48
- expect(notification.as_json['priority']).to eq 'normal'
49
- end
50
-
51
- it 'validates the priority is either "normal" or "high"' do
52
- notification.priority = 'invalid'
53
- expect(notification.errors[:priority]).to eq ['must be one of either "normal" or "high"']
54
- end
55
-
56
- it 'excludes the priority if it is not defined' do
57
- expect(notification.as_json).not_to have_key 'priority'
58
- end
59
-
60
- it 'includes the notification payload if defined' do
61
- notification.notification = { key: 'any key is allowed' }
62
- expect(notification.as_json).to have_key 'notification'
63
- end
64
-
65
- it 'excludes the notification payload if undefined' do
66
- expect(notification.as_json).not_to have_key 'notification'
67
- end
68
-
69
- it 'includes the dry_run payload if defined' do
70
- notification.dry_run = true
71
- expect(notification.as_json['dry_run']).to eq true
72
- end
73
-
74
- it 'excludes the dry_run payload if undefined' do
75
- expect(notification.as_json).not_to have_key 'dry_run'
76
- end
77
- end
@@ -1,108 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Daemon::Apns::Delivery do
4
- let(:app) { double(name: 'MyApp') }
5
- let(:notification1) { double.as_null_object }
6
- let(:notification2) { double.as_null_object }
7
- let(:batch) { double(mark_all_failed: nil, mark_all_delivered: nil, all_processed: nil) }
8
- let(:logger) { double(error: nil, info: nil) }
9
- let(:connection) { double(select: false, write: nil, reconnect: nil, close: nil, connect: nil) }
10
- let(:delivery) { Rpush::Daemon::Apns::Delivery.new(app, connection, batch) }
11
-
12
- before do
13
- allow(batch).to receive(:each_notification) do |&blk|
14
- [notification1, notification2].each(&blk)
15
- end
16
- allow(Rpush).to receive_messages(logger: logger)
17
- end
18
-
19
- it 'writes the binary batch' do
20
- allow(notification1).to receive_messages(to_binary: 'binary1')
21
- allow(notification2).to receive_messages(to_binary: 'binary2')
22
- expect(connection).to receive(:write).with('binary1binary2')
23
- delivery.perform
24
- end
25
-
26
- it 'logs the notification deliveries' do
27
- allow(notification1).to receive_messages(id: 666, device_token: 'abc123')
28
- allow(notification2).to receive_messages(id: 42, device_token: 'abc456')
29
- expect(logger).to receive(:info).with('[MyApp] 666 sent to abc123')
30
- expect(logger).to receive(:info).with('[MyApp] 42 sent to abc456')
31
- delivery.perform
32
- end
33
-
34
- it 'marks all notifications as delivered' do
35
- expect(delivery).to receive(:mark_batch_delivered)
36
- delivery.perform
37
- end
38
-
39
- it 'notifies the batch all notifications have been processed' do
40
- expect(batch).to receive(:all_processed)
41
- delivery.perform
42
- end
43
-
44
- describe 'when an error is raised' do
45
- it 'marks all notifications as failed' do
46
- error = StandardError.new
47
- allow(connection).to receive(:write).and_raise(error)
48
- expect(delivery).to receive(:mark_batch_failed).with(error)
49
- expect { delivery.perform }.to raise_error(error)
50
- end
51
- end
52
-
53
- # describe "when delivery fails" do
54
- # before { connection.stub(select: true, read: [8, 4, 69].pack("ccN")) }
55
- #
56
- # it "marks the notification as failed" do
57
- # delivery.should_receive(:mark_failed).with(4, "Unable to deliver notification 69, received error 4 (Missing payload)")
58
- # perform
59
- # end
60
- #
61
- # it "logs the delivery error" do
62
- # # checking for the doublebed error doesn't work in jruby, but checking
63
- # # for the exception by class does.
64
- #
65
- # # error = Rpush::DeliveryError.new(4, 12, "Missing payload")
66
- # # Rpush::DeliveryError.stub(new: error)
67
- # # expect { delivery.perform }.to raise_error(error)
68
- #
69
- # expect { delivery.perform }.to raise_error(Rpush::DeliveryError)
70
- # end
71
- #
72
- # it "reads 6 bytes from the socket" do
73
- # connection.should_receive(:read).with(6).and_return(nil)
74
- # perform
75
- # end
76
- #
77
- # it "does not attempt to read from the socket if the socket was not selected for reading after the timeout" do
78
- # connection.stub(select: nil)
79
- # connection.should_not_receive(:read)
80
- # perform
81
- # end
82
- #
83
- # it "reconnects the socket" do
84
- # connection.should_receive(:reconnect)
85
- # perform
86
- # end
87
- #
88
- # it "logs that the connection is being reconnected" do
89
- # Rpush.logger.should_receive(:error).with("[MyApp] Error received, reconnecting...")
90
- # perform
91
- # end
92
- #
93
- # context "when the APNs disconnects without returning an error" do
94
- # before do
95
- # connection.stub(read: nil)
96
- # end
97
- #
98
- # it 'raises a DisconnectError error if the connection is closed without an error being returned' do
99
- # expect { delivery.perform }.to raise_error(Rpush::DisconnectionError)
100
- # end
101
- #
102
- # it 'marks the notification as failed' do
103
- # delivery.should_receive(:mark_failed).with(nil, "The APNs disconnected without returning an error. This may indicate you are using an invalid certificate for the host.")
104
- # perform
105
- # end
106
- # end
107
- # end
108
- end
@@ -1,137 +0,0 @@
1
- require 'unit_spec_helper'
2
- require 'rpush/daemon/store/active_record'
3
-
4
- describe Rpush::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
5
- let(:host) { 'feedback.push.apple.com' }
6
- let(:port) { 2196 }
7
- let(:frequency) { 60 }
8
- let(:certificate) { double }
9
- let(:password) { double }
10
- let(:feedback_enabled) { true }
11
- let(:app) do
12
- double(
13
- name: 'my_app',
14
- password: password,
15
- certificate: certificate,
16
- feedback_enabled: feedback_enabled,
17
- environment: 'production'
18
- )
19
- end
20
- let(:connection) { double(connect: nil, read: nil, close: nil) }
21
- let(:logger) { double(error: nil, info: nil) }
22
- let(:receiver) { Rpush::Daemon::Apns::FeedbackReceiver.new(app) }
23
- let(:feedback) { double }
24
- let(:sleeper) { double(Rpush::Daemon::InterruptibleSleep, sleep: nil, stop: nil) }
25
- let(:store) { double(Rpush::Daemon::Store::ActiveRecord, create_apns_feedback: feedback, release_connection: nil) }
26
-
27
- before do
28
- Rpush.config.apns.feedback_receiver.frequency = frequency
29
- allow(Rpush::Daemon::InterruptibleSleep).to receive_messages(new: sleeper)
30
- allow(Rpush).to receive_messages(logger: logger)
31
- allow(Rpush::Daemon::TcpConnection).to receive_messages(new: connection)
32
- receiver.instance_variable_set("@stop", false)
33
- allow(Rpush::Daemon).to receive_messages(store: store)
34
- end
35
-
36
- def double_connection_read_with_tuple
37
- def connection.read(*)
38
- unless @called
39
- @called = true
40
- "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"
41
- end
42
- end
43
- end
44
-
45
- it 'initializes the sleeper with the feedback polling frequency' do
46
- expect(Rpush::Daemon::InterruptibleSleep).to receive_messages(new: sleeper)
47
- Rpush::Daemon::Apns::FeedbackReceiver.new(app)
48
- end
49
-
50
- it 'instantiates a new connection' do
51
- expect(Rpush::Daemon::TcpConnection).to receive(:new).with(app, host, port)
52
- receiver.check_for_feedback
53
- end
54
-
55
- it 'connects to the feeback service' do
56
- expect(connection).to receive(:connect)
57
- receiver.check_for_feedback
58
- end
59
-
60
- it 'closes the connection' do
61
- expect(connection).to receive(:close)
62
- receiver.check_for_feedback
63
- end
64
-
65
- it 'reads from the connection' do
66
- expect(connection).to receive(:read).with(38)
67
- receiver.check_for_feedback
68
- end
69
-
70
- it 'logs the feedback' do
71
- double_connection_read_with_tuple
72
- expect(Rpush.logger).to receive(:info).with("[my_app] [FeedbackReceiver] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17.")
73
- receiver.check_for_feedback
74
- end
75
-
76
- it 'creates the feedback' do
77
- expect(Rpush::Daemon.store).to receive(:create_apns_feedback).with(Time.at(1_323_533_325), '834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17', app)
78
- double_connection_read_with_tuple
79
- receiver.check_for_feedback
80
- end
81
-
82
- it 'logs errors' do
83
- error = StandardError.new('bork!')
84
- allow(connection).to receive(:read).and_raise(error)
85
- expect(Rpush.logger).to receive(:error).with(error)
86
- receiver.check_for_feedback
87
- end
88
-
89
- describe 'start' do
90
- before do
91
- allow(Thread).to receive(:new).and_yield
92
- allow(receiver).to receive(:loop).and_yield
93
- end
94
-
95
- it 'sleeps' do
96
- allow(receiver).to receive(:check_for_feedback)
97
- expect(sleeper).to receive(:sleep).at_least(:once)
98
- receiver.start
99
- end
100
-
101
- it 'checks for feedback when started' do
102
- expect(receiver).to receive(:check_for_feedback).at_least(:once)
103
- receiver.start
104
- end
105
-
106
- context 'with feedback_enabled false' do
107
- let(:feedback_enabled) { false }
108
-
109
- it 'does not check for feedback when started' do
110
- expect(receiver).not_to receive(:check_for_feedback)
111
- receiver.start
112
- end
113
- end
114
- end
115
-
116
- describe 'stop' do
117
- it 'interrupts sleep when stopped' do
118
- allow(receiver).to receive(:check_for_feedback)
119
- expect(sleeper).to receive(:stop)
120
- receiver.stop
121
- end
122
-
123
- it 'releases the store connection' do
124
- allow(Thread).to receive(:new).and_yield
125
- allow(receiver).to receive(:loop).and_yield
126
- expect(Rpush::Daemon.store).to receive(:release_connection)
127
- receiver.start
128
- receiver.stop
129
- end
130
- end
131
-
132
- it 'reflects feedback was received' do
133
- double_connection_read_with_tuple
134
- expect(receiver).to receive(:reflect).with(:apns_feedback, feedback)
135
- receiver.check_for_feedback
136
- end
137
- end
@@ -1,32 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Rpush::Daemon::Dispatcher::Tcp do
4
- let(:app) { double }
5
- let(:delivery) { double(perform: nil) }
6
- let(:delivery_class) { double(new: delivery) }
7
- let(:notification) { double }
8
- let(:batch) { double }
9
- let(:connection) { double(Rpush::Daemon::TcpConnection, connect: nil) }
10
- let(:host) { 'localhost' }
11
- let(:port) { 1234 }
12
- let(:host_proc) { proc { [host, port] } }
13
- let(:queue_payload) { Rpush::Daemon::QueuePayload.new(batch, notification) }
14
- let(:dispatcher) { Rpush::Daemon::Dispatcher::Tcp.new(app, delivery_class, host: host_proc) }
15
-
16
- before { allow(Rpush::Daemon::TcpConnection).to receive_messages(new: connection) }
17
-
18
- describe 'dispatch' do
19
- it 'delivers the notification' do
20
- expect(delivery_class).to receive(:new).with(app, connection, notification, batch).and_return(delivery)
21
- expect(delivery).to receive(:perform)
22
- dispatcher.dispatch(queue_payload)
23
- end
24
- end
25
-
26
- describe 'cleanup' do
27
- it 'closes the connection' do
28
- expect(connection).to receive(:close)
29
- dispatcher.cleanup
30
- end
31
- end
32
- end