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.
Files changed (46) hide show
  1. data/CHANGELOG.md +10 -2
  2. data/README.md +26 -3
  3. data/bin/rapns +2 -7
  4. data/lib/generators/templates/add_gcm.rb +3 -1
  5. data/lib/generators/templates/rapns.rb +42 -11
  6. data/lib/rapns.rb +11 -1
  7. data/lib/rapns/apns/notification.rb +8 -2
  8. data/lib/rapns/app.rb +3 -3
  9. data/lib/rapns/configuration.rb +46 -13
  10. data/lib/rapns/daemon.rb +33 -22
  11. data/lib/rapns/daemon/apns/connection.rb +12 -9
  12. data/lib/rapns/daemon/apns/delivery_handler.rb +1 -1
  13. data/lib/rapns/daemon/apns/feedback_receiver.rb +6 -2
  14. data/lib/rapns/daemon/app_runner.rb +23 -7
  15. data/lib/rapns/daemon/delivery.rb +5 -1
  16. data/lib/rapns/daemon/delivery_handler.rb +4 -0
  17. data/lib/rapns/daemon/feeder.rb +26 -5
  18. data/lib/rapns/daemon/reflectable.rb +13 -0
  19. data/lib/rapns/embed.rb +28 -0
  20. data/lib/rapns/gcm/notification.rb +7 -2
  21. data/lib/rapns/gcm/payload_data_size_validator.rb +13 -0
  22. data/lib/rapns/gcm/registration_ids_count_validator.rb +13 -0
  23. data/lib/rapns/push.rb +12 -0
  24. data/lib/rapns/reflection.rb +44 -0
  25. data/lib/rapns/version.rb +1 -1
  26. data/spec/support/cert_with_password.pem +90 -0
  27. data/spec/support/cert_without_password.pem +59 -0
  28. data/spec/unit/apns/app_spec.rb +15 -1
  29. data/spec/unit/apns/notification_spec.rb +16 -1
  30. data/spec/unit/configuration_spec.rb +10 -1
  31. data/spec/unit/daemon/apns/connection_spec.rb +11 -2
  32. data/spec/unit/daemon/apns/delivery_handler_spec.rb +1 -1
  33. data/spec/unit/daemon/apns/delivery_spec.rb +10 -0
  34. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +16 -7
  35. data/spec/unit/daemon/delivery_handler_shared.rb +8 -0
  36. data/spec/unit/daemon/feeder_spec.rb +37 -6
  37. data/spec/unit/daemon/gcm/delivery_spec.rb +33 -1
  38. data/spec/unit/daemon/reflectable_spec.rb +27 -0
  39. data/spec/unit/daemon_spec.rb +55 -9
  40. data/spec/unit/embed_spec.rb +44 -0
  41. data/spec/unit/gcm/notification_spec.rb +9 -3
  42. data/spec/unit/push_spec.rb +28 -0
  43. data/spec/unit/reflection_spec.rb +34 -0
  44. data/spec/unit_spec_helper.rb +4 -62
  45. metadata +22 -5
  46. 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-----
@@ -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 real certificate' do
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 convert-available as a non-aps attribute' do
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
- config.on_apns_feedback(&b)
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(:connection) { Rapns::Daemon::Apns::Connection.new('Connection 0', host, port, certificate, password) }
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.name, host, port, certificate, password)
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("FeedbackReceiver:#{app.name}", host, port, certificate, password)
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("[FeedbackReceiver:my_app] Delivery failed at 2011-12-10 16:08:45 UTC for 834f786655eb9f84614a05ad7d00af31e5cfe93ac3ea078f1da44d2a4eb0ce17")
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.config.on_apns_feedback &callback
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.config.on_apns_feedback &callback
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::Daemon.stub(:logger => logger, :config => config)
11
- Rapns::Daemon::Feeder.instance_variable_set("@stop", true)
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(0)
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 "enqueue the notification" do
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(2)
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
- Rapns::Daemon::Gcm::Delivery.perform(app, http, notification)
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