rpush 1.0.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +99 -0
- data/LICENSE +7 -0
- data/README.md +189 -0
- data/bin/rpush +36 -0
- data/config/database.yml +44 -0
- data/lib/generators/rpush_generator.rb +44 -0
- data/lib/generators/templates/add_adm.rb +23 -0
- data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
- data/lib/generators/templates/add_app_to_rapns.rb +11 -0
- data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
- data/lib/generators/templates/add_gcm.rb +102 -0
- data/lib/generators/templates/add_rpush.rb +349 -0
- data/lib/generators/templates/add_wpns.rb +16 -0
- data/lib/generators/templates/create_rapns_apps.rb +16 -0
- data/lib/generators/templates/create_rapns_feedback.rb +18 -0
- data/lib/generators/templates/create_rapns_notifications.rb +29 -0
- data/lib/generators/templates/rename_rapns_to_rpush.rb +63 -0
- data/lib/generators/templates/rpush.rb +104 -0
- data/lib/rpush.rb +62 -0
- data/lib/rpush/TODO +3 -0
- data/lib/rpush/adm/app.rb +15 -0
- data/lib/rpush/adm/data_validator.rb +11 -0
- data/lib/rpush/adm/notification.rb +29 -0
- data/lib/rpush/apns/app.rb +29 -0
- data/lib/rpush/apns/binary_notification_validator.rb +12 -0
- data/lib/rpush/apns/device_token_format_validator.rb +12 -0
- data/lib/rpush/apns/feedback.rb +16 -0
- data/lib/rpush/apns/notification.rb +84 -0
- data/lib/rpush/apns_feedback.rb +13 -0
- data/lib/rpush/app.rb +18 -0
- data/lib/rpush/configuration.rb +75 -0
- data/lib/rpush/daemon.rb +140 -0
- data/lib/rpush/daemon/adm.rb +9 -0
- data/lib/rpush/daemon/adm/delivery.rb +222 -0
- data/lib/rpush/daemon/apns.rb +16 -0
- data/lib/rpush/daemon/apns/certificate_expired_error.rb +20 -0
- data/lib/rpush/daemon/apns/delivery.rb +64 -0
- data/lib/rpush/daemon/apns/disconnection_error.rb +20 -0
- data/lib/rpush/daemon/apns/feedback_receiver.rb +79 -0
- data/lib/rpush/daemon/app_runner.rb +187 -0
- data/lib/rpush/daemon/batch.rb +115 -0
- data/lib/rpush/daemon/constants.rb +59 -0
- data/lib/rpush/daemon/delivery.rb +28 -0
- data/lib/rpush/daemon/delivery_error.rb +19 -0
- data/lib/rpush/daemon/dispatcher/http.rb +21 -0
- data/lib/rpush/daemon/dispatcher/tcp.rb +30 -0
- data/lib/rpush/daemon/dispatcher_loop.rb +54 -0
- data/lib/rpush/daemon/dispatcher_loop_collection.rb +33 -0
- data/lib/rpush/daemon/feeder.rb +68 -0
- data/lib/rpush/daemon/gcm.rb +9 -0
- data/lib/rpush/daemon/gcm/delivery.rb +222 -0
- data/lib/rpush/daemon/interruptible_sleep.rb +61 -0
- data/lib/rpush/daemon/loggable.rb +31 -0
- data/lib/rpush/daemon/reflectable.rb +13 -0
- data/lib/rpush/daemon/retry_header_parser.rb +23 -0
- data/lib/rpush/daemon/retryable_error.rb +20 -0
- data/lib/rpush/daemon/service_config_methods.rb +33 -0
- data/lib/rpush/daemon/store/active_record.rb +154 -0
- data/lib/rpush/daemon/store/active_record/reconnectable.rb +68 -0
- data/lib/rpush/daemon/tcp_connection.rb +143 -0
- data/lib/rpush/daemon/too_many_requests_error.rb +20 -0
- data/lib/rpush/daemon/wpns.rb +9 -0
- data/lib/rpush/daemon/wpns/delivery.rb +132 -0
- data/lib/rpush/deprecatable.rb +23 -0
- data/lib/rpush/deprecation.rb +23 -0
- data/lib/rpush/embed.rb +28 -0
- data/lib/rpush/gcm/app.rb +11 -0
- data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
- data/lib/rpush/gcm/notification.rb +30 -0
- data/lib/rpush/logger.rb +63 -0
- data/lib/rpush/multi_json_helper.rb +16 -0
- data/lib/rpush/notification.rb +69 -0
- data/lib/rpush/notifier.rb +52 -0
- data/lib/rpush/payload_data_size_validator.rb +10 -0
- data/lib/rpush/push.rb +16 -0
- data/lib/rpush/railtie.rb +11 -0
- data/lib/rpush/reflection.rb +58 -0
- data/lib/rpush/registration_ids_count_validator.rb +10 -0
- data/lib/rpush/version.rb +3 -0
- data/lib/rpush/wpns/app.rb +9 -0
- data/lib/rpush/wpns/notification.rb +26 -0
- data/lib/tasks/cane.rake +18 -0
- data/lib/tasks/rpush.rake +16 -0
- data/lib/tasks/test.rake +38 -0
- data/spec/functional/adm_spec.rb +43 -0
- data/spec/functional/apns_spec.rb +58 -0
- data/spec/functional/embed_spec.rb +49 -0
- data/spec/functional/gcm_spec.rb +42 -0
- data/spec/functional/wpns_spec.rb +41 -0
- data/spec/support/cert_with_password.pem +90 -0
- data/spec/support/cert_without_password.pem +59 -0
- data/spec/support/install.sh +32 -0
- data/spec/support/simplecov_helper.rb +20 -0
- data/spec/support/simplecov_quality_formatter.rb +8 -0
- data/spec/tmp/.gitkeep +0 -0
- data/spec/unit/adm/app_spec.rb +58 -0
- data/spec/unit/adm/notification_spec.rb +45 -0
- data/spec/unit/apns/app_spec.rb +29 -0
- data/spec/unit/apns/feedback_spec.rb +9 -0
- data/spec/unit/apns/notification_spec.rb +208 -0
- data/spec/unit/apns_feedback_spec.rb +21 -0
- data/spec/unit/app_spec.rb +30 -0
- data/spec/unit/configuration_spec.rb +45 -0
- data/spec/unit/daemon/adm/delivery_spec.rb +243 -0
- data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
- data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
- data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
- data/spec/unit/daemon/apns/feedback_receiver_spec.rb +117 -0
- data/spec/unit/daemon/app_runner_spec.rb +292 -0
- data/spec/unit/daemon/batch_spec.rb +232 -0
- data/spec/unit/daemon/delivery_error_spec.rb +13 -0
- data/spec/unit/daemon/delivery_spec.rb +38 -0
- data/spec/unit/daemon/dispatcher/http_spec.rb +33 -0
- data/spec/unit/daemon/dispatcher/tcp_spec.rb +38 -0
- data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +37 -0
- data/spec/unit/daemon/dispatcher_loop_spec.rb +71 -0
- data/spec/unit/daemon/feeder_spec.rb +98 -0
- data/spec/unit/daemon/gcm/delivery_spec.rb +310 -0
- data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
- data/spec/unit/daemon/reflectable_spec.rb +27 -0
- data/spec/unit/daemon/retryable_error_spec.rb +14 -0
- data/spec/unit/daemon/service_config_methods_spec.rb +33 -0
- data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
- data/spec/unit/daemon/store/active_record_spec.rb +357 -0
- data/spec/unit/daemon/tcp_connection_spec.rb +287 -0
- data/spec/unit/daemon/too_many_requests_error_spec.rb +14 -0
- data/spec/unit/daemon/wpns/delivery_spec.rb +159 -0
- data/spec/unit/daemon_spec.rb +159 -0
- data/spec/unit/deprecatable_spec.rb +32 -0
- data/spec/unit/deprecation_spec.rb +15 -0
- data/spec/unit/embed_spec.rb +50 -0
- data/spec/unit/gcm/app_spec.rb +4 -0
- data/spec/unit/gcm/notification_spec.rb +36 -0
- data/spec/unit/logger_spec.rb +127 -0
- data/spec/unit/notification_shared.rb +105 -0
- data/spec/unit/notification_spec.rb +15 -0
- data/spec/unit/notifier_spec.rb +49 -0
- data/spec/unit/push_spec.rb +43 -0
- data/spec/unit/reflection_spec.rb +30 -0
- data/spec/unit/rpush_spec.rb +9 -0
- data/spec/unit/wpns/app_spec.rb +4 -0
- data/spec/unit/wpns/notification_spec.rb +30 -0
- data/spec/unit_spec_helper.rb +101 -0
- metadata +276 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
require 'rpush/daemon/store/active_record'
|
|
3
|
+
|
|
4
|
+
describe Rpush::Daemon, "when starting" do
|
|
5
|
+
module Rails; end
|
|
6
|
+
|
|
7
|
+
let(:certificate) { double }
|
|
8
|
+
let(:password) { double }
|
|
9
|
+
let(:config) { double(:pid_file => nil, :foreground => true,
|
|
10
|
+
:embedded => false, :push => false, :store => :active_record,
|
|
11
|
+
:logger => nil) }
|
|
12
|
+
let(:logger) { double(:logger, :info => nil, :error => nil, :warn => nil) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
Rpush.stub(:config => config, :logger => logger)
|
|
16
|
+
Rpush::Daemon::Feeder.stub(:start)
|
|
17
|
+
Rpush::Daemon::AppRunner.stub(:sync => nil, :stop => nil)
|
|
18
|
+
Rpush::Daemon.stub(:daemonize => nil, :exit => nil, :puts => nil)
|
|
19
|
+
File.stub(:open)
|
|
20
|
+
Rails.stub(:root).and_return("/rails_root")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
unless Rpush.jruby?
|
|
24
|
+
it "forks into a daemon if the foreground option is false" do
|
|
25
|
+
config.stub(:foreground => false)
|
|
26
|
+
Rpush::Daemon.initialize_store
|
|
27
|
+
Rpush::Daemon.store.stub(:after_daemonize => nil)
|
|
28
|
+
Rpush::Daemon.should_receive(:daemonize)
|
|
29
|
+
Rpush::Daemon.start
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'notifies the store after forking' do
|
|
33
|
+
config.stub(:foreground => false)
|
|
34
|
+
Rpush::Daemon.initialize_store
|
|
35
|
+
Rpush::Daemon.store.should_receive(:after_daemonize)
|
|
36
|
+
Rpush::Daemon.start
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "does not fork into a daemon if the foreground option is true" do
|
|
40
|
+
config.stub(:foreground => true)
|
|
41
|
+
Rpush::Daemon.should_not_receive(:daemonize)
|
|
42
|
+
Rpush::Daemon.start
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "does not fork into a daemon if the push option is true" do
|
|
46
|
+
config.stub(:push => true)
|
|
47
|
+
Rpush::Daemon.should_not_receive(:daemonize)
|
|
48
|
+
Rpush::Daemon.start
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "does not fork into a daemon if the embedded option is true" do
|
|
52
|
+
config.stub(:embedded => true)
|
|
53
|
+
Rpush::Daemon.should_not_receive(:daemonize)
|
|
54
|
+
Rpush::Daemon.start
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'sets up setup signal traps' do
|
|
59
|
+
Rpush::Daemon.should_receive(:setup_signal_traps)
|
|
60
|
+
Rpush::Daemon.start
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'does not setup signal traps when embedded' do
|
|
64
|
+
config.stub(:embedded => true)
|
|
65
|
+
Rpush::Daemon.should_not_receive(:setup_signal_traps)
|
|
66
|
+
Rpush::Daemon.start
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'instantiates the store' do
|
|
70
|
+
config.stub(:store => :active_record)
|
|
71
|
+
Rpush::Daemon.start
|
|
72
|
+
Rpush::Daemon.store.should be_kind_of(Rpush::Daemon::Store::ActiveRecord)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'logs an error if the store cannot be loaded' do
|
|
76
|
+
config.stub(:store => :foo_bar)
|
|
77
|
+
Rpush.logger.should_receive(:error).with(kind_of(LoadError))
|
|
78
|
+
Rpush::Daemon.start
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "writes the process ID to the PID file" do
|
|
82
|
+
Rpush::Daemon.should_receive(:write_pid_file)
|
|
83
|
+
Rpush::Daemon.start
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "logs an error if the PID file could not be written" do
|
|
87
|
+
config.stub(:pid_file => '/rails_root/rpush.pid')
|
|
88
|
+
File.stub(:open).and_raise(Errno::ENOENT)
|
|
89
|
+
logger.should_receive(:error).with("Failed to write PID to '/rails_root/rpush.pid': #<Errno::ENOENT: No such file or directory>")
|
|
90
|
+
Rpush::Daemon.start
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "starts the feeder" do
|
|
94
|
+
Rpush::Daemon::Feeder.should_receive(:start)
|
|
95
|
+
Rpush::Daemon.start
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "syncs apps" do
|
|
99
|
+
Rpush::Daemon::AppRunner.should_receive(:sync)
|
|
100
|
+
Rpush::Daemon.start
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe Rpush::Daemon, "when being shutdown" do
|
|
105
|
+
let(:config) { double(:pid_file => '/rails_root/rpush.pid') }
|
|
106
|
+
let(:logger) { double(:info => nil, :error => nil, :warn => nil) }
|
|
107
|
+
|
|
108
|
+
before do
|
|
109
|
+
Rpush.stub(:config => config)
|
|
110
|
+
Rpush::Daemon.stub(:puts => nil)
|
|
111
|
+
Rpush::Daemon::Feeder.stub(:stop)
|
|
112
|
+
Rpush::Daemon::AppRunner.stub(:stop)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# These tests do not work on JRuby.
|
|
116
|
+
unless Rpush.jruby?
|
|
117
|
+
it "shuts down when signaled signaled SIGINT" do
|
|
118
|
+
Rpush::Daemon.setup_signal_traps
|
|
119
|
+
Rpush::Daemon.should_receive(:shutdown)
|
|
120
|
+
Process.kill("SIGINT", Process.pid)
|
|
121
|
+
sleep 0.01
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "shuts down when signaled signaled SIGTERM" do
|
|
125
|
+
Rpush::Daemon.setup_signal_traps
|
|
126
|
+
Rpush::Daemon.should_receive(:shutdown)
|
|
127
|
+
Process.kill("SIGTERM", Process.pid)
|
|
128
|
+
sleep 0.01
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "stops the feeder" do
|
|
133
|
+
Rpush::Daemon::Feeder.should_receive(:stop)
|
|
134
|
+
Rpush::Daemon.shutdown
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "stops the app runners" do
|
|
138
|
+
Rpush::Daemon::AppRunner.should_receive(:stop)
|
|
139
|
+
Rpush::Daemon.shutdown
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "removes the PID file if one was written" do
|
|
143
|
+
File.stub(:exists?).and_return(true)
|
|
144
|
+
File.should_receive(:delete).with("/rails_root/rpush.pid")
|
|
145
|
+
Rpush::Daemon.shutdown
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "does not attempt to remove the PID file if it does not exist" do
|
|
149
|
+
File.stub(:exists?).and_return(false)
|
|
150
|
+
File.should_not_receive(:delete)
|
|
151
|
+
Rpush::Daemon.shutdown
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "does not attempt to remove the PID file if one was not written" do
|
|
155
|
+
config.stub(:pid_file).and_return(nil)
|
|
156
|
+
File.should_not_receive(:delete)
|
|
157
|
+
Rpush::Daemon.shutdown
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rpush::Deprecatable do
|
|
4
|
+
class HasDeprecatedMethod
|
|
5
|
+
include Rpush::Deprecatable
|
|
6
|
+
|
|
7
|
+
def original_called?
|
|
8
|
+
@called == true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def deprecated_method
|
|
12
|
+
@called = true
|
|
13
|
+
end
|
|
14
|
+
deprecated(:deprecated_method, '4.0')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
let(:klass) { HasDeprecatedMethod.new }
|
|
18
|
+
|
|
19
|
+
before do
|
|
20
|
+
Rpush::Deprecation.stub(:warn)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'warns the method is deprecated when called' do
|
|
24
|
+
Rpush::Deprecation.should_receive(:warn).with("deprecated_method is deprecated and will be removed from Rpush 4.0.")
|
|
25
|
+
klass.deprecated_method
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'calls the original method' do
|
|
29
|
+
klass.deprecated_method
|
|
30
|
+
klass.original_called?.should be_true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rpush::Deprecation do
|
|
4
|
+
it 'prints a warning' do
|
|
5
|
+
STDERR.should_receive(:puts).with("DEPRECATION WARNING: msg")
|
|
6
|
+
Rpush::Deprecation.warn("msg")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'does not print a warning when muted' do
|
|
10
|
+
STDERR.should_not_receive(:puts)
|
|
11
|
+
Rpush::Deprecation.muted do
|
|
12
|
+
Rpush::Deprecation.warn("msg")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Rpush, 'embed' do
|
|
4
|
+
before do
|
|
5
|
+
Rpush::Daemon.stub(:start)
|
|
6
|
+
Kernel.stub(:at_exit)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'sets the embedded config option to true' do
|
|
10
|
+
Rpush.embed
|
|
11
|
+
Rpush.config.embedded.should be_true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'starts the daemon' do
|
|
15
|
+
Rpush::Daemon.should_receive(:start)
|
|
16
|
+
Rpush.embed
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'overrides the default config options with those given as a hash' do
|
|
20
|
+
Rpush.config.push_poll = 4
|
|
21
|
+
expect { Rpush.embed(:push_poll => 2) }.to change(Rpush.config, :push_poll).to(2)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe Rpush, 'shutdown' do
|
|
26
|
+
before { Rpush.config.embedded = true }
|
|
27
|
+
|
|
28
|
+
it 'shuts down the daemon' do
|
|
29
|
+
Rpush::Daemon.should_receive(:shutdown)
|
|
30
|
+
Rpush.shutdown
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe Rpush, 'sync' do
|
|
35
|
+
before { Rpush.config.embedded = true }
|
|
36
|
+
|
|
37
|
+
it 'syncs the AppRunner' do
|
|
38
|
+
Rpush::Daemon::AppRunner.should_receive(:sync)
|
|
39
|
+
Rpush.sync
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe Rpush, 'debug' do
|
|
44
|
+
before { Rpush.config.embedded = true }
|
|
45
|
+
|
|
46
|
+
it 'debugs the AppRunner' do
|
|
47
|
+
Rpush::Daemon::AppRunner.should_receive(:debug)
|
|
48
|
+
Rpush.debug
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'unit_spec_helper'
|
|
2
|
+
require 'unit/notification_shared.rb'
|
|
3
|
+
|
|
4
|
+
describe Rpush::Gcm::Notification do
|
|
5
|
+
it_should_behave_like 'an Notification subclass'
|
|
6
|
+
|
|
7
|
+
let(:app) { Rpush::Gcm::App.create!(:name => 'test', :auth_key => 'abc') }
|
|
8
|
+
let(:notification_class) { Rpush::Gcm::Notification }
|
|
9
|
+
let(:notification) { notification_class.new }
|
|
10
|
+
let(:data_setter) { 'data=' }
|
|
11
|
+
let(:data_getter) { 'data' }
|
|
12
|
+
|
|
13
|
+
it "has a 'data' payload limit of 4096 bytes" do
|
|
14
|
+
notification.data = { :key => "a" * 4096 }
|
|
15
|
+
notification.valid?.should be_false
|
|
16
|
+
notification.errors[:base].should eq ["Notification payload data cannot be larger than 4096 bytes."]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'limits the number of registration ids to 1000' do
|
|
20
|
+
notification.registration_ids = ['a']*(1000+1)
|
|
21
|
+
notification.valid?.should be_false
|
|
22
|
+
notification.errors[:base].should eq ["Number of registration_ids cannot be larger than 1000."]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'validates expiry is present if collapse_key is set' do
|
|
26
|
+
notification.collapse_key = 'test'
|
|
27
|
+
notification.expiry = nil
|
|
28
|
+
notification.valid?.should be_false
|
|
29
|
+
notification.errors[:expiry].should eq ['must be set when using a collapse_key']
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'includes time_to_live in the payload' do
|
|
33
|
+
notification.expiry = 100
|
|
34
|
+
notification.as_json['time_to_live'].should eq 100
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require "unit_spec_helper"
|
|
2
|
+
|
|
3
|
+
module Rails
|
|
4
|
+
def self.logger
|
|
5
|
+
@logger
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.logger=(logger)
|
|
9
|
+
@logger = logger
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module HoptoadNotifier
|
|
14
|
+
def self.notify(e)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe Rpush::Logger do
|
|
19
|
+
let(:log) { double(:sync= => true) }
|
|
20
|
+
|
|
21
|
+
before do
|
|
22
|
+
Rails.stub(:root).and_return("/rails_root")
|
|
23
|
+
|
|
24
|
+
@logger_class = if defined?(ActiveSupport::BufferedLogger)
|
|
25
|
+
ActiveSupport::BufferedLogger
|
|
26
|
+
else
|
|
27
|
+
ActiveSupport::Logger
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
@logger = double(@logger_class.name, :info => nil, :error => nil, :level => 0, :auto_flushing => 1, :auto_flushing= => nil)
|
|
31
|
+
@logger_class.stub(:new).and_return(@logger)
|
|
32
|
+
Rails.logger = @logger
|
|
33
|
+
File.stub(:open => log)
|
|
34
|
+
FileUtils.stub(:mkdir_p => nil)
|
|
35
|
+
STDERR.stub(:puts)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "disables logging if the log file cannot be opened" do
|
|
39
|
+
File.stub(:open).and_raise(Errno::ENOENT)
|
|
40
|
+
STDERR.should_receive(:puts).with(/No such file or directory/)
|
|
41
|
+
STDERR.should_receive(:puts).with(/Logging disabled/)
|
|
42
|
+
Rpush::Logger.new(:foreground => true)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'creates the log directory' do
|
|
46
|
+
FileUtils.should_receive(:mkdir_p).with('/rails_root/log')
|
|
47
|
+
Rpush::Logger.new(:foreground => true)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should open the a log file in the Rails log directory" do
|
|
51
|
+
File.should_receive(:open).with('/rails_root/log/rpush.log', 'a')
|
|
52
|
+
Rpush::Logger.new(:foreground => true)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'sets sync mode on the log descriptor' do
|
|
56
|
+
log.should_receive(:sync=).with(true)
|
|
57
|
+
Rpush::Logger.new(:foreground => true)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'uses the user-defined logger' do
|
|
61
|
+
my_logger = double
|
|
62
|
+
Rpush.config.logger = my_logger
|
|
63
|
+
logger = Rpush::Logger.new({})
|
|
64
|
+
my_logger.should_receive(:info)
|
|
65
|
+
logger.info('test')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'uses ActiveSupport::BufferedLogger if a user-defined logger is not set' do
|
|
69
|
+
if ActiveSupport.const_defined?('BufferedLogger')
|
|
70
|
+
ActiveSupport::BufferedLogger.should_receive(:new).with(log, Rails.logger.level)
|
|
71
|
+
Rpush::Logger.new(:foreground => true)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'uses ActiveSupport::Logger if BufferedLogger does not exist' do
|
|
76
|
+
stub_const('ActiveSupport::Logger', double)
|
|
77
|
+
ActiveSupport.stub(:const_defined? => false)
|
|
78
|
+
ActiveSupport::Logger.should_receive(:new).with(log, Rails.logger.level)
|
|
79
|
+
Rpush::Logger.new(:foreground => true)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should print out the msg if running in the foreground" do
|
|
83
|
+
logger = Rpush::Logger.new(:foreground => true)
|
|
84
|
+
STDOUT.should_receive(:puts).with(/hi mom/)
|
|
85
|
+
logger.info("hi mom")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should not print out the msg if not running in the foreground" do
|
|
89
|
+
logger = Rpush::Logger.new(:foreground => false)
|
|
90
|
+
STDOUT.should_not_receive(:puts).with(/hi mom/)
|
|
91
|
+
logger.info("hi mom")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should prefix log lines with the current time" do
|
|
95
|
+
now = Time.now
|
|
96
|
+
Time.stub(:now).and_return(now)
|
|
97
|
+
logger = Rpush::Logger.new(:foreground => false)
|
|
98
|
+
@logger.should_receive(:info).with(/#{Regexp.escape("[#{now.to_s(:db)}]")}/)
|
|
99
|
+
logger.info("blah")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should prefix error logs with the ERROR label" do
|
|
103
|
+
logger = Rpush::Logger.new(:foreground => false)
|
|
104
|
+
@logger.should_receive(:error).with(/#{Regexp.escape("[ERROR]")}/)
|
|
105
|
+
logger.error("eeek")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should prefix warn logs with the WARNING label" do
|
|
109
|
+
logger = Rpush::Logger.new(:foreground => false)
|
|
110
|
+
@logger.should_receive(:warn).with(/#{Regexp.escape("[WARNING]")}/)
|
|
111
|
+
logger.warn("eeek")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should handle an Exception instance" do
|
|
115
|
+
e = RuntimeError.new("hi mom")
|
|
116
|
+
e.stub(:backtrace => [])
|
|
117
|
+
logger = Rpush::Logger.new(:foreground => false)
|
|
118
|
+
@logger.should_receive(:error).with(/RuntimeError, hi mom/)
|
|
119
|
+
logger.error(e)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'defaults auto_flushing to true if the Rails logger does not respond to auto_flushing' do
|
|
123
|
+
rails_logger = double(:info => nil, :error => nil, :level => 0)
|
|
124
|
+
Rails.logger = rails_logger
|
|
125
|
+
@logger.auto_flushing.should be_true
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
shared_examples_for "an Notification subclass" do
|
|
2
|
+
describe "when assigning data for the device" do
|
|
3
|
+
before { Rpush::Deprecation.stub(:warn) }
|
|
4
|
+
|
|
5
|
+
it "calls MultiJson.dump when multi_json responds to :dump" do
|
|
6
|
+
notification = notification_class.new
|
|
7
|
+
MultiJson.stub(:respond_to?).with(:dump).and_return(true)
|
|
8
|
+
MultiJson.should_receive(:dump).with(any_args())
|
|
9
|
+
notification.send(data_setter, { :pirates => 1 })
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "calls MultiJson.encode when multi_json does not respond to :dump" do
|
|
13
|
+
notification = notification_class.new
|
|
14
|
+
MultiJson.stub(:respond_to?).with(:dump).and_return(false)
|
|
15
|
+
MultiJson.should_receive(:encode).with(any_args())
|
|
16
|
+
notification.send(data_setter, { :ninjas => 1 })
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "raises an ArgumentError if something other than a Hash is assigned" do
|
|
20
|
+
expect do
|
|
21
|
+
notification.send(data_setter, Array.new)
|
|
22
|
+
end.to raise_error(ArgumentError, "must be a Hash")
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "encodes the given Hash as JSON" do
|
|
26
|
+
notification.send(data_setter, { :hi => "mom" })
|
|
27
|
+
notification.read_attribute(:data).should eq "{\"hi\":\"mom\"}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "decodes the JSON when using the reader method" do
|
|
31
|
+
notification.send(data_setter, { :hi => "mom" })
|
|
32
|
+
notification.send(data_getter).should eq ({"hi" => "mom"})
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe 'scopes' do
|
|
36
|
+
before do
|
|
37
|
+
Timecop.freeze(Time.now)
|
|
38
|
+
|
|
39
|
+
(@delivered_notification = notification_class.new(:app => app, :delivered => true, :failed => false)).save!(:validate => false)
|
|
40
|
+
(@failed_notification = notification_class.new(:app => app, :delivered => false, :failed => true)).save!(:validate => false)
|
|
41
|
+
(@new_notification = notification_class.new(:app => app, :delivered => false, :failed => false)).save!(:validate => false)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
after do
|
|
45
|
+
Timecop.return
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '.completed' do
|
|
49
|
+
it 'should return notifications that have been delivered or failed' do
|
|
50
|
+
completed_notification_ids = Rpush::Notification.completed.map(&:id)
|
|
51
|
+
|
|
52
|
+
completed_notification_ids.size.should eq 2
|
|
53
|
+
completed_notification_ids.should include(@delivered_notification.id, @failed_notification.id)
|
|
54
|
+
completed_notification_ids.should_not include(@new_notification.id)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe '.created_before' do
|
|
59
|
+
it 'should return notifications that were created before the specified date' do
|
|
60
|
+
@delivered_notification.created_at = Time.now - 30.days - 1.second
|
|
61
|
+
@delivered_notification.save!(:validate => false)
|
|
62
|
+
|
|
63
|
+
notification_ids = Rpush::Notification.created_before(Time.now - 30.days).map(&:id)
|
|
64
|
+
|
|
65
|
+
notification_ids.size.should eq 1
|
|
66
|
+
notification_ids.should include(@delivered_notification.id)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '.completed_and_older_than' do
|
|
71
|
+
before do
|
|
72
|
+
@delivered_notification.created_at = Time.now - 30.days - 1.second
|
|
73
|
+
@delivered_notification.save!(:validate => false)
|
|
74
|
+
|
|
75
|
+
@failed_notification.created_at = Time.now - 20.days - 1.second
|
|
76
|
+
@failed_notification.save!(:validate => false)
|
|
77
|
+
|
|
78
|
+
@new_notification.created_at = Time.now - 30.days - 1.second
|
|
79
|
+
@new_notification.save!(:validate => false)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'should only include completed notifications' do
|
|
83
|
+
notification_ids = Rpush::Notification.completed_and_older_than(Time.now - 30.days).map(&:id)
|
|
84
|
+
|
|
85
|
+
notification_ids.size.should eq 1
|
|
86
|
+
notification_ids.should include(@delivered_notification.id)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'should not include completed notifications if not older than specified date' do
|
|
90
|
+
notification_ids = Rpush::Notification.completed_and_older_than(Time.now - 30.days).map(&:id)
|
|
91
|
+
|
|
92
|
+
notification_ids.size.should eq 1
|
|
93
|
+
notification_ids.should_not include(@failed_notification.id)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'should return notifications that are completed and created before the specified date' do
|
|
97
|
+
notification_ids = Rpush::Notification.completed_and_older_than(Time.now - 20.days).map(&:id)
|
|
98
|
+
|
|
99
|
+
notification_ids.size.should eq 2
|
|
100
|
+
notification_ids.should include(@delivered_notification.id, @failed_notification.id)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|