rpush 1.0.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.
- 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/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/adm/delivery.rb +222 -0
- data/lib/rpush/daemon/adm.rb +9 -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/apns.rb +16 -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/delivery.rb +222 -0
- data/lib/rpush/daemon/gcm.rb +9 -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/reconnectable.rb +68 -0
- data/lib/rpush/daemon/store/active_record.rb +154 -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/delivery.rb +132 -0
- data/lib/rpush/daemon/wpns.rb +9 -0
- data/lib/rpush/daemon.rb +140 -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/rpush.rb +62 -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 +304 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
module Rpush
|
2
|
+
class Notification < ActiveRecord::Base
|
3
|
+
include Rpush::MultiJsonHelper
|
4
|
+
|
5
|
+
self.table_name = 'rpush_notifications'
|
6
|
+
|
7
|
+
# TODO: Dump using multi json.
|
8
|
+
serialize :registration_ids
|
9
|
+
|
10
|
+
belongs_to :app, :class_name => 'Rpush::App'
|
11
|
+
|
12
|
+
if Rpush.attr_accessible_available?
|
13
|
+
attr_accessible :badge, :device_token, :sound, :alert, :data, :expiry,:delivered,
|
14
|
+
:delivered_at, :failed, :failed_at, :error_code, :error_description, :deliver_after,
|
15
|
+
:alert_is_json, :app, :app_id, :collapse_key, :delay_while_idle, :registration_ids, :uri
|
16
|
+
end
|
17
|
+
|
18
|
+
validates :expiry, :numericality => true, :allow_nil => true
|
19
|
+
validates :app, :presence => true
|
20
|
+
|
21
|
+
scope :ready_for_delivery, lambda {
|
22
|
+
where('delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)',
|
23
|
+
false, false, Time.now)
|
24
|
+
}
|
25
|
+
|
26
|
+
scope :for_apps, lambda { |apps|
|
27
|
+
where('app_id IN (?)', apps.map(&:id))
|
28
|
+
}
|
29
|
+
|
30
|
+
scope :completed, lambda { where("delivered = ? OR failed = ?", true, true) }
|
31
|
+
|
32
|
+
def data=(attrs)
|
33
|
+
return unless attrs
|
34
|
+
raise ArgumentError, "must be a Hash" if !attrs.is_a?(Hash)
|
35
|
+
write_attribute(:data, multi_json_dump(attrs.merge(data || {})))
|
36
|
+
end
|
37
|
+
|
38
|
+
def registration_ids=(ids)
|
39
|
+
ids = [ids] if ids && !ids.is_a?(Array)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def data
|
44
|
+
multi_json_load(read_attribute(:data)) if read_attribute(:data)
|
45
|
+
end
|
46
|
+
|
47
|
+
def payload
|
48
|
+
multi_json_dump(as_json)
|
49
|
+
end
|
50
|
+
|
51
|
+
def payload_size
|
52
|
+
payload.bytesize
|
53
|
+
end
|
54
|
+
|
55
|
+
def payload_data_size
|
56
|
+
multi_json_dump(as_json['data']).bytesize
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def created_before(dt)
|
61
|
+
where("created_at < ?", dt)
|
62
|
+
end
|
63
|
+
|
64
|
+
def completed_and_older_than(dt)
|
65
|
+
completed.created_before(dt)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Rpush
|
4
|
+
# This class notifies the sleeping Rpush Daemon that there are new Notifications to send,
|
5
|
+
# and to interrupt its sleep to send them immediately. The purpose of this is to allow
|
6
|
+
# much higher sleep times to reduce database polling activity.
|
7
|
+
class Notifier
|
8
|
+
def initialize(host, port)
|
9
|
+
@host, @port = host, port
|
10
|
+
end
|
11
|
+
|
12
|
+
# notify the daemon that there is a Notification to send.
|
13
|
+
def notify
|
14
|
+
socket.write('x')
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [UDPSocket]
|
18
|
+
def socket
|
19
|
+
if @socket.nil?
|
20
|
+
@socket = UDPSocket.new
|
21
|
+
@socket.connect(@host, @port)
|
22
|
+
end
|
23
|
+
@socket
|
24
|
+
end
|
25
|
+
|
26
|
+
# close the udp socket
|
27
|
+
def close
|
28
|
+
if @socket
|
29
|
+
@socket.close
|
30
|
+
@socket = nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# Call this from a client application after saving a Notification to the database to wakeup the Rpush
|
37
|
+
# Daemon to deliver the notification immediately.
|
38
|
+
def self.wakeup
|
39
|
+
notifier.notify
|
40
|
+
end
|
41
|
+
|
42
|
+
# Default notifier instance. This uses the :connect, :port values in Rpush.config.wakeup to connect to the
|
43
|
+
# wakeup socket in the Rpush Daemon. It will fall back to :host, :port if :connect is not specified.
|
44
|
+
def self.notifier
|
45
|
+
unless @notifier
|
46
|
+
if Rpush.config.wakeup
|
47
|
+
@notifier = Notifier.new(Rpush.config.wakeup[:connect] || Rpush.config.wakeup[:host], Rpush.config.wakeup[:port])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@notifier
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Rpush
|
2
|
+
class PayloadDataSizeValidator < ActiveModel::Validator
|
3
|
+
def validate(record)
|
4
|
+
limit = options[:limit] || 1024
|
5
|
+
if !record.data.nil? && record.payload_data_size > limit
|
6
|
+
record.errors[:base] << "Notification payload data cannot be larger than #{limit} bytes."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/rpush/push.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Rpush
|
2
|
+
def self.push(options = {})
|
3
|
+
Rpush.require_for_daemon
|
4
|
+
|
5
|
+
config = Rpush::ConfigurationWithoutDefaults.new
|
6
|
+
options.each { |k, v| config.send("#{k}=", v) }
|
7
|
+
config.push = true
|
8
|
+
Rpush.config.update(config)
|
9
|
+
|
10
|
+
Rpush::Daemon.initialize_store
|
11
|
+
Rpush::Daemon::AppRunner.sync
|
12
|
+
Rpush::Daemon::Feeder.start
|
13
|
+
Rpush::Daemon::AppRunner.wait
|
14
|
+
Rpush::Daemon::AppRunner.stop
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Rpush
|
2
|
+
def self.reflect
|
3
|
+
yield reflections if block_given?
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.reflections
|
7
|
+
@reflections ||= Reflections.new
|
8
|
+
end
|
9
|
+
|
10
|
+
class Reflections
|
11
|
+
class NoSuchReflectionError < StandardError; end
|
12
|
+
|
13
|
+
REFLECTIONS = [
|
14
|
+
:apns_feedback, :notification_enqueued, :notification_delivered,
|
15
|
+
:notification_failed, :notification_will_retry, :apns_connection_lost,
|
16
|
+
:gcm_delivered_to_recipient, :gcm_failed_to_recipient, :gcm_canonical_id,
|
17
|
+
:gcm_invalid_registration_id, :error, :apns_certificate_will_expire,
|
18
|
+
:adm_canonical_id, :tcp_connection_lost, :ssl_certificate_will_expire
|
19
|
+
]
|
20
|
+
|
21
|
+
DEPRECATIONS = {
|
22
|
+
:apns_connection_lost => [:tcp_connection_lost, '4.1'],
|
23
|
+
:apns_certificate_will_expire => [:ssl_certificate_will_expire, '4.1']
|
24
|
+
}
|
25
|
+
|
26
|
+
REFLECTIONS.each do |reflection|
|
27
|
+
class_eval(<<-RUBY, __FILE__, __LINE__)
|
28
|
+
def #{reflection}(*args, &blk)
|
29
|
+
raise "block required" unless block_given?
|
30
|
+
reflections[:#{reflection}] = blk
|
31
|
+
end
|
32
|
+
RUBY
|
33
|
+
end
|
34
|
+
|
35
|
+
def __dispatch(reflection, *args)
|
36
|
+
reflection = reflection.to_sym
|
37
|
+
|
38
|
+
unless REFLECTIONS.include?(reflection)
|
39
|
+
raise NoSuchReflectionError, reflection
|
40
|
+
end
|
41
|
+
|
42
|
+
if DEPRECATIONS.key?(reflection)
|
43
|
+
replacement, removal_version = DEPRECATIONS[reflection]
|
44
|
+
Rpush::Deprecation.warn("#{reflection} is deprecated and will be removed in version #{removal_version}. Use #{replacement} instead.")
|
45
|
+
end
|
46
|
+
|
47
|
+
if reflections[reflection]
|
48
|
+
reflections[reflection].call(*args)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def reflections
|
55
|
+
@reflections ||= {}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Rpush
|
2
|
+
class RegistrationIdsCountValidator < ActiveModel::Validator
|
3
|
+
def validate(record)
|
4
|
+
limit = options[:limit] || 100
|
5
|
+
if record.registration_ids && record.registration_ids.size > limit
|
6
|
+
record.errors[:base] << "Number of registration_ids cannot be larger than #{limit}."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rpush
|
2
|
+
module Wpns
|
3
|
+
class Notification < Rpush::Notification
|
4
|
+
validates :uri, presence: true
|
5
|
+
validates :uri, format: { with: /https?:\/\/[\S]+/ }
|
6
|
+
validates :alert, presence: true
|
7
|
+
|
8
|
+
def as_json
|
9
|
+
json = {
|
10
|
+
'message' => alert,
|
11
|
+
'uri' => uri
|
12
|
+
}
|
13
|
+
|
14
|
+
if collapse_key
|
15
|
+
json['consolidationKey'] = collapse_key
|
16
|
+
end
|
17
|
+
|
18
|
+
json
|
19
|
+
end
|
20
|
+
|
21
|
+
def uri_is_valid?
|
22
|
+
return (/https?:\/\/[\S]+/.match(uri) != nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/rpush.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Rpush
|
5
|
+
def self.attr_accessible_available?
|
6
|
+
require 'rails'
|
7
|
+
::Rails::VERSION::STRING < '4'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rpush/railtie' if defined?(Rails)
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'rpush/version'
|
14
|
+
require 'rpush/deprecation'
|
15
|
+
require 'rpush/deprecatable'
|
16
|
+
require 'rpush/logger'
|
17
|
+
require 'rpush/multi_json_helper'
|
18
|
+
require 'rpush/notification'
|
19
|
+
require 'rpush/app'
|
20
|
+
require 'rpush/configuration'
|
21
|
+
require 'rpush/reflection'
|
22
|
+
require 'rpush/embed'
|
23
|
+
require 'rpush/push'
|
24
|
+
require 'rpush/apns_feedback'
|
25
|
+
require 'rpush/notifier'
|
26
|
+
require 'rpush/payload_data_size_validator'
|
27
|
+
require 'rpush/registration_ids_count_validator'
|
28
|
+
|
29
|
+
require 'rpush/apns/binary_notification_validator'
|
30
|
+
require 'rpush/apns/device_token_format_validator'
|
31
|
+
require 'rpush/apns/notification'
|
32
|
+
require 'rpush/apns/feedback'
|
33
|
+
require 'rpush/apns/app'
|
34
|
+
|
35
|
+
require 'rpush/gcm/expiry_collapse_key_mutual_inclusion_validator'
|
36
|
+
require 'rpush/gcm/notification'
|
37
|
+
require 'rpush/gcm/app'
|
38
|
+
|
39
|
+
require 'rpush/wpns/notification'
|
40
|
+
require 'rpush/wpns/app'
|
41
|
+
|
42
|
+
require 'rpush/adm/data_validator'
|
43
|
+
require 'rpush/adm/notification'
|
44
|
+
require 'rpush/adm/app'
|
45
|
+
|
46
|
+
module Rpush
|
47
|
+
def self.jruby?
|
48
|
+
defined? JRUBY_VERSION
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.require_for_daemon
|
52
|
+
require 'rpush/daemon'
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.logger
|
56
|
+
@logger ||= Logger.new(:foreground => Rpush.config.foreground)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.logger=(logger)
|
60
|
+
@logger = logger
|
61
|
+
end
|
62
|
+
end
|
data/lib/tasks/cane.rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'cane/rake_task'
|
3
|
+
|
4
|
+
desc "Run cane to check quality metrics"
|
5
|
+
Cane::RakeTask.new(:quality) do |cane|
|
6
|
+
cane.add_threshold 'coverage/covered_percent', :>=, 98
|
7
|
+
cane.no_style = false
|
8
|
+
cane.style_measure = 1000
|
9
|
+
cane.no_doc = true
|
10
|
+
cane.abc_max = 20
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :spec do
|
14
|
+
task :cane => ['spec', 'quality']
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
warn "cane not available, quality task not provided."
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
namespace :rpush do
|
2
|
+
namespace :notifications do
|
3
|
+
desc "Delete completed notifications older than number of days (DAYS > 0)"
|
4
|
+
task :clean => :environment do
|
5
|
+
date = (ENV['DAYS'].blank? || ENV['DAYS'].to_i <= 0) ? nil : Time.zone.now.end_of_day - (ENV['DAYS'].to_i).days
|
6
|
+
|
7
|
+
if(date.nil?)
|
8
|
+
puts "DAYS is required and must be greater than 0"
|
9
|
+
else
|
10
|
+
puts "BEG: Delete completed notifications before '#{date}'\n"
|
11
|
+
deleted_count = Rpush::Notification.completed_and_older_than(date).delete_all
|
12
|
+
puts "END: Deleted #{deleted_count} notifications"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/tasks/test.rake
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
namespace :test do
|
2
|
+
task :build_rails do
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
def cmd(str, clean_env = true)
|
6
|
+
puts "* #{str}"
|
7
|
+
retval = if clean_env
|
8
|
+
Bundler.with_clean_env { `#{str}` }
|
9
|
+
else
|
10
|
+
`#{str}`
|
11
|
+
end
|
12
|
+
puts retval.strip
|
13
|
+
retval
|
14
|
+
end
|
15
|
+
|
16
|
+
rpush_root = Dir.pwd
|
17
|
+
path = '/tmp/rails_test'
|
18
|
+
cmd("rm -rf #{path}")
|
19
|
+
FileUtils.mkdir_p(path)
|
20
|
+
pwd = Dir.pwd
|
21
|
+
|
22
|
+
cmd("bundle exec rails --version", false)
|
23
|
+
cmd("bundle exec rails new #{path} --skip-bundle", false)
|
24
|
+
|
25
|
+
begin
|
26
|
+
Dir.chdir(path)
|
27
|
+
cmd('echo "gem \'rake\'" >> Gemfile')
|
28
|
+
cmd("echo \"gem 'rpush', :path => '#{rpush_root}'\" >> Gemfile")
|
29
|
+
cmd('bundle install')
|
30
|
+
cmd('bundle exec rails g rpush')
|
31
|
+
cmd('bundle exec rake db:migrate')
|
32
|
+
ensure
|
33
|
+
Dir.chdir(pwd)
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Built into #{path}"
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe 'ADM' do
|
4
|
+
let(:app) { Rpush::Adm::App.new }
|
5
|
+
let(:notification) { Rpush::Adm::Notification.new }
|
6
|
+
let(:response) { double(Net::HTTPResponse, code: 200) }
|
7
|
+
let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
app.name = 'test'
|
11
|
+
app.client_id = 'abc'
|
12
|
+
app.client_secret = '123'
|
13
|
+
app.save!
|
14
|
+
|
15
|
+
notification.app = app
|
16
|
+
notification.registration_ids = ['foo']
|
17
|
+
notification.data = { message: 'test' }
|
18
|
+
notification.save!
|
19
|
+
|
20
|
+
Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
|
21
|
+
Rpush.config.logger = ::Logger.new(STDOUT)
|
22
|
+
|
23
|
+
Net::HTTP::Persistent.stub(new: http)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'delivers a notification successfully' do
|
27
|
+
response.stub(body: JSON.dump({registrationID: notification.registration_ids.first.to_s}))
|
28
|
+
|
29
|
+
expect do
|
30
|
+
Rpush.push
|
31
|
+
notification.reload
|
32
|
+
end.to change(notification, :delivered).to(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'fails to deliver a notification successfully' do
|
36
|
+
response.stub(code: 400, body: JSON.dump({reason: 'error', registrationID: notification.registration_ids.first.to_s}))
|
37
|
+
|
38
|
+
expect do
|
39
|
+
Rpush.push
|
40
|
+
notification.reload
|
41
|
+
end.to_not change(notification, :delivered).to(true)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe 'APNs' do
|
4
|
+
let(:app) { Rpush::Apns::App.new }
|
5
|
+
let(:notification) { Rpush::Apns::Notification.new }
|
6
|
+
let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
|
7
|
+
let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
|
8
|
+
write: nil, flush: nil, read: nil, close: nil) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
app.certificate = TEST_CERT
|
12
|
+
app.name = 'test'
|
13
|
+
app.environment = 'sandbox'
|
14
|
+
app.save!
|
15
|
+
|
16
|
+
notification.app = app
|
17
|
+
notification.alert = 'test'
|
18
|
+
notification.device_token = 'a' * 64
|
19
|
+
notification.save!
|
20
|
+
|
21
|
+
Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
|
22
|
+
Rpush.config.logger = ::Logger.new(STDOUT)
|
23
|
+
|
24
|
+
stub_tcp_connection
|
25
|
+
end
|
26
|
+
|
27
|
+
def stub_tcp_connection
|
28
|
+
TCPSocket.stub(:new => tcp_socket)
|
29
|
+
OpenSSL::SSL::SSLSocket.stub(:new => ssl_socket)
|
30
|
+
IO.stub(:select => nil)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'delivers a notification successfully' do
|
34
|
+
expect do
|
35
|
+
Rpush.push
|
36
|
+
notification.reload
|
37
|
+
end.to change(notification, :delivered).to(true)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'fails to deliver a notification successfully' do
|
41
|
+
IO.stub(:select => true)
|
42
|
+
ssl_socket.stub(:read => [8, 4, 69].pack('ccN'))
|
43
|
+
|
44
|
+
expect do
|
45
|
+
Rpush.push
|
46
|
+
notification.reload
|
47
|
+
end.to_not change(notification, :delivered).to(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'receives feedback' do
|
51
|
+
tuple = "N\xE3\x84\r\x00 \x83OxfU\xEB\x9F\x84aJ\x05\xAD}\x00\xAF1\xE5\xCF\xE9:\xC3\xEA\a\x8F\x1D\xA4M*N\xB0\xCE\x17"
|
52
|
+
allow(ssl_socket).to receive(:read).and_return(tuple, nil)
|
53
|
+
|
54
|
+
expect do
|
55
|
+
Rpush.apns_feedback
|
56
|
+
end.to change(Rpush::Apns::Feedback, :count).to(1)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe 'embedding' do
|
4
|
+
let(:app) { Rpush::Apns::App.new }
|
5
|
+
let(:notification) { Rpush::Apns::Notification.new }
|
6
|
+
let(:tcp_socket) { double(TCPSocket, setsockopt: nil, close: nil) }
|
7
|
+
let(:ssl_socket) { double(OpenSSL::SSL::SSLSocket, :sync= => nil, connect: nil,
|
8
|
+
write: nil, flush: nil, read: nil, close: nil) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
app.certificate = TEST_CERT
|
12
|
+
app.name = 'test'
|
13
|
+
app.environment = 'sandbox'
|
14
|
+
app.save!
|
15
|
+
|
16
|
+
notification.app = app
|
17
|
+
notification.alert = 'test'
|
18
|
+
notification.device_token = 'a' * 64
|
19
|
+
notification.save!
|
20
|
+
|
21
|
+
Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
|
22
|
+
Rpush.config.logger = ::Logger.new(STDOUT)
|
23
|
+
|
24
|
+
stub_tcp_connection
|
25
|
+
end
|
26
|
+
|
27
|
+
def stub_tcp_connection
|
28
|
+
TCPSocket.stub(:new => tcp_socket)
|
29
|
+
OpenSSL::SSL::SSLSocket.stub(:new => ssl_socket)
|
30
|
+
IO.stub(:select => nil)
|
31
|
+
Rpush::Daemon::Apns::FeedbackReceiver.stub(:new => double.as_null_object)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'delivers a notification successfully' do
|
35
|
+
expect do
|
36
|
+
::ActiveRecord::Base.clear_all_connections!
|
37
|
+
|
38
|
+
pid = fork do
|
39
|
+
Rpush.embed
|
40
|
+
sleep 0.5
|
41
|
+
Rpush.shutdown
|
42
|
+
Kernel.at_exit { exit! } # Don't run any at_exit hooks.
|
43
|
+
end
|
44
|
+
|
45
|
+
Process.waitpid(pid)
|
46
|
+
notification.reload
|
47
|
+
end.to change(notification, :delivered).to(true)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe 'GCM' do
|
4
|
+
let(:app) { Rpush::Gcm::App.new }
|
5
|
+
let(:notification) { Rpush::Gcm::Notification.new }
|
6
|
+
let(:response) { double(Net::HTTPResponse, code: 200) }
|
7
|
+
let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
app.name = 'test'
|
11
|
+
app.auth_key = 'abc123'
|
12
|
+
app.save!
|
13
|
+
|
14
|
+
notification.app = app
|
15
|
+
notification.registration_ids = ['foo']
|
16
|
+
notification.data = { message: 'test' }
|
17
|
+
notification.save!
|
18
|
+
|
19
|
+
Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
|
20
|
+
Rpush.config.logger = ::Logger.new(STDOUT)
|
21
|
+
|
22
|
+
Net::HTTP::Persistent.stub(new: http)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'delivers a notification successfully' do
|
26
|
+
response.stub(body: JSON.dump({results: [{message_id: notification.registration_ids.first.to_s}]}))
|
27
|
+
|
28
|
+
expect do
|
29
|
+
Rpush.push
|
30
|
+
notification.reload
|
31
|
+
end.to change(notification, :delivered).to(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'fails to deliver a notification successfully' do
|
35
|
+
response.stub(body: JSON.dump({results: [{error: 'Err'}]}))
|
36
|
+
|
37
|
+
expect do
|
38
|
+
Rpush.push
|
39
|
+
notification.reload
|
40
|
+
end.to_not change(notification, :delivered).to(true)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'unit_spec_helper'
|
2
|
+
|
3
|
+
describe 'GCM' do
|
4
|
+
let(:app) { Rpush::Wpns::App.new }
|
5
|
+
let(:notification) { Rpush::Wpns::Notification.new }
|
6
|
+
let(:response) { double(Net::HTTPResponse, code: 200) }
|
7
|
+
let(:http) { double(Net::HTTP::Persistent, request: response, shutdown: nil) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
app.name = 'test'
|
11
|
+
app.save!
|
12
|
+
|
13
|
+
notification.app = app
|
14
|
+
notification.uri = 'http://sn1.notify.live.net/'
|
15
|
+
notification.alert = 'test'
|
16
|
+
notification.save!
|
17
|
+
|
18
|
+
Rails.stub(root: File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp')))
|
19
|
+
Rpush.config.logger = ::Logger.new(STDOUT)
|
20
|
+
|
21
|
+
Net::HTTP::Persistent.stub(new: http)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'delivers a notification successfully' do
|
25
|
+
response.stub(to_hash: {'x-notificationstatus' => ['Received']})
|
26
|
+
|
27
|
+
expect do
|
28
|
+
Rpush.push
|
29
|
+
notification.reload
|
30
|
+
end.to change(notification, :delivered).to(true)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'fails to deliver a notification successfully' do
|
34
|
+
response.stub(code: 400)
|
35
|
+
|
36
|
+
expect do
|
37
|
+
Rpush.push
|
38
|
+
notification.reload
|
39
|
+
end.to_not change(notification, :delivered).to(true)
|
40
|
+
end
|
41
|
+
end
|