rapns 3.0.1-java → 3.1.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.
- data/CHANGELOG.md +10 -2
- data/README.md +26 -3
- data/bin/rapns +2 -7
- data/lib/generators/templates/add_gcm.rb +3 -1
- data/lib/generators/templates/rapns.rb +42 -11
- data/lib/rapns.rb +11 -1
- data/lib/rapns/apns/notification.rb +8 -2
- data/lib/rapns/app.rb +3 -3
- data/lib/rapns/configuration.rb +46 -13
- data/lib/rapns/daemon.rb +33 -22
- data/lib/rapns/daemon/apns/connection.rb +12 -9
- data/lib/rapns/daemon/apns/delivery_handler.rb +1 -1
- data/lib/rapns/daemon/apns/feedback_receiver.rb +6 -2
- data/lib/rapns/daemon/app_runner.rb +23 -7
- data/lib/rapns/daemon/delivery.rb +5 -1
- data/lib/rapns/daemon/delivery_handler.rb +4 -0
- data/lib/rapns/daemon/feeder.rb +26 -5
- data/lib/rapns/daemon/reflectable.rb +13 -0
- data/lib/rapns/embed.rb +28 -0
- data/lib/rapns/gcm/notification.rb +7 -2
- data/lib/rapns/gcm/payload_data_size_validator.rb +13 -0
- data/lib/rapns/gcm/registration_ids_count_validator.rb +13 -0
- data/lib/rapns/push.rb +12 -0
- data/lib/rapns/reflection.rb +44 -0
- data/lib/rapns/version.rb +1 -1
- data/spec/support/cert_with_password.pem +90 -0
- data/spec/support/cert_without_password.pem +59 -0
- data/spec/unit/apns/app_spec.rb +15 -1
- data/spec/unit/apns/notification_spec.rb +16 -1
- data/spec/unit/configuration_spec.rb +10 -1
- data/spec/unit/daemon/apns/connection_spec.rb +11 -2
- data/spec/unit/daemon/apns/delivery_handler_spec.rb +1 -1
- data/spec/unit/daemon/apns/delivery_spec.rb +10 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +16 -7
- data/spec/unit/daemon/delivery_handler_shared.rb +8 -0
- data/spec/unit/daemon/feeder_spec.rb +37 -6
- data/spec/unit/daemon/gcm/delivery_spec.rb +33 -1
- data/spec/unit/daemon/reflectable_spec.rb +27 -0
- data/spec/unit/daemon_spec.rb +55 -9
- data/spec/unit/embed_spec.rb +44 -0
- data/spec/unit/gcm/notification_spec.rb +9 -3
- data/spec/unit/push_spec.rb +28 -0
- data/spec/unit/reflection_spec.rb +34 -0
- data/spec/unit_spec_helper.rb +4 -62
- metadata +22 -5
- data/lib/rapns/gcm/payload_size_validator.rb +0 -13
@@ -0,0 +1,59 @@
|
|
1
|
+
Bag Attributes
|
2
|
+
friendlyName: test certificate
|
3
|
+
localKeyID: 00 93 8F E4 A3 C3 75 64 3D 7E EA 14 0B 0A EA DD 15 85 8A D5
|
4
|
+
subject=/CN=test certificate/O=Example/OU=Example/ST=QLD/C=AU/L=Example/emailAddress=user@example.com
|
5
|
+
issuer=/CN=test certificate/O=Example/OU=Example/ST=QLD/C=AU/L=Example/emailAddress=user@example.com
|
6
|
+
-----BEGIN CERTIFICATE-----
|
7
|
+
MIID5jCCAs6gAwIBAgIBATALBgkqhkiG9w0BAQswgY0xGTAXBgNVBAMMEHRlc3Qg
|
8
|
+
Y2VydGlmaWNhdGUxEDAOBgNVBAoMB0V4YW1wbGUxEDAOBgNVBAsMB0V4YW1wbGUx
|
9
|
+
DDAKBgNVBAgMA1FMRDELMAkGA1UEBhMCQVUxEDAOBgNVBAcMB0V4YW1wbGUxHzAd
|
10
|
+
BgkqhkiG9w0BCQEWEHVzZXJAZXhhbXBsZS5jb20wHhcNMTIwOTA5MDMxODMyWhcN
|
11
|
+
MjIwOTA3MDMxODMyWjCBjTEZMBcGA1UEAwwQdGVzdCBjZXJ0aWZpY2F0ZTEQMA4G
|
12
|
+
A1UECgwHRXhhbXBsZTEQMA4GA1UECwwHRXhhbXBsZTEMMAoGA1UECAwDUUxEMQsw
|
13
|
+
CQYDVQQGEwJBVTEQMA4GA1UEBwwHRXhhbXBsZTEfMB0GCSqGSIb3DQEJARYQdXNl
|
14
|
+
ckBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKF+
|
15
|
+
UDsN1sLen8g+97PNTiWju9+wkSv+H5rQlvb6YFLPx11YvqpK8ms6kFU1OmWeLfmh
|
16
|
+
cpsT+bZtKupC7aGPoSG3RXzzf/YUMgs/ZSXA0idZHA6tkReAEzIX6jL5otfPWbaP
|
17
|
+
luCTUoVMeP4u9ywk628zlqh9IQHC1Agl0R1xGCpULDk8kn1gPyEisl38wI5aDbzy
|
18
|
+
6lYQGNUKOqt1xfVjtIFe/jyY/v0sxFjIJlRLcAFBuJx4sRV+PwRBkusOQtYwcwpI
|
19
|
+
loMxJj+GQe66ueATW81aC4iOU66DAFFEuGzwIwm3bOilimGGQbGb92F339RfmSOo
|
20
|
+
TPAvVhsakI3mzESb4lkCAwEAAaNRME8wDgYDVR0PAQH/BAQDAgeAMCAGA1UdJQEB
|
21
|
+
/wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAbBgNVHREEFDASgRB1c2VyQGV4YW1w
|
22
|
+
bGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA5UbNR+83ZdI2DiaB4dRmy0V5RDAqJ
|
23
|
+
k9+QskcTV4gBTjsOBS46Dw1tI6iTrfTyjYJdnyH0Y2Y2YVWBnvtON41UCZak+4ed
|
24
|
+
/IqyzU0dtfZ+frWa0RY4reyl80TwqnzyJfni0nDo4zGGvz70cxyaz2u1BWqwLjqb
|
25
|
+
dh8Dxvt+aHW2MQi0iGKh/HNbgwVanR4+ubNwziK9sR1Rnq9MkHWtwBw16SXQG6ao
|
26
|
+
SZKASWNaH8VL08Zz0E98cwd137UJkPsldCwJ8kHR5OzkcjPdXvnGD3d64yy2TC1Z
|
27
|
+
Gy1Aazt98wPcTYBytlhK8Rvzg9OoY9QmsdpmWxz1ZCXECJNqCa3IKsqO
|
28
|
+
-----END CERTIFICATE-----
|
29
|
+
Bag Attributes
|
30
|
+
friendlyName: test certificate
|
31
|
+
localKeyID: 00 93 8F E4 A3 C3 75 64 3D 7E EA 14 0B 0A EA DD 15 85 8A D5
|
32
|
+
Key Attributes: <No Attributes>
|
33
|
+
-----BEGIN RSA PRIVATE KEY-----
|
34
|
+
MIIEpQIBAAKCAQEAoX5QOw3Wwt6fyD73s81OJaO737CRK/4fmtCW9vpgUs/HXVi+
|
35
|
+
qkryazqQVTU6ZZ4t+aFymxP5tm0q6kLtoY+hIbdFfPN/9hQyCz9lJcDSJ1kcDq2R
|
36
|
+
F4ATMhfqMvmi189Zto+W4JNShUx4/i73LCTrbzOWqH0hAcLUCCXRHXEYKlQsOTyS
|
37
|
+
fWA/ISKyXfzAjloNvPLqVhAY1Qo6q3XF9WO0gV7+PJj+/SzEWMgmVEtwAUG4nHix
|
38
|
+
FX4/BEGS6w5C1jBzCkiWgzEmP4ZB7rq54BNbzVoLiI5TroMAUUS4bPAjCbds6KWK
|
39
|
+
YYZBsZv3YXff1F+ZI6hM8C9WGxqQjebMRJviWQIDAQABAoIBAQCTiLIDQUFSBdAz
|
40
|
+
QFNLD+S0vkCEuunlJuP4q1c/ir006l1YChsluBJ/o6D4NwiCjV+zDquEwVsALftm
|
41
|
+
yH4PewfZpXT2Ef508T5GyEO/mchj6iSXxDkpHvhqay6qIyWBwwxSnBtaTzy0Soi+
|
42
|
+
rmlhCtmLXbXld2sQEM1kJChGnWtWPtvSyrn+mapNPZviGRtgRNK+YsrAti1nUext
|
43
|
+
2syO5mTdHf1D8GR7I98OaX6odREuSocEV9PzfapWZx2GK5tvRiS1skiug5ciieTd
|
44
|
+
Am5/C+bb31h4drFslihLb5BRGO5SFQJvMJL2Sx1f19BCC4XikS01P4/zZbxQNq79
|
45
|
+
kxEQuDGBAoGBANP4pIYZ5xshCkx7cTYqmxzWLClGKE2S7Oa8N89mtOwfmqT9AFun
|
46
|
+
t9Us9Ukbi8BaKlKhGpQ1HlLf/KVcpyW0x2qLou6AyIWYH+/5VaR3graNgUnzpK9f
|
47
|
+
1F5HoaNHbhlAoebqhzhASFlJI2aqUdQjdOv73z+s9szJU4gpILNwGDFnAoGBAMMJ
|
48
|
+
j+vIxtG9J2jldyoXzpg5mbMXSj9u/wFLBVdjXWyOoiqVMMBto53RnoqAom7Ifr9D
|
49
|
+
49LxRAT1Q3l4vs/YnM3ziMsIg2vQK1EbrLsY9OnD/kvPaLXOlNIOdfLM8UeVWZMc
|
50
|
+
I4LPbbZrhv/7CC8RjbRhMoWWdGYPvxmvD6V4ZDY/AoGBALoI6OxA45Htx4okdNHj
|
51
|
+
RstiNNPsnQaoQn6nBhxiubraafEPkzbd1fukP4pwQJELEUX/2sHkdL6rkqLW1GPF
|
52
|
+
a5dZAiBsqpCFWNJWdBGqSfBJ9QSgbxLz+gDcwUH6OOi0zuNJRm/aCyVBiW5bYQHc
|
53
|
+
NIvAPMk31ksZDtTbs7WIVdNVAoGBALZ1+KWNxKqs+fSBT5UahpUUtfy8miJz9a7A
|
54
|
+
/3M8q0cGvSF3Rw+OwpW/aEGMi+l2OlU27ykFuyukRAac9m296RwnbF79TO2M5ylO
|
55
|
+
6a5zb5ROXlWP6RbE96b4DlIidssQJqegmHwlEC+rsrVBpOtb0aThlYEyOxzMOGyP
|
56
|
+
wOR9l8rDAoGADZ4TUHFM6VrvPlUZBkGbqiyXH9IM/y9JWk+22JQCEGnM6RFZemSs
|
57
|
+
jxWqQiPAdJtb3xKryJSCMtFPH9azedoCrSgaMflJ1QgoXgpiKZyoEXWraVUggh/0
|
58
|
+
CEavgZcTZ6SvMuayqJdGGB+zb1V8XwXMtCjApR/kTm47DjxO4DmpOPs=
|
59
|
+
-----END RSA PRIVATE KEY-----
|
data/spec/unit/apns/app_spec.rb
CHANGED
@@ -7,9 +7,23 @@ describe Rapns::App do
|
|
7
7
|
app.errors[:certificate].should == ['Certificate value must contain a certificate and a private key.']
|
8
8
|
end
|
9
9
|
|
10
|
-
it 'validates a
|
10
|
+
it 'validates a certificate without a password' do
|
11
11
|
app = Rapns::Apns::App.new :key => 'test', :environment => 'development', :certificate => TEST_CERT
|
12
12
|
app.valid?
|
13
13
|
app.errors[:certificate].should == []
|
14
14
|
end
|
15
|
+
|
16
|
+
it 'validates a certificate with a password' do
|
17
|
+
app = Rapns::Apns::App.new :key => 'test', :environment => 'development',
|
18
|
+
:certificate => TEST_CERT_WITH_PASSWORD, :password => 'fubar'
|
19
|
+
app.valid?
|
20
|
+
app.errors[:certificate].should == []
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'validates a certificate with an incorrect password' do
|
24
|
+
app = Rapns::Apns::App.new :key => 'test', :environment => 'development',
|
25
|
+
:certificate => TEST_CERT_WITH_PASSWORD, :password => 'incorrect'
|
26
|
+
app.valid?
|
27
|
+
app.errors[:certificate].should == ["Certificate value must contain a certificate and a private key."]
|
28
|
+
end
|
15
29
|
end
|
@@ -128,10 +128,25 @@ describe Rapns::Apns::Notification, 'content-available' do
|
|
128
128
|
notification.as_json['aps'].key?('content-available').should be_false
|
129
129
|
end
|
130
130
|
|
131
|
-
it 'does not include
|
131
|
+
it 'does not include content-available as a non-aps attribute' do
|
132
132
|
notification.content_available = true
|
133
133
|
notification.as_json.key?('content-available').should be_false
|
134
134
|
end
|
135
|
+
|
136
|
+
it 'does not overwrite existing attributes for the device' do
|
137
|
+
notification.data = {:hi => :mom}
|
138
|
+
notification.content_available = true
|
139
|
+
notification.as_json['aps']['content-available'].should == 1
|
140
|
+
notification.as_json['hi'].should == 'mom'
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'does not overwrite the content-available flag when setting attributes for the device' do
|
144
|
+
notification.content_available = true
|
145
|
+
notification.data = {:hi => :mom}
|
146
|
+
notification.as_json['aps']['content-available'].should == 1
|
147
|
+
notification.as_json['hi'].should == 'mom'
|
148
|
+
end
|
149
|
+
|
135
150
|
end
|
136
151
|
|
137
152
|
describe Rapns::Apns::Notification, "to_binary" do
|
@@ -15,7 +15,9 @@ describe Rapns::Configuration do
|
|
15
15
|
|
16
16
|
it 'configures a feedback callback' do
|
17
17
|
b = Proc.new {}
|
18
|
-
|
18
|
+
Rapns::Deprecation.silenced do
|
19
|
+
config.on_apns_feedback(&b)
|
20
|
+
end
|
19
21
|
config.apns_feedback_callback.should == b
|
20
22
|
end
|
21
23
|
|
@@ -35,4 +37,11 @@ describe Rapns::Configuration do
|
|
35
37
|
config.pid_file = '/tmp/rapns.pid'
|
36
38
|
config.pid_file.should == '/tmp/rapns.pid'
|
37
39
|
end
|
40
|
+
|
41
|
+
it 'does not allow foreground to be set to false if the platform is JRuby' do
|
42
|
+
config.foreground = true
|
43
|
+
stub_const('Rapns::Configuration::JRUBY_VERSION', '1.7.1')
|
44
|
+
config.foreground = false
|
45
|
+
config.foreground.should be_true
|
46
|
+
end
|
38
47
|
end
|
@@ -11,7 +11,8 @@ describe Rapns::Daemon::Apns::Connection do
|
|
11
11
|
let(:tcp_socket) { stub(:setsockopt => nil, :close => nil) }
|
12
12
|
let(:ssl_socket) { stub(:sync= => nil, :connect => nil, :close => nil, :write => nil, :flush => nil) }
|
13
13
|
let(:logger) { stub(:info => nil, :error => nil) }
|
14
|
-
let(:
|
14
|
+
let(:app) { stub(:name => 'Connection 0', :certificate => certificate, :password => password)}
|
15
|
+
let(:connection) { Rapns::Daemon::Apns::Connection.new(app, host, port) }
|
15
16
|
|
16
17
|
before do
|
17
18
|
OpenSSL::SSL::SSLContext.stub(:new => ssl_context)
|
@@ -121,6 +122,14 @@ describe Rapns::Daemon::Apns::Connection do
|
|
121
122
|
ssl_socket.stub(:write).and_raise(error_type)
|
122
123
|
end
|
123
124
|
|
125
|
+
it 'reflects the connection has been lost' do
|
126
|
+
connection.should_receive(:reflect).with(:apns_connection_lost, app, kind_of(error_type))
|
127
|
+
begin
|
128
|
+
connection.write(nil)
|
129
|
+
rescue Rapns::Daemon::Apns::ConnectionError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
124
133
|
it "logs that the connection has been lost once only" do
|
125
134
|
logger.should_receive(:error).with("[Connection 0] Lost connection to gateway.push.apple.com:2195 (#{error_type.name}), reconnecting...").once
|
126
135
|
begin
|
@@ -231,4 +240,4 @@ describe Rapns::Daemon::Apns::Connection do
|
|
231
240
|
connection.write('blah')
|
232
241
|
end
|
233
242
|
end
|
234
|
-
end
|
243
|
+
end
|
@@ -23,7 +23,7 @@ describe Rapns::Daemon::Apns::DeliveryHandler do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it "instantiates a new connection" do
|
26
|
-
Rapns::Daemon::Apns::Connection.should_receive(:new).with(app
|
26
|
+
Rapns::Daemon::Apns::Connection.should_receive(:new).with(app, host, port)
|
27
27
|
Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port)
|
28
28
|
end
|
29
29
|
|
@@ -37,6 +37,11 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
37
37
|
perform
|
38
38
|
end
|
39
39
|
|
40
|
+
it 'reflects the notification was delivered' do
|
41
|
+
delivery.should_receive(:reflect).with(:notification_delivered, notification)
|
42
|
+
perform
|
43
|
+
end
|
44
|
+
|
40
45
|
it "sets the time the notification was delivered" do
|
41
46
|
now = Time.now
|
42
47
|
Time.stub(:now).and_return(now)
|
@@ -83,6 +88,11 @@ describe Rapns::Daemon::Apns::Delivery do
|
|
83
88
|
perform
|
84
89
|
end
|
85
90
|
|
91
|
+
it 'reflects the notification delivery failed' do
|
92
|
+
delivery.should_receive(:reflect).with(:notification_failed, notification)
|
93
|
+
perform
|
94
|
+
end
|
95
|
+
|
86
96
|
it "sets the notification failed_at timestamp" do
|
87
97
|
now = Time.now
|
88
98
|
Time.stub(:now).and_return(now)
|
@@ -10,12 +10,13 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
10
10
|
let(:connection) { stub(:connect => nil, :read => nil, :close => nil) }
|
11
11
|
let(:logger) { stub(:error => nil, :info => nil) }
|
12
12
|
let(:receiver) { Rapns::Daemon::Apns::FeedbackReceiver.new(app, host, port, poll) }
|
13
|
+
let(:feedback) { stub }
|
13
14
|
|
14
15
|
before do
|
15
16
|
receiver.stub(:interruptible_sleep)
|
16
17
|
Rapns::Daemon.logger = logger
|
17
18
|
Rapns::Daemon::Apns::Connection.stub(:new => connection)
|
18
|
-
Rapns::Apns::Feedback.stub(:create!)
|
19
|
+
Rapns::Apns::Feedback.stub(:create! => feedback)
|
19
20
|
receiver.instance_variable_set("@stop", false)
|
20
21
|
end
|
21
22
|
|
@@ -31,7 +32,7 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
31
32
|
end
|
32
33
|
|
33
34
|
it 'instantiates a new connection' do
|
34
|
-
Rapns::Daemon::Apns::Connection.should_receive(:new).with(
|
35
|
+
Rapns::Daemon::Apns::Connection.should_receive(:new).with(app, host, port)
|
35
36
|
receiver.check_for_feedback
|
36
37
|
end
|
37
38
|
|
@@ -52,7 +53,7 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
52
53
|
|
53
54
|
it 'logs the feedback' do
|
54
55
|
stub_connection_read_with_tuple
|
55
|
-
Rapns::Daemon.logger.should_receive(:info).with("[
|
56
|
+
Rapns::Daemon.logger.should_receive(:info).with("[my_app] [FeedbackReceiver] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17.")
|
56
57
|
receiver.check_for_feedback
|
57
58
|
end
|
58
59
|
|
@@ -90,11 +91,15 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
90
91
|
receiver.stop
|
91
92
|
end
|
92
93
|
|
94
|
+
it 'reflects feedback was received' do
|
95
|
+
stub_connection_read_with_tuple
|
96
|
+
receiver.should_receive(:reflect).with(:apns_feedback, feedback)
|
97
|
+
receiver.check_for_feedback
|
98
|
+
end
|
99
|
+
|
93
100
|
it 'calls the apns_feedback_callback when feedback is received and the callback is set' do
|
94
101
|
stub_connection_read_with_tuple
|
95
102
|
Rapns.config.apns_feedback_callback = Proc.new {}
|
96
|
-
feedback = Object.new
|
97
|
-
Rapns::Apns::Feedback.stub(:create! => feedback)
|
98
103
|
Rapns.config.apns_feedback_callback.should_receive(:call).with(feedback)
|
99
104
|
receiver.check_for_feedback
|
100
105
|
end
|
@@ -103,7 +108,9 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
103
108
|
error = StandardError.new('bork!')
|
104
109
|
stub_connection_read_with_tuple
|
105
110
|
callback = Proc.new { raise error }
|
106
|
-
Rapns.
|
111
|
+
Rapns::Deprecation.silenced do
|
112
|
+
Rapns.config.on_apns_feedback &callback
|
113
|
+
end
|
107
114
|
expect { receiver.check_for_feedback }.not_to raise_error
|
108
115
|
end
|
109
116
|
|
@@ -112,7 +119,9 @@ describe Rapns::Daemon::Apns::FeedbackReceiver, 'check_for_feedback' do
|
|
112
119
|
stub_connection_read_with_tuple
|
113
120
|
callback = Proc.new { raise error }
|
114
121
|
Rapns::Daemon.logger.should_receive(:error).with(error)
|
115
|
-
Rapns.
|
122
|
+
Rapns::Deprecation.silenced do
|
123
|
+
Rapns.config.on_apns_feedback &callback
|
124
|
+
end
|
116
125
|
receiver.check_for_feedback
|
117
126
|
end
|
118
127
|
end
|
@@ -8,6 +8,14 @@ shared_examples_for 'an DeliveryHandler subclass' do
|
|
8
8
|
delivery_handler.send(:handle_next_notification)
|
9
9
|
end
|
10
10
|
|
11
|
+
it 'reflects an exception' do
|
12
|
+
Rapns::Daemon.stub(:logger => stub(:error => nil))
|
13
|
+
error = StandardError.new
|
14
|
+
delivery_handler.stub(:deliver).and_raise(error)
|
15
|
+
delivery_handler.should_receive(:reflect).with(:error, error)
|
16
|
+
delivery_handler.send(:handle_next_notification)
|
17
|
+
end
|
18
|
+
|
11
19
|
it "instructs the queue to wakeup the thread when told to stop" do
|
12
20
|
thread = stub(:join => nil)
|
13
21
|
Thread.stub(:new => thread)
|
@@ -1,19 +1,27 @@
|
|
1
1
|
require "unit_spec_helper"
|
2
2
|
|
3
3
|
describe Rapns::Daemon::Feeder do
|
4
|
-
let(:config) { stub(:batch_size => 5000
|
4
|
+
let(:config) { stub(:batch_size => 5000, :push_poll => 0, :embedded => false,
|
5
|
+
:push => false) }
|
5
6
|
let!(:app) { Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
|
6
7
|
let(:notification) { Rapns::Apns::Notification.create!(:device_token => "a" * 64, :app => app) }
|
7
8
|
let(:logger) { stub }
|
8
9
|
|
9
10
|
before do
|
10
|
-
Rapns
|
11
|
-
Rapns::Daemon::Feeder.
|
11
|
+
Rapns.stub(:config => config)
|
12
|
+
Rapns::Daemon::Feeder.stub(:stop? => true)
|
12
13
|
Rapns::Daemon::AppRunner.stub(:idle => [stub(:app => app)])
|
13
14
|
end
|
14
15
|
|
15
16
|
def start
|
16
|
-
Rapns::Daemon::Feeder.start
|
17
|
+
Rapns::Daemon::Feeder.start
|
18
|
+
end
|
19
|
+
|
20
|
+
it "starts the loop in a new thread if embedded" do
|
21
|
+
config.stub(:embedded => true)
|
22
|
+
Thread.should_receive(:new).and_yield
|
23
|
+
Rapns::Daemon::Feeder.should_receive(:feed_forever)
|
24
|
+
start
|
17
25
|
end
|
18
26
|
|
19
27
|
it "checks for new notifications with the ability to reconnect the database" do
|
@@ -21,6 +29,13 @@ describe Rapns::Daemon::Feeder do
|
|
21
29
|
start
|
22
30
|
end
|
23
31
|
|
32
|
+
it 'enqueues notifications without looping if in push mode' do
|
33
|
+
config.stub(:push => true)
|
34
|
+
Rapns::Daemon::Feeder.should_not_receive(:feed_forever)
|
35
|
+
Rapns::Daemon::Feeder.should_receive(:enqueue_notifications)
|
36
|
+
start
|
37
|
+
end
|
38
|
+
|
24
39
|
it 'loads notifications in batches' do
|
25
40
|
relation = stub.as_null_object
|
26
41
|
relation.should_receive(:limit).with(5000)
|
@@ -28,12 +43,27 @@ describe Rapns::Daemon::Feeder do
|
|
28
43
|
start
|
29
44
|
end
|
30
45
|
|
31
|
-
it
|
46
|
+
it 'does not load notification in batches if in push mode' do
|
47
|
+
config.stub(:push => true)
|
48
|
+
relation = stub.as_null_object
|
49
|
+
relation.should_not_receive(:limit)
|
50
|
+
Rapns::Notification.stub(:ready_for_delivery => relation)
|
51
|
+
start
|
52
|
+
end
|
53
|
+
|
54
|
+
it "enqueues the notification" do
|
32
55
|
notification.update_attributes!(:delivered => false)
|
33
56
|
Rapns::Daemon::AppRunner.should_receive(:enqueue).with(notification)
|
34
57
|
start
|
35
58
|
end
|
36
59
|
|
60
|
+
it 'reflects the notification has been enqueued' do
|
61
|
+
notification.update_attributes!(:delivered => false)
|
62
|
+
Rapns::Daemon::AppRunner.stub(:enqueue)
|
63
|
+
Rapns::Daemon::Feeder.should_receive(:reflect).with(:notification_enqueued, notification)
|
64
|
+
start
|
65
|
+
end
|
66
|
+
|
37
67
|
it 'does not enqueue the notification if the app runner is still processing the previous batch' do
|
38
68
|
Rapns::Daemon::AppRunner.should_not_receive(:enqueue)
|
39
69
|
start
|
@@ -88,8 +118,9 @@ describe Rapns::Daemon::Feeder do
|
|
88
118
|
end
|
89
119
|
|
90
120
|
it "sleeps for the given period" do
|
121
|
+
config.stub(:push_poll => 2)
|
91
122
|
Rapns::Daemon::Feeder.should_receive(:interruptible_sleep).with(2)
|
92
123
|
Rapns::Daemon::Feeder.stub(:loop).and_yield
|
93
|
-
Rapns::Daemon::Feeder.start
|
124
|
+
Rapns::Daemon::Feeder.start
|
94
125
|
end
|
95
126
|
end
|
@@ -7,9 +7,10 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
7
7
|
let(:response) { stub(:code => 200, :header => {}) }
|
8
8
|
let(:http) { stub(:shutdown => nil, :request => response)}
|
9
9
|
let(:now) { Time.parse('2012-10-14 00:00:00') }
|
10
|
+
let(:delivery) { Rapns::Daemon::Gcm::Delivery.new(app, http, notification) }
|
10
11
|
|
11
12
|
def perform
|
12
|
-
|
13
|
+
delivery.perform
|
13
14
|
end
|
14
15
|
|
15
16
|
before do
|
@@ -29,6 +30,12 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
29
30
|
end.to change(notification, :delivered).to(true)
|
30
31
|
end
|
31
32
|
|
33
|
+
it 'reflects the notification was delivered' do
|
34
|
+
response.stub(:body => JSON.dump({ 'failure' => 0 }))
|
35
|
+
delivery.should_receive(:reflect).with(:notification_delivered, notification)
|
36
|
+
perform
|
37
|
+
end
|
38
|
+
|
32
39
|
it 'logs that the notification was delivered' do
|
33
40
|
response.stub(:body => JSON.dump({ 'failure' => 0 }))
|
34
41
|
logger.should_receive(:info).with("[MyApp] 1 sent to xyz")
|
@@ -105,6 +112,11 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
105
112
|
notification.error_description.should == error_description
|
106
113
|
end
|
107
114
|
|
115
|
+
it 'reflects the notification delivery failed' do
|
116
|
+
delivery.should_receive(:reflect).with(:notification_failed, notification)
|
117
|
+
perform rescue Rapns::DeliveryError
|
118
|
+
end
|
119
|
+
|
108
120
|
it 'creates a new notification for the unavailable devices' do
|
109
121
|
notification.update_attributes(:registration_ids => ['id_0', 'id_1', 'id_2'], :data => {'one' => 1}, :collapse_key => 'thing', :delay_while_idle => true)
|
110
122
|
perform rescue Rapns::DeliveryError
|
@@ -179,6 +191,11 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
179
191
|
perform
|
180
192
|
end.to change(notification, :deliver_after).to(now + 2 ** 1)
|
181
193
|
end
|
194
|
+
|
195
|
+
it 'reflects the notification will be retried' do
|
196
|
+
delivery.should_receive(:reflect).with(:notification_will_retry, notification)
|
197
|
+
perform
|
198
|
+
end
|
182
199
|
end
|
183
200
|
|
184
201
|
describe 'an 500 response' do
|
@@ -198,6 +215,11 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
198
215
|
notification.reload
|
199
216
|
end.to change(notification, :deliver_after).to(now + 2 ** 3)
|
200
217
|
end
|
218
|
+
|
219
|
+
it 'reflects the notification will be retried' do
|
220
|
+
delivery.should_receive(:reflect).with(:notification_will_retry, notification)
|
221
|
+
perform
|
222
|
+
end
|
201
223
|
end
|
202
224
|
|
203
225
|
describe 'an 401 response' do
|
@@ -219,6 +241,11 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
219
241
|
notification.error_code.should == 400
|
220
242
|
notification.error_description.should == 'GCM failed to parse the JSON request. Possibly an rapns bug, please open an issue.'
|
221
243
|
end
|
244
|
+
|
245
|
+
it 'reflects the notification delivery failed' do
|
246
|
+
delivery.should_receive(:reflect).with(:notification_failed, notification)
|
247
|
+
perform rescue Rapns::DeliveryError
|
248
|
+
end
|
222
249
|
end
|
223
250
|
|
224
251
|
describe 'an un-handled response' do
|
@@ -232,5 +259,10 @@ describe Rapns::Daemon::Gcm::Delivery do
|
|
232
259
|
notification.error_code.should == 418
|
233
260
|
notification.error_description.should == "I'm a Teapot"
|
234
261
|
end
|
262
|
+
|
263
|
+
it 'reflects the notification delivery failed' do
|
264
|
+
delivery.should_receive(:reflect).with(:notification_failed, notification)
|
265
|
+
perform rescue Rapns::DeliveryError
|
266
|
+
end
|
235
267
|
end
|
236
268
|
end
|