rapns 2.0.5 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/lib/generators/rapns_generator.rb +1 -0
  2. data/lib/generators/templates/add_gcm.rb +86 -0
  3. data/lib/generators/templates/create_rapns_notifications.rb +1 -1
  4. data/lib/rapns/apns/app.rb +8 -0
  5. data/lib/rapns/apns/binary_notification_validator.rb +12 -0
  6. data/lib/rapns/apns/device_token_format_validator.rb +12 -0
  7. data/lib/rapns/apns/feedback.rb +14 -0
  8. data/lib/rapns/apns/notification.rb +84 -0
  9. data/lib/rapns/app.rb +5 -6
  10. data/lib/rapns/{config.rb → configuration.rb} +5 -5
  11. data/lib/rapns/daemon/apns/app_runner.rb +36 -0
  12. data/lib/rapns/daemon/apns/connection.rb +113 -0
  13. data/lib/rapns/daemon/apns/delivery.rb +63 -0
  14. data/lib/rapns/daemon/apns/delivery_handler.rb +21 -0
  15. data/lib/rapns/daemon/apns/disconnection_error.rb +20 -0
  16. data/lib/rapns/daemon/apns/feedback_receiver.rb +74 -0
  17. data/lib/rapns/daemon/app_runner.rb +76 -77
  18. data/lib/rapns/daemon/database_reconnectable.rb +3 -3
  19. data/lib/rapns/daemon/delivery.rb +43 -0
  20. data/lib/rapns/daemon/delivery_error.rb +6 -2
  21. data/lib/rapns/daemon/delivery_handler.rb +13 -79
  22. data/lib/rapns/daemon/delivery_queue_18.rb +2 -2
  23. data/lib/rapns/daemon/delivery_queue_19.rb +3 -3
  24. data/lib/rapns/daemon/feeder.rb +5 -5
  25. data/lib/rapns/daemon/gcm/app_runner.rb +13 -0
  26. data/lib/rapns/daemon/gcm/delivery.rb +206 -0
  27. data/lib/rapns/daemon/gcm/delivery_handler.rb +20 -0
  28. data/lib/rapns/daemon.rb +31 -20
  29. data/lib/rapns/gcm/app.rb +7 -0
  30. data/lib/rapns/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
  31. data/lib/rapns/gcm/notification.rb +31 -0
  32. data/lib/rapns/gcm/payload_size_validator.rb +13 -0
  33. data/lib/rapns/multi_json_helper.rb +16 -0
  34. data/lib/rapns/notification.rb +28 -95
  35. data/lib/rapns/version.rb +1 -1
  36. data/lib/rapns.rb +14 -4
  37. data/lib/tasks/cane.rake +19 -0
  38. data/lib/tasks/test.rake +34 -0
  39. data/spec/acceptance/gcm_upgrade_spec.rb +34 -0
  40. data/spec/acceptance_spec_helper.rb +85 -0
  41. data/spec/support/simplecov_helper.rb +13 -0
  42. data/spec/support/simplecov_quality_formatter.rb +8 -0
  43. data/spec/unit/apns/app_spec.rb +15 -0
  44. data/spec/unit/apns/feedback_spec.rb +12 -0
  45. data/spec/{rapns → unit/apns}/notification_spec.rb +44 -72
  46. data/spec/unit/app_spec.rb +18 -0
  47. data/spec/unit/daemon/apns/app_runner_spec.rb +37 -0
  48. data/spec/{rapns/daemon → unit/daemon/apns}/connection_spec.rb +9 -9
  49. data/spec/unit/daemon/apns/delivery_handler_spec.rb +48 -0
  50. data/spec/unit/daemon/apns/delivery_spec.rb +154 -0
  51. data/spec/{rapns/daemon → unit/daemon/apns}/feedback_receiver_spec.rb +14 -14
  52. data/spec/unit/daemon/app_runner_shared.rb +66 -0
  53. data/spec/unit/daemon/app_runner_spec.rb +78 -0
  54. data/spec/{rapns → unit}/daemon/database_reconnectable_spec.rb +4 -5
  55. data/spec/{rapns → unit}/daemon/delivery_error_spec.rb +2 -2
  56. data/spec/unit/daemon/delivery_handler_shared.rb +19 -0
  57. data/spec/{rapns → unit}/daemon/delivery_queue_spec.rb +1 -1
  58. data/spec/{rapns → unit}/daemon/feeder_spec.rb +33 -33
  59. data/spec/unit/daemon/gcm/app_runner_spec.rb +15 -0
  60. data/spec/unit/daemon/gcm/delivery_handler_spec.rb +36 -0
  61. data/spec/unit/daemon/gcm/delivery_spec.rb +236 -0
  62. data/spec/{rapns → unit}/daemon/interruptible_sleep_spec.rb +1 -1
  63. data/spec/{rapns → unit}/daemon/logger_spec.rb +1 -1
  64. data/spec/{rapns → unit}/daemon_spec.rb +1 -1
  65. data/spec/unit/gcm/app_spec.rb +5 -0
  66. data/spec/unit/gcm/notification_spec.rb +55 -0
  67. data/spec/unit/notification_shared.rb +38 -0
  68. data/spec/unit/notification_spec.rb +6 -0
  69. data/spec/{rapns/app_spec.rb → unit_spec_helper.rb} +76 -16
  70. metadata +107 -45
  71. data/lib/rapns/binary_notification_validator.rb +0 -10
  72. data/lib/rapns/daemon/connection.rb +0 -114
  73. data/lib/rapns/daemon/delivery_handler_pool.rb +0 -18
  74. data/lib/rapns/daemon/disconnection_error.rb +0 -14
  75. data/lib/rapns/daemon/feedback_receiver.rb +0 -82
  76. data/lib/rapns/device_token_format_validator.rb +0 -10
  77. data/lib/rapns/feedback.rb +0 -12
  78. data/spec/rapns/daemon/app_runner_spec.rb +0 -193
  79. data/spec/rapns/daemon/delivery_handler_pool_spec.rb +0 -17
  80. data/spec/rapns/daemon/delivery_handler_spec.rb +0 -206
  81. data/spec/rapns/feedback_spec.rb +0 -12
  82. data/spec/spec_helper.rb +0 -78
