diff --git a/.gitignore b/.gitignore index f979559b..6cf79dee 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ nbproject .env .env.* + +/test/dummy/log/ diff --git a/lib/resque-scheduler.rb b/lib/resque-scheduler.rb index b770cd91..5c64f324 100644 --- a/lib/resque-scheduler.rb +++ b/lib/resque-scheduler.rb @@ -1,4 +1,5 @@ # vim:fileencoding=utf-8 require_relative 'resque/scheduler' +require 'resque/scheduler/engine' Resque.extend Resque::Scheduler::Extension diff --git a/lib/resque/scheduler/engine.rb b/lib/resque/scheduler/engine.rb new file mode 100644 index 00000000..ef6a1cbc --- /dev/null +++ b/lib/resque/scheduler/engine.rb @@ -0,0 +1,48 @@ +require 'resque_web' + +module ResqueWeb + module Plugins + module ResqueScheduler + class Engine < Rails::Engine + isolate_namespace ResqueWeb::Plugins::ResqueScheduler + paths['app'] << 'lib/resque/scheduler/engine/app' + paths['app/helpers'] << 'lib/resque/scheduler/engine/app/helpers' + paths['app/views'] << 'lib/resque/scheduler/engine/app/views' + paths['app/controllers'] << 'lib/resque/scheduler/'\ + 'engine/app/controllers' + end + + Engine.routes do + get 'schedule', to: 'schedules#index', as: 'schedules' + post 'schedule/requeue', to: 'schedules#requeue', as: 'requeue' + post 'schedule/requeue_with_params', + to: 'schedules#requeue_with_params', + as: 'requeue_with_params' + delete 'schedule', to: 'schedules#destroy', as: 'schedule' + + get 'delayed', to: 'delayed#index', as: 'delayed' + get 'delayed/jobs/:klass', + to: 'delayed#jobs_klass', + as: 'delayed_job_class' + post 'delayed/search', to: 'delayed#search', as: 'delayed_search' + get 'delayed/:timestamp', to: 'delayed#timestamp', as: 'timestamp' + post 'delayed/queue_now', to: 'delayed#queue_now', as: 'queue_now' + post 'delayed/cancel_now', to: 'delayed#cancel_now', as: 'cancel_now' + post '/delayed/clear', to: 'delayed#clear', as: 'clear' + end + + def self.engine_path + '/scheduler' + end + + def self.tabs + [ + { + 'schedule' => Engine.app.url_helpers.schedules_path, + 'delayed' => Engine.app.url_helpers.delayed_path + } + ] + end + end + end +end diff --git a/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb b/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb new file mode 100644 index 00000000..c0f45982 --- /dev/null +++ b/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb @@ -0,0 +1,100 @@ +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedController < ResqueWeb::ApplicationController + def index + end + + def jobs_klass + klass = Resque::Scheduler::Util.constantize(params[:klass]) + @args = JSON.load(URI.decode(params[:args])) + @timestamps = Resque.scheduled_at(klass, *@args) + rescue + @timestamps = [] + end + + def search + @jobs = find_job(params[:search]) + end + + def cancel_now + klass = Resque::Scheduler::Util.constantize(params['klass']) + timestamp = params['timestamp'] + args = Resque.decode params['args'] + Resque.remove_delayed_job_from_timestamp(timestamp, klass, *args) + redirect_to Engine.app.url_helpers.delayed_path + end + + def clear + Resque.reset_delayed_queue + redirect_to Engine.app.url_helpers.delayed_path + end + + def queue_now + timestamp = params['timestamp'].to_i + if timestamp > 0 + Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp) + end + redirect_to ResqueWeb::Engine.app.url_helpers.overview_path + end + + def timestamp + @timestamp = params[:timestamp].to_i + end + + protected + + def find_job(worker) + worker = worker.downcase + results = working_jobs_for_worker(worker) + + dels = delayed_jobs_for_worker(worker) + results += dels.select do |j| + j['class'].downcase.include?(worker) && + j.merge!('where_at' => 'delayed') + end + + Resque.queues.each do |queue| + queued = Resque.peek(queue, 0, Resque.size(queue)) + queued = [queued] unless queued.is_a?(Array) + results += queued.select do |j| + j['class'].downcase.include?(worker) && + j.merge!('queue' => queue, 'where_at' => 'queued') + end + end + + results + end + + def working_jobs_for_worker(worker) + [].tap do |results| + working = [*Resque.working] + work = working.select do |w| + w.job && w.job['payload'] && + w.job['payload']['class'].downcase.include?(worker) + end + work.each do |w| + results += [ + w.job['payload'].merge( + 'queue' => w.job['queue'], 'where_at' => 'working' + ) + ] + end + end + end + + def delayed_jobs_for_worker(_worker) + [].tap do |dels| + schedule_size = Resque.delayed_queue_schedule_size + Resque.delayed_queue_peek(0, schedule_size).each do |d| + Resque.delayed_timestamp_peek( + d, 0, Resque.delayed_timestamp_size(d)).each do |j| + dels << j.merge!('timestamp' => d) + end + end + end + end + end + end + end +end diff --git a/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb b/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb new file mode 100644 index 00000000..a5002403 --- /dev/null +++ b/lib/resque/scheduler/engine/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb @@ -0,0 +1,50 @@ +module ResqueWeb + module Plugins + module ResqueScheduler + class SchedulesController < ResqueWeb::ApplicationController + def index + Resque.reload_schedule! if Resque::Scheduler.dynamic + end + + def destroy + if Resque::Scheduler.dynamic + job_name = params['job_name'] || params[:job_name] + Resque.remove_schedule(job_name) + end + redirect_to Engine.app.url_helpers.schedules_path + end + + def requeue + @job_name = params['job_name'] || params[:job_name] + config = Resque.schedule[@job_name] + @parameters = config['parameters'] || config[:parameters] + if @parameters + render 'requeue-params' + else + Resque::Scheduler.enqueue_from_config(config) + redirect_to ResqueWeb::Engine.app.url_helpers.overview_path + end + end + + def requeue_with_params + job_name = params['job_name'] || params[:job_name] + config = Resque.schedule[job_name] + # Build args hash from post data (removing the job name) + submitted_args = params.reject do |key, _value| + %w(job_name action controller).include?(key) + end + + # Merge constructed args hash with existing args hash for + # the job, if it exists + config_args = config['args'] || config[:args] || {} + config_args = config_args.merge(submitted_args) + + # Insert the args hash into config and queue the resque job + config = config.merge('args' => config_args) + Resque::Scheduler.enqueue_from_config(config) + redirect_to ResqueWeb::Engine.app.url_helpers.overview_path + end + end + end + end +end diff --git a/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb b/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb new file mode 100644 index 00000000..0f84f06f --- /dev/null +++ b/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb @@ -0,0 +1,11 @@ +module ResqueWeb + module Plugins + module ResqueScheduler + module DelayedHelper + def format_time(t) + t.strftime('%Y-%m-%d %H:%M:%S %z') + end + end + end + end +end diff --git a/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb b/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb new file mode 100644 index 00000000..e4170605 --- /dev/null +++ b/lib/resque/scheduler/engine/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb @@ -0,0 +1,53 @@ +module ResqueWeb + module Plugins + module ResqueScheduler + module SchedulesHelper + def scheduled_in_this_env?(name) + return true if Resque.schedule[name]['rails_env'].nil? + rails_env(name).split(/[\s,]+/).include?(Resque::Scheduler.env) + end + + def rails_env(name) + Resque.schedule[name]['rails_env'] + end + + def schedule_interval_every(every) + every = [*every] + s = 'every: ' << every.first + + return s unless every.length > 1 + + s << ' (' + meta = every.last.map do |key, value| + "#{key.to_s.gsub(/_/, ' ')} #{value}" + end + s << meta.join(', ') << ')' + end + + def schedule_interval(config) + if config['every'] + schedule_interval_every(config['every']) + elsif config['cron'] + 'cron: ' + config['cron'].to_s + else + 'Not currently scheduled' + end + end + + def schedule_class(config) + if config['class'].nil? && !config['custom_job_class'].nil? + config['custom_job_class'] + else + config['class'] + end + end + + def queue_from_class_name(class_name) + Resque.queue_from_class( + Resque::Scheduler::Util.constantize(class_name) + ) + end + end + end + end +end diff --git a/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_next_more.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_next_more.erb new file mode 100644 index 00000000..784233df --- /dev/null +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_next_more.erb @@ -0,0 +1,23 @@ +<% # per_page was added in 1.23.1; gems which add to resque-server don't pass that variable along so it would crash %> +<% # without a default value %> +<% per_page ||= 20 %> +<% if start - per_page >= 0 || start + per_page <= size %> +

+ <% if start + per_page <= size %> + « + Next + <% end %> + + <% (size / per_page.to_f - 1).ceil.downto(0).each do |page_num| %> + <% if start == page_num * per_page %> + <%= page_num %> + <% else %> + <%= page_num %> + <% end %> + <% end %> + + <% if start - per_page >= 0 %> + Previous » + <% end %> +

+<% end %> \ No newline at end of file diff --git a/lib/resque/scheduler/server/views/search_form.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb similarity index 67% rename from lib/resque/scheduler/server/views/search_form.erb rename to lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb index c150c67a..f89eee9a 100644 --- a/lib/resque/scheduler/server/views/search_form.erb +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb @@ -1,4 +1,4 @@ -
+
diff --git a/lib/resque/scheduler/server/views/delayed.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb similarity index 52% rename from lib/resque/scheduler/server/views/delayed.erb rename to lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb index 857d16cf..d5197e70 100644 --- a/lib/resque/scheduler/server/views/delayed.erb +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb @@ -1,7 +1,7 @@

Delayed Jobs

-<%- size = resque.delayed_queue_schedule_size %> +<%- size = Resque.delayed_queue_schedule_size %> -<%= scheduler_view :search_form, layout: false %> +<%= render partial: 'search_form' %>

This list below contains the timestamps for scheduled delayed jobs. @@ -12,7 +12,7 @@ Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <%= size %> timestamps

- +
@@ -21,28 +21,28 @@ - <% resque.delayed_queue_peek(start, 20).each do |timestamp| %> + <% Resque.delayed_queue_peek(start, 20).each do |timestamp| %> - - - <% job = resque.delayed_timestamp_peek(timestamp, 0, 1).first %> + + + <% job = Resque.delayed_timestamp_peek(timestamp, 0, 1).first %> @@ -51,9 +51,10 @@ <% if size > 0 %>
- + <% end %> -<%= partial :next_more, :start => start, :size => size %> +<%= render partial: 'next_more', locals: { :start => start, :size => size } %> + diff --git a/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb new file mode 100644 index 00000000..f3a4e48a --- /dev/null +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb @@ -0,0 +1,20 @@ +

Delayed jobs scheduled for <%= params[:klass] %> (<%= @args %>)

+ +
TimestampArgs All schedules
-
" method="post"> + - +
"><%= format_time(Time.at(timestamp)) %><%= delayed_timestamp_size = resque.delayed_timestamp_size(timestamp) %><%= format_time(Time.at(timestamp)) %><%= delayed_timestamp_size = Resque.delayed_timestamp_size(timestamp) %> <% if job && delayed_timestamp_size == 1 %> <%= h(job['class']) %> <% else %> - ">see details + see details <% end %> <%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %> <% if job %> - All schedules + All schedules <% end %>
+ + + + + <% @timestamps.each do |t| %> + + + + <% end %> + <% if @timestamps.empty? %> + + + + <% end %> +
Timestamp
+ <%= Time.at(t) %> +
There are no such jobs scheduled.
diff --git a/lib/resque/scheduler/server/views/search.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb similarity index 82% rename from lib/resque/scheduler/server/views/search.erb rename to lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb index ff8252c2..e81dbbdd 100644 --- a/lib/resque/scheduler/server/views/search.erb +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb @@ -1,9 +1,9 @@

Search Results

-<%= scheduler_view :search_form, layout: false %> +<%= render partial: 'search_form' %>
<% delayed = @jobs.select { |j| j['where_at'] == 'delayed' } %>

Delayed jobs

- +
@@ -14,13 +14,13 @@ <% delayed.each do |job| %>
-
" method="post"> + - +
-
" method="post"> + @@ -37,7 +37,7 @@ <% queued = @jobs.select { |j| j['where_at'] == 'queued' } %>

Queued jobs

- +
@@ -54,7 +54,7 @@ <% working = @jobs.select { |j| j['where_at'] == 'working' } %>

Working jobs

-
Queue Class
+
diff --git a/lib/resque/scheduler/server/views/delayed_timestamp.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/timestamp.erb similarity index 58% rename from lib/resque/scheduler/server/views/delayed_timestamp.erb rename to lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/timestamp.erb index f7145b90..abd18c60 100644 --- a/lib/resque/scheduler/server/views/delayed_timestamp.erb +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/delayed/timestamp.erb @@ -1,15 +1,13 @@ -<% timestamp = params[:timestamp].to_i %> +

Delayed jobs scheduled for <%= format_time(Time.at(@timestamp)) %>

-

Delayed jobs scheduled for <%= format_time(Time.at(timestamp)) %>

- -

Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <%=size = resque.delayed_timestamp_size(timestamp)%> jobs

+

Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <%=size = Resque.delayed_timestamp_size(@timestamp)%> jobs

Queue Class
- <% jobs = resque.delayed_timestamp_peek(timestamp, start, 20) %> + <% jobs = Resque.delayed_timestamp_peek(@timestamp, start, 20) %> <% jobs.each do |job| %> @@ -23,4 +21,5 @@ <% end %>
Class Args
<%= job['class'] %>
-<%= partial :next_more, :start => start, :size => size %> +<%= render partial: 'next_more', locals: {:start => start, :size => size} %> + diff --git a/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/index.html.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/index.html.erb new file mode 100644 index 00000000..5437eb35 --- /dev/null +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/index.html.erb @@ -0,0 +1,53 @@ +

Schedule

+ +

+ The list below contains all scheduled jobs. Click "Queue now" to + queue + a job immediately. + Server local time: <%= Time.now %> + Current master: <%= Resque.redis.get(Resque::Scheduler.master_lock.key) %> +

