resque_manager 3.3.0 → 3.3.1

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