rails-four-queueing 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,111 @@
1
+ # Original File: RAILS_ROOT/activesupport/test/queueing/threaded_consumer_test.rb
2
+ require "support/active_support_abstract_unit"
3
+ require "rails/four/queueing"
4
+ require "active_support/log_subscriber/test_helper"
5
+
6
+ class TestThreadConsumer < ActiveSupport::TestCase
7
+ class Job
8
+ attr_reader :id
9
+ def initialize(id = 1, &block)
10
+ @id = id
11
+ @block = block
12
+ end
13
+
14
+ def run
15
+ @block.call if @block
16
+ end
17
+ end
18
+
19
+ def setup
20
+ @logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
21
+ @queue = Rails::Four::Queueing::Queue.new(logger: @logger)
22
+ end
23
+
24
+ def teardown
25
+ @queue.drain
26
+ end
27
+
28
+ test "the jobs are executed" do
29
+ ran = false
30
+ job = Job.new { ran = true }
31
+
32
+ @queue.push job
33
+ @queue.drain
34
+
35
+ assert_equal true, ran
36
+ end
37
+
38
+ test "the jobs are not executed synchronously" do
39
+ run, ran = Queue.new, Queue.new
40
+ job = Job.new { ran.push run.pop }
41
+
42
+ @queue.consumer.start
43
+ @queue.push job
44
+ assert ran.empty?
45
+
46
+ run.push true
47
+ assert_equal true, ran.pop
48
+ end
49
+
50
+ test "shutting down the queue synchronously drains the jobs" do
51
+ ran = false
52
+ job = Job.new do
53
+ sleep 0.1
54
+ ran = true
55
+ end
56
+
57
+ @queue.consumer.start
58
+ @queue.push job
59
+ assert_equal false, ran
60
+
61
+ @queue.consumer.shutdown
62
+ assert_equal true, ran
63
+ end
64
+
65
+ test "log job that raises an exception" do
66
+ job = Job.new { raise "RuntimeError: Error!" }
67
+
68
+ @queue.push job
69
+ consume_queue @queue
70
+
71
+ assert_equal 1, @logger.logged(:error).size
72
+ assert_match "Job Error: #{job.inspect}\nRuntimeError: Error!", @logger.logged(:error).last
73
+ end
74
+
75
+ test "logger defaults to stderr" do
76
+ begin
77
+ $stderr, old_stderr = StringIO.new, $stderr
78
+ queue = Rails::Four::Queueing::Queue.new
79
+ queue.push Job.new { raise "RuntimeError: Error!" }
80
+ consume_queue queue
81
+ assert_match 'Job Error', $stderr.string
82
+ ensure
83
+ $stderr = old_stderr
84
+ end
85
+ end
86
+
87
+ test "test overriding exception handling" do
88
+ @queue.consumer.instance_eval do
89
+ def handle_exception(job, exception)
90
+ @last_error = exception.message
91
+ end
92
+
93
+ def last_error
94
+ @last_error
95
+ end
96
+ end
97
+
98
+ job = Job.new { raise "RuntimeError: Error!" }
99
+
100
+ @queue.push job
101
+ consume_queue @queue
102
+
103
+ assert_equal "RuntimeError: Error!", @queue.consumer.last_error
104
+ end
105
+
106
+ private
107
+ def consume_queue(queue)
108
+ queue.push nil
109
+ queue.consumer.consume
110
+ end
111
+ end
@@ -0,0 +1,247 @@
1
+ # require "isolation/abstract_unit"
2
+ # require 'set'
3
+
4
+ # module ApplicationTests
5
+ # class FrameworksTest < ActiveSupport::TestCase
6
+ # include ActiveSupport::Testing::Isolation
7
+
8
+ # def setup
9
+ # build_app
10
+ # boot_rails
11
+ # FileUtils.rm_rf "#{app_path}/config/environments"
12
+ # end
13
+
14
+ # def teardown
15
+ # teardown_app
16
+ # end
17
+
18
+ # # AC & AM
19
+ # test "set load paths set only if action controller or action mailer are in use" do
20
+ # assert_nothing_raised NameError do
21
+ # add_to_config <<-RUBY
22
+ # config.root = "#{app_path}"
23
+ # RUBY
24
+
25
+ # use_frameworks []
26
+ # require "#{app_path}/config/environment"
27
+ # end
28
+ # end
29
+
30
+ # test "sets action_controller and action_mailer load paths" do
31
+ # add_to_config <<-RUBY
32
+ # config.root = "#{app_path}"
33
+ # RUBY
34
+
35
+ # require "#{app_path}/config/environment"
36
+
37
+ # expanded_path = File.expand_path("app/views", app_path)
38
+ # assert_equal ActionController::Base.view_paths[0].to_s, expanded_path
39
+ # assert_equal ActionMailer::Base.view_paths[0].to_s, expanded_path
40
+ # end
41
+
42
+ # test "allows me to configure default url options for ActionMailer" do
43
+ # app_file "config/environments/development.rb", <<-RUBY
44
+ # AppTemplate::Application.configure do
45
+ # config.action_mailer.default_url_options = { :host => "test.rails" }
46
+ # end
47
+ # RUBY
48
+
49
+ # require "#{app_path}/config/environment"
50
+ # assert_equal "test.rails", ActionMailer::Base.default_url_options[:host]
51
+ # end
52
+
53
+ # test "uses the default queue for ActionMailer" do
54
+ # require "#{app_path}/config/environment"
55
+ # assert_kind_of ActiveSupport::Queue, ActionMailer::Base.queue
56
+ # end
57
+
58
+ # test "allows me to configure queue for ActionMailer" do
59
+ # app_file "config/environments/development.rb", <<-RUBY
60
+ # AppTemplate::Application.configure do
61
+ # config.action_mailer.queue = ActiveSupport::TestQueue.new
62
+ # end
63
+ # RUBY
64
+
65
+ # require "#{app_path}/config/environment"
66
+ # assert_kind_of ActiveSupport::TestQueue, ActionMailer::Base.queue
67
+ # end
68
+
69
+ # test "does not include url helpers as action methods" do
70
+ # app_file "config/routes.rb", <<-RUBY
71
+ # AppTemplate::Application.routes.draw do
72
+ # get "/foo", :to => lambda { |env| [200, {}, []] }, :as => :foo
73
+ # end
74
+ # RUBY
75
+
76
+ # app_file "app/mailers/foo.rb", <<-RUBY
77
+ # class Foo < ActionMailer::Base
78
+ # def notify
79
+ # end
80
+ # end
81
+ # RUBY
82
+
83
+ # require "#{app_path}/config/environment"
84
+ # assert Foo.method_defined?(:foo_path)
85
+ # assert Foo.method_defined?(:main_app)
86
+ # assert_equal Set.new(["notify"]), Foo.action_methods
87
+ # end
88
+
89
+ # test "allows to not load all helpers for controllers" do
90
+ # add_to_config "config.action_controller.include_all_helpers = false"
91
+
92
+ # app_file "app/controllers/application_controller.rb", <<-RUBY
93
+ # class ApplicationController < ActionController::Base
94
+ # end
95
+ # RUBY
96
+
97
+ # app_file "app/controllers/foo_controller.rb", <<-RUBY
98
+ # class FooController < ApplicationController
99
+ # def included_helpers
100
+ # render :inline => "<%= from_app_helper -%> <%= from_foo_helper %>"
101
+ # end
102
+
103
+ # def not_included_helper
104
+ # render :inline => "<%= respond_to?(:from_bar_helper) -%>"
105
+ # end
106
+ # end
107
+ # RUBY
108
+
109
+ # app_file "app/helpers/application_helper.rb", <<-RUBY
110
+ # module ApplicationHelper
111
+ # def from_app_helper
112
+ # "from_app_helper"
113
+ # end
114
+ # end
115
+ # RUBY
116
+
117
+ # app_file "app/helpers/foo_helper.rb", <<-RUBY
118
+ # module FooHelper
119
+ # def from_foo_helper
120
+ # "from_foo_helper"
121
+ # end
122
+ # end
123
+ # RUBY
124
+
125
+ # app_file "app/helpers/bar_helper.rb", <<-RUBY
126
+ # module BarHelper
127
+ # def from_bar_helper
128
+ # "from_bar_helper"
129
+ # end
130
+ # end
131
+ # RUBY
132
+
133
+ # app_file "config/routes.rb", <<-RUBY
134
+ # AppTemplate::Application.routes.draw do
135
+ # get "/:controller(/:action)"
136
+ # end
137
+ # RUBY
138
+
139
+ # require 'rack/test'
140
+ # extend Rack::Test::Methods
141
+
142
+ # get "/foo/included_helpers"
143
+ # assert_equal "from_app_helper from_foo_helper", last_response.body
144
+
145
+ # get "/foo/not_included_helper"
146
+ # assert_equal "false", last_response.body
147
+ # end
148
+
149
+ # # AD
150
+ # test "action_dispatch extensions are applied to ActionDispatch" do
151
+ # add_to_config "config.action_dispatch.tld_length = 2"
152
+ # require "#{app_path}/config/environment"
153
+ # assert_equal 2, ActionDispatch::Http::URL.tld_length
154
+ # end
155
+
156
+ # test "assignment config.encoding to default_charset" do
157
+ # charset = 'Shift_JIS'
158
+ # add_to_config "config.encoding = '#{charset}'"
159
+ # require "#{app_path}/config/environment"
160
+ # assert_equal charset, ActionDispatch::Response.default_charset
161
+ # end
162
+
163
+ # # AS
164
+ # test "if there's no config.active_support.bare, all of ActiveSupport is required" do
165
+ # use_frameworks []
166
+ # require "#{app_path}/config/environment"
167
+ # assert_nothing_raised { [1,2,3].sample }
168
+ # end
169
+
170
+ # test "config.active_support.bare does not require all of ActiveSupport" do
171
+ # add_to_config "config.active_support.bare = true"
172
+
173
+ # use_frameworks []
174
+
175
+ # Dir.chdir("#{app_path}/app") do
176
+ # require "#{app_path}/config/environment"
177
+ # assert_raises(NoMethodError) { "hello".exclude? "lo" }
178
+ # end
179
+ # end
180
+
181
+ # # AR
182
+ # test "active_record extensions are applied to ActiveRecord" do
183
+ # add_to_config "config.active_record.table_name_prefix = 'tbl_'"
184
+ # require "#{app_path}/config/environment"
185
+ # assert_equal 'tbl_', ActiveRecord::Base.table_name_prefix
186
+ # end
187
+
188
+ # test "database middleware doesn't initialize when activerecord is not in frameworks" do
189
+ # use_frameworks []
190
+ # require "#{app_path}/config/environment"
191
+ # assert_nil defined?(ActiveRecord::Base)
192
+ # end
193
+
194
+ # test "use schema cache dump" do
195
+ # Dir.chdir(app_path) do
196
+ # `rails generate model post title:string;
197
+ # bundle exec rake db:migrate db:schema:cache:dump`
198
+ # end
199
+ # require "#{app_path}/config/environment"
200
+ # ActiveRecord::Base.connection.drop_table("posts") # force drop posts table for test.
201
+ # assert ActiveRecord::Base.connection.schema_cache.tables["posts"]
202
+ # end
203
+
204
+ # test "expire schema cache dump" do
205
+ # Dir.chdir(app_path) do
206
+ # `rails generate model post title:string;
207
+ # bundle exec rake db:migrate db:schema:cache:dump db:rollback`
208
+ # end
209
+ # silence_warnings {
210
+ # require "#{app_path}/config/environment"
211
+ # assert !ActiveRecord::Base.connection.schema_cache.tables["posts"]
212
+ # }
213
+ # end
214
+
215
+ # test "active record establish_connection uses Rails.env if DATABASE_URL is not set" do
216
+ # begin
217
+ # require "#{app_path}/config/environment"
218
+ # orig_database_url = ENV.delete("DATABASE_URL")
219
+ # orig_rails_env, Rails.env = Rails.env, 'development'
220
+ # ActiveRecord::Base.establish_connection
221
+ # assert ActiveRecord::Base.connection
222
+ # assert_match /#{ActiveRecord::Base.configurations[Rails.env]['database']}/, ActiveRecord::Base.connection_config[:database]
223
+ # ensure
224
+ # ActiveRecord::Base.remove_connection
225
+ # ENV["DATABASE_URL"] = orig_database_url if orig_database_url
226
+ # Rails.env = orig_rails_env if orig_rails_env
227
+ # end
228
+ # end
229
+
230
+ # test "active record establish_connection uses DATABASE_URL even if Rails.env is set" do
231
+ # begin
232
+ # require "#{app_path}/config/environment"
233
+ # orig_database_url = ENV.delete("DATABASE_URL")
234
+ # orig_rails_env, Rails.env = Rails.env, 'development'
235
+ # database_url_db_name = "db/database_url_db.sqlite3"
236
+ # ENV["DATABASE_URL"] = "sqlite3://:@localhost/#{database_url_db_name}"
237
+ # ActiveRecord::Base.establish_connection
238
+ # assert ActiveRecord::Base.connection
239
+ # assert_match /#{database_url_db_name}/, ActiveRecord::Base.connection_config[:database]
240
+ # ensure
241
+ # ActiveRecord::Base.remove_connection
242
+ # ENV["DATABASE_URL"] = orig_database_url if orig_database_url
243
+ # Rails.env = orig_rails_env if orig_rails_env
244
+ # end
245
+ # end
246
+ # end
247
+ # end
@@ -0,0 +1,169 @@
1
+ require "support/isolation_abstract_unit"
2
+
3
+ class QueueTest < ActiveSupport::TestCase
4
+ include ActiveSupport::Testing::Isolation
5
+
6
+ # overwrite the default `build_app` method to inject the gem for testing
7
+ def build_app
8
+ super
9
+
10
+ # inject the path to the gem we're testing
11
+ environment = File.read("#{app_path}/config/application.rb")
12
+ if environment =~ /(module AppTemplate)/
13
+ rails_four_queueing_path = File.expand_path(
14
+ "../../../lib/rails-four-queueing", __FILE__
15
+ )
16
+ File.open("#{app_path}/config/application.rb", 'w') do |f|
17
+ # BOOYA!!
18
+ f.puts $` + %Q(\nrequire "#{rails_four_queueing_path}"\n) + $1 + $'
19
+ end
20
+ end
21
+ end
22
+
23
+ def setup
24
+ build_app
25
+ boot_rails
26
+ end
27
+
28
+ def teardown
29
+ teardown_app
30
+ end
31
+
32
+ def app_const
33
+ @app_const ||= Class.new(Rails::Application)
34
+ end
35
+
36
+ test "the queue is a SynchronousQueue in test mode" do
37
+ app("test")
38
+ assert_kind_of Rails::Four::Queueing::SynchronousQueue, Rails.application.queue
39
+ assert_kind_of Rails::Four::Queueing::SynchronousQueue, Rails.queue
40
+ end
41
+
42
+ test "the queue is a SynchronousQueue in development mode" do
43
+ app("development")
44
+ assert_kind_of Rails::Four::Queueing::SynchronousQueue, Rails.application.queue
45
+ assert_kind_of Rails::Four::Queueing::SynchronousQueue, Rails.queue
46
+ end
47
+
48
+ class ThreadTrackingJob
49
+ def initialize
50
+ @origin = Thread.current.object_id
51
+ end
52
+
53
+ def run
54
+ @target = Thread.current.object_id
55
+ end
56
+
57
+ def ran_in_different_thread?
58
+ @origin != @target
59
+ end
60
+
61
+ def ran?
62
+ @target
63
+ end
64
+ end
65
+
66
+ test "in development mode, an enqueued job will be processed in the same thread" do
67
+ app("development")
68
+
69
+ job = ThreadTrackingJob.new
70
+ Rails.queue.push job
71
+ sleep 0.1
72
+
73
+ assert job.ran?, "Expected job to be run"
74
+ refute job.ran_in_different_thread?, "Expected job to run in the same thread"
75
+ end
76
+
77
+ test "in test mode, an enqueued job will be processed in the same thread" do
78
+ app("test")
79
+
80
+ job = ThreadTrackingJob.new
81
+ Rails.queue.push job
82
+ sleep 0.1
83
+
84
+ assert job.ran?, "Expected job to be run"
85
+ refute job.ran_in_different_thread?, "Expected job to run in the same thread"
86
+ end
87
+
88
+ test "in production, automatically spawn a queue consumer in a background thread" do
89
+ add_to_env_config "production", <<-RUBY
90
+ config.queue = Rails::Four::Queueing::Queue.new
91
+ RUBY
92
+
93
+ app("production")
94
+
95
+ assert_nil Rails.application.config.queue_consumer
96
+ assert_kind_of Rails::Four::Queueing::ThreadedQueueConsumer, Rails.application.queue_consumer
97
+ assert_equal Rails.logger, Rails.application.queue_consumer.logger
98
+ end
99
+
100
+ test "attempting to marshal a queue will raise an exception" do
101
+ app("test")
102
+ assert_raises TypeError do
103
+ Marshal.dump Rails.queue
104
+ end
105
+ end
106
+
107
+ def setup_custom_queue
108
+ add_to_env_config "production", <<-RUBY
109
+ require "my_queue"
110
+ config.queue = MyQueue.new
111
+ RUBY
112
+
113
+ app_file "lib/my_queue.rb", <<-RUBY
114
+ class MyQueue
115
+ def push(job)
116
+ job.run
117
+ end
118
+ end
119
+ RUBY
120
+
121
+ app("production")
122
+ end
123
+
124
+ test "a custom queue implementation can be provided" do
125
+ setup_custom_queue
126
+
127
+ assert_kind_of MyQueue, Rails.queue
128
+
129
+ job = Struct.new(:id, :ran) do
130
+ def run
131
+ self.ran = true
132
+ end
133
+ end
134
+
135
+ job1 = job.new(1)
136
+ Rails.queue.push job1
137
+
138
+ assert_equal true, job1.ran
139
+ end
140
+
141
+ test "a custom consumer implementation can be provided" do
142
+ add_to_env_config "production", <<-RUBY
143
+ require "my_queue_consumer"
144
+ config.queue = Rails::Four::Queueing::Queue.new
145
+ config.queue_consumer = MyQueueConsumer.new
146
+ RUBY
147
+
148
+ app_file "lib/my_queue_consumer.rb", <<-RUBY
149
+ class MyQueueConsumer
150
+ attr_reader :started
151
+
152
+ def start
153
+ @started = true
154
+ end
155
+ end
156
+ RUBY
157
+
158
+ app("production")
159
+
160
+ assert_kind_of MyQueueConsumer, Rails.application.queue_consumer
161
+ assert Rails.application.queue_consumer.started
162
+ end
163
+
164
+ test "default consumer is not used with custom queue implementation" do
165
+ setup_custom_queue
166
+
167
+ assert_nil Rails.application.queue_consumer
168
+ end
169
+ end