resque_manager 3.3.0 → 3.3.1

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.
@@ -1,9 +1,306 @@
1
- require 'test_helper'
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
+ require 'resque_manager/resque_controller.rb'
2
3
 
3
4
  module ResqueManager
4
5
  class ResqueControllerTest < ActionController::TestCase
5
- # test "the truth" do
6
- # assert true
7
- # end
6
+ context 'ResqueManager::ResqueController' do
7
+ setup { Resque.redis.flushdb } # flush redis
8
+ context '#working' do
9
+ should 'respond with success and render the _working partial' do
10
+ get :working, use_route: :resque_manager
11
+ assert_response :success
12
+ assert_template partial: '_working'
13
+ end
14
+ end
15
+
16
+ context '#queues' do
17
+ should 'respond with success and render the _queues partial' do
18
+ get :queues, use_route: :resque_manager
19
+ assert_response :success
20
+ assert_template partial: '_queues'
21
+ end
22
+ end
23
+
24
+ context '#poll' do
25
+ should 'respond with success and start the live polling' do
26
+ get :poll, { page: 'overview', use_route: :resque_manager }
27
+ assert_response :success
28
+ assert_select 'p.poll', text: /Last Updated: [0-9]{2}:[0-9]{2}:[0-9]{2}/, count: 1
29
+ end
30
+ end
31
+
32
+ context '#status_poll' do
33
+ should 'respond with success and start the live polling' do
34
+ get :status_poll, use_route: :resque_manager
35
+ assert_response :success
36
+ assert_select 'p.poll', text: /Last Updated: [0-9]{2}:[0-9]{2}:[0-9]{2}/, count: 1
37
+ end
38
+ end
39
+
40
+ context '#remove_job' do
41
+ should 'always redirect' do
42
+ @request.env['HTTP_REFERER'] = '/resque/queues/single_record_loader'
43
+ post :remove_job, { class: SingleRecordLoader, use_route: :resque_manager }
44
+ assert_redirected_to '/resque/queues/single_record_loader'
45
+ end
46
+
47
+ should 'dequeue' do
48
+ ResqueManager.applications.expects(:blank?).returns(true)
49
+ Resque.expects(:dequeue)
50
+ @request.env['HTTP_REFERER'] = '/resque/queues/single_record_loader'
51
+ post :remove_job, { class: SingleRecordLoader, use_route: :resque_manager }
52
+ assert_redirected_to '/resque/queues/single_record_loader'
53
+ end
54
+ end
55
+
56
+ context '#stop_worker' do
57
+ should 'always redirect to workers path' do
58
+ post :stop_worker, use_route: :resque_manager
59
+ assert_redirected_to '/resque/workers'
60
+ end
61
+
62
+ should 'stop a worker and redirect' do
63
+ worker = Resque::Worker.new(:data_contribution_file)
64
+ worker.expects(:quit)
65
+ ResqueManager::ResqueController.any_instance.expects(:find_worker).returns(worker)
66
+ post :stop_worker, { worker: worker, use_route: :resque_manager }
67
+ assert_redirected_to '/resque/workers'
68
+ end
69
+ end
70
+
71
+ context '#pause_worker' do
72
+ should 'always redirect to workers path' do
73
+ post :pause_worker, use_route: :resque_manager
74
+ assert_redirected_to '/resque/workers'
75
+ end
76
+
77
+ should 'pause a worker and redirect' do
78
+ worker = Resque::Worker.new(:data_contribution_file)
79
+ worker.expects(:pause)
80
+ ResqueManager::ResqueController.any_instance.expects(:find_worker).returns(worker)
81
+ post :pause_worker, { worker: worker, use_route: :resque_manager }
82
+ assert_redirected_to '/resque/workers'
83
+ end
84
+ end
85
+
86
+ context '#continue_worker' do
87
+ should 'always redirect to workers path' do
88
+ post :continue_worker, use_route: :resque_manager
89
+ assert_redirected_to '/resque/workers'
90
+ end
91
+
92
+ should 'continue a worker and redirect' do
93
+ worker = Resque::Worker.new(:data_contribution_file)
94
+ worker.expects(:continue)
95
+ ResqueManager::ResqueController.any_instance.expects(:find_worker).returns(worker)
96
+ post :continue_worker, { worker: worker, use_route: :resque_manager }
97
+ assert_redirected_to '/resque/workers'
98
+ end
99
+ end
100
+
101
+ context '#restart_worker' do
102
+ should 'always redirect to workers path' do
103
+ post :restart_worker, use_route: :resque_manager
104
+ assert_redirected_to '/resque/workers'
105
+ end
106
+
107
+ should 'continue a worker and redirect' do
108
+ worker = Resque::Worker.new(:data_contribution_file)
109
+ worker.expects(:restart)
110
+ ResqueManager::ResqueController.any_instance.expects(:find_worker).returns(worker)
111
+ post :restart_worker, { worker: worker, use_route: :resque_manager }
112
+ assert_redirected_to '/resque/workers'
113
+ end
114
+ end
115
+
116
+ context '#start_worker' do
117
+ should 'always redirect to workers path' do
118
+ post :start_worker, use_route: :resque_manager
119
+ assert_redirected_to '/resque/workers'
120
+ end
121
+
122
+ should 'continue a worker and redirect' do
123
+ worker = Resque::Worker.new(:data_contribution_file)
124
+ Resque::Worker.expects(:start)
125
+ post :start_worker, { worker: worker, use_route: :resque_manager }
126
+ assert_redirected_to '/resque/workers'
127
+ end
128
+ end
129
+
130
+ context '#stats' do
131
+ should 'redirect to /stats/resque for a missing id' do
132
+ post :stats, use_route: :resque_manager
133
+ assert_redirected_to '/resque/stats?id=resque'
134
+ end
135
+
136
+ should 'render resque info text when id is txt' do
137
+ post :stats, id: 'txt', use_route: :resque_manager
138
+ assert_equal 'resque.pending=0</br>resque.processed+=0</br>resque.failed+=0</br>resque.workers=0</br>resque.working=0', @response.body, @response.body
139
+ end
140
+ end
141
+
142
+ context '#schedule' do
143
+ should 'have a response of success' do
144
+ get :schedule, use_route: :resque_manager
145
+ assert_response :success
146
+ end
147
+ end
148
+
149
+ context '#schedule_requeue' do
150
+ should 'always redirect to overview' do
151
+ Resque::Scheduler.stubs(:enqueue_from_config)
152
+ post :schedule_requeue, use_route: :resque_manager
153
+ assert_redirected_to '/resque/overview'
154
+ end
155
+ end
156
+
157
+ context '#add_scheduled_job' do
158
+ should 'have an error for a name already existing and missing ip and missing cron' do
159
+ # Resque.schedule.keys.expects(:include?).returns(true)
160
+ # Stub on array instead of Resque.schedule.keys otherwise the stub never works.
161
+ Array.any_instance.expects(:include?).returns(true).at_least_once
162
+ post :add_scheduled_job, { name: 'key', use_route: :resque_manager }
163
+ assert_redirected_to '/resque/schedule'
164
+ errors = flash[:error].split('<br>')
165
+ assert_includes errors, 'You must enter an ip address for the server you want this job to run on.', errors.inspect
166
+ assert_includes errors, 'You must enter the cron schedule.', errors.inspect
167
+ assert_includes errors, 'Name already exists.'
168
+ end
169
+
170
+ should 'add a job to the scheduler' do
171
+ ip = '0.0.0.0'
172
+ Resque.redis.expects(:rpush)
173
+ ResqueScheduler.expects(:restart).with(ip)
174
+ post :add_scheduled_job, { 'name'=> 'TestName', 'class' => 'SingleRecordLoader', 'ip' => ip, 'args' => nil, 'description' => 'Test job', 'cron' => 'TestCron', use_route: :resque_manager }
175
+ assert_nil flash[:error]
176
+ end
177
+ end
178
+
179
+ context '#remove_from_schedule' do
180
+ should 'always redirect to schedule' do
181
+ post :remove_from_schedule, use_route: :resque_manager
182
+ assert_redirected_to '/resque/schedule'
183
+ end
184
+
185
+ should 'restart schedule from ip' do
186
+ Resque.stubs(:list_range).returns([{'SingleRecordLoader' => 'test data'}])
187
+ Resque.redis.expects(:lrem).with(:scheduled, 0, {'SingleRecordLoader' => 'test data'}.to_json)
188
+ ResqueScheduler.expects(:restart).with('0.0.0.0')
189
+ post :remove_from_schedule, { ip: '0.0.0.0', job_name: 'SingleRecordLoader', use_route: :resque_manager }
190
+ assert_redirected_to '/resque/schedule'
191
+ end
192
+ end
193
+
194
+ context '#start_scheduler' do
195
+ should 'always redirect to schedule and call ResqueScheduler.start' do
196
+ ResqueScheduler.expects(:start).with('0.0.0.0')
197
+ post :start_scheduler, { ip: '0.0.0.0', use_route: :resque_manager }
198
+ assert_redirected_to '/resque/schedule'
199
+ end
200
+ end
201
+
202
+ context '#stop_scheduler' do
203
+ should 'always redirect to schedule and call ResqueScheduler.start' do
204
+ ResqueScheduler.expects(:quit).with('0.0.0.0')
205
+ post :stop_scheduler, { ip: '0.0.0.0', use_route: :resque_manager }
206
+ assert_redirected_to '/resque/schedule'
207
+ end
208
+ end
209
+
210
+ context '#statuses' do
211
+ should 'respond with a status in json format' do
212
+ hash = Resque::Plugins::Status::Hash.set('UUID', 'message')
213
+ Resque::Plugins::Status::Hash.stubs(:status_ids).returns(%w(UUID))
214
+ post :statuses, { format: :js, use_route: :resque_manager }
215
+ assert_equal hash, JSON.parse(@response.body).first, JSON.parse(@response.body).inspect
216
+ end
217
+ end
218
+
219
+ context '#clear_statuses' do
220
+ should 'always redirect to statuses page and call Resque::Plugins::Status::Hash.clear' do
221
+ Resque::Plugins::Status::Hash.expects(:clear)
222
+ post :clear_statuses, use_route: :resque_manager
223
+ assert_redirected_to '/resque/statuses'
224
+ end
225
+ end
226
+
227
+ context '#status' do
228
+ should 'render a status in json' do
229
+ hash = Resque::Plugins::Status::Hash.set('UUID', 'message')
230
+ post :status, { id: 'UUID', format: :js, use_route: :resque_manager }
231
+ assert_equal hash, JSON.parse(@response.body), JSON.parse(@response.body).inspect
232
+ end
233
+ end
234
+
235
+ context '#kill' do
236
+ should 'redirect to statuses and kill a status' do
237
+ Resque::Plugins::Status::Hash.set('UUID', 'message')
238
+ post :kill, { id: 'UUID', use_route: :resque_manager }
239
+ assert_redirected_to '/resque/statuses'
240
+ hash = Resque::Plugins::Status::Hash.get('UUID')
241
+ assert_equal 'killed', hash['status']
242
+ end
243
+ end
244
+
245
+ context '#cleaner_stale' do
246
+ should 'always redirect to cleaner' do
247
+ Resque::Plugins::ResqueCleaner.any_instance.expects(:clear_stale)
248
+ post :cleaner_stale, use_route: :resque_manager
249
+ assert_redirected_to '/resque/cleaner'
250
+ end
251
+ end
252
+
253
+ context 'private' do
254
+ setup { @controller = ResqueController.new }
255
+ context '#check_connection' do
256
+ should 'return true' do
257
+ assert @controller.send(:check_connection)
258
+ end
259
+
260
+ should 'rescue a Errno::ECONNRFUSED exception and render template resque/error' do
261
+ # Check connection is a before_filter stub an exception and make a get request to working
262
+ # We need an actual request to render the template
263
+ Resque.expects(:keys).raises(Errno::ECONNREFUSED.new)
264
+ get :working, use_route: :resque_manager
265
+ assert_match /#{Resque.redis_id}/, @response.body, @response.body.inspect
266
+ assert_template 'resque/error'
267
+ end
268
+ end
269
+
270
+ context '#find_worker' do
271
+ should 'return nil for a missing worker' do
272
+ assert_nil @controller.send(:find_worker, '')
273
+ end
274
+
275
+ should 'find the correct worker' do
276
+ worker = Resque::Worker.new(:data_contribution_file)
277
+ Resque::Worker.expects(:exists?).returns(true)
278
+ response = @controller.send(:find_worker, worker.to_s)
279
+ first, *rest=worker.to_s.split(':')
280
+ first.gsub!(/_/, '.')
281
+ worker_id = "#{first}:#{rest.join(':')}"
282
+ worker.to_s = worker_id
283
+ assert_equal worker, response
284
+ end
285
+ end
286
+
287
+ context '#get_cleaner' do
288
+ should 'return a cleaner' do
289
+ cleaner = @controller.send(:get_cleaner)
290
+ assert_kind_of Resque::Plugins::ResqueCleaner, cleaner
291
+ refute cleaner.print_message
292
+ end
293
+ end
294
+
295
+ context '#hours_ago' do
296
+ should 'return the correctly formatted hours ago time' do
297
+ now = Time.now
298
+ Time.expects(:now).returns(now).at_least_once
299
+ hours = @controller.send(:hours_ago, 2)
300
+ assert_equal now - 2*60*60, hours
301
+ end
302
+ end
303
+ end
304
+ end
8
305
  end