+
+ + + <% if Resque::Scheduler.dynamic %> + + <% end %> + + + + + + + + + + <% Resque.schedule.keys.sort.select { |n| scheduled_in_this_env?(n) }.each do |name| %> + <% config = Resque.schedule[name] %> + + <% if Resque::Scheduler.dynamic %> + + <% end %> + + + + + + + + + + <% end %> +
NameDescriptionIntervalClassQueueArgumentsLast Enqueued
+ + + + + + +
+ + +
+
<%= h name %><%= h config['description'] %><%= h schedule_interval(config) %><%= h schedule_class(config) %><%= h config['queue'] || queue_from_class_name(config['class']) %><%= h config['args'].inspect %><%= h Resque.get_last_enqueued_at(name) || 'Never' %>
+
diff --git a/lib/resque/scheduler/server/views/requeue-params.erb b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/requeue-params.erb similarity index 87% rename from lib/resque/scheduler/server/views/requeue-params.erb rename to lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/requeue-params.erb index 1464f5bb..fa69c28b 100644 --- a/lib/resque/scheduler/server/views/requeue-params.erb +++ b/lib/resque/scheduler/engine/app/views/resque_web/plugins/resque_scheduler/schedules/requeue-params.erb @@ -4,7 +4,7 @@ This job requires parameters:

-
" method="post"> + <% @parameters.each do |key, value| %> <% value ||= {} %> diff --git a/lib/resque/scheduler/server.rb b/lib/resque/scheduler/server.rb deleted file mode 100644 index 6767a17f..00000000 --- a/lib/resque/scheduler/server.rb +++ /dev/null @@ -1,251 +0,0 @@ -# vim:fileencoding=utf-8 -require 'resque-scheduler' -require 'resque/server' -require 'json' - -# Extend Resque::Server to add tabs -module Resque - module Scheduler - module Server - unless defined?(::Resque::Scheduler::Server::VIEW_PATH) - VIEW_PATH = File.join(File.dirname(__FILE__), 'server', 'views') - end - - def self.included(base) - base.class_eval do - helpers { include HelperMethods } - include ServerMethods - - get('/schedule') { schedule } - post('/schedule/requeue') { schedule_requeue } - post('/schedule/requeue_with_params') do - schedule_requeue_with_params - end - delete('/schedule') { delete_schedule } - get('/delayed') { delayed } - get('/delayed/jobs/:klass') { delayed_jobs_klass } - post('/delayed/search') { delayed_search } - get('/delayed/:timestamp') { delayed_timestamp } - post('/delayed/queue_now') { delayed_queue_now } - post('/delayed/cancel_now') { delayed_cancel_now } - post('/delayed/clear') { delayed_clear } - end - end - - module ServerMethods - def schedule - Resque.reload_schedule! if Resque::Scheduler.dynamic - erb scheduler_template('scheduler') - end - - def schedule_requeue - @job_name = params['job_name'] || params[:job_name] - config = Resque.schedule[@job_name] - @parameters = config['parameters'] || config[:parameters] - if @parameters - erb scheduler_template('requeue-params') - else - Resque::Scheduler.enqueue_from_config(config) - redirect u('/overview') - end - end - - def schedule_requeue_with_params - job_name = params['job_name'] || params[:job_name] - config = Resque.schedule[job_name] - # Build args hash from post data (removing the job name) - submitted_args = params.reject do |key, _value| - key == 'job_name' || key == :job_name - end - - # Merge constructed args hash with existing args hash for - # the job, if it exists - config_args = config['args'] || config[:args] || {} - config_args = config_args.merge(submitted_args) - - # Insert the args hash into config and queue the resque job - config = config.merge('args' => config_args) - Resque::Scheduler.enqueue_from_config(config) - redirect u('/overview') - end - - def delete_schedule - if Resque::Scheduler.dynamic - job_name = params['job_name'] || params[:job_name] - Resque.remove_schedule(job_name) - end - redirect u('/schedule') - end - - def delayed - erb scheduler_template('delayed') - end - - def delayed_jobs_klass - begin - klass = Resque::Scheduler::Util.constantize(params[:klass]) - @args = JSON.load(URI.decode(params[:args])) - @timestamps = Resque.scheduled_at(klass, *@args) - rescue - @timestamps = [] - end - - erb scheduler_template('delayed_schedules') - end - - def delayed_search - @jobs = find_job(params[:search]) - erb scheduler_template('search') - end - - def delayed_timestamp - erb scheduler_template('delayed_timestamp') - end - - def delayed_queue_now - timestamp = params['timestamp'].to_i - if timestamp > 0 - Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp) - end - redirect u('/overview') - end - - def delayed_cancel_now - klass = Resque::Scheduler::Util.constantize(params['klass']) - timestamp = params['timestamp'] - args = Resque.decode params['args'] - Resque.remove_delayed_job_from_timestamp(timestamp, klass, *args) - redirect u('/delayed') - end - - def delayed_clear - Resque.reset_delayed_queue - redirect u('delayed') - end - end - - module HelperMethods - def format_time(t) - t.strftime('%Y-%m-%d %H:%M:%S %z') - end - - def queue_from_class_name(class_name) - Resque.queue_from_class( - Resque::Scheduler::Util.constantize(class_name) - ) - end - - def find_job(worker) - worker = worker.downcase - results = working_jobs_for_worker(worker) - - dels = delayed_jobs_for_worker(worker) - results += dels.select do |j| - j['class'].downcase.include?(worker) && - j.merge!('where_at' => 'delayed') - end - - Resque.queues.each do |queue| - queued = Resque.peek(queue, 0, Resque.size(queue)) - queued = [queued] unless queued.is_a?(Array) - results += queued.select do |j| - j['class'].downcase.include?(worker) && - j.merge!('queue' => queue, 'where_at' => 'queued') - end - end - - results - end - - def schedule_interval(config) - if config['every'] - schedule_interval_every(config['every']) - elsif config['cron'] - 'cron: ' + config['cron'].to_s - else - 'Not currently scheduled' - end - end - - def schedule_interval_every(every) - every = [*every] - s = 'every: ' << every.first - - return s unless every.length > 1 - - s << ' (' - meta = every.last.map do |key, value| - "#{key.to_s.gsub(/_/, ' ')} #{value}" - end - s << meta.join(', ') << ')' - end - - def schedule_class(config) - if config['class'].nil? && !config['custom_job_class'].nil? - config['custom_job_class'] - else - config['class'] - end - end - - def scheduler_template(name) - File.read( - File.expand_path("../server/views/#{name}.erb", __FILE__) - ) - end - - def scheduled_in_this_env?(name) - return true if Resque.schedule[name]['rails_env'].nil? - rails_env(name).split(/[\s,]+/).include?(Resque::Scheduler.env) - end - - def rails_env(name) - Resque.schedule[name]['rails_env'] - end - - def scheduler_view(filename, options = {}, locals = {}) - source = File.read(File.join(VIEW_PATH, "#{filename}.erb")) - erb source, options, locals - end - - private - - def working_jobs_for_worker(worker) - [].tap do |results| - working = [*Resque.working] - work = working.select do |w| - w.job && w.job['payload'] && - w.job['payload']['class'].downcase.include?(worker) - end - work.each do |w| - results += [ - w.job['payload'].merge( - 'queue' => w.job['queue'], 'where_at' => 'working' - ) - ] - end - end - end - - def delayed_jobs_for_worker(_worker) - [].tap do |dels| - schedule_size = Resque.delayed_queue_schedule_size - Resque.delayed_queue_peek(0, schedule_size).each do |d| - Resque.delayed_timestamp_peek( - d, 0, Resque.delayed_timestamp_size(d)).each do |j| - dels << j.merge!('timestamp' => d) - end - end - end - end - end - end - end -end - -Resque::Server.tabs << 'Schedule' -Resque::Server.tabs << 'Delayed' - -Resque::Server.class_eval do - include Resque::Scheduler::Server -end diff --git a/lib/resque/scheduler/server/views/delayed_schedules.erb b/lib/resque/scheduler/server/views/delayed_schedules.erb deleted file mode 100644 index 6bf9dd4b..00000000 --- a/lib/resque/scheduler/server/views/delayed_schedules.erb +++ /dev/null @@ -1,20 +0,0 @@ -

Delayed jobs scheduled for <%= params[:klass] %> (<%= @args %>)

- -
- - - - -<% @timestamps.each do |t| %> - - - -<% end %> -<% if @timestamps.empty? %> - - - -<% end %> -
Timestamp
- <%= Time.at(t) %> -
There are no such jobs scheduled.
diff --git a/lib/resque/scheduler/server/views/scheduler.erb b/lib/resque/scheduler/server/views/scheduler.erb deleted file mode 100644 index 1a97e932..00000000 --- a/lib/resque/scheduler/server/views/scheduler.erb +++ /dev/null @@ -1,52 +0,0 @@ -

Schedule

- -

- The list below contains all scheduled jobs. Click "Queue now" to queue - a job immediately. - Server local time: <%= Time.now %> - Current master: <%= Resque.redis.get(Resque::Scheduler.master_lock.key) %> -

-
- - - <% if Resque::Scheduler.dynamic %> - - <% end %> - - - - - - - - - - <% Resque.schedule.keys.sort.select { |n| scheduled_in_this_env?(n) }.each do |name| %> - <% config = Resque.schedule[name] %> - - <% if Resque::Scheduler.dynamic %> - - <% end %> - - - - - - - - - - <% end %> -
NameDescriptionIntervalClassQueueArgumentsLast Enqueued
- " method="post" style="margin-left: 0"> - - - - - -
" method="post" style="margin-left: 0"> - - -
-
<%= h name %><%= h config['description'] %><%= h schedule_interval(config) %><%= h schedule_class(config) %><%= h config['queue'] || queue_from_class_name(config['class']) %><%= h config['args'].inspect %><%= h Resque.get_last_enqueued_at(name) || 'Never' %>
-
diff --git a/resque-scheduler.gemspec b/resque-scheduler.gemspec index f0c671aa..3f978dd0 100644 --- a/resque-scheduler.gemspec +++ b/resque-scheduler.gemspec @@ -25,12 +25,19 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'bundler' spec.add_development_dependency 'json' spec.add_development_dependency 'kramdown' + spec.add_development_dependency 'minitest', '~> 5.0' + spec.add_development_dependency 'minitest-rails' spec.add_development_dependency 'mocha' spec.add_development_dependency 'pry' spec.add_development_dependency 'rack-test' spec.add_development_dependency 'rake' spec.add_development_dependency 'simplecov' spec.add_development_dependency 'yard' + spec.add_development_dependency 'rails', '~> 4.2.0' + spec.add_development_dependency 'resque-web' + spec.add_development_dependency 'sqlite3' + spec.add_development_dependency 'capybara' + spec.add_development_dependency 'launchy' # We pin rubocop because new cops have a tendency to result in false-y # positives for new contributors, which is not a nice experience. diff --git a/test/cli_test.rb b/test/cli_test.rb index 61a428a7..00afc2fd 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -1,7 +1,9 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'Cli' do +describe 'Cli' do + before { reset_resque_scheduler } + def mock_runtime_env mock.tap { |m| m.stubs(:setup) } end @@ -12,214 +14,214 @@ def new_cli(argv = [], env = {}) end end - test 'does not require any positional arguments' do + it 'does not require any positional arguments' do assert(!new_cli.nil?) end - test 'initializes verbose from the env' do + it 'initializes verbose from the env' do cli = new_cli([], 'VERBOSE' => 'foo') assert_equal('foo', cli.send(:options)[:verbose]) end - test 'defaults to non-verbose' do + it 'defaults to non-verbose' do assert_equal(false, !!new_cli.send(:options)[:verbose]) end - test 'accepts verbose via -v' do + it 'accepts verbose via -v' do cli = new_cli(%w(-v)) cli.parse_options assert_equal(true, cli.send(:options)[:verbose]) end - test 'accepts verbose via --verbose' do + it 'accepts verbose via --verbose' do cli = new_cli(%w(--verbose)) cli.parse_options assert_equal(true, cli.send(:options)[:verbose]) end - test 'initializes background from the env' do + it 'initializes background from the env' do cli = new_cli([], 'BACKGROUND' => '1') assert_equal('1', cli.send(:options)[:background]) end - test 'defaults to background=false' do + it 'defaults to background=false' do assert_equal(false, !!new_cli.send(:options)[:background]) end - test 'accepts background via -B' do + it 'accepts background via -B' do cli = new_cli(%w(-B)) cli.parse_options assert_equal(true, cli.send(:options)[:background]) end - test 'accepts background via --background' do + it 'accepts background via --background' do cli = new_cli(%w(--background)) cli.parse_options assert_equal(true, cli.send(:options)[:background]) end - test 'initializes pidfile from the env' do + it 'initializes pidfile from the env' do cli = new_cli([], 'PIDFILE' => 'bar') assert_equal('bar', cli.send(:options)[:pidfile]) end - test 'defaults to nil pidfile' do + it 'defaults to nil pidfile' do assert_equal(nil, new_cli.send(:options)[:pidfile]) end - test 'accepts pidfile via -P' do + it 'accepts pidfile via -P' do cli = new_cli(%w(-P foo)) cli.parse_options assert_equal('foo', cli.send(:options)[:pidfile]) end - test 'accepts pidfile via --pidfile' do + it 'accepts pidfile via --pidfile' do cli = new_cli(%w(--pidfile foo)) cli.parse_options assert_equal('foo', cli.send(:options)[:pidfile]) end - test 'defaults to nil dynamic' do + it 'defaults to nil dynamic' do assert_equal(nil, new_cli.send(:options)[:dynamic]) end - test 'initializes env from the env' do + it 'initializes env from the env' do cli = new_cli([], 'RAILS_ENV' => 'flurb') assert_equal('flurb', cli.send(:options)[:env]) end - test 'defaults to nil env' do + it 'defaults to nil env' do assert_equal(nil, new_cli.send(:options)[:env]) end - test 'accepts env via -E' do + it 'accepts env via -E' do cli = new_cli(%w(-E bork)) cli.parse_options assert_equal('bork', cli.send(:options)[:env]) end - test 'accepts env via --environment' do + it 'accepts env via --environment' do cli = new_cli(%w(--environment hork)) cli.parse_options assert_equal('hork', cli.send(:options)[:env]) end - test 'initializes initializer_path from the env' do + it 'initializes initializer_path from the env' do cli = new_cli([], 'INITIALIZER_PATH' => 'herp.rb') assert_equal('herp.rb', cli.send(:options)[:initializer_path]) end - test 'defaults to nil initializer_path' do + it 'defaults to nil initializer_path' do assert_equal(nil, new_cli.send(:options)[:initializer_path]) end - test 'accepts initializer_path via -I' do + it 'accepts initializer_path via -I' do cli = new_cli(%w(-I hambone.rb)) cli.parse_options assert_equal('hambone.rb', cli.send(:options)[:initializer_path]) end - test 'accepts initializer_path via --initalizer-path' do + it 'accepts initializer_path via --initalizer-path' do cli = new_cli(%w(--initializer-path cookies.rb)) cli.parse_options assert_equal('cookies.rb', cli.send(:options)[:initializer_path]) end - test 'loads given initilalizer_path' do + it 'loads given initilalizer_path' do cli = new_cli(%w(--initializer-path fuzzbert.rb)) cli.expects(:load).with('fuzzbert.rb') cli.pre_run end - test 'initializes quiet from the env' do + it 'initializes quiet from the env' do cli = new_cli([], 'QUIET' => '1') assert_equal('1', cli.send(:options)[:quiet]) end - test 'defaults to un-quieted' do + it 'defaults to un-quieted' do assert_equal(false, !!new_cli.send(:options)[:quiet]) end - test 'accepts quiet via -q' do + it 'accepts quiet via -q' do cli = new_cli(%w(-q)) cli.parse_options assert_equal(true, cli.send(:options)[:quiet]) end - test 'accepts quiet via --quiet' do + it 'accepts quiet via --quiet' do cli = new_cli(%w(--quiet)) cli.parse_options assert_equal(true, cli.send(:options)[:quiet]) end - test 'initializes logfile from the env' do + it 'initializes logfile from the env' do cli = new_cli([], 'LOGFILE' => 'example.log') assert_equal('example.log', cli.send(:options)[:logfile]) end - test 'defaults to nil logfile' do + it 'defaults to nil logfile' do assert_equal(nil, new_cli.send(:options)[:logfile]) end - test 'accepts logfile via -l' do + it 'accepts logfile via -l' do cli = new_cli(%w(-l hurm.out)) cli.parse_options assert_equal('hurm.out', cli.send(:options)[:logfile]) end - test 'accepts logfile via --logfile' do + it 'accepts logfile via --logfile' do cli = new_cli(%w(--logfile flam.log)) cli.parse_options assert_equal('flam.log', cli.send(:options)[:logfile]) end - test 'initializes logformat from the env' do + it 'initializes logformat from the env' do cli = new_cli([], 'LOGFORMAT' => 'fancy') assert_equal('fancy', cli.send(:options)[:logformat]) end - test 'defaults to nil logformat' do + it 'defaults to nil logformat' do assert_equal(nil, new_cli.send(:options)[:logformat]) end - test 'accepts logformat via -F' do + it 'accepts logformat via -F' do cli = new_cli(%w(-F silly)) cli.parse_options assert_equal('silly', cli.send(:options)[:logformat]) end - test 'accepts logformat via --logformat' do + it 'accepts logformat via --logformat' do cli = new_cli(%w(--logformat flimsy)) cli.parse_options assert_equal('flimsy', cli.send(:options)[:logformat]) end - test 'defaults to dynamic=false' do + it 'defaults to dynamic=false' do assert_equal(false, !!new_cli.send(:options)[:dynamic]) end - test 'initializes app_name from the env' do + it 'initializes app_name from the env' do cli = new_cli([], 'APP_NAME' => 'sprocket') assert_equal('sprocket', cli.send(:options)[:app_name]) end - test 'defaults to nil app_name' do + it 'defaults to nil app_name' do assert_equal(nil, new_cli.send(:options)[:app_name]) end - test 'accepts app_name via -n' do + it 'accepts app_name via -n' do cli = new_cli(%w(-n hambone)) cli.parse_options assert_equal('hambone', cli.send(:options)[:app_name]) end - test 'accepts app_name via --app-name' do + it 'accepts app_name via --app-name' do cli = new_cli(%w(--app-name flimsy)) cli.parse_options assert_equal('flimsy', cli.send(:options)[:app_name]) end - test 'runs Resque::Scheduler' do + it 'runs Resque::Scheduler' do Resque::Scheduler.expects(:run) Resque::Scheduler::Cli.run!([], {}) end diff --git a/test/delayed_queue_test.rb b/test/delayed_queue_test.rb index 6d043443..f0f9dea4 100644 --- a/test/delayed_queue_test.rb +++ b/test/delayed_queue_test.rb @@ -1,13 +1,12 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'DelayedQueue' do - setup do - Resque::Scheduler.quiet = true - Resque.redis.flushall +describe 'DelayedQueue' do + before do + reset_resque_scheduler end - test 'enqueue_at adds correct list and zset' do + it 'enqueue_at adds correct list and zset' do timestamp = Time.now + 1 encoded_job = Resque.encode( class: SomeIvarJob.to_s, @@ -48,7 +47,7 @@ 'job timestamps set should be empty') end - test 'enqueue_at with queue adds correct list and zset and queue' do + it 'enqueue_at with queue adds correct list and zset and queue' do timestamp = Time.now + 1 encoded_job = Resque.encode( class: SomeIvarJob.to_s, @@ -91,7 +90,7 @@ 'job timestamps set should be empty') end - test "a job in the future doesn't come out" do + it "a job in the future doesn't come out" do timestamp = Time.now + 600 encoded_job = Resque.encode( class: SomeIvarJob.to_s, @@ -119,7 +118,7 @@ assert_nil(read_timestamp, 'No timestamps should be ready for queueing') end - test 'a job in the future comes out if you want it to' do + it 'a job in the future comes out if you want it to' do timestamp = Time.now + 600 # 10 minutes from now Resque.enqueue_at(timestamp, SomeIvarJob, 'path') @@ -131,7 +130,7 @@ 'one we put in') end - test 'enqueue_at and enqueue_in are equivelent' do + it 'enqueue_at and enqueue_in are equivelent' do timestamp = Time.now + 60 encoded_job = Resque.encode( class: SomeIvarJob.to_s, @@ -150,11 +149,11 @@ 'job timestamps should have one entry now') end - test 'empty delayed_queue_peek returns empty array' do + it 'empty delayed_queue_peek returns empty array' do assert_equal([], Resque.delayed_queue_peek(0, 20)) end - test 'delayed_queue_peek returns stuff' do + it 'delayed_queue_peek returns stuff' do t = Time.now expected_timestamps = (1..5).to_a.map do |i| (t + 60 + i).to_i @@ -169,30 +168,30 @@ assert_equal(expected_timestamps[1, 2], timestamps) end - test 'delayed_queue_schedule_size returns correct size' do + it 'delayed_queue_schedule_size returns correct size' do assert_equal(0, Resque.delayed_queue_schedule_size) Resque.enqueue_at(Time.now + 60, SomeIvarJob) assert_equal(1, Resque.delayed_queue_schedule_size) end - test 'delayed_timestamp_size returns 0 when nothing is queue' do + it 'delayed_timestamp_size returns 0 when nothing is queue' do t = Time.now + 60 assert_equal(0, Resque.delayed_timestamp_size(t)) end - test 'delayed_timestamp_size returns 1 when one thing is queued' do + it 'delayed_timestamp_size returns 1 when one thing is queued' do t = Time.now + 60 Resque.enqueue_at(t, SomeIvarJob) assert_equal(1, Resque.delayed_timestamp_size(t)) end - test 'delayed_timestamp_peek returns empty array when nothings in it' do + it 'delayed_timestamp_peek returns empty array when nothings in it' do t = Time.now + 60 assert_equal([], Resque.delayed_timestamp_peek(t, 0, 1), "make sure it's an empty array, not nil") end - test 'delayed_timestamp_peek returns an array containing one job ' \ + it 'delayed_timestamp_peek returns an array containing one job ' \ 'when one thing is queued' do t = Time.now + 60 Resque.enqueue_at(t, SomeIvarJob) @@ -202,7 +201,7 @@ ) end - test 'delayed_timestamp_peek returns an array of multiple jobs ' \ + it 'delayed_timestamp_peek returns an array of multiple jobs ' \ 'when more than one job is queued' do t = Time.now + 60 Resque.enqueue_at(t, SomeIvarJob) @@ -211,7 +210,7 @@ assert_equal([job, job], Resque.delayed_timestamp_peek(t, 0, 2)) end - test 'delayed_timestamp_peek only returns an array of one job ' \ + it 'delayed_timestamp_peek only returns an array of one job ' \ 'if only asked for 1' do t = Time.now + 60 Resque.enqueue_at(t, SomeIvarJob) @@ -220,12 +219,12 @@ assert_equal([job], Resque.delayed_timestamp_peek(t, 0, 1)) end - test 'handle_delayed_items with no items' do + it 'handle_delayed_items with no items' do Resque::Scheduler.expects(:enqueue).never Resque::Scheduler.handle_delayed_items end - test 'handle_delayed_item with items' do + it 'handle_delayed_item with items' do t = Time.now - 60 # in the past # 2 SomeIvarJob jobs should be created in the "ivar" queue @@ -234,7 +233,7 @@ Resque.enqueue_at(t, SomeIvarJob) end - test 'handle_delayed_items with items in the future' do + it 'handle_delayed_items with items in the future' do t = Time.now + 60 # in the future Resque.enqueue_at(t, SomeIvarJob) Resque.enqueue_at(t, SomeIvarJob) @@ -244,14 +243,14 @@ Resque::Scheduler.handle_delayed_items(t) end - test 'calls klass#scheduled when enqueuing jobs if it exists' do + it 'calls klass#scheduled when enqueuing jobs if it exists' do t = Time.now - 60 FakeCustomJobClassEnqueueAt.expects(:scheduled) .once.with(:test, FakeCustomJobClassEnqueueAt.to_s, foo: 'bar') Resque.enqueue_at(t, FakeCustomJobClassEnqueueAt, foo: 'bar') end - test 'when Resque.inline = true, calls klass#scheduled ' \ + it 'when Resque.inline = true, calls klass#scheduled ' \ 'when enqueuing jobs if it exists' do old_val = Resque.inline begin @@ -265,7 +264,7 @@ end end - test 'enqueue_delayed_items_for_timestamp creates jobs ' \ + it 'enqueue_delayed_items_for_timestamp creates jobs ' \ 'and empties the delayed queue' do t = Time.now + 60 @@ -281,7 +280,7 @@ assert_equal(0, Resque.delayed_timestamp_peek(t, 0, 3).length) end - test 'enqueue_delayed creates jobs and empties the delayed queue' do + it 'enqueue_delayed creates jobs and empties the delayed queue' do t = Time.now + 60 Resque.enqueue_at(t, SomeIvarJob, 'foo') @@ -299,7 +298,7 @@ assert_equal(1, Resque.delayed_timestamp_peek(t, 0, 3).length) end - test 'handle_delayed_items works with out specifying queue ' \ + it 'handle_delayed_items works with out specifying queue ' \ '(upgrade case)' do t = Time.now - 60 Resque.delayed_push(t, class: 'SomeIvarJob') @@ -312,7 +311,7 @@ Resque::Scheduler.handle_delayed_items end - test 'reset_delayed_queue clears the queue' do + it 'reset_delayed_queue clears the queue' do t = Time.now + 120 4.times { Resque.enqueue_at(t, SomeIvarJob) } 4.times { Resque.enqueue_at(Time.now + rand(100), SomeIvarJob) } @@ -322,7 +321,7 @@ assert_equal(0, Resque.redis.keys('timestamps:*').size) end - test 'remove_delayed removes job and returns the count' do + it 'remove_delayed removes job and returns the count' do t = Time.now + 120 encoded_job = Resque.encode( class: SomeIvarJob.to_s, @@ -335,14 +334,14 @@ assert_equal(0, Resque.redis.scard("timestamps:#{encoded_job}")) end - test 'scheduled_at returns an array containing job schedule time' do + it 'scheduled_at returns an array containing job schedule time' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob) assert_equal([t.to_i], Resque.scheduled_at(SomeIvarJob)) end - test "remove_delayed doesn't remove things it shouldn't" do + it "remove_delayed doesn't remove things it shouldn't" do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeIvarJob, 'bar') @@ -352,7 +351,7 @@ assert_equal(0, Resque.remove_delayed(SomeIvarJob)) end - test 'remove_delayed respected param' do + it 'remove_delayed respected param' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeIvarJob, 'bar') @@ -363,7 +362,7 @@ assert_equal(1, Resque.delayed_queue_schedule_size) end - test 'remove_delayed removes items in different timestamps' do + it 'remove_delayed removes items in different timestamps' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t + 1, SomeIvarJob, 'bar') @@ -374,7 +373,7 @@ assert_equal(2, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes multiple items matching ' \ + it 'remove_delayed_selection removes multiple items matching ' \ 'arguments at same timestamp' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'bar', 'llama') @@ -389,7 +388,7 @@ assert_equal(2, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes single item matching arguments' do + it 'remove_delayed_selection removes single item matching arguments' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t + 1, SomeIvarJob, 'bar') @@ -400,7 +399,7 @@ assert_equal(3, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes multiple items matching arguments' do + it 'remove_delayed_selection removes multiple items matching arguments' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t + 1, SomeIvarJob, 'bar') @@ -411,7 +410,7 @@ assert_equal(2, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes multiple items matching ' \ + it 'remove_delayed_selection removes multiple items matching ' \ 'arguments as hash' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, foo: 'foo') @@ -425,7 +424,7 @@ assert_equal(2, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection ignores jobs with no arguments' do + it 'remove_delayed_selection ignores jobs with no arguments' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob) Resque.enqueue_at(t + 1, SomeIvarJob) @@ -436,7 +435,7 @@ assert_equal(4, Resque.count_all_scheduled_jobs) end - test "remove_delayed_selection doesn't remove items it shouldn't" do + it "remove_delayed_selection doesn't remove items it shouldn't" do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t + 1, SomeIvarJob, 'bar') @@ -447,7 +446,7 @@ assert_equal(4, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection ignores last_enqueued_at redis key' do + it 'remove_delayed_selection ignores last_enqueued_at redis key' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob) Resque.last_enqueued_at(SomeIvarJob, t) @@ -456,7 +455,7 @@ assert_equal(t.to_s, Resque.get_last_enqueued_at(SomeIvarJob)) end - test 'remove_delayed_selection removes item by class' do + it 'remove_delayed_selection removes item by class' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeQuickJob, 'foo') @@ -467,7 +466,7 @@ assert_equal(1, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes item by class name as a string' do + it 'remove_delayed_selection removes item by class name as a string' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeQuickJob, 'foo') @@ -478,7 +477,7 @@ assert_equal(1, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes item by class name as a symbol' do + it 'remove_delayed_selection removes item by class name as a symbol' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeQuickJob, 'foo') @@ -489,7 +488,7 @@ assert_equal(1, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes items only from matching job class' do + it 'remove_delayed_selection removes items only from matching job class' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') Resque.enqueue_at(t, SomeQuickJob, 'foo') @@ -504,7 +503,7 @@ assert_equal(4, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_selection removes items from matching job class ' \ + it 'remove_delayed_selection removes items from matching job class ' \ 'without params' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob) @@ -516,7 +515,7 @@ assert_equal(2, Resque.count_all_scheduled_jobs) end - test 'remove_delayed_job_from_timestamp removes instances of jobs ' \ + it 'remove_delayed_job_from_timestamp removes instances of jobs ' \ 'at a given timestamp' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') @@ -526,7 +525,7 @@ assert_equal 0, Resque.delayed_timestamp_size(t) end - test "remove_delayed_job_from_timestamp doesn't remove items from " \ + it "remove_delayed_job_from_timestamp doesn't remove items from " \ 'other timestamps' do t1 = Time.now + 120 t2 = t1 + 1 @@ -539,7 +538,7 @@ assert_equal 0, Resque.delayed_timestamp_size(t2) end - test 'remove_delayed_job_from_timestamp removes nothing if there ' \ + it 'remove_delayed_job_from_timestamp removes nothing if there ' \ 'are no matches' do t = Time.now + 120 assert_equal( @@ -547,7 +546,7 @@ ) end - test 'remove_delayed_job_from_timestamp only removes items that ' \ + it 'remove_delayed_job_from_timestamp only removes items that ' \ 'match args' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') @@ -558,7 +557,7 @@ assert_equal 1, Resque.delayed_timestamp_size(t) end - test 'remove_delayed_job_from_timestamp returns the number of ' \ + it 'remove_delayed_job_from_timestamp returns the number of ' \ 'items removed' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') @@ -567,7 +566,7 @@ ) end - test 'remove_delayed_job_from_timestamp should cleanup the delayed ' \ + it 'remove_delayed_job_from_timestamp should cleanup the delayed ' \ 'timestamp list if not jobs are left' do t = Time.now + 120 Resque.enqueue_at(t, SomeIvarJob, 'foo') @@ -578,13 +577,13 @@ assert Resque.delayed_queue_peek(0, 100).empty? end - test 'invalid job class' do + it 'invalid job class' do assert_raises Resque::NoQueueError do Resque.enqueue_in(10, String) end end - test 'inlining jobs with Resque.inline config' do + it 'inlining jobs with Resque.inline config' do begin Resque.inline = true Resque::Job.expects(:create).once.with(:ivar, SomeIvarJob, 'foo', 'bar') @@ -599,7 +598,7 @@ end end - test 'delayed?' do + it 'delayed?' do Resque.enqueue_at Time.now + 1, SomeIvarJob Resque.enqueue_at Time.now + 1, SomeIvarJob, id: 1 diff --git a/test/dummy/README.rdoc b/test/dummy/README.rdoc new file mode 100644 index 00000000..dd4e97e2 --- /dev/null +++ b/test/dummy/README.rdoc @@ -0,0 +1,28 @@ +== README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... + + +Please feel free to use a different markup language if you do not plan to run +rake doc:app. diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 00000000..dfa3aa4b --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,7 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be +# available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Rails.application.load_tasks diff --git a/test/dummy/app/assets/images/.keep b/test/dummy/app/assets/images/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/app/assets/javascripts/application.js b/test/dummy/app/assets/javascripts/application.js new file mode 100644 index 00000000..c28e5bad --- /dev/null +++ b/test/dummy/app/assets/javascripts/application.js @@ -0,0 +1,13 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require_tree . diff --git a/test/dummy/app/assets/stylesheets/application.css b/test/dummy/app/assets/stylesheets/application.css new file mode 100644 index 00000000..f9cd5b34 --- /dev/null +++ b/test/dummy/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any styles + * defined in the other CSS/SCSS files in this directory. It is generally better to create a new + * file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/test/dummy/app/controllers/application_controller.rb b/test/dummy/app/controllers/application_controller.rb new file mode 100644 index 00000000..d83690e1 --- /dev/null +++ b/test/dummy/app/controllers/application_controller.rb @@ -0,0 +1,5 @@ +class ApplicationController < ActionController::Base + # Prevent CSRF attacks by raising an exception. + # For APIs, you may want to use :null_session instead. + protect_from_forgery with: :exception +end diff --git a/test/dummy/app/controllers/concerns/.keep b/test/dummy/app/controllers/concerns/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 00000000..de6be794 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/test/dummy/app/mailers/.keep b/test/dummy/app/mailers/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/app/models/.keep b/test/dummy/app/models/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/app/models/concerns/.keep b/test/dummy/app/models/concerns/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb new file mode 100644 index 00000000..593a778b --- /dev/null +++ b/test/dummy/app/views/layouts/application.html.erb @@ -0,0 +1,14 @@ + + + + Dummy + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> + <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + +<%= yield %> + + + diff --git a/test/dummy/bin/bundle b/test/dummy/bin/bundle new file mode 100755 index 00000000..66e9889e --- /dev/null +++ b/test/dummy/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/test/dummy/bin/rails b/test/dummy/bin/rails new file mode 100755 index 00000000..5191e692 --- /dev/null +++ b/test/dummy/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../../config/application', __FILE__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/test/dummy/bin/rake b/test/dummy/bin/rake new file mode 100755 index 00000000..17240489 --- /dev/null +++ b/test/dummy/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/test/dummy/bin/setup b/test/dummy/bin/setup new file mode 100755 index 00000000..00ce4d30 --- /dev/null +++ b/test/dummy/bin/setup @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +Dir.chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file: + + puts '== Installing dependencies ==' + system 'gem install bundler --conservative' + system 'bundle check || bundle install' + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # system "cp config/database.yml.sample config/database.yml" + # end + + puts "\n== Preparing database ==" + system 'bin/rake db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system 'rm -f log/*' + system 'rm -rf tmp/cache' + + puts "\n== Restarting application server ==" + system 'touch tmp/restart.txt' +end diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 00000000..bd83b254 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,4 @@ +# This file is used by Rack-based servers to start the application. + +require ::File.expand_path('../config/environment', __FILE__) +run Rails.application diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 00000000..495da3f3 --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,31 @@ +require File.expand_path('../boot', __FILE__) + +require 'rails/all' + +Bundler.require(*Rails.groups) +require 'resque_web' +require 'resque-scheduler' + +module Dummy + class Application < Rails::Application + # Settings in config/environments/* take precedence over those specified + # here. Application configuration should go into files in + # config/initializers + # -- all .rb files in that directory are automatically loaded. + + # Set Time.zone default to the specified zone and make Active Record + # auto-convert to this zone. Run "rake -D time" for a list of tasks for + # finding time zone names. Default is UTC. + # config.time_zone = 'Central Time (US & Canada)' + + # The default locale is :en and all translations from + # config/locales/*.rb,yml are auto loaded. + # config.i18n.load_path += Dir[Rails.root.join('my', + # 'locales', + # '*.{rb,yml}').to_s] + # config.i18n.default_locale = :de + + # Do not swallow errors in after_commit/after_rollback callbacks. + config.active_record.raise_in_transactional_callbacks = true + end +end diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 00000000..6266cfc5 --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,5 @@ +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) diff --git a/test/dummy/config/database.yml b/test/dummy/config/database.yml new file mode 100644 index 00000000..1c1a37ca --- /dev/null +++ b/test/dummy/config/database.yml @@ -0,0 +1,25 @@ +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 00000000..ee8d90dc --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require File.expand_path('../application', __FILE__) + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/test/dummy/config/environments/development.rb b/test/dummy/config/environments/development.rb new file mode 100644 index 00000000..cd391aca --- /dev/null +++ b/test/dummy/config/environments/development.rb @@ -0,0 +1,42 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in + # config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Asset digests allow you to set far-future HTTP expiration dates on all + # assets, yet still be able to expire them through the digest params. + config.assets.digest = true + + # Adds additional error checking when serving assets at runtime. + # Checks for improperly declared sprockets dependencies. + # Raises helpful error messages. + config.assets.raise_runtime_errors = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/test/dummy/config/environments/production.rb b/test/dummy/config/environments/production.rb new file mode 100644 index 00000000..fd19fdf1 --- /dev/null +++ b/test/dummy/config/environments/production.rb @@ -0,0 +1,83 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in + # config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Enable Rack::Cache to put a simple HTTP cache in front of your application + # Add `rack-cache` to your Gemfile before enabling this. + # For large-scale production use, consider using a caching reverse proxy like + # NGINX, varnish or squid. + # config.action_dispatch.rack_cache = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Asset digests allow you to set far-future HTTP expiration dates on all + # assets, # yet still be able to expire them through the digest params. + config.assets.digest = true + + # `config.assets.precompile` and `config.assets.version` have moved to + # config/initializers/assets.rb + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Force all access to the app over SSL, use Strict-Transport-Security, and + # use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + # config.log_tags = [ :subdomain, :uuid ] + + # Use a different logger for distributed setups. + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to + # raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 00000000..7ac80d3c --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,43 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in + # config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure static file server for tests with Cache-Control for performance. + config.serve_static_files = true + config.static_cache_control = 'public, max-age=3600' + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Randomize the order test cases are executed. + config.active_support.test_order = :random + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/test/dummy/config/initializers/assets.rb b/test/dummy/config/initializers/assets.rb new file mode 100644 index 00000000..a71e9524 --- /dev/null +++ b/test/dummy/config/initializers/assets.rb @@ -0,0 +1,12 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in app/assets folder are +# already added. +# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/test/dummy/config/initializers/backtrace_silencers.rb b/test/dummy/config/initializers/backtrace_silencers.rb new file mode 100644 index 00000000..cf74fe3d --- /dev/null +++ b/test/dummy/config/initializers/backtrace_silencers.rb @@ -0,0 +1,9 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't +# wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem +# that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/test/dummy/config/initializers/cookies_serializer.rb b/test/dummy/config/initializers/cookies_serializer.rb new file mode 100644 index 00000000..7f70458d --- /dev/null +++ b/test/dummy/config/initializers/cookies_serializer.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/test/dummy/config/initializers/filter_parameter_logging.rb b/test/dummy/config/initializers/filter_parameter_logging.rb new file mode 100644 index 00000000..4a994e1e --- /dev/null +++ b/test/dummy/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/test/dummy/config/initializers/inflections.rb b/test/dummy/config/initializers/inflections.rb new file mode 100644 index 00000000..ac033bf9 --- /dev/null +++ b/test/dummy/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/test/dummy/config/initializers/mime_types.rb b/test/dummy/config/initializers/mime_types.rb new file mode 100644 index 00000000..dc189968 --- /dev/null +++ b/test/dummy/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/test/dummy/config/initializers/session_store.rb b/test/dummy/config/initializers/session_store.rb new file mode 100644 index 00000000..e766b67b --- /dev/null +++ b/test/dummy/config/initializers/session_store.rb @@ -0,0 +1,3 @@ +# Be sure to restart your server when you modify this file. + +Rails.application.config.session_store :cookie_store, key: '_dummy_session' diff --git a/test/dummy/config/initializers/wrap_parameters.rb b/test/dummy/config/initializers/wrap_parameters.rb new file mode 100644 index 00000000..6fffb713 --- /dev/null +++ b/test/dummy/config/initializers/wrap_parameters.rb @@ -0,0 +1,15 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format +# to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] if respond_to?(:wrap_parameters) +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/test/dummy/config/locales/en.yml b/test/dummy/config/locales/en.yml new file mode 100644 index 00000000..06539571 --- /dev/null +++ b/test/dummy/config/locales/en.yml @@ -0,0 +1,23 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb new file mode 100644 index 00000000..26e2f14e --- /dev/null +++ b/test/dummy/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + mount ResqueWeb::Engine => '/resque_web' +end diff --git a/test/dummy/config/secrets.yml b/test/dummy/config/secrets.yml new file mode 100644 index 00000000..6d98ee1d --- /dev/null +++ b/test/dummy/config/secrets.yml @@ -0,0 +1,22 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rake secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +development: + secret_key_base: 2a5a8b4c8fb5a5d1ee434d88aa5447bba18a60ea8a2f78b938a1d6deef36f5eea8d233e7742e0e371c6c506d71103fd2dce88e6ce66951ae338daf933bae0ade + +test: + secret_key_base: ba1227c183b4f8418c63c49e730d93eb16c09006b47665358598f6cf4191c256064fd84f5cdf4aa9f802b8f9ca507b5b06eb413d53e57fc748c5b72545f5da5b + +# Do not keep production secrets in the repository, +# instead read values from the environment. +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/test/dummy/db/development.sqlite3 b/test/dummy/db/development.sqlite3 new file mode 100644 index 00000000..7ad34b64 Binary files /dev/null and b/test/dummy/db/development.sqlite3 differ diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb new file mode 100644 index 00000000..49479b37 --- /dev/null +++ b/test/dummy/db/schema.rb @@ -0,0 +1,18 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema +# definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more +# migrations you'll amass, the slower it'll run and the greater likelihood for +# issues). +# +# It's strongly recommended that you check this file into your version control +# system. + +ActiveRecord::Schema.define(version: 0) do +end diff --git a/test/dummy/db/test.sqlite3 b/test/dummy/db/test.sqlite3 new file mode 100644 index 00000000..4b781765 Binary files /dev/null and b/test/dummy/db/test.sqlite3 differ diff --git a/test/dummy/lib/assets/.keep b/test/dummy/lib/assets/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/log/.keep b/test/dummy/log/.keep new file mode 100644 index 00000000..e69de29b diff --git a/test/dummy/public/404.html b/test/dummy/public/404.html new file mode 100644 index 00000000..b612547f --- /dev/null +++ b/test/dummy/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/422.html b/test/dummy/public/422.html new file mode 100644 index 00000000..a21f82b3 --- /dev/null +++ b/test/dummy/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/500.html b/test/dummy/public/500.html new file mode 100644 index 00000000..061abc58 --- /dev/null +++ b/test/dummy/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/test/dummy/public/favicon.ico b/test/dummy/public/favicon.ico new file mode 100644 index 00000000..e69de29b diff --git a/test/env_test.rb b/test/env_test.rb index b280100e..fb824d87 100644 --- a/test/env_test.rb +++ b/test/env_test.rb @@ -1,18 +1,21 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' +require 'resque/scheduler/env' + +describe 'Env' do + before { reset_resque_scheduler } -context 'Env' do def new_env(options = {}) Resque::Scheduler::Env.new(options) end - test 'daemonizes when background is true' do + it 'daemonizes when background is true' do Process.expects(:daemon) env = new_env(background: true) env.setup end - test 'reconnects redis when background is true' do + it 'reconnects redis when background is true' do Process.stubs(:daemon) mock_redis_client = mock('redis_client') mock_redis = mock('redis') @@ -23,7 +26,7 @@ def new_env(options = {}) env.setup end - test 'aborts when background is given and Process does not support daemon' do + it 'aborts when background is given and Process does not support daemon' do Process.stubs(:daemon) Process.expects(:respond_to?).with('daemon').returns(false) env = new_env(background: true) @@ -31,14 +34,14 @@ def new_env(options = {}) env.setup end - test 'keep set config if no option given' do + it 'keep set config if no option given' do Resque::Scheduler.configure { |c| c.dynamic = true } env = new_env env.setup assert_equal(true, Resque::Scheduler.dynamic) end - test 'override config if option given' do + it 'override config if option given' do Resque::Scheduler.configure { |c| c.dynamic = true } env = new_env(dynamic: false) env.setup diff --git a/test/integration/resque_web_engine/delayed/cancel_now_test.rb b/test/integration/resque_web_engine/delayed/cancel_now_test.rb new file mode 100644 index 00000000..45242ba1 --- /dev/null +++ b/test/integration/resque_web_engine/delayed/cancel_now_test.rb @@ -0,0 +1,15 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class CancelNowTest < ActionDispatch::IntegrationTest + test 'redirects to overview' do + post Engine.app.url_helpers.cancel_now_path + assert response.status == 302 + assert response.header['Location'].include? '/delayed' + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/clear_test.rb b/test/integration/resque_web_engine/delayed/clear_test.rb new file mode 100644 index 00000000..d3774a1b --- /dev/null +++ b/test/integration/resque_web_engine/delayed/clear_test.rb @@ -0,0 +1,16 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedClearTest < ActionDispatch::IntegrationTest + # 'on POST to /delayed/clear' do + test 'redirects to delayed' do + post Engine.app.url_helpers.clear_path + assert response.status == 302 + assert response.header['Location'].include? '/delayed' + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/delayed_job_class_page_test.rb b/test/integration/resque_web_engine/delayed/delayed_job_class_page_test.rb new file mode 100644 index 00000000..49fa5dd2 --- /dev/null +++ b/test/integration/resque_web_engine/delayed/delayed_job_class_page_test.rb @@ -0,0 +1,25 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedJobClassPageTest < ActionDispatch::IntegrationTest + fixtures :all + + setup do + @t = Time.now + 3600 + Resque.enqueue_at(@t, SomeIvarJob, 'foo', 'bar') + params = { klass: 'SomeIvarJob', + args: URI.encode(%w(foo bar).to_json) } + visit Engine.app.url_helpers.delayed_job_class_path params + end + + test('is 200') { assert page.status_code == 200 } + + test 'see the scheduled job' do + assert page.body.include?(@t.to_s) + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/delayed_job_namespaced_class_page_test.rb b/test/integration/resque_web_engine/delayed/delayed_job_namespaced_class_page_test.rb new file mode 100644 index 00000000..d8b790c9 --- /dev/null +++ b/test/integration/resque_web_engine/delayed/delayed_job_namespaced_class_page_test.rb @@ -0,0 +1,24 @@ +require_relative '../../../test_helper' +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedJobNamespacedClassPageTest < ActionDispatch::IntegrationTest + fixtures :all + + setup do + @t = Time.now + 3600 + + Resque.enqueue_at(@t, Foo::Bar, 'foo', 'bar') + params = { klass: 'Foo::Bar', args: URI.encode(%w(foo bar).to_json) } + visit Engine.app.url_helpers.delayed_job_class_path params + end + + test('is 200') { assert page.status_code == 200 } + + test 'see the scheduled job' do + assert page.body.include?(@t.to_s) + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/delayed_page_test.rb b/test/integration/resque_web_engine/delayed/delayed_page_test.rb new file mode 100644 index 00000000..1c26455e --- /dev/null +++ b/test/integration/resque_web_engine/delayed/delayed_page_test.rb @@ -0,0 +1,16 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedTest < ActionDispatch::IntegrationTest + test 'Link to delayed page in navigation works' do + visit '/resque_web' + click_link 'Delayed' + assert page.status_code == 200 + assert page.has_css? 'h1', 'Delayed Jobs' + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/delayed_search_test.rb b/test/integration/resque_web_engine/delayed/delayed_search_test.rb new file mode 100644 index 00000000..7710cc32 --- /dev/null +++ b/test/integration/resque_web_engine/delayed/delayed_search_test.rb @@ -0,0 +1,27 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedSearchTest < ActionDispatch::IntegrationTest + setup do + t = Time.now + 60 + Resque.enqueue_at(t, SomeIvarJob) + Resque.enqueue(SomeQuickJob) + end + + test 'should find matching scheduled job' do + post Engine.app.url_helpers.delayed_search_path, 'search' => 'ivar' + assert response.status == 200 + assert response.body.include?('SomeIvarJob') + end + + test 'should find matching queued job' do + post Engine.app.url_helpers.delayed_search_path, 'search' => 'quick' + assert response.status == 200 + assert response.body.include?('SomeQuickJob') + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/queue_now_test.rb b/test/integration/resque_web_engine/delayed/queue_now_test.rb new file mode 100644 index 00000000..c002e7e0 --- /dev/null +++ b/test/integration/resque_web_engine/delayed/queue_now_test.rb @@ -0,0 +1,16 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class QueueNowTest < ActionDispatch::IntegrationTest + # 'on POST to /delayed/queue_now' do + test 'redirects to overview' do + post Engine.app.url_helpers.queue_now_path + assert response.status == 302 + assert response.header['Location'].include? '/overview' + end + end + end + end +end diff --git a/test/integration/resque_web_engine/delayed/timestamp_test.rb b/test/integration/resque_web_engine/delayed/timestamp_test.rb new file mode 100644 index 00000000..f873bf0e --- /dev/null +++ b/test/integration/resque_web_engine/delayed/timestamp_test.rb @@ -0,0 +1,14 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class TimestampTest < ActionDispatch::IntegrationTest + test 'shows delayed_timestamp view' do + get Engine.app.url_helpers.timestamp_path timestamp: '1234567890' + assert response.status == 200 + end + end + end + end +end diff --git a/test/integration/resque_web_engine/schedules/delete_dynamic_test.rb b/test/integration/resque_web_engine/schedules/delete_dynamic_test.rb new file mode 100644 index 00000000..5c9715f4 --- /dev/null +++ b/test/integration/resque_web_engine/schedules/delete_dynamic_test.rb @@ -0,0 +1,45 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DeleteDynamicScheduleTest < ActionDispatch::IntegrationTest + setup do + Resque.schedule = Test::RESQUE_SCHEDULE + Resque::Scheduler.load_schedule! + Resque::Scheduler.stubs(:dynamic).returns(true) + end + + test 'redirects to schedule page' do + delete Engine.app.url_helpers.schedule_path + + status = response.status + redirect_location = response.headers['Location'] + status_msg = "Expected response to be a 302, but was a #{status}." + redirect_msg = "Redirect to #{redirect_location} "\ + 'instead of /schedule.' + + assert status == 302, status_msg + assert_match %r{/schedule/?$}, redirect_location, redirect_msg + end + + test 'does not show the deleted job' do + params = { job_name: 'job_with_params' } + delete Engine.app.url_helpers.schedule_path params + follow_redirect! + + msg = 'The job should not have been shown on the /schedule page.' + assert !response.body.include?('job_with_params'), msg + end + + test 'removes job from redis' do + params = { job_name: 'job_with_params' } + delete Engine.app.url_helpers.schedule_path, params + + msg = 'The job was not deleted from redis.' + assert_nil Resque.fetch_schedule('job_with_params'), msg + end + end + end + end +end diff --git a/test/integration/resque_web_engine/schedules/delete_static_test.rb b/test/integration/resque_web_engine/schedules/delete_static_test.rb new file mode 100644 index 00000000..54f92802 --- /dev/null +++ b/test/integration/resque_web_engine/schedules/delete_static_test.rb @@ -0,0 +1,32 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class DelayedSearchTest < ActionDispatch::IntegrationTest + setup do + Resque.schedule = Test::RESQUE_SCHEDULE + Resque::Scheduler.load_schedule! + Resque::Scheduler.stubs(:dynamic).returns(false) + end + + test 'does not remove the job from the UI' do + params = { job_name: 'job_with_params' } + delete Engine.app.url_helpers.schedule_path, params + follow_redirect! + + msg = 'The job should not have been removed from the /schedule page.' + assert response.body.include?('job_with_params'), msg + end + + test 'does not remove job from redis' do + params = { job_name: 'job_with_params' } + delete Engine.app.url_helpers.schedule_path, params + + msg = 'The job should not have been deleted from redis.' + assert Resque.fetch_schedule('job_with_params'), msg + end + end + end + end +end diff --git a/test/integration/resque_web_engine/schedules/requeue_test.rb b/test/integration/resque_web_engine/schedules/requeue_test.rb new file mode 100644 index 00000000..b81e55c3 --- /dev/null +++ b/test/integration/resque_web_engine/schedules/requeue_test.rb @@ -0,0 +1,53 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class RequeueTest < ActionDispatch::IntegrationTest + fixtures :all + + setup do + Resque.schedule = Test::RESQUE_SCHEDULE + Resque::Scheduler.load_schedule! + end + + test 'job without params' do + # Regular jobs without params should redirect to /overview + job_name = 'job_without_params' + Resque::Scheduler.stubs(:enqueue_from_config) + .once.with(Resque.schedule[job_name]) + + post Engine.app.url_helpers.requeue_path, 'job_name' => job_name + follow_redirect! + assert_equal 'http://www.example.com/resque_web/overview', request.url + assert response.ok? + end + + test 'job with params' do + # If a job has params defined, + # it should render the template with a form for the job params + job_name = 'job_with_params' + post Engine.app.url_helpers.requeue_path, 'job_name' => job_name + + assert response.ok? + assert response.body.include?('This job requires parameters') + assert response.body.include?( + %() + ) + + Resque.schedule[job_name]['parameters'].each do |_param_name, + param_config| + assert response.body.include?( + '(?)] + ) + assert response.body.include?( + ') + ) + end + end + end + end + end +end diff --git a/test/integration/resque_web_engine/schedules/requeue_with_params_test.rb b/test/integration/resque_web_engine/schedules/requeue_with_params_test.rb new file mode 100644 index 00000000..c9613ec4 --- /dev/null +++ b/test/integration/resque_web_engine/schedules/requeue_with_params_test.rb @@ -0,0 +1,34 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class RequeueWithParamsTest < ActionDispatch::IntegrationTest + setup do + Resque.schedule = Test::RESQUE_SCHEDULE + Resque::Scheduler.load_schedule! + end + + test 'job with params' do + job_name = 'job_with_params' + log_level = 'error' + + job_config = Resque.schedule[job_name] + args = job_config['args'].merge('log_level' => log_level) + job_config = job_config.merge('args' => args) + + Resque::Scheduler.stubs(:enqueue_from_config).once.with(job_config) + + post Engine.app.url_helpers.requeue_with_params_path, + 'job_name' => job_name, + 'log_level' => log_level + + follow_redirect! + assert_equal 'http://www.example.com/resque_web/overview', request.url + + assert response.ok? + end + end + end + end +end diff --git a/test/integration/resque_web_engine/schedules/schedule_page_test.rb b/test/integration/resque_web_engine/schedules/schedule_page_test.rb new file mode 100644 index 00000000..e9715902 --- /dev/null +++ b/test/integration/resque_web_engine/schedules/schedule_page_test.rb @@ -0,0 +1,86 @@ +require_relative '../../../test_helper' + +module ResqueWeb + module Plugins + module ResqueScheduler + class ScheduleTest < ActionDispatch::IntegrationTest + fixtures :all + + def visit_scheduler_page + visit Engine.app.url_helpers.schedules_path + end + + setup do + Resque::Scheduler.env = 'production' + Resque.schedule = { + 'some_ivar_job' => { + 'cron' => '* * * * *', + 'class' => 'SomeIvarJob', + 'args' => '/tmp', + 'rails_env' => 'production' + }, + 'some_other_job' => { + 'every' => ['1m', ['1h']], + 'queue' => 'high', + 'custom_job_class' => 'SomeOtherJob', + 'args' => { + 'b' => 'blah' + } + }, + 'some_fancy_job' => { + 'every' => ['1m'], + 'queue' => 'fancy', + 'class' => 'SomeFancyJob', + 'args' => 'sparkles', + 'rails_env' => 'fancy' + }, + 'shared_env_job' => { + 'cron' => '* * * * *', + 'class' => 'SomeSharedEnvJob', + 'args' => '/tmp', + 'rails_env' => 'fancy, production' + } + } + Resque::Scheduler.load_schedule! + visit_scheduler_page + end + + test 'Link to Schedule page in navigation works' do + visit '/resque_web' + click_link 'Schedule' + assert page.has_css? 'h1', 'Schedule' + end + + test '200' do + assert page.has_css?('h1', 'Schedule') + end + + test 'see the scheduled job' do + assert page.body.include?('SomeIvarJob') + end + + test 'excludes jobs for other envs' do + assert !page.body.include?('SomeFancyJob') + end + + test 'includes job used in multiple environments' do + assert page.body.include?('SomeSharedEnvJob') + end + + test 'allows delete when dynamic' do + Resque::Scheduler.stubs(:dynamic).returns(true) + visit_scheduler_page + + assert page.body.include?('Delete') + end + + test "doesn't allow delete when static" do + Resque::Scheduler.stubs(:dynamic).returns(false) + visit_scheduler_page + + assert !page.body.include?('Delete') + end + end + end + end +end diff --git a/test/multi_process_test.rb b/test/multi_process_test.rb index 90d0102a..44ed2386 100644 --- a/test/multi_process_test.rb +++ b/test/multi_process_test.rb @@ -1,8 +1,10 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'Multi Process' do - test 'setting schedule= from many process does not corrupt the schedules' do +describe 'Multi Process' do + before { reset_resque_scheduler } + + it 'setting schedule= from many process does not corrupt the schedules' do schedules = {} counts = [] threads = [] diff --git a/test/resque-web_test.rb b/test/resque-web_test.rb deleted file mode 100644 index 356b7ce7..00000000 --- a/test/resque-web_test.rb +++ /dev/null @@ -1,331 +0,0 @@ -# vim:fileencoding=utf-8 -require_relative 'test_helper' - -require 'resque/server/test_helper' - -context 'on GET to /schedule' do - setup { get '/schedule' } - - test('is 200') { assert last_response.ok? } -end - -context 'on GET to /schedule with scheduled jobs' do - setup do - Resque::Scheduler.env = 'production' - Resque.schedule = { - 'some_ivar_job' => { - 'cron' => '* * * * *', - 'class' => 'SomeIvarJob', - 'args' => '/tmp', - 'rails_env' => 'production' - }, - 'some_other_job' => { - 'every' => ['1m', ['1h']], - 'queue' => 'high', - 'custom_job_class' => 'SomeOtherJob', - 'args' => { - 'b' => 'blah' - } - }, - 'some_fancy_job' => { - 'every' => ['1m'], - 'queue' => 'fancy', - 'class' => 'SomeFancyJob', - 'args' => 'sparkles', - 'rails_env' => 'fancy' - }, - 'shared_env_job' => { - 'cron' => '* * * * *', - 'class' => 'SomeSharedEnvJob', - 'args' => '/tmp', - 'rails_env' => 'fancy, production' - } - } - Resque::Scheduler.load_schedule! - get '/schedule' - end - - test('is 200') { assert last_response.ok? } - - test 'see the scheduled job' do - assert last_response.body.include?('SomeIvarJob') - end - - test 'excludes jobs for other envs' do - assert !last_response.body.include?('SomeFancyJob') - end - - test 'includes job used in multiple environments' do - assert last_response.body.include?('SomeSharedEnvJob') - end - - test 'allows delete when dynamic' do - Resque::Scheduler.stubs(:dynamic).returns(true) - get '/schedule' - - assert last_response.body.include?('Delete') - end - - test "doesn't allow delete when static" do - Resque::Scheduler.stubs(:dynamic).returns(false) - get '/schedule' - - assert !last_response.body.include?('Delete') - end -end - -context 'on GET to /delayed' do - setup { get '/delayed' } - - test('is 200') { assert last_response.ok? } -end - -context 'on GET to /delayed/jobs/:klass'do - setup do - @t = Time.now + 3600 - Resque.enqueue_at(@t, SomeIvarJob, 'foo', 'bar') - get( - URI('/delayed/jobs/SomeIvarJob?args=' << - URI.encode(%w(foo bar).to_json)).to_s - ) - end - - test('is 200') { assert last_response.ok? } - - test 'see the scheduled job' do - assert last_response.body.include?(@t.to_s) - end - - context 'with a namespaced class' do - setup do - @t = Time.now + 3600 - module Foo - class Bar - def self.queue - 'bar' - end - end - end - Resque.enqueue_at(@t, Foo::Bar, 'foo', 'bar') - get( - URI('/delayed/jobs/Foo::Bar?args=' << - URI.encode(%w(foo bar).to_json)).to_s - ) - end - - test('is 200') { assert last_response.ok? } - - test 'see the scheduled job' do - assert last_response.body.include?(@t.to_s) - end - end -end - -module Test - RESQUE_SCHEDULE = { - 'job_without_params' => { - 'cron' => '* * * * *', - 'class' => 'JobWithoutParams', - 'args' => { - 'host' => 'localhost' - }, - 'rails_env' => 'production' - }, - 'job_with_params' => { - 'every' => '1m', - 'class' => 'JobWithParams', - 'args' => { - 'host' => 'localhost' - }, - 'parameters' => { - 'log_level' => { - 'description' => 'The level of logging', - 'default' => 'warn' - } - } - } - } -end - -context 'POST /schedule/requeue' do - setup do - Resque.schedule = Test::RESQUE_SCHEDULE - Resque::Scheduler.load_schedule! - end - - test 'job without params' do - # Regular jobs without params should redirect to /overview - job_name = 'job_without_params' - Resque::Scheduler.stubs(:enqueue_from_config) - .once.with(Resque.schedule[job_name]) - - post '/schedule/requeue', 'job_name' => job_name - follow_redirect! - assert_equal 'http://example.org/overview', last_request.url - assert last_response.ok? - end - - test 'job with params' do - # If a job has params defined, - # it should render the template with a form for the job params - job_name = 'job_with_params' - post '/schedule/requeue', 'job_name' => job_name - - assert last_response.ok?, last_response.errors - assert last_response.body.include?('This job requires parameters') - assert last_response.body.include?( - %() - ) - - Resque.schedule[job_name]['parameters'].each do |_param_name, param_config| - assert last_response.body.include?( - '(?)] - ) - assert last_response.body.include?( - ') - ) - end - end -end - -context 'POST /schedule/requeue_with_params' do - setup do - Resque.schedule = Test::RESQUE_SCHEDULE - Resque::Scheduler.load_schedule! - end - - test 'job with params' do - job_name = 'job_with_params' - log_level = 'error' - - job_config = Resque.schedule[job_name] - args = job_config['args'].merge('log_level' => log_level) - job_config = job_config.merge('args' => args) - - Resque::Scheduler.stubs(:enqueue_from_config).once.with(job_config) - - post '/schedule/requeue_with_params', - 'job_name' => job_name, - 'log_level' => log_level - - follow_redirect! - assert_equal 'http://example.org/overview', last_request.url - - assert last_response.ok?, last_response.errors - end -end - -context 'on POST to /delayed/search' do - setup do - t = Time.now + 60 - Resque.enqueue_at(t, SomeIvarJob) - Resque.enqueue(SomeQuickJob) - end - - test 'should find matching scheduled job' do - post '/delayed/search', 'search' => 'ivar' - assert last_response.status == 200 - assert last_response.body.include?('SomeIvarJob') - end - - test 'should find matching queued job' do - post '/delayed/search', 'search' => 'quick' - assert last_response.status == 200 - assert last_response.body.include?('SomeQuickJob') - end -end - -context 'on POST to /delayed/cancel_now' do - setup { post '/delayed/cancel_now' } - - test 'redirects to overview' do - assert last_response.status == 302 - assert last_response.header['Location'].include? '/delayed' - end -end - -context 'on POST to /delayed/clear' do - setup { post '/delayed/clear' } - - test 'redirects to delayed' do - assert last_response.status == 302 - assert last_response.header['Location'].include? '/delayed' - end -end - -context 'on POST to /delayed/queue_now' do - setup { post '/delayed/queue_now' } - - test 'redirects to overview' do - assert last_response.status == 302 - assert last_response.header['Location'].include? '/overview' - end -end - -context 'on GET to /delayed/:timestamp' do - setup { get '/delayed/1234567890' } - - test 'shows delayed_timestamp view' do - assert last_response.status == 200 - end -end - -context 'DELETE /schedule when dynamic' do - setup do - Resque.schedule = Test::RESQUE_SCHEDULE - Resque::Scheduler.load_schedule! - Resque::Scheduler.stubs(:dynamic).returns(true) - end - - test 'redirects to schedule page' do - delete '/schedule' - - status = last_response.status - redirect_location = last_response.original_headers['Location'] - response_status_msg = "Expected response to be a 302, but was a #{status}." - redirect_msg = "Redirect to #{redirect_location} instead of /schedule." - - assert status == 302, response_status_msg - assert_match %r{/schedule/?$}, redirect_location, redirect_msg - end - - test 'does not show the deleted job' do - delete '/schedule', job_name: 'job_with_params' - follow_redirect! - - msg = 'The job should not have been shown on the /schedule page.' - assert !last_response.body.include?('job_with_params'), msg - end - - test 'removes job from redis' do - delete '/schedule', job_name: 'job_with_params' - - msg = 'The job was not deleted from redis.' - assert_nil Resque.fetch_schedule('job_with_params'), msg - end -end - -context 'DELETE /schedule when static' do - setup do - Resque.schedule = Test::RESQUE_SCHEDULE - Resque::Scheduler.load_schedule! - Resque::Scheduler.stubs(:dynamic).returns(false) - end - - test 'does not remove the job from the UI' do - delete '/schedule', job_name: 'job_with_params' - follow_redirect! - - msg = 'The job should not have been removed from the /schedule page.' - assert last_response.body.include?('job_with_params'), msg - end - - test 'does not remove job from redis' do - delete '/schedule', job_name: 'job_with_params' - - msg = 'The job should not have been deleted from redis.' - assert Resque.fetch_schedule('job_with_params'), msg - end -end diff --git a/test/scheduler_args_test.rb b/test/scheduler_args_test.rb index 0655369c..71a0e737 100644 --- a/test/scheduler_args_test.rb +++ b/test/scheduler_args_test.rb @@ -2,17 +2,15 @@ require_relative 'test_helper' -context 'scheduling jobs with arguments' do - setup do - Resque::Scheduler.clear_schedule! +describe 'scheduling jobs with arguments' do + before do + reset_resque_scheduler Resque::Scheduler.configure do |c| - c.dynamic = false - c.quiet = true c.poll_sleep_amount = nil end end - test 'enqueue_from_config puts stuff in resque without class loaded' do + it 'enqueue_from_config puts stuff in resque without class loaded' do Resque::Job.stubs(:create).once.returns(true) .with('joes_queue', 'UndefinedJob', '/tmp') Resque::Scheduler.enqueue_from_config( @@ -23,7 +21,7 @@ ) end - test 'enqueue_from_config with_every_syntax' do + it 'enqueue_from_config with_every_syntax' do Resque::Job.stubs(:create).once.returns(true) .with('james_queue', 'JamesJob', '/tmp') Resque::Scheduler.enqueue_from_config( @@ -34,7 +32,7 @@ ) end - test 'enqueue_from_config puts jobs in the resque queue' do + it 'enqueue_from_config puts jobs in the resque queue' do Resque::Job.stubs(:create).once.returns(true) .with(:ivar, SomeIvarJob, '/tmp') Resque::Scheduler.enqueue_from_config( @@ -44,7 +42,7 @@ ) end - test 'enqueue_from_config with custom_class_job in resque' do + it 'enqueue_from_config with custom_class_job in resque' do FakeCustomJobClass.stubs(:scheduled).once.returns(true) .with(:ivar, 'SomeIvarJob', '/tmp') Resque::Scheduler.enqueue_from_config( @@ -55,7 +53,7 @@ ) end - test 'enqueue_from_config puts stuff in resque when env matches' do + it 'enqueue_from_config puts stuff in resque when env matches' do Resque::Scheduler.env = 'production' assert_equal(0, Resque::Scheduler.rufus_scheduler.jobs.size) @@ -84,7 +82,7 @@ assert_equal(2, Resque::Scheduler.rufus_scheduler.jobs.size) end - test 'enqueue_from_config does not enqueue when env does not match' do + it 'enqueue_from_config does not enqueue when env does not match' do Resque::Scheduler.env = nil assert_equal(0, Resque::Scheduler.rufus_scheduler.jobs.size) Resque.schedule = { @@ -112,7 +110,7 @@ assert_equal(0, Resque::Scheduler.rufus_scheduler.jobs.size) end - test 'enqueue_from_config when env env arg is not set' do + it 'enqueue_from_config when env env arg is not set' do Resque::Scheduler.env = 'production' assert_equal(0, Resque::Scheduler.rufus_scheduler.jobs.size) @@ -127,7 +125,7 @@ assert_equal(1, Resque::Scheduler.rufus_scheduler.jobs.size) end - test "calls the worker without arguments when 'args' is missing " \ + it "calls the worker without arguments when 'args' is missing " \ 'from the config' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob @@ -136,7 +134,7 @@ Resque.reserve('ivar').perform end - test "calls the worker without arguments when 'args' is blank " \ + it "calls the worker without arguments when 'args' is blank " \ 'in the config' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob @@ -146,7 +144,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with a string when the config lists a string' do + it 'calls the worker with a string when the config lists a string' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob args: string @@ -155,7 +153,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with a Fixnum when the config lists an integer' do + it 'calls the worker with a Fixnum when the config lists an integer' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob args: 1 @@ -164,7 +162,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with multiple arguments when the config ' \ + it 'calls the worker with multiple arguments when the config ' \ 'lists an array' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob @@ -176,7 +174,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with an array when the config lists ' \ + it 'calls the worker with an array when the config lists ' \ 'a nested array' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob @@ -188,7 +186,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with a hash when the config lists a hash' do + it 'calls the worker with a hash when the config lists a hash' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob args: @@ -198,7 +196,7 @@ Resque.reserve('ivar').perform end - test 'calls the worker with a nested hash when the config lists ' \ + it 'calls the worker with a nested hash when the config lists ' \ 'a nested hash' do Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML)) class: SomeIvarJob @@ -211,11 +209,11 @@ Resque.reserve('ivar').perform end - test 'poll_sleep_amount defaults to 5' do + it 'poll_sleep_amount defaults to 5' do assert_equal 5, Resque::Scheduler.poll_sleep_amount end - test 'poll_sleep_amount is settable' do + it 'poll_sleep_amount is settable' do Resque::Scheduler.poll_sleep_amount = 1 assert_equal 1, Resque::Scheduler.poll_sleep_amount end diff --git a/test/scheduler_hooks_test.rb b/test/scheduler_hooks_test.rb index 1a36bcdd..531ffde5 100644 --- a/test/scheduler_hooks_test.rb +++ b/test/scheduler_hooks_test.rb @@ -1,10 +1,10 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'scheduling jobs with hooks' do - setup { Resque.redis.flushall } +describe 'scheduling jobs with hooks' do + before { reset_resque_scheduler } - test 'before_schedule hook that does not return false should be enqueued' do + it 'before_schedule hook that does not return false should be enqueued' do enqueue_time = Time.now SomeRealClass.expects(:before_schedule_example).with(:foo) SomeRealClass.expects(:after_schedule_example).with(:foo) @@ -13,7 +13,7 @@ 'job should be enqueued') end - test 'before_schedule hook that returns false should not be enqueued' do + it 'before_schedule hook that returns false should not be enqueued' do enqueue_time = Time.now SomeRealClass.expects(:before_schedule_example).with(:foo).returns(false) SomeRealClass.expects(:after_schedule_example).never diff --git a/test/scheduler_locking_test.rb b/test/scheduler_locking_test.rb index aa940a20..5f7ae409 100644 --- a/test/scheduler_locking_test.rb +++ b/test/scheduler_locking_test.rb @@ -7,32 +7,35 @@ def lock_is_not_held(lock) end end -context '#master_lock_key' do - setup do +describe '#master_lock_key' do + before do + reset_resque_scheduler @subject = Class.new { extend Resque::Scheduler::Locking } end - teardown do + after do Resque.redis.del(@subject.master_lock.key) end - test 'should have resque prefix' do + it 'should have resque prefix' do assert_equal( @subject.master_lock.key, 'resque:resque_scheduler_master_lock' ) end - context 'with a prefix set via ENV' do - setup do + describe 'with a prefix set via ENV' do + before do + reset_resque_scheduler ENV['RESQUE_SCHEDULER_MASTER_LOCK_PREFIX'] = 'my.prefix' @subject = Class.new { extend Resque::Scheduler::Locking } end - teardown do + after do + ENV.delete 'RESQUE_SCHEDULER_MASTER_LOCK_PREFIX' Resque.redis.del(@subject.master_lock.key) end - test 'should have ENV prefix' do + it 'should have ENV prefix' do assert_equal( @subject.master_lock.key, 'resque:my.prefix:resque_scheduler_master_lock' @@ -40,36 +43,39 @@ def lock_is_not_held(lock) end end - context 'with a namespace set for resque' do - setup do + describe 'with a namespace set for resque' do + before do + reset_resque_scheduler Resque.redis.namespace = 'my.namespace' @subject = Class.new { extend Resque::Scheduler::Locking } end - teardown do + after do Resque.redis.namespace = 'resque' Resque.redis.del(@subject.master_lock.key) end - test 'should have resque prefix' do + it 'should have resque prefix' do assert_equal( @subject.master_lock.key, 'my.namespace:resque_scheduler_master_lock' ) end - context 'with a prefix set via ENV' do - setup do + describe 'with a prefix set via ENV' do + before do + reset_resque_scheduler Resque.redis.namespace = 'my.namespace' ENV['RESQUE_SCHEDULER_MASTER_LOCK_PREFIX'] = 'my.prefix' @subject = Class.new { extend Resque::Scheduler::Locking } end - teardown do + after do Resque.redis.namespace = 'resque' + ENV.delete 'RESQUE_SCHEDULER_MASTER_LOCK_PREFIX' Resque.redis.del(@subject.master_lock.key) end - test 'should have ENV prefix' do + it 'should have ENV prefix' do assert_equal( @subject.master_lock.key, 'my.namespace:my.prefix:resque_scheduler_master_lock' @@ -79,22 +85,23 @@ def lock_is_not_held(lock) end end -context 'Resque::Scheduler::Locking' do - setup do +describe 'Resque::Scheduler::Locking' do + before do + reset_resque_scheduler @subject = Class.new { extend Resque::Scheduler::Locking } end - teardown do + after do Resque.redis.del(@subject.master_lock.key) end - test 'should use the basic lock mechanism for <= Redis 2.4' do + it 'should use the basic lock mechanism for <= Redis 2.4' do Resque.redis.stubs(:info).returns('redis_version' => '2.4.16') assert_equal @subject.master_lock.class, Resque::Scheduler::Lock::Basic end - test 'should use the resilient lock mechanism for > Redis 2.4' do + it 'should use the resilient lock mechanism for > Redis 2.4' do Resque.redis.stubs(:info).returns('redis_version' => '2.5.12') assert_equal( @@ -102,77 +109,79 @@ def lock_is_not_held(lock) ) end - test 'should be the master if the lock is held' do + it 'should be the master if the lock is held' do @subject.master_lock.acquire! assert @subject.master?, 'should be master' end - test 'should not be the master if the lock is held by someone else' do + it 'should not be the master if the lock is held by someone else' do Resque.redis.set(@subject.master_lock.key, 'somethingelse:1234') assert !@subject.master?, 'should not be master' end - test 'release_master_lock should delegate to master_lock' do + it 'release_master_lock should delegate to master_lock' do @subject.master_lock.expects(:release) @subject.release_master_lock end - test 'release_master_lock! should delegate to master_lock' do + it 'release_master_lock! should delegate to master_lock' do @subject.expects(:warn) @subject.master_lock.expects(:release!) @subject.release_master_lock! end end -context 'Resque::Scheduler::Lock::Base' do - setup do +describe 'Resque::Scheduler::Lock::Base' do + before do + reset_resque_scheduler @lock = Resque::Scheduler::Lock::Base.new('test_lock_key') end - test '#acquire! should be not implemented' do + it '#acquire! should be not implemented' do assert_raises NotImplementedError do @lock.acquire! end end - test '#locked? should be not implemented' do + it '#locked? should be not implemented' do assert_raises NotImplementedError do @lock.locked? end end end -context 'Resque::Scheduler::Lock::Basic' do +describe 'Resque::Scheduler::Lock::Basic' do include LockTestHelper - setup do + before do + reset_resque_scheduler @lock = Resque::Scheduler::Lock::Basic.new('test_lock_key') end - teardown do + after do @lock.release! end - test 'you should not have the lock if someone else holds it' do + it 'you should not have the lock if someone else holds it' do lock_is_not_held(@lock) assert !@lock.locked? end - test 'you should not be able to acquire the lock if someone ' \ + it 'you should not be able to acquire the lock if someone ' \ 'else holds it' do lock_is_not_held(@lock) assert !@lock.acquire! end - test 'the lock should receive a TTL on acquiring' do + it 'the lock should receive a TTL on acquiring' do @lock.acquire! assert Resque.redis.ttl(@lock.key) > 0, 'lock should expire' end - test 'releasing should release the master lock' do + it 'releasing should release the master lock' do assert @lock.acquire!, 'should have acquired the master lock' assert @lock.locked?, 'should be locked' @@ -181,7 +190,7 @@ def lock_is_not_held(lock) assert !@lock.locked?, 'should not be locked' end - test 'checking the lock should increase the TTL if we hold it' do + it 'checking the lock should increase the TTL if we hold it' do @lock.acquire! Resque.redis.setex(@lock.key, 10, @lock.value) @@ -190,7 +199,7 @@ def lock_is_not_held(lock) assert Resque.redis.ttl(@lock.key) > 10, 'TTL should have been updated' end - test 'checking the lock should not increase the TTL if we do not hold it' do + it 'checking the lock should not increase the TTL if we do not hold it' do Resque.redis.setex(@lock.key, 10, @lock.value) lock_is_not_held(@lock) @@ -201,41 +210,42 @@ def lock_is_not_held(lock) end end -context 'Resque::Scheduler::Lock::Resilient' do +describe 'Resque::Scheduler::Lock::Resilient' do include LockTestHelper if !Resque::Scheduler.supports_lua? puts '*** Skipping Resque::Scheduler::Lock::Resilient ' \ 'tests, as they require Redis >= 2.5.' else - setup do + before do + reset_resque_scheduler @lock = Resque::Scheduler::Lock::Resilient.new('test_resilient_lock') end - teardown do + after do @lock.release! end - test 'you should not have the lock if someone else holds it' do + it 'you should not have the lock if someone else holds it' do lock_is_not_held(@lock) assert !@lock.locked?, 'you should not have the lock' end - test 'you should not be able to acquire the lock if someone ' \ + it 'you should not be able to acquire the lock if someone ' \ 'else holds it' do lock_is_not_held(@lock) assert !@lock.acquire! end - test 'the lock should receive a TTL on acquiring' do + it 'the lock should receive a TTL on acquiring' do @lock.acquire! assert Resque.redis.ttl(@lock.key) > 0, 'lock should expire' end - test 'releasing should release the master lock' do + it 'releasing should release the master lock' do assert @lock.acquire!, 'should have acquired the master lock' assert @lock.locked?, 'should be locked' @@ -244,7 +254,7 @@ def lock_is_not_held(lock) assert !@lock.locked?, 'should not be locked' end - test 'checking the lock should increase the TTL if we hold it' do + it 'checking the lock should increase the TTL if we hold it' do @lock.acquire! Resque.redis.setex(@lock.key, 10, @lock.value) @@ -253,7 +263,7 @@ def lock_is_not_held(lock) assert Resque.redis.ttl(@lock.key) > 10, 'TTL should have been updated' end - test 'checking the lock should not increase the TTL if we do ' \ + it 'checking the lock should not increase the TTL if we do ' \ 'not hold it' do Resque.redis.setex(@lock.key, 10, @lock.value) lock_is_not_held(@lock) @@ -264,7 +274,7 @@ def lock_is_not_held(lock) 'TTL should not have been updated' end - test 'setting the lock timeout changes the key TTL if we hold it' do + it 'setting the lock timeout changes the key TTL if we hold it' do @lock.acquire! @lock.stubs(:locked?).returns(true) @@ -278,7 +288,7 @@ def lock_is_not_held(lock) assert_send [ttl, :>, 120] end - test 'setting lock timeout is a noop if not held' do + it 'setting lock timeout is a noop if not held' do @lock.acquire! @lock.timeout = 100 @lock.stubs(:locked?).returns(false) @@ -286,31 +296,31 @@ def lock_is_not_held(lock) assert_equal 100, @lock.timeout end - test 'setting lock timeout nils out lock script' do + it 'setting lock timeout nils out lock script' do @lock.acquire! @lock.timeout = 100 assert_equal nil, @lock.instance_variable_get(:@locked_sha) end - test 'setting lock timeout does not nil out lock script if not held' do + it 'setting lock timeout does not nil out lock script if not held' do @lock.acquire! @lock.locked? @lock.stubs(:locked?).returns(false) @lock.timeout = 100 - assert_not_nil @lock.instance_variable_get(:@locked_sha) + refute_nil @lock.instance_variable_get(:@locked_sha) end - test 'setting lock timeout nils out acquire script' do + it 'setting lock timeout nils out acquire script' do @lock.acquire! @lock.timeout = 100 assert_equal nil, @lock.instance_variable_get(:@acquire_sha) end - test 'setting lock timeout does not nil out acquire script if not held' do + it 'setting lock timeout does not nil out acquire script if not held' do @lock.acquire! @lock.stubs(:locked?).returns(false) @lock.timeout = 100 - assert_not_nil @lock.instance_variable_get(:@acquire_sha) + refute_nil @lock.instance_variable_get(:@acquire_sha) end end end diff --git a/test/scheduler_setup_test.rb b/test/scheduler_setup_test.rb index 00a09937..2c76887a 100644 --- a/test/scheduler_setup_test.rb +++ b/test/scheduler_setup_test.rb @@ -1,24 +1,23 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'Resque::Scheduler' do - setup do +describe 'Resque::Scheduler' do + before do + reset_resque_scheduler + ENV['VERBOSE'] = nil nullify_logger - Resque::Scheduler.dynamic = false - Resque.redis.flushall - Resque::Scheduler.clear_schedule! end - teardown { restore_devnull_logfile } + after { restore_devnull_logfile } - test 'set custom logger' do + it 'set custom logger' do custom_logger = MonoLogger.new('/dev/null') Resque::Scheduler.send(:logger=, custom_logger) assert_equal(custom_logger, Resque::Scheduler.send(:logger)) end - test 'configure block' do + it 'configure block' do Resque::Scheduler.quiet = false Resque::Scheduler.configure do |c| c.quiet = true @@ -26,57 +25,70 @@ assert_equal(Resque::Scheduler.quiet, true) end - context 'when getting the env' do + describe 'when getting the env' do def wipe Resque::Scheduler.env = nil - Rails.env = nil ENV['RAILS_ENV'] = nil end - setup { wipe } - teardown { wipe } + before do + reset_resque_scheduler + wipe + end + after { wipe } - test 'uses the value if set' do - Resque::Scheduler.env = 'foo' - assert_equal('foo', Resque::Scheduler.env) + it 'uses the value if set' do + Rails.stub(:env, nil) do + Resque::Scheduler.env = 'foo' + assert_equal('foo', Resque::Scheduler.env) + end end - test 'uses Rails.env if present' do - Rails.env = 'bar' - assert_equal('bar', Resque::Scheduler.env) + it 'uses Rails.env if present' do + Rails.stub(:env, 'bar') do + assert_equal('bar', Resque::Scheduler.env) + end end - test 'uses $RAILS_ENV if present' do - ENV['RAILS_ENV'] = 'baz' - assert_equal('baz', Resque::Scheduler.env) + it 'uses $RAILS_ENV if present' do + Rails.stub(:env, nil) do + ENV['RAILS_ENV'] = 'baz' + assert_equal('baz', Resque::Scheduler.env) + end end end - context 'logger default settings' do - setup { nullify_logger } - teardown { restore_devnull_logfile } + describe 'logger default settings' do + before do + reset_resque_scheduler + nullify_logger + end + after { restore_devnull_logfile } - test 'uses STDOUT' do + it 'uses STDOUT' do assert_equal( Resque::Scheduler.send(:logger) .instance_variable_get(:@logdev).dev, $stdout ) end - test 'not verbose' do + it 'not verbose' do assert Resque::Scheduler.send(:logger).level > MonoLogger::DEBUG end - test 'not quieted' do + it 'not quieted' do assert Resque::Scheduler.send(:logger).level < MonoLogger::FATAL end end - context 'logger custom settings' do - setup { nullify_logger } - teardown { restore_devnull_logfile } + describe 'logger custom settings' do + before do + reset_resque_scheduler + nullify_logger + end + after { restore_devnull_logfile } - test 'uses logfile' do + it 'uses logfile' do Resque::Scheduler.logfile = '/dev/null' assert_equal( Resque::Scheduler.send(:logger) @@ -85,46 +97,48 @@ def wipe ) end - test 'set verbosity' do + it 'set verbosity' do Resque::Scheduler.verbose = true assert Resque::Scheduler.send(:logger).level == MonoLogger::DEBUG end - test 'quiet logger' do + it 'quiet logger' do Resque::Scheduler.quiet = true assert Resque::Scheduler.send(:logger).level == MonoLogger::FATAL end end - context 'logger with json formatter' do - setup do + describe 'logger with json formatter' do + before do + reset_resque_scheduler nullify_logger Resque::Scheduler.logformat = 'json' $stdout = StringIO.new end - teardown do + after do $stdout = STDOUT end - test 'logs with json' do + it 'logs with json' do Resque::Scheduler.log! 'whatever' assert $stdout.string =~ /"msg":"whatever"/ end end - context 'logger with text formatter' do - setup do + describe 'logger with text formatter' do + before do + reset_resque_scheduler nullify_logger Resque::Scheduler.logformat = 'text' $stdout = StringIO.new end - teardown do + after do $stdout = STDOUT end - test 'logs with text' do + it 'logs with text' do Resque::Scheduler.log! 'another thing' assert $stdout.string =~ /: another thing/ end diff --git a/test/scheduler_task_test.rb b/test/scheduler_task_test.rb index 75a18835..6de7e37d 100644 --- a/test/scheduler_task_test.rb +++ b/test/scheduler_task_test.rb @@ -1,27 +1,22 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'Resque::Scheduler' do - setup do +describe 'Resque::Scheduler' do + before do + reset_resque_scheduler Resque::Scheduler.configure do |c| - c.dynamic = false c.poll_sleep_amount = 0.1 end - Resque.redis.flushall - Resque::Scheduler.quiet = true - Resque::Scheduler.clear_schedule! - Resque::Scheduler.send(:instance_variable_set, :@scheduled_jobs, {}) - Resque::Scheduler.send(:instance_variable_set, :@shutdown, false) end - test 'shutdown raises Interrupt when sleeping' do + it 'shutdown raises Interrupt when sleeping' do Thread.current.expects(:raise).with(Interrupt) Resque::Scheduler.send(:instance_variable_set, :@th, Thread.current) Resque::Scheduler.send(:instance_variable_set, :@sleeping, true) Resque::Scheduler.shutdown end - test 'sending TERM to scheduler breaks out of poll_sleep' do + it 'sending TERM to scheduler breaks out of poll_sleep' do Resque::Scheduler.expects(:release_master_lock) @pid = Process.pid diff --git a/test/scheduler_test.rb b/test/scheduler_test.rb index cf64cb83..5b233464 100644 --- a/test/scheduler_test.rb +++ b/test/scheduler_test.rb @@ -1,20 +1,12 @@ # vim:fileencoding=utf-8 require_relative 'test_helper' -context 'Resque::Scheduler' do - setup do - Resque::Scheduler.configure do |c| - c.dynamic = false - c.quiet = true - c.env = nil - c.app_name = nil - end - Resque.redis.flushall - Resque::Scheduler.clear_schedule! - Resque::Scheduler.send(:instance_variable_set, :@scheduled_jobs, {}) +describe 'Resque::Scheduler' do + before do + reset_resque_scheduler end - test 'enqueue constantizes' do + it 'enqueue constantizes' do Resque::Scheduler.env = 'production' config = { 'cron' => '* * * * *', @@ -27,7 +19,7 @@ Resque::Scheduler.enqueue_from_config(config) end - test 'enqueue runs hooks' do + it 'enqueue runs hooks' do Resque::Scheduler.env = 'production' config = { 'cron' => '* * * * *', @@ -45,7 +37,7 @@ Resque::Scheduler.enqueue_from_config(config) end - test 'enqueue_from_config respects queue params' do + it 'enqueue_from_config respects queue params' do config = { 'cron' => '* * * * *', 'class' => 'SomeIvarJob', @@ -55,7 +47,7 @@ Resque::Scheduler.enqueue_from_config(config) end - test 'config makes it into the rufus_scheduler' do + it 'config makes it into the rufus_scheduler' do assert_equal(0, Resque::Scheduler.rufus_scheduler.jobs.size) Resque.schedule = { @@ -71,7 +63,7 @@ assert Resque::Scheduler.scheduled_jobs.include?('some_ivar_job') end - test 'can reload schedule' do + it 'can reload schedule' do Resque::Scheduler.dynamic = true Resque.schedule = { 'some_ivar_job' => { @@ -99,7 +91,7 @@ assert Resque::Scheduler.scheduled_jobs.include?('some_ivar_job2') end - test 'load_schedule_job loads a schedule' do + it 'load_schedule_job loads a schedule' do Resque::Scheduler.load_schedule_job( 'some_ivar_job', 'cron' => '* * * * *', @@ -112,7 +104,7 @@ assert Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job') end - test 'load_schedule_job with every with options' do + it 'load_schedule_job with every with options' do Resque::Scheduler.load_schedule_job( 'some_ivar_job', 'every' => ['30s', { 'first_in' => '60s' }], @@ -127,7 +119,7 @@ assert job.opts.keys.include?(:first_in) end - test 'load_schedule_job with cron with options' do + it 'load_schedule_job with cron with options' do Resque::Scheduler.load_schedule_job( 'some_ivar_job', 'cron' => ['* * * * *', { 'allow_overlapping' => 'true' }], @@ -142,7 +134,7 @@ assert job.opts.keys.include?(:allow_overlapping) end - test 'load_schedule_job without cron' do + it 'load_schedule_job without cron' do Resque::Scheduler.load_schedule_job( 'some_ivar_job', 'class' => 'SomeIvarJob', @@ -154,7 +146,7 @@ assert !Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job') end - test 'load_schedule_job with an empty cron' do + it 'load_schedule_job with an empty cron' do Resque::Scheduler.load_schedule_job( 'some_ivar_job', 'cron' => '', @@ -167,7 +159,7 @@ assert !Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job') end - test 'update_schedule' do + it 'update_schedule' do Resque::Scheduler.dynamic = true Resque.schedule = { 'some_ivar_job' => { @@ -210,7 +202,7 @@ assert_equal 0, Resque.redis.scard(:schedules_changed) end - test 'update_schedule when all jobs have been removed' do + it 'update_schedule when all jobs have been removed' do Resque::Scheduler.dynamic = true Resque.schedule = { 'some_ivar_job' => { @@ -230,7 +222,7 @@ assert_equal 0, Resque.redis.scard(:schedules_changed) end - test 'update_schedule with mocks' do + it 'update_schedule with mocks' do Resque::Scheduler.dynamic = true Resque.schedule = { 'some_ivar_job' => { @@ -272,7 +264,7 @@ assert_equal 0, Resque.redis.scard(:schedules_changed) end - test 'concurrent update_schedule calls' do + it 'concurrent update_schedule calls' do Resque::Scheduler.dynamic = true Resque::Scheduler.load_schedule! jobs_count = 100 @@ -296,7 +288,7 @@ assert_equal 0, Resque.redis.scard(:schedules_changed) end - test 'schedule= sets the schedule' do + it 'schedule= sets the schedule' do Resque::Scheduler.dynamic = true Resque.schedule = { 'my_ivar_job' => { @@ -311,7 +303,7 @@ ) end - test 'schedule= removes schedules not present in the given ' \ + it 'schedule= removes schedules not present in the given ' \ 'schedule argument' do Resque::Scheduler.dynamic = true @@ -333,7 +325,7 @@ ) end - test "schedule= uses job name as 'class' argument if it's missing" do + it "schedule= uses job name as 'class' argument if it's missing" do Resque::Scheduler.dynamic = true Resque.schedule = { 'SomeIvarJob' => { 'cron' => '* * * * *', 'args' => '/tmp/75' @@ -345,7 +337,7 @@ assert_equal('SomeIvarJob', Resque.schedule['SomeIvarJob']['class']) end - test 'schedule= does not mutate argument' do + it 'schedule= does not mutate argument' do schedule = { 'SomeIvarJob' => { 'cron' => '* * * * *', 'args' => '/tmp/75' } } @@ -353,7 +345,7 @@ assert !schedule['SomeIvarJob'].key?('class') end - test 'set_schedule can set an individual schedule' do + it 'set_schedule can set an individual schedule' do Resque.set_schedule( 'some_ivar_job', 'cron' => '* * * * *', 'class' => 'SomeIvarJob', 'args' => '/tmp/22' @@ -365,7 +357,7 @@ assert Resque.redis.sismember(:schedules_changed, 'some_ivar_job') end - test 'fetch_schedule returns a schedule' do + it 'fetch_schedule returns a schedule' do Resque.redis.hset(:schedules, 'some_ivar_job2', Resque.encode( 'cron' => '* * * * *', 'class' => 'SomeIvarJob', 'args' => '/tmp/33' )) @@ -375,7 +367,7 @@ ) end - test 'remove_schedule removes a schedule' do + it 'remove_schedule removes a schedule' do Resque.set_schedule( 'some_ivar_job3', 'cron' => '* * * * *', @@ -390,7 +382,7 @@ assert_equal [], Resque.redis.smembers(:persisted_schedules) end - test 'persisted schedules' do + it 'persisted schedules' do Resque.set_schedule( 'some_ivar_job', 'cron' => '* * * * *', @@ -419,41 +411,51 @@ assert_equal(nil, Resque.schedule['some_job']) end - test 'adheres to lint' do - assert_nothing_raised do - Resque::Plugin.lint(Resque::Scheduler) - Resque::Plugin.lint(Resque::Scheduler::Extension) - end + # The failure to raise an error is implicit here. + it 'adheres to lint' do + Resque::Plugin.lint(Resque::Scheduler) + Resque::Plugin.lint(Resque::Scheduler::Extension) end - test 'procline contains app_name when present' do - Resque::Scheduler.app_name = 'foo' - assert Resque::Scheduler.send(:build_procline, 'bar') =~ /\[foo\]:/ + it 'procline contains app_name when present' do + Rails.stub(:env, nil) do + Resque::Scheduler.app_name = 'foo' + assert Resque::Scheduler.send(:build_procline, 'bar') =~ /\[foo\]:/ + end end - test 'procline omits app_name when absent' do - Resque::Scheduler.app_name = nil - assert Resque::Scheduler.send(:build_procline, 'bar') =~ - /#{Resque::Scheduler.send(:internal_name)}: bar/ + it 'procline omits app_name when absent' do + Rails.stub(:env, nil) do + Resque::Scheduler.app_name = nil + regexp = /#{Resque::Scheduler.send(:internal_name)}: bar/ + message = "Got #{Resque::Scheduler.send(:build_procline, 'bar')}, "\ + "instead of #{Resque::Scheduler.send(:internal_name)}: bar" + assert Resque::Scheduler.send(:build_procline, 'bar') =~ regexp, message + end end - test 'procline contains env when present' do - Resque::Scheduler.env = 'xyz' - assert Resque::Scheduler.send(:build_procline, 'cage') =~ /\[xyz\]: cage/ + it 'procline contains env when present' do + Rails.stub(:env, nil) do + Resque::Scheduler.env = 'xyz' + assert Resque::Scheduler.send(:build_procline, 'cage') =~ /\[xyz\]: cage/ + end end - test 'procline omits env when absent' do - Resque::Scheduler.env = nil - assert Resque::Scheduler.send(:build_procline, 'cage') =~ - /#{Resque::Scheduler.send(:internal_name)}: cage/ + it 'procline omits env when absent' do + Rails.stub(:env, nil) do + Resque::Scheduler.env = nil + assert Resque::Scheduler.send(:build_procline, 'cage') =~ + /#{Resque::Scheduler.send(:internal_name)}: cage/ + end end - context 'printing schedule' do - setup do + describe 'printing schedule' do + before do + reset_resque_scheduler Resque::Scheduler.expects(:log!).at_least_once end - test 'prints schedule' do + it 'prints schedule' do fake_rufus_scheduler = mock fake_rufus_scheduler.expects(:jobs).at_least_once .returns(foo: OpenStruct.new(t: nil, last: nil)) diff --git a/test/support/integration_case.rb b/test/support/integration_case.rb new file mode 100644 index 00000000..7e680fa5 --- /dev/null +++ b/test/support/integration_case.rb @@ -0,0 +1,7 @@ +# Define a bare test case to use with Capybara +module ActionDispatch + class IntegrationTest + include Capybara::DSL + include Rails.application.routes.url_helpers + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index c75aeff1..774bfc13 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,15 +1,22 @@ # vim:fileencoding=utf-8 require 'simplecov' -require 'test/unit' -require 'mocha/setup' -require 'rack/test' +ENV['RAILS_ENV'] = 'test' +require File.expand_path('../../test/dummy/config/environment.rb', __FILE__) +ActiveRecord::Migrator.migrations_paths = [File.expand_path( + '../../test/dummy/db/migrate', + __FILE__ + )] +ActiveRecord::Migrator.migrations_paths << File.expand_path( + '../../db/migrate', + __FILE__ + ) + +# This bit needs to be above the minitest require (in rails/test_help), but +# after the Rails app is started. This is because otherwise, the +# at_exit calls are in the wrong order and Redis shuts down before the tests +# run. require 'resque' - -$LOAD_PATH.unshift File.dirname(File.expand_path(__FILE__)) + '/../lib' -require 'resque-scheduler' -require 'resque/scheduler/server' - unless ENV['RESQUE_SCHEDULER_DISABLE_TEST_REDIS_SERVER'] # Start our own Redis when the tests start. RedisInstance will take care of # starting and stopping. @@ -17,34 +24,24 @@ RedisInstance.run! end -at_exit { exit MiniTest::Unit.new.run(ARGV) || 0 } +require 'rails/test_help' -## -# test/spec/mini 3 -# original work: http://gist.github.com/25455 -# forked and modified: https://gist.github.com/meatballhat/8906709 -# -def context(*args, &block) - return super unless (name = args.first) && block - require 'test/unit' - klass = Class.new(Test::Unit::TestCase) do - def self.test(name, &block) - define_method("test_#{name.gsub(/\W/, '_')}", &block) if block - end - def self.xtest(*_args) - end - def self.setup(&block) - define_method(:setup, &block) - end - def self.teardown(&block) - define_method(:teardown, &block) - end - end - (class << klass; self end).send(:define_method, :name) do - name.gsub(/\W/, '_') - end - klass.class_eval(&block) -end +require 'minitest/spec' +require 'minitest/mock' +require 'mocha/setup' +require 'rack/test' + +require 'capybara/rails' +Capybara.default_driver = :rack_test +Capybara.default_selector = :css +require_relative 'support/integration_case' + +# Filter out Minitest backtrace while allowing backtrace from other libraries +# to be shown. +Minitest.backtrace_filter = Minitest::BacktraceFilter.new + +$LOAD_PATH.unshift File.dirname(File.expand_path(__FILE__)) + '/../lib' +require 'resque-scheduler' unless defined?(Rails) module Rails @@ -100,6 +97,14 @@ def self.perform(*args) end end +module Foo + class Bar + def self.queue + 'bar' + end + end +end + JobWithoutParams = Class.new(JobWithParams) %w( @@ -115,6 +120,32 @@ def self.perform(*args) ENV[envvar] = nil end +module Test + RESQUE_SCHEDULE = { + 'job_without_params' => { + 'cron' => '* * * * *', + 'class' => 'JobWithoutParams', + 'args' => { + 'host' => 'localhost' + }, + 'rails_env' => 'production' + }, + 'job_with_params' => { + 'every' => '1m', + 'class' => 'JobWithParams', + 'args' => { + 'host' => 'localhost' + }, + 'parameters' => { + 'log_level' => { + 'description' => 'The level of logging', + 'default' => 'warn' + } + } + } + } +end + def nullify_logger Resque::Scheduler.configure do |c| c.quiet = nil @@ -131,4 +162,30 @@ def restore_devnull_logfile ENV['LOGFILE'] = '/dev/null' end +# Tests need to avoid leaking configuration into the environment, so that they +# do not cause failures due to ordering. This function should be run before +# every test. +def reset_resque_scheduler + # Scheduler test + Resque::Scheduler.configure do |c| + c.dynamic = false + c.quiet = true + c.env = nil + c.app_name = nil + c.poll_sleep_amount = nil + end + Resque.redis.flushall + Resque::Scheduler.clear_schedule! + Resque::Scheduler.send(:instance_variable_set, :@scheduled_jobs, {}) + + # When run with --seed 3432, the bottom test fails without the next line: + # Minitest::Assertion: [SystemExit] exception expected, not + # Class : + # Message : <"\"0\" is not in range 1..31"> + # No problem when run in isolation + Resque.schedule = {} # Schedule leaks out from other tests without this. + + Resque::Scheduler.send(:instance_variable_set, :@shutdown, false) +end + restore_devnull_logfile diff --git a/test/util_test.rb b/test/util_test.rb index 8fdad2c9..b0fc113d 100644 --- a/test/util_test.rb +++ b/test/util_test.rb @@ -1,11 +1,14 @@ # vim:fileencoding=utf-8 +require_relative 'test_helper' -context 'Util' do +describe 'Util' do def util Resque::Scheduler::Util end - test 'constantizing' do + before { reset_resque_scheduler } + + it 'constantizing' do assert util.constantize('Resque::Scheduler') == Resque::Scheduler end end