rapns 3.0.1-java → 3.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
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