9
306
  end
@@ -1,8 +1,11 @@
1
1
  # Configure Rails Environment
2
- ENV["RAILS_ENV"] = "test"
2
+ ENV['RAILS_ENV'] = 'test'
3
+ require 'resque_scheduler' # require here for tests since we don't require it in the Gemfile since it's optional
3
4
 
4
- require File.expand_path("../dummy/config/environment.rb", __FILE__)
5
- require "rails/test_help"
5
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
6
+ require 'rails/test_help'
7
+
8
+ require 'shoulda'
6
9
 
7
10
  Rails.backtrace_cleaner.remove_silencers!
8
11
 
@@ -11,5 +14,5 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
11
14
 
12
15
  # Load fixtures from the engine
13
16
  if ActiveSupport::TestCase.method_defined?(:fixture_path=)
14
- ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
17
+ ActiveSupport::TestCase.fixture_path = File.expand_path('../fixtures', __FILE__)
15
18
  end
@@ -0,0 +1,169 @@
1
+ require 'test/unit'
2
+ require 'socket'
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../../test_helper')
4
+
5
+ class WorkerTest < Test::Unit::TestCase
6
+ context 'Worker' do
7
+ setup do
8
+ Resque.redis.flushdb # flush redis
9
+ Thread.current[:queues] = '*'
10
+ Thread.current[:path] = 'path'
11
+ @worker = Resque::Worker.new(:data_contribution_file)
12
+ end
13
+
14
+ context '#local_ip' do
15
+ should 'set the local_ip' do
16
+ assert_equal IPSocket.getaddress(Socket.gethostname), @worker.local_ip
17
+ end
18
+ end
19
+
20
+ context '#to_s' do
21
+ should 'return the correct string representation of the worker'do
22
+ Process.stubs(:pid).returns(27415)
23
+ object_id = Thread.current.object_id
24
+ assert_equal "#{Socket.gethostname}(#{IPSocket.getaddress(Socket.gethostname)}):27415:#{object_id}:path:*", @worker.to_s
25
+ end
26
+
27
+ should 'alias to_s as id' do
28
+ assert_not_nil @worker.id
29
+ end
30
+ end
31
+
32
+ context '#pause' do
33
+ should 'return a correctly formatted pause key' do
34
+ Process.stubs(:pid).returns(27415)
35
+ assert_equal "worker:#{Socket.gethostname}(#{IPSocket.getaddress(Socket.gethostname)}):27415:all_workers:paused", @worker.pause_key
36
+ end
37
+ end
38
+
39
+ context '#pid' do
40
+ should 'return the correct pid' do
41
+ Process.stubs(:pid).returns(27415)
42
+ assert_equal '27415', @worker.pid
43
+ end
44
+ end
45
+
46
+ context '#thread' do
47
+ should 'return the correct thread' do
48
+ assert_equal Thread.current.object_id.to_s, @worker.thread
49
+ end
50
+ end
51
+
52
+ context '#path' do
53
+ should 'return the correct path' do
54
+ assert_equal Thread.current[:path], @worker.path
55
+ end
56
+ end
57
+
58
+ context '#queue' do
59
+ should 'return the correct queue' do
60
+ assert_equal Thread.current[:queues], @worker.queue
61
+ end
62
+ end
63
+
64
+ context '#workers_in_pid' do
65
+ should 'return the worker in the redis' do
66
+ Resque.redis.sadd(:workers, @worker.to_s)
67
+ assert_equal @worker.to_s, @worker.workers_in_pid.first.to_s
68
+ end
69
+
70
+ should 'return an empty array' do
71
+ assert_empty @worker.workers_in_pid
72
+ end
73
+ end
74
+
75
+ context '#ip' do
76
+ should 'return the correct ip' do
77
+ assert_equal IPSocket.getaddress(Socket.gethostname), @worker.ip
78
+ end
79
+ end
80
+
81
+ context '#queues_in_pid' do
82
+ should 'return the correct queue' do
83
+ Resque.redis.sadd(:workers, @worker.to_s)
84
+ assert_equal '*', @worker.queues_in_pid.first
85
+ end
86
+ end
87
+
88
+ context '#queues' do
89
+ should 'return an array of queues when the queue is not *' do
90
+ Thread.current[:queues] = 'data_contribution,single_record_loader'
91
+ assert_equal %w(data_contribution single_record_loader), @worker.queues
92
+ end
93
+
94
+ should 'return an array of sorted resque queues' do
95
+ Resque.redis.sadd(:queues, @worker.to_s)
96
+ assert_equal @worker.to_s, @worker.queues.first
97
+ end
98
+ end
99
+
100
+ context '#shutdown' do
101
+ should 'set @shutdown to true and threads shutdown to true' do
102
+ @worker.expects(:log).with('Exiting...')
103
+ @worker.shutdown
104
+ Thread.list.each { |t| assert t[:shutdown] }
105
+ assert @worker.shutdown?
106
+ end
107
+ end
108
+
109
+ context '#paused' do
110
+ should 'return the correct pause_key' do
111
+ now = Time.now.to_s
112
+ Resque.redis.set(@worker.pause_key, Time.now.to_s)
113
+ assert_equal now, @worker.paused
114
+ end
115
+ end
116
+
117
+ context '#paused?' do
118
+ should 'return true when paused is present and @paused is false' do
119
+ now = Time.now.to_s
120
+ Resque.redis.set(@worker.pause_key, now)
121
+ @worker.instance_variable_set(:@paused, false)
122
+ assert @worker.paused?
123
+ end
124
+
125
+ should 'return true when @paused is true' do
126
+ @worker.instance_variable_set(:@paused, true)
127
+ assert @worker.paused?
128
+ end
129
+ end
130
+
131
+ context '#pause_processing' do
132
+ should 'set the worker pause key to Time.now and log the pausing process' do
133
+ @worker.expects(:log).with('USR2 received; pausing job processing')
134
+ now = Time.now
135
+ Time.expects(:now).returns(now).at_least_once
136
+ @worker.pause_processing
137
+ assert_equal now.to_s, @worker.paused
138
+ end
139
+ end
140
+
141
+ context '#unpause_processing' do
142
+ should 'delete the worker pause key and log the un-pausing process' do
143
+ Resque.redis.set(@worker.pause_key, Time.now.to_s) # Set the pause key
144
+ @worker.expects(:log).with('CONT received; resuming job processing')
145
+ @worker.unpause_processing
146
+ assert_nil @worker.paused
147
+ refute @worker.paused?
148
+ end
149
+ end
150
+
151
+ context '#prune_dead_workers' do
152
+ should 'unregister a worker when its pid is not included in worker_pids' do
153
+ Resque.redis.sadd(:workers, @worker.to_s)
154
+ @worker.expects(:worker_pids).returns([])
155
+ @worker.expects(:log!).with("Pruning dead worker: #{@worker.to_s}")
156
+ Resque::Worker.any_instance.expects(:unregister_worker)
157
+ @worker.prune_dead_workers
158
+ end
159
+ end
160
+
161
+ context '#unregister_worker_with_pause' do
162
+ should 'delete the pause key from redis' do
163
+ Resque.redis.set(@worker.pause_key, Time.now.to_s)
164
+ Redis.any_instance.expects(:del).at_least_once
165
+ @worker.unregister_worker_with_pause
166
+ end
167
+ end
168
+ end
169
+ end