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.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +99 -0
  3. data/LICENSE +7 -0
  4. data/README.md +189 -0
  5. data/bin/rpush +36 -0
  6. data/config/database.yml +44 -0
  7. data/lib/generators/rpush_generator.rb +44 -0
  8. data/lib/generators/templates/add_adm.rb +23 -0
  9. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  10. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  11. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
  12. data/lib/generators/templates/add_gcm.rb +102 -0
  13. data/lib/generators/templates/add_rpush.rb +349 -0
  14. data/lib/generators/templates/add_wpns.rb +16 -0
  15. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  16. data/lib/generators/templates/create_rapns_feedback.rb +18 -0
  17. data/lib/generators/templates/create_rapns_notifications.rb +29 -0
  18. data/lib/generators/templates/rename_rapns_to_rpush.rb +63 -0
  19. data/lib/generators/templates/rpush.rb +104 -0
  20. data/lib/rpush/TODO +3 -0
  21. data/lib/rpush/adm/app.rb +15 -0
  22. data/lib/rpush/adm/data_validator.rb +11 -0
  23. data/lib/rpush/adm/notification.rb +29 -0
  24. data/lib/rpush/apns/app.rb +29 -0
  25. data/lib/rpush/apns/binary_notification_validator.rb +12 -0
  26. data/lib/rpush/apns/device_token_format_validator.rb +12 -0
  27. data/lib/rpush/apns/feedback.rb +16 -0
  28. data/lib/rpush/apns/notification.rb +84 -0
  29. data/lib/rpush/apns_feedback.rb +13 -0
  30. data/lib/rpush/app.rb +18 -0
  31. data/lib/rpush/configuration.rb +75 -0
  32. data/lib/rpush/daemon/adm/delivery.rb +222 -0
  33. data/lib/rpush/daemon/adm.rb +9 -0
  34. data/lib/rpush/daemon/apns/certificate_expired_error.rb +20 -0
  35. data/lib/rpush/daemon/apns/delivery.rb +64 -0
  36. data/lib/rpush/daemon/apns/disconnection_error.rb +20 -0
  37. data/lib/rpush/daemon/apns/feedback_receiver.rb +79 -0
  38. data/lib/rpush/daemon/apns.rb +16 -0
  39. data/lib/rpush/daemon/app_runner.rb +187 -0
  40. data/lib/rpush/daemon/batch.rb +115 -0
  41. data/lib/rpush/daemon/constants.rb +59 -0
  42. data/lib/rpush/daemon/delivery.rb +28 -0
  43. data/lib/rpush/daemon/delivery_error.rb +19 -0
  44. data/lib/rpush/daemon/dispatcher/http.rb +21 -0
  45. data/lib/rpush/daemon/dispatcher/tcp.rb +30 -0
  46. data/lib/rpush/daemon/dispatcher_loop.rb +54 -0
  47. data/lib/rpush/daemon/dispatcher_loop_collection.rb +33 -0
  48. data/lib/rpush/daemon/feeder.rb +68 -0
  49. data/lib/rpush/daemon/gcm/delivery.rb +222 -0
  50. data/lib/rpush/daemon/gcm.rb +9 -0
  51. data/lib/rpush/daemon/interruptible_sleep.rb +61 -0
  52. data/lib/rpush/daemon/loggable.rb +31 -0
  53. data/lib/rpush/daemon/reflectable.rb +13 -0
  54. data/lib/rpush/daemon/retry_header_parser.rb +23 -0
  55. data/lib/rpush/daemon/retryable_error.rb +20 -0
  56. data/lib/rpush/daemon/service_config_methods.rb +33 -0
  57. data/lib/rpush/daemon/store/active_record/reconnectable.rb +68 -0
  58. data/lib/rpush/daemon/store/active_record.rb +154 -0
  59. data/lib/rpush/daemon/tcp_connection.rb +143 -0
  60. data/lib/rpush/daemon/too_many_requests_error.rb +20 -0
  61. data/lib/rpush/daemon/wpns/delivery.rb +132 -0
  62. data/lib/rpush/daemon/wpns.rb +9 -0
  63. data/lib/rpush/daemon.rb +140 -0
  64. data/lib/rpush/deprecatable.rb +23 -0
  65. data/lib/rpush/deprecation.rb +23 -0
  66. data/lib/rpush/embed.rb +28 -0
  67. data/lib/rpush/gcm/app.rb +11 -0
  68. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
  69. data/lib/rpush/gcm/notification.rb +30 -0
  70. data/lib/rpush/logger.rb +63 -0
  71. data/lib/rpush/multi_json_helper.rb +16 -0
  72. data/lib/rpush/notification.rb +69 -0
  73. data/lib/rpush/notifier.rb +52 -0
  74. data/lib/rpush/payload_data_size_validator.rb +10 -0
  75. data/lib/rpush/push.rb +16 -0
  76. data/lib/rpush/railtie.rb +11 -0
  77. data/lib/rpush/reflection.rb +58 -0
  78. data/lib/rpush/registration_ids_count_validator.rb +10 -0
  79. data/lib/rpush/version.rb +3 -0
  80. data/lib/rpush/wpns/app.rb +9 -0
  81. data/lib/rpush/wpns/notification.rb +26 -0
  82. data/lib/rpush.rb +62 -0
  83. data/lib/tasks/cane.rake +18 -0
  84. data/lib/tasks/rpush.rake +16 -0
  85. data/lib/tasks/test.rake +38 -0
  86. data/spec/functional/adm_spec.rb +43 -0
  87. data/spec/functional/apns_spec.rb +58 -0
  88. data/spec/functional/embed_spec.rb +49 -0
  89. data/spec/functional/gcm_spec.rb +42 -0
  90. data/spec/functional/wpns_spec.rb +41 -0
  91. data/spec/support/cert_with_password.pem +90 -0
  92. data/spec/support/cert_without_password.pem +59 -0
  93. data/spec/support/install.sh +32 -0
  94. data/spec/support/simplecov_helper.rb +20 -0
  95. data/spec/support/simplecov_quality_formatter.rb +8 -0
  96. data/spec/tmp/.gitkeep +0 -0
  97. data/spec/unit/adm/app_spec.rb +58 -0
  98. data/spec/unit/adm/notification_spec.rb +45 -0
  99. data/spec/unit/apns/app_spec.rb +29 -0
  100. data/spec/unit/apns/feedback_spec.rb +9 -0
  101. data/spec/unit/apns/notification_spec.rb +208 -0
  102. data/spec/unit/apns_feedback_spec.rb +21 -0
  103. data/spec/unit/app_spec.rb +30 -0
  104. data/spec/unit/configuration_spec.rb +45 -0
  105. data/spec/unit/daemon/adm/delivery_spec.rb +243 -0
  106. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  107. data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
  108. data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
  109. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +117 -0
  110. data/spec/unit/daemon/app_runner_spec.rb +292 -0
  111. data/spec/unit/daemon/batch_spec.rb +232 -0
  112. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  113. data/spec/unit/daemon/delivery_spec.rb +38 -0
  114. data/spec/unit/daemon/dispatcher/http_spec.rb +33 -0
  115. data/spec/unit/daemon/dispatcher/tcp_spec.rb +38 -0
  116. data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +37 -0
  117. data/spec/unit/daemon/dispatcher_loop_spec.rb +71 -0
  118. data/spec/unit/daemon/feeder_spec.rb +98 -0
  119. data/spec/unit/daemon/gcm/delivery_spec.rb +310 -0
  120. data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
  121. data/spec/unit/daemon/reflectable_spec.rb +27 -0
  122. data/spec/unit/daemon/retryable_error_spec.rb +14 -0
  123. data/spec/unit/daemon/service_config_methods_spec.rb +33 -0
  124. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
  125. data/spec/unit/daemon/store/active_record_spec.rb +357 -0
  126. data/spec/unit/daemon/tcp_connection_spec.rb +287 -0
  127. data/spec/unit/daemon/too_many_requests_error_spec.rb +14 -0
  128. data/spec/unit/daemon/wpns/delivery_spec.rb +159 -0
  129. data/spec/unit/daemon_spec.rb +159 -0
  130. data/spec/unit/deprecatable_spec.rb +32 -0
  131. data/spec/unit/deprecation_spec.rb +15 -0
  132. data/spec/unit/embed_spec.rb +50 -0
  133. data/spec/unit/gcm/app_spec.rb +4 -0
  134. data/spec/unit/gcm/notification_spec.rb +36 -0
  135. data/spec/unit/logger_spec.rb +127 -0
  136. data/spec/unit/notification_shared.rb +105 -0
  137. data/spec/unit/notification_spec.rb +15 -0
  138. data/spec/unit/notifier_spec.rb +49 -0
  139. data/spec/unit/push_spec.rb +43 -0
  140. data/spec/unit/reflection_spec.rb +30 -0
  141. data/spec/unit/rpush_spec.rb +9 -0
  142. data/spec/unit/wpns/app_spec.rb +4 -0
  143. data/spec/unit/wpns/notification_spec.rb +30 -0
  144. data/spec/unit_spec_helper.rb +101 -0
  145. 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,11 @@
1
+ require 'rails'
2
+
3
+ module MyPlugin
4
+ class Railtie < Rails::Railtie
5
+ railtie_name :rpush
6
+
7
+ rake_tasks do
8
+ load "tasks/rpush.rake"
9
+ end
10
+ end
11
+ 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,3 @@
1
+ module Rpush
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,9 @@
1
+ module Rpush
2
+ module Wpns
3
+ class App < Rpush::App
4
+ def service_name
5
+ 'wpns'
6
+ end
7
+ end
8
+ end
9
+ 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
@@ -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
@@ -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