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