@@ -0,0 +1,85 @@
1
+ require 'unit_spec_helper'
2
+ require 'fileutils'
3
+
4
+ ENV['RAILS_ENV'] = 'test'
5
+ require 'bundler'
6
+ Bundler.require(:default)
7
+
8
+ TMP_DIR = '/tmp'
9
+ RAILS_DIR = File.join(TMP_DIR, 'rapns_test')
10
+ if ENV['TRAVIS']
11
+ TRAVIS_BRANCH = 'gcm'
12
+ RAPNS_ROOT = 'git://github.com/ileitch/rapns.git'
13
+ else
14
+ RAPNS_ROOT = File.expand_path(__FILE__ + '/../../')
15
+ end
16
+
17
+ def setup_rails
18
+ return if $rails_is_setup
19
+ `rm -rf #{RAILS_DIR}`
20
+ FileUtils.mkdir_p(RAILS_DIR)
21
+ cmd("bundle exec rails new #{RAILS_DIR} --skip-bundle")
22
+ branch = `git branch | grep '\*'`.split(' ').last
23
+ in_test_rails do
24
+ cmd('echo "gem \'rake\'" >> Gemfile')
25
+ if ENV['TRAVIS']
26
+ cmd("echo \"gem 'rapns', :git => '#{RAPNS_ROOT}', :branch => '#{TRAVIS_BRANCH}'\" >> Gemfile")
27
+ else
28
+ cmd("echo \"gem 'rapns', :git => '#{RAPNS_ROOT}', :branch => '#{branch}'\" >> Gemfile")
29
+ end
30
+
31
+ cmd("bundle install")
32
+ end
33
+ end
34
+
35
+ def as_test_rails_db(env='development')
36
+ orig_config = ActiveRecord::Base.connection_config
37
+ begin
38
+ in_test_rails do
39
+ config = YAML.load_file('config/database.yml')
40
+ ActiveRecord::Base.establish_connection(config[env])
41
+ yield
42
+ end
43
+ ensure
44
+ ActiveRecord::Base.establish_connection(orig_config)
45
+ end
46
+ end
47
+
48
+ def cmd(str, echo = true)
49
+ puts "* #{str.strip}" if echo
50
+ retval = Bundler.with_clean_env { `#{str}` }
51
+ puts retval.strip if echo
52
+ retval
53
+ end
54
+
55
+ def generate
56
+ in_test_rails { cmd('bundle exec rails g rapns') }
57
+ end
58
+
59
+ def migrate(*migrations)
60
+ in_test_rails do
61
+ if migrations.present?
62
+ migrations.each do |name|
63
+ migration = Dir.entries('db/migrate').find { |entry| entry =~ /#{name}/ }
64
+ version = migration.split('_').first
65
+ cmd("bundle exec rake db:migrate VERSION=#{version} RAILS_ENV=development")
66
+ end
67
+ else
68
+ cmd('bundle exec rake db:migrate RAILS_ENV=development')
69
+ end
70
+ end
71
+ end
72
+
73
+ def in_test_rails
74
+ pwd = Dir.pwd
75
+ begin
76
+ Dir.chdir(RAILS_DIR)
77
+ yield
78
+ ensure
79
+ Dir.chdir(pwd)
80
+ end
81
+ end
82
+
83
+ def runner(str)
84
+ in_test_rails { cmd("rails runner -e test '#{str}'").strip }
85
+ end
@@ -0,0 +1,13 @@
1
+ require 'simplecov'
2
+ require './spec/support/simplecov_quality_formatter'
3
+
4
+ module SimpleCovHelper
5
+ def start_simple_cov(name)
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ add_filter '/lib/generators'
9
+ command_name name
10
+ formatter SimpleCov::Formatter::QualityFormatter
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ class SimpleCov::Formatter::QualityFormatter
2
+ def format(result)
3
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
4
+ File.open("coverage/covered_percent", "w") do |f|
5
+ f.puts result.source_files.covered_percent.to_f
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rapns::App do
4
+ it 'does not validate an app with an invalid certificate' do
5
+ app = Rapns::Apns::App.new(:key => 'test', :environment => 'development', :certificate => 'foo')
6
+ app.valid?
7
+ app.errors[:certificate].should == ['Certificate value must contain a certificate and a private key.']
8
+ end
9
+
10
+ it 'validates a real certificate' do
11
+ app = Rapns::Apns::App.new :key => 'test', :environment => 'development', :certificate => TEST_CERT
12
+ app.valid?
13
+ app.errors[:certificate].should == []
14
+ end
15
+ end
@@ -0,0 +1,12 @@
1
+ require "unit_spec_helper"
2
+
3
+ describe Rapns::Apns::Feedback do
4
+ it { should validate_presence_of(:device_token) }
5
+ it { should validate_presence_of(:failed_at) }
6
+
7
+ it "should validate the format of the device_token" do
8
+ notification = Rapns::Apns::Feedback.new(:device_token => "{$%^&*()}")
9
+ notification.valid?.should be_false
10
+ notification.errors[:device_token].include?("is invalid").should be_true
11
+ end
12
+ end
@@ -1,19 +1,24 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rapns::Apns::Notification do
5
+ it_should_behave_like 'an Notification subclass'
2
6
 
3
- describe Rapns::Notification do
4
- it { should validate_presence_of(:app) }
5
7
  it { should validate_presence_of(:device_token) }
6
8
  it { should validate_numericality_of(:badge) }
7
- it { should validate_numericality_of(:expiry) }
9
+
10
+ let(:notification_class) { Rapns::Apns::Notification }
11
+ let(:notification) { notification_class.new }
12
+ let(:data_setter) { 'attributes_for_device=' }
13
+ let(:data_getter) { 'attributes_for_device' }
8
14
 
9
15
  it "should validate the format of the device_token" do
10
- notification = Rapns::Notification.new(:device_token => "{$%^&*()}")
16
+ notification = Rapns::Apns::Notification.new(:device_token => "{$%^&*()}")
11
17
  notification.valid?.should be_false
12
18
  notification.errors[:device_token].include?("is invalid").should be_true
13
19
  end
14
20
 
15
21
  it "should validate the length of the binary conversion of the notification" do
16
- notification = Rapns::Notification.new
17
22
  notification.device_token = "a" * 64
18
23
  notification.alert = "way too long!" * 100
19
24
  notification.valid?.should be_false
@@ -21,90 +26,73 @@ describe Rapns::Notification do
21
26
  end
22
27
 
23
28
  it "should default the sound to 1.aiff" do
24
- Rapns::Notification.new.sound.should == "1.aiff"
29
+ notification.sound.should == "1.aiff"
25
30
  end
26
31
 
27
32
  it "should default the expiry to 1 day" do
28
- Rapns::Notification.new.expiry.should == 1.day.to_i
33
+ notification.expiry.should == 1.day.to_i
29
34
  end
30
35
  end
31
36
 
32
- describe Rapns::Notification, "when assigning the device token" do
37
+ describe Rapns::Apns::Notification, "when assigning the device token" do
33
38
  it "should strip spaces from the given string" do
34
- notification = Rapns::Notification.new(:device_token => "o m g")
39
+ notification = Rapns::Apns::Notification.new(:device_token => "o m g")
35
40
  notification.device_token.should == "omg"
36
41
  end
37
42
 
38
43
  it "should strip chevrons from the given string" do
39
- notification = Rapns::Notification.new(:device_token => "<omg>")
44
+ notification = Rapns::Apns::Notification.new(:device_token => "<omg>")
40
45
  notification.device_token.should == "omg"
41
46
  end
42
47
  end
43
48
 
44
- describe Rapns::Notification, "when assigning the attributes for the device" do
45
- it "should raise an ArgumentError if something other than a Hash is assigned" do
46
- expect { Rapns::Notification.new(:attributes_for_device => Array.new) }.to \
47
- raise_error(ArgumentError, "attributes_for_device must be a Hash")
48
- end
49
-
50
- it "should encode the given Hash as JSON" do
51
- notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
52
- notification.read_attribute(:attributes_for_device).should == "{\"hi\":\"mom\"}"
53
- end
54
-
55
- it "should decode the JSON when using the reader method" do
56
- notification = Rapns::Notification.new(:attributes_for_device => {:hi => "mom"})
57
- notification.attributes_for_device.should == {"hi" => "mom"}
58
- end
59
- end
60
-
61
- describe Rapns::Notification, "as_json" do
49
+ describe Rapns::Apns::Notification, "as_json" do
62
50
  it "should include the alert if present" do
63
- notification = Rapns::Notification.new(:alert => "hi mom")
51
+ notification = Rapns::Apns::Notification.new(:alert => "hi mom")
64
52
  notification.as_json["aps"]["alert"].should == "hi mom"
65
53
  end
66
54
 
67
55
  it "should not include the alert key if the alert is not present" do
68
- notification = Rapns::Notification.new(:alert => nil)
56
+ notification = Rapns::Apns::Notification.new(:alert => nil)
69
57
  notification.as_json["aps"].key?("alert").should be_false
70
58
  end
71
59
 
72
60
  it "should encode the alert as JSON if it is a Hash" do
73
- notification = Rapns::Notification.new(:alert => { 'body' => "hi mom", 'alert-loc-key' => "View" })
61
+ notification = Rapns::Apns::Notification.new(:alert => { 'body' => "hi mom", 'alert-loc-key' => "View" })
74
62
  notification.as_json["aps"]["alert"].should == { 'body' => "hi mom", 'alert-loc-key' => "View" }
75
63
  end
76
64
 
77
65
  it "should include the badge if present" do
78
- notification = Rapns::Notification.new(:badge => 6)
66
+ notification = Rapns::Apns::Notification.new(:badge => 6)
79
67
  notification.as_json["aps"]["badge"].should == 6
80
68
  end
81
69
 
82
70
  it "should not include the badge key if the badge is not present" do
83
- notification = Rapns::Notification.new(:badge => nil)
71
+ notification = Rapns::Apns::Notification.new(:badge => nil)
84
72
  notification.as_json["aps"].key?("badge").should be_false
85
73
  end
86
74
 
87
75
  it "should include the sound if present" do
88
- notification = Rapns::Notification.new(:alert => "my_sound.aiff")
76
+ notification = Rapns::Apns::Notification.new(:alert => "my_sound.aiff")
89
77
  notification.as_json["aps"]["alert"].should == "my_sound.aiff"
90
78
  end
91
79
 
92
80
  it "should not include the sound key if the sound is not present" do
93
- notification = Rapns::Notification.new(:sound => false)
81
+ notification = Rapns::Apns::Notification.new(:sound => false)
94
82
  notification.as_json["aps"].key?("sound").should be_false
95
83
  end
96
84
 
97
- it "should include attrbutes for the device" do
98
- notification = Rapns::Notification.new
85
+ it "should include attributes for the device" do
86
+ notification = Rapns::Apns::Notification.new
99
87
  notification.attributes_for_device = {:omg => :lol, :wtf => :dunno}
100
88
  notification.as_json["omg"].should == "lol"
101
89
  notification.as_json["wtf"].should == "dunno"
102
90
  end
103
91
  end
104
92
 
105
- describe Rapns::Notification, 'MDM' do
93
+ describe Rapns::Apns::Notification, 'MDM' do
106
94
  let(:magic) { 'abc123' }
107
- let(:notification) { Rapns::Notification.new }
95
+ let(:notification) { Rapns::Apns::Notification.new }
108
96
 
109
97
  it 'includes the mdm magic in the payload' do
110
98
  notification.mdm = magic
@@ -118,8 +106,8 @@ describe Rapns::Notification, 'MDM' do
118
106
  end
119
107
  end
120
108
 
121
- describe Rapns::Notification, 'content-available' do
122
- let(:notification) { Rapns::Notification.new }
109
+ describe Rapns::Apns::Notification, 'content-available' do
110
+ let(:notification) { Rapns::Apns::Notification.new }
123
111
 
124
112
  it 'includes content-available in the payload' do
125
113
  notification.content_available = true
@@ -136,43 +124,43 @@ describe Rapns::Notification, 'content-available' do
136
124
  end
137
125
  end
138
126
 
139
- describe Rapns::Notification, "to_binary" do
127
+ describe Rapns::Apns::Notification, "to_binary" do
140
128
  it "should correctly convert the notification to binary" do
141
- notification = Rapns::Notification.new
129
+ notification = Rapns::Apns::Notification.new
142
130
  notification.device_token = "a" * 64
143
131
  notification.sound = "1.aiff"
144
132
  notification.badge = 3
145
133
  notification.alert = "Don't panic Mr Mainwaring, don't panic!"
146
134
  notification.attributes_for_device = {:hi => :mom}
147
135
  notification.expiry = 86400 # 1 day, \x00\x01Q\x80
148
- notification.app = 'my_app'
136
+ notification.app = Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
149
137
  notification.save!
150
138
  notification.stub(:id).and_return(1234)
151
139
  notification.to_binary.should == "\x01\x00\x00\x04\xD2\x00\x01Q\x80\x00 \xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\x00a{\"aps\":{\"alert\":\"Don't panic Mr Mainwaring, don't panic!\",\"badge\":3,\"sound\":\"1.aiff\"},\"hi\":\"mom\"}"
152
140
  end
153
141
  end
154
142
 
155
- describe Rapns::Notification, "bug #31" do
143
+ describe Rapns::Apns::Notification, "bug #31" do
156
144
  it 'does not confuse a JSON looking string as JSON' do
157
- notification = Rapns::Notification.new
145
+ notification = Rapns::Apns::Notification.new
158
146
  notification.alert = "{\"one\":2}"
159
147
  notification.alert.should == "{\"one\":2}"
160
148
  end
161
149
 
162
150
  it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
163
- notification = Rapns::Notification.new
151
+ notification = Rapns::Apns::Notification.new
164
152
  notification.stub(:has_attribute? => false)
165
153
  notification.alert = "{\"one\":2}"
166
154
  notification.alert.should == {"one" => 2}
167
155
  end
168
156
  end
169
157
 
170
- describe Rapns::Notification, "bug #35" do
158
+ describe Rapns::Apns::Notification, "bug #35" do
171
159
  it "should limit payload size to 256 bytes but not the entire packet" do
172
- notification = Rapns::Notification.new do |n|
160
+ notification = Rapns::Apns::Notification.new do |n|
173
161
  n.device_token = "a" * 64
174
162
  n.alert = "a" * 210
175
- n.app = 'my_app'
163
+ n.app = Rapns::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
176
164
  end
177
165
 
178
166
  notification.to_binary(:for_validation => true).bytesize.should > 256
@@ -181,36 +169,20 @@ describe Rapns::Notification, "bug #35" do
181
169
  end
182
170
  end
183
171
 
184
- describe Rapns::Notification, "multi_json usage" do
185
- describe Rapns::Notification, "alert" do
172
+ describe Rapns::Apns::Notification, "multi_json usage" do
173
+ describe Rapns::Apns::Notification, "alert" do
186
174
  it "should call MultiJson.load when multi_json version is 1.3.0" do
187
- notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
175
+ notification = Rapns::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
188
176
  Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.3.0') } )
189
177
  MultiJson.should_receive(:load).with(any_args())
190
178
  notification.alert
191
179
  end
192
180
 
193
181
  it "should call MultiJson.decode when multi_json version is 1.2.9" do
194
- notification = Rapns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
182
+ notification = Rapns::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
195
183
  Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.2.9') } )
196
184
  MultiJson.should_receive(:decode).with(any_args())
197
185
  notification.alert
198
186
  end
199
187
  end
200
-
201
- describe Rapns::Notification, "attributes_for_device=" do
202
- it "should call MultiJson.dump when multi_json responds to :dump" do
203
- notification = Rapns::Notification.new
204
- MultiJson.stub(:respond_to?).with(:dump).and_return(true)
205
- MultiJson.should_receive(:dump).with(any_args())
206
- notification.attributes_for_device = { :pirates => 1 }
207
- end
208
-
209
- it "should call MultiJson.encode when multi_json does not respond to :dump" do
210
- notification = Rapns::Notification.new
211
- MultiJson.stub(:respond_to?).with(:dump).and_return(false)
212
- MultiJson.should_receive(:encode).with(any_args())
213
- notification.attributes_for_device = { :ninjas => 1 }
214
- end
215
- end
216
- end
188
+ end
@@ -0,0 +1,18 @@
1
+ require "unit_spec_helper"
2
+
3
+ describe Rapns::App do
4
+ it { should validate_numericality_of(:connections) }
5
+
6
+ it 'validates the uniqueness of name within type and environment' do
7
+ Rapns::Apns::App.create!(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
8
+ app = Rapns::Apns::App.new(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
9
+ app.valid?.should be_false
10
+ app.errors[:name].should == ['has already been taken']
11
+
12
+ app = Rapns::Apns::App.new(:name => 'test', :environment => 'development', :certificate => TEST_CERT)
13
+ app.valid?.should be_true
14
+
15
+ app = Rapns::Gcm::App.new(:name => 'test', :environment => 'production', :auth_key => TEST_CERT)
16
+ app.valid?.should be_true
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ require 'unit_spec_helper'
2
+ require File.dirname(__FILE__) + '/../app_runner_shared.rb'
3
+
4
+ describe Rapns::Daemon::Apns::AppRunner do
5
+ it_behaves_like 'an AppRunner subclass'
6
+
7
+ let(:app_class) { Rapns::Apns::App }
8
+ let(:app) { app_class.create!(:name => 'my_app', :environment => 'development',
9
+ :certificate => TEST_CERT, :password => 'pass') }
10
+ let(:runner) { Rapns::Daemon::Apns::AppRunner.new(app) }
11
+ let(:handler) { stub(:start => nil, :stop => nil, :queue= => nil) }
12
+ let(:receiver) { stub(:start => nil, :stop => nil) }
13
+ let(:config) { {:feedback_poll => 60 } }
14
+
15
+ before do
16
+ Rapns::Daemon::Apns::DeliveryHandler.stub(:new => handler)
17
+ Rapns::Daemon::Apns::FeedbackReceiver.stub(:new => receiver)
18
+ Rapns::Daemon.stub(:config => config)
19
+ end
20
+
21
+ it 'instantiates a new feedback receiver when started' do
22
+ Rapns::Daemon::Apns::FeedbackReceiver.should_receive(:new).with(app, 'feedback.sandbox.push.apple.com',
23
+ 2196, 60)
24
+ runner.start
25
+ end
26
+
27
+ it 'starts the feedback receiver' do
28
+ receiver.should_receive(:start)
29
+ runner.start
30
+ end
31
+
32
+ it 'stops the feedback receiver' do
33
+ runner.start
34
+ receiver.should_receive(:stop)
35
+ runner.stop
36
+ end
37
+ end
@@ -1,6 +1,6 @@
1
- require "spec_helper"
1
+ require "unit_spec_helper"
2
2
 
3
- describe Rapns::Daemon::Connection do
3
+ describe Rapns::Daemon::Apns::Connection do
4
4
  let(:ssl_context) { stub(:key= => nil, :cert= => nil) }
5
5
  let(:rsa_key) { stub }
6
6
  let(:certificate) { stub }
@@ -11,7 +11,7 @@ describe Rapns::Daemon::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::Connection.new('Connection 0', host, port, certificate, password) }
14
+ let(:connection) { Rapns::Daemon::Apns::Connection.new('Connection 0', host, port, certificate, password) }
15
15
 
16
16
  before do
17
17
  OpenSSL::SSL::SSLContext.stub(:new => ssl_context)
@@ -125,7 +125,7 @@ describe Rapns::Daemon::Connection do
125
125
  logger.should_receive(:error).with("[Connection 0] Lost connection to gateway.push.apple.com:2195 (#{error_type.name}), reconnecting...").once
126
126
  begin
127
127
  connection.write(nil)
128
- rescue Rapns::Daemon::ConnectionError
128
+ rescue Rapns::Daemon::Apns::ConnectionError
129
129
  end
130
130
  end
131
131
 
@@ -133,21 +133,21 @@ describe Rapns::Daemon::Connection do
133
133
  connection.should_receive(:reconnect).exactly(3).times
134
134
  begin
135
135
  connection.write(nil)
136
- rescue Rapns::Daemon::ConnectionError
136
+ rescue Rapns::Daemon::Apns::ConnectionError
137
137
  end
138
138
  end
139
139
 
140
140
  it "raises a ConnectionError after 3 attempts at reconnecting" do
141
141
  expect do
142
142
  connection.write(nil)
143
- end.to raise_error(Rapns::Daemon::ConnectionError, "Connection 0 tried 3 times to reconnect but failed (#{error_type.name}).")
143
+ end.to raise_error(Rapns::Daemon::Apns::ConnectionError, "Connection 0 tried 3 times to reconnect but failed (#{error_type.name}).")
144
144
  end
145
145
 
146
146
  it "sleeps 1 second before retrying the connection" do
147
147
  connection.should_receive(:sleep).with(1)
148
148
  begin
149
149
  connection.write(nil)
150
- rescue Rapns::Daemon::ConnectionError
150
+ rescue Rapns::Daemon::Apns::ConnectionError
151
151
  end
152
152
  end
153
153
  end
@@ -206,7 +206,7 @@ describe Rapns::Daemon::Connection do
206
206
  before { connection.connect }
207
207
 
208
208
  it 'reconnects if the connection has been idle for more than the defined period' do
209
- Rapns::Daemon::Connection.stub(:idle_period => 0.1)
209
+ Rapns::Daemon::Apns::Connection.stub(:idle_period => 0.1)
210
210
  sleep 0.2
211
211
  connection.should_receive(:reconnect)
212
212
  connection.write('blah')
@@ -225,7 +225,7 @@ describe Rapns::Daemon::Connection do
225
225
  end
226
226
 
227
227
  it 'logs the the connection is idle' do
228
- Rapns::Daemon::Connection.stub(:idle_period => 0.1)
228
+ Rapns::Daemon::Apns::Connection.stub(:idle_period => 0.1)
229
229
  sleep 0.2
230
230
  Rapns::Daemon.logger.should_receive(:info).with('[Connection 0] Idle period exceeded, reconnecting...')
231
231
  connection.write('blah')
@@ -0,0 +1,48 @@
1
+ require 'unit_spec_helper'
2
+ require File.dirname(__FILE__) + '/../delivery_handler_shared.rb'
3
+
4
+ describe Rapns::Daemon::Apns::DeliveryHandler do
5
+ it_should_behave_like 'an DeliveryHandler subclass'
6
+
7
+ let(:host) { 'localhost' }
8
+ let(:port) { 2195 }
9
+ let(:certificate) { stub }
10
+ let(:password) { stub }
11
+ let(:app) { stub(:password => password, :certificate => certificate, :name => 'MyApp')}
12
+ let(:delivery_handler) { Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port) }
13
+ let(:connection) { stub('Connection', :select => false, :write => nil, :reconnect => nil, :close => nil, :connect => nil) }
14
+ let(:notification) { stub }
15
+ let(:http) { stub(:shutdown => nil)}
16
+ let(:queue) { Rapns::Daemon::DeliveryQueue.new }
17
+
18
+ before do
19
+ Rapns::Daemon::Apns::Connection.stub(:new => connection)
20
+ Rapns::Daemon::Apns::Delivery.stub(:perform)
21
+ delivery_handler.queue = queue
22
+ queue.push(notification)
23
+ end
24
+
25
+ it "instantiates a new connection" do
26
+ Rapns::Daemon::Apns::Connection.should_receive(:new).with(app.name, host, port, certificate, password)
27
+ Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port)
28
+ end
29
+
30
+ it 'performs delivery of an notification' do
31
+ Rapns::Daemon::Apns::Delivery.should_receive(:perform).with(app, connection, notification)
32
+ delivery_handler.start
33
+ delivery_handler.stop
34
+ end
35
+
36
+ it "connects the socket when instantiated" do
37
+ connection.should_receive(:connect)
38
+ Rapns::Daemon::Apns::DeliveryHandler.new(app, host, port)
39
+ delivery_handler.start
40
+ delivery_handler.stop
41
+ end
42
+
43
+ it 'closes the connection stopped' do
44
+ connection.should_receive(:close)
45
+ delivery_handler.start
46
+ delivery_handler.stop
47
+ end
48
+ end