1
0
Fork 0
mirror of https://github.com/mperham/sidekiq.git synced 2022-11-09 13:52:34 -05:00

Switch all tests to use Minitest::Spec for consistency

This commit is contained in:
Mike Perham 2019-02-28 12:43:50 -08:00
parent 870516f472
commit 85a1be3684
26 changed files with 2535 additions and 2578 deletions

View file

@ -5,7 +5,7 @@ require 'sidekiq/fetch'
require 'sidekiq/scheduled'
require 'sidekiq/processor'
class TestActors < Minitest::Test
describe 'Actors' do
class JoeWorker
include Sidekiq::Worker
def perform(slp)
@ -15,124 +15,122 @@ class TestActors < Minitest::Test
end
end
describe 'threads' do
before do
Sidekiq.redis {|c| c.flushdb}
end
describe 'scheduler' do
it 'can start and stop' do
f = Sidekiq::Scheduled::Poller.new
f.start
f.terminate
end
it 'can schedule' do
ss = Sidekiq::ScheduledSet.new
q = Sidekiq::Queue.new
JoeWorker.perform_in(0.01, 0)
assert_equal 0, q.size
assert_equal 1, ss.size
sleep 0.015
s = Sidekiq::Scheduled::Poller.new
s.enqueue
assert_equal 1, q.size
assert_equal 0, ss.size
s.terminate
end
end
describe 'processor' do
before do
Sidekiq.redis {|c| c.flushdb}
$count = 0
end
describe 'scheduler' do
it 'can start and stop' do
f = Sidekiq::Scheduled::Poller.new
f.start
f.terminate
it 'can start and stop' do
f = Sidekiq::Processor.new(Mgr.new)
f.terminate
end
class Mgr
attr_reader :latest_error
attr_reader :mutex
attr_reader :cond
def initialize
@mutex = ::Mutex.new
@cond = ::ConditionVariable.new
end
it 'can schedule' do
ss = Sidekiq::ScheduledSet.new
q = Sidekiq::Queue.new
JoeWorker.perform_in(0.01, 0)
assert_equal 0, q.size
assert_equal 1, ss.size
sleep 0.015
s = Sidekiq::Scheduled::Poller.new
s.enqueue
assert_equal 1, q.size
assert_equal 0, ss.size
s.terminate
def processor_died(inst, err)
@latest_error = err
@mutex.synchronize do
@cond.signal
end
end
def processor_stopped(inst)
@mutex.synchronize do
@cond.signal
end
end
def options
{ :concurrency => 3, :queues => ['default'] }
end
end
describe 'processor' do
before do
$count = 0
end
it 'can process' do
mgr = Mgr.new
it 'can start and stop' do
f = Sidekiq::Processor.new(Mgr.new)
f.terminate
end
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async(0)
class Mgr
attr_reader :latest_error
attr_reader :mutex
attr_reader :cond
def initialize
@mutex = ::Mutex.new
@cond = ::ConditionVariable.new
end
def processor_died(inst, err)
@latest_error = err
@mutex.synchronize do
@cond.signal
end
end
def processor_stopped(inst)
@mutex.synchronize do
@cond.signal
end
end
def options
{ :concurrency => 3, :queues => ['default'] }
end
end
a = $count
p.process_one
b = $count
assert_equal a + 1, b
end
it 'can process' do
mgr = Mgr.new
it 'deals with errors' do
mgr = Mgr.new
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async(0)
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async("boom")
q = Sidekiq::Queue.new
assert_equal 1, q.size
a = $count
p.process_one
b = $count
assert_equal a + 1, b
end
it 'deals with errors' do
mgr = Mgr.new
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async("boom")
q = Sidekiq::Queue.new
assert_equal 1, q.size
a = $count
mgr.mutex.synchronize do
p.start
mgr.cond.wait(mgr.mutex)
end
b = $count
assert_equal a, b
sleep 0.001
assert_equal false, p.thread.status
p.terminate(true)
refute_nil mgr.latest_error
assert_equal RuntimeError, mgr.latest_error.class
end
it 'gracefully kills' do
mgr = Mgr.new
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async(1)
q = Sidekiq::Queue.new
assert_equal 1, q.size
a = $count
a = $count
mgr.mutex.synchronize do
p.start
sleep(0.05)
p.terminate
p.kill(true)
b = $count
assert_equal a, b
assert_equal false, p.thread.status
refute mgr.latest_error, mgr.latest_error.to_s
mgr.cond.wait(mgr.mutex)
end
b = $count
assert_equal a, b
sleep 0.001
assert_equal false, p.thread.status
p.terminate(true)
refute_nil mgr.latest_error
assert_equal RuntimeError, mgr.latest_error.class
end
it 'gracefully kills' do
mgr = Mgr.new
p = Sidekiq::Processor.new(mgr)
JoeWorker.perform_async(1)
q = Sidekiq::Queue.new
assert_equal 1, q.size
a = $count
p.start
sleep(0.05)
p.terminate
p.kill(true)
b = $count
assert_equal a, b
assert_equal false, p.thread.status
refute mgr.latest_error, mgr.latest_error.to_s
end
end
end

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
require_relative 'helper'
require 'sidekiq/cli'
class TestCLI < Minitest::Test
describe Sidekiq::CLI do
describe '#parse' do
before do
Sidekiq.options = Sidekiq::DEFAULTS.dup

View file

@ -2,7 +2,7 @@
require_relative 'helper'
require 'sidekiq/api'
class TestClient < Minitest::Test
describe Sidekiq::Client do
describe 'errors' do
it 'raises ArgumentError with invalid params' do
assert_raises ArgumentError do

View file

@ -2,49 +2,45 @@
require_relative 'helper'
require 'sidekiq/api'
class TestDeadSet < Minitest::Test
describe 'dead_set' do
describe 'zomg' do
def dead_set
Sidekiq::DeadSet.new
describe 'DeadSet' do
def dead_set
Sidekiq::DeadSet.new
end
it 'should put passed serialized job to the "dead" sorted set' do
serialized_job = Sidekiq.dump_json(jid: '123123', class: 'SomeWorker', args: [])
dead_set.kill(serialized_job)
assert_equal dead_set.find_job('123123').value, serialized_job
end
it 'should remove dead jobs older than Sidekiq::DeadSet.timeout' do
Sidekiq::DeadSet.stub(:timeout, 10) do
Time.stub(:now, Time.now - 11) do
dead_set.kill(Sidekiq.dump_json(jid: '000103', class: 'MyWorker3', args: [])) # the oldest
end
it 'should put passed serialized job to the "dead" sorted set' do
serialized_job = Sidekiq.dump_json(jid: '123123', class: 'SomeWorker', args: [])
dead_set.kill(serialized_job)
assert_equal dead_set.find_job('123123').value, serialized_job
Time.stub(:now, Time.now - 9) do
dead_set.kill(Sidekiq.dump_json(jid: '000102', class: 'MyWorker2', args: []))
end
it 'should remove dead jobs older than Sidekiq::DeadSet.timeout' do
Sidekiq::DeadSet.stub(:timeout, 10) do
Time.stub(:now, Time.now - 11) do
dead_set.kill(Sidekiq.dump_json(jid: '000103', class: 'MyWorker3', args: [])) # the oldest
end
Time.stub(:now, Time.now - 9) do
dead_set.kill(Sidekiq.dump_json(jid: '000102', class: 'MyWorker2', args: []))
end
dead_set.kill(Sidekiq.dump_json(jid: '000101', class: 'MyWorker1', args: []))
end
assert_nil dead_set.find_job('000103')
assert dead_set.find_job('000102')
assert dead_set.find_job('000101')
end
it 'should remove all but last Sidekiq::DeadSet.max_jobs-1 jobs' do
Sidekiq::DeadSet.stub(:max_jobs, 3) do
dead_set.kill(Sidekiq.dump_json(jid: '000101', class: 'MyWorker1', args: []))
dead_set.kill(Sidekiq.dump_json(jid: '000102', class: 'MyWorker2', args: []))
dead_set.kill(Sidekiq.dump_json(jid: '000103', class: 'MyWorker3', args: []))
end
assert_nil dead_set.find_job('000101')
assert dead_set.find_job('000102')
assert dead_set.find_job('000103')
end
dead_set.kill(Sidekiq.dump_json(jid: '000101', class: 'MyWorker1', args: []))
end
assert_nil dead_set.find_job('000103')
assert dead_set.find_job('000102')
assert dead_set.find_job('000101')
end
it 'should remove all but last Sidekiq::DeadSet.max_jobs-1 jobs' do
Sidekiq::DeadSet.stub(:max_jobs, 3) do
dead_set.kill(Sidekiq.dump_json(jid: '000101', class: 'MyWorker1', args: []))
dead_set.kill(Sidekiq.dump_json(jid: '000102', class: 'MyWorker2', args: []))
dead_set.kill(Sidekiq.dump_json(jid: '000103', class: 'MyWorker3', args: []))
end
assert_nil dead_set.find_job('000101')
assert dead_set.find_job('000102')
assert dead_set.find_job('000103')
end
end

View file

@ -17,7 +17,7 @@ class Component
end
end
class TestExceptionHandler < Minitest::Test
describe Sidekiq::ExceptionHandler do
describe "with mock logger" do
before do
@old_logger = Sidekiq.logger

View file

@ -5,115 +5,112 @@ require 'active_record'
require 'action_mailer'
Sidekiq::Extensions.enable_delay!
class TestExtensions < Minitest::Test
describe 'sidekiq extensions' do
before do
Sidekiq.redis {|c| c.flushdb }
end
describe Sidekiq::Extensions do
before do
Sidekiq.redis {|c| c.flushdb }
end
class MyModel < ActiveRecord::Base
def self.long_class_method
raise "Should not be called!"
end
end
it 'allows delayed execution of ActiveRecord class methods' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new
assert_equal 0, q.size
MyModel.delay.long_class_method
assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'uses and stringifies specified options' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new('notdefault')
assert_equal 0, q.size
MyModel.delay(queue: :notdefault).long_class_method
assert_equal ['notdefault'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'allows delayed scheduling of AR class methods' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
MyModel.delay_for(5.days).long_class_method
assert_equal 1, ss.size
end
it 'allows until delayed scheduling of AR class methods' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
MyModel.delay_until(1.day.from_now).long_class_method
assert_equal 1, ss.size
end
class UserMailer < ActionMailer::Base
def greetings(a, b)
raise "Should not be called!"
end
end
it 'allows delayed delivery of ActionMailer mails' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new
assert_equal 0, q.size
UserMailer.delay.greetings(1, 2)
assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'allows delayed scheduling of AM mails' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
UserMailer.delay_for(5.days).greetings(1, 2)
assert_equal 1, ss.size
end
it 'allows until delay scheduling of AM mails' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
UserMailer.delay_until(5.days.from_now).greetings(1, 2)
assert_equal 1, ss.size
end
class SomeClass
def self.doit(arg)
end
end
it 'allows delay of any ole class method' do
q = Sidekiq::Queue.new
assert_equal 0, q.size
SomeClass.delay.doit(Date.today)
assert_equal 1, q.size
end
module SomeModule
def self.doit(arg)
end
end
it 'logs large payloads' do
output = capture_logging(Logger::WARN) do
SomeClass.delay.doit('a' * 8192)
end
assert_match(/#{SomeClass}.doit job argument is/, output)
end
it 'allows delay of any module class method' do
q = Sidekiq::Queue.new
assert_equal 0, q.size
SomeModule.delay.doit(Date.today)
assert_equal 1, q.size
end
it 'allows Psych to serialize anonymous structs' do
obj = Struct.new(:attribute).new(my: 'data')
assert_equal obj.attribute, Psych.load(Psych.dump(obj)).attribute
class MyModel < ActiveRecord::Base
def self.long_class_method
raise "Should not be called!"
end
end
it 'allows delayed execution of ActiveRecord class methods' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new
assert_equal 0, q.size
MyModel.delay.long_class_method
assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'uses and stringifies specified options' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new('notdefault')
assert_equal 0, q.size
MyModel.delay(queue: :notdefault).long_class_method
assert_equal ['notdefault'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'allows delayed scheduling of AR class methods' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
MyModel.delay_for(5.days).long_class_method
assert_equal 1, ss.size
end
it 'allows until delayed scheduling of AR class methods' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
MyModel.delay_until(1.day.from_now).long_class_method
assert_equal 1, ss.size
end
class UserMailer < ActionMailer::Base
def greetings(a, b)
raise "Should not be called!"
end
end
it 'allows delayed delivery of ActionMailer mails' do
assert_equal [], Sidekiq::Queue.all.map(&:name)
q = Sidekiq::Queue.new
assert_equal 0, q.size
UserMailer.delay.greetings(1, 2)
assert_equal ['default'], Sidekiq::Queue.all.map(&:name)
assert_equal 1, q.size
end
it 'allows delayed scheduling of AM mails' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
UserMailer.delay_for(5.days).greetings(1, 2)
assert_equal 1, ss.size
end
it 'allows until delay scheduling of AM mails' do
ss = Sidekiq::ScheduledSet.new
assert_equal 0, ss.size
UserMailer.delay_until(5.days.from_now).greetings(1, 2)
assert_equal 1, ss.size
end
class SomeClass
def self.doit(arg)
end
end
it 'allows delay of any ole class method' do
q = Sidekiq::Queue.new
assert_equal 0, q.size
SomeClass.delay.doit(Date.today)
assert_equal 1, q.size
end
module SomeModule
def self.doit(arg)
end
end
it 'logs large payloads' do
output = capture_logging(Logger::WARN) do
SomeClass.delay.doit('a' * 8192)
end
assert_match(/#{SomeClass}.doit job argument is/, output)
end
it 'allows delay of any module class method' do
q = Sidekiq::Queue.new
assert_equal 0, q.size
SomeModule.delay.doit(Date.today)
assert_equal 1, q.size
end
it 'allows Psych to serialize anonymous structs' do
obj = Struct.new(:attribute).new(my: 'data')
assert_equal obj.attribute, Psych.load(Psych.dump(obj)).attribute
end
end

View file

@ -3,44 +3,42 @@ require_relative 'helper'
require 'sidekiq/fetch'
require 'sidekiq/api'
class TestFetcher < Minitest::Test
describe 'fetcher' do
before do
Sidekiq.redis do |conn|
conn.flushdb
conn.rpush('queue:basic', 'msg')
end
describe Sidekiq::BasicFetch do
before do
Sidekiq.redis do |conn|
conn.flushdb
conn.rpush('queue:basic', 'msg')
end
it 'retrieves' do
fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar'])
uow = fetch.retrieve_work
refute_nil uow
assert_equal 'basic', uow.queue_name
assert_equal 'msg', uow.job
q = Sidekiq::Queue.new('basic')
assert_equal 0, q.size
uow.requeue
assert_equal 1, q.size
assert_nil uow.acknowledge
end
it 'retrieves with strict setting' do
fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar', 'bar'], :strict => true)
cmd = fetch.queues_cmd
assert_equal cmd, ['queue:basic', 'queue:bar', Sidekiq::BasicFetch::TIMEOUT]
end
it 'bulk requeues' do
q1 = Sidekiq::Queue.new('foo')
q2 = Sidekiq::Queue.new('bar')
assert_equal 0, q1.size
assert_equal 0, q2.size
uow = Sidekiq::BasicFetch::UnitOfWork
Sidekiq::BasicFetch.bulk_requeue([uow.new('fuzzy:queue:foo', 'bob'), uow.new('fuzzy:queue:foo', 'bar'), uow.new('fuzzy:queue:bar', 'widget')], {:queues => []})
assert_equal 2, q1.size
assert_equal 1, q2.size
end
end
it 'retrieves' do
fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar'])
uow = fetch.retrieve_work
refute_nil uow
assert_equal 'basic', uow.queue_name
assert_equal 'msg', uow.job
q = Sidekiq::Queue.new('basic')
assert_equal 0, q.size
uow.requeue
assert_equal 1, q.size
assert_nil uow.acknowledge
end
it 'retrieves with strict setting' do
fetch = Sidekiq::BasicFetch.new(:queues => ['basic', 'bar', 'bar'], :strict => true)
cmd = fetch.queues_cmd
assert_equal cmd, ['queue:basic', 'queue:bar', Sidekiq::BasicFetch::TIMEOUT]
end
it 'bulk requeues' do
q1 = Sidekiq::Queue.new('foo')
q2 = Sidekiq::Queue.new('bar')
assert_equal 0, q1.size
assert_equal 0, q2.size
uow = Sidekiq::BasicFetch::UnitOfWork
Sidekiq::BasicFetch.bulk_requeue([uow.new('fuzzy:queue:foo', 'bob'), uow.new('fuzzy:queue:foo', 'bar'), uow.new('fuzzy:queue:bar', 'widget')], {:queues => []})
assert_equal 2, q1.size
assert_equal 1, q2.size
end
end

View file

@ -3,91 +3,88 @@ require_relative 'helper'
require 'sidekiq/launcher'
require 'sidekiq/cli'
class TestLauncher < Minitest::Test
describe 'launcher' do
before do
Sidekiq.redis {|c| c.flushdb }
end
def new_manager(opts)
Sidekiq::Manager.new(opts)
end
describe 'heartbeat' do
before do
@mgr = new_manager(options)
@launcher = Sidekiq::Launcher.new(options)
@launcher.manager = @mgr
@id = @launcher.identity
Sidekiq::Processor::WORKER_STATE.set('a', {'b' => 1})
@proctitle = $0
end
after do
Sidekiq::Processor::WORKER_STATE.clear
$0 = @proctitle
end
it 'fires new heartbeat events' do
i = 0
Sidekiq.on(:heartbeat) do
i += 1
end
assert_equal 0, i
@launcher.heartbeat
assert_equal 1, i
@launcher.heartbeat
assert_equal 1, i
end
describe 'when manager is active' do
before do
Sidekiq::CLI::PROCTITLES << proc { "xyz" }
@launcher.heartbeat
Sidekiq::CLI::PROCTITLES.pop
end
it 'sets useful info to proctitle' do
assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] xyz", $0
end
it 'stores process info in redis' do
info = Sidekiq.redis { |c| c.hmget(@id, 'busy') }
assert_equal ["1"], info
expires = Sidekiq.redis { |c| c.pttl(@id) }
assert_in_delta 60000, expires, 500
end
end
describe 'when manager is stopped' do
before do
@launcher.quiet
@launcher.heartbeat
end
#after do
#puts system('redis-cli -n 15 keys "*" | while read LINE ; do TTL=`redis-cli -n 15 ttl "$LINE"`; if [ "$TTL" -eq -1 ]; then echo "$LINE"; fi; done;')
#end
it 'indicates stopping status in proctitle' do
assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] stopping", $0
end
it 'stores process info in redis' do
info = Sidekiq.redis { |c| c.hmget(@id, 'busy') }
assert_equal ["1"], info
expires = Sidekiq.redis { |c| c.pttl(@id) }
assert_in_delta 60000, expires, 50
end
end
end
def options
{ :concurrency => 3, :queues => ['default'], :tag => 'myapp' }
end
describe Sidekiq::Launcher do
before do
Sidekiq.redis {|c| c.flushdb }
end
def new_manager(opts)
Sidekiq::Manager.new(opts)
end
describe 'heartbeat' do
before do
@mgr = new_manager(options)
@launcher = Sidekiq::Launcher.new(options)
@launcher.manager = @mgr
@id = @launcher.identity
Sidekiq::Processor::WORKER_STATE.set('a', {'b' => 1})
@proctitle = $0
end
after do
Sidekiq::Processor::WORKER_STATE.clear
$0 = @proctitle
end
it 'fires new heartbeat events' do
i = 0
Sidekiq.on(:heartbeat) do
i += 1
end
assert_equal 0, i
@launcher.heartbeat
assert_equal 1, i
@launcher.heartbeat
assert_equal 1, i
end
describe 'when manager is active' do
before do
Sidekiq::CLI::PROCTITLES << proc { "xyz" }
@launcher.heartbeat
Sidekiq::CLI::PROCTITLES.pop
end
it 'sets useful info to proctitle' do
assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] xyz", $0
end
it 'stores process info in redis' do
info = Sidekiq.redis { |c| c.hmget(@id, 'busy') }
assert_equal ["1"], info
expires = Sidekiq.redis { |c| c.pttl(@id) }
assert_in_delta 60000, expires, 500
end
end
describe 'when manager is stopped' do
before do
@launcher.quiet
@launcher.heartbeat
end
#after do
#puts system('redis-cli -n 15 keys "*" | while read LINE ; do TTL=`redis-cli -n 15 ttl "$LINE"`; if [ "$TTL" -eq -1 ]; then echo "$LINE"; fi; done;')
#end
it 'indicates stopping status in proctitle' do
assert_equal "sidekiq #{Sidekiq::VERSION} myapp [1 of 3 busy] stopping", $0
end
it 'stores process info in redis' do
info = Sidekiq.redis { |c| c.hmget(@id, 'busy') }
assert_equal ["1"], info
expires = Sidekiq.redis { |c| c.pttl(@id) }
assert_in_delta 60000, expires, 50
end
end
end
def options
{ :concurrency => 3, :queues => ['default'], :tag => 'myapp' }
end
end

View file

@ -2,34 +2,32 @@
require_relative 'helper'
require 'sidekiq/logging'
class TestLogging < Minitest::Test
describe Sidekiq::Logging do
describe "#with_context" do
def ctx
Sidekiq::Logging.logger.formatter.context
end
describe Sidekiq::Logging do
describe "#with_context" do
def ctx
Sidekiq::Logging.logger.formatter.context
end
it "has no context by default" do
assert_nil ctx
end
it "has no context by default" do
assert_nil ctx
end
it "can add a context" do
Sidekiq::Logging.with_context "xx" do
assert_equal " xx", ctx
it "can add a context" do
Sidekiq::Logging.with_context "xx" do
assert_equal " xx", ctx
end
assert_nil ctx
end
it "can use multiple contexts" do
Sidekiq::Logging.with_context "xx" do
assert_equal " xx", ctx
Sidekiq::Logging.with_context "yy" do
assert_equal " xx yy", ctx
end
assert_nil ctx
end
it "can use multiple contexts" do
Sidekiq::Logging.with_context "xx" do
assert_equal " xx", ctx
Sidekiq::Logging.with_context "yy" do
assert_equal " xx yy", ctx
end
assert_equal " xx", ctx
end
assert_nil ctx
assert_equal " xx", ctx
end
assert_nil ctx
end
end
end

View file

@ -2,49 +2,46 @@
require_relative 'helper'
require 'sidekiq/manager'
class TestManager < Minitest::Test
describe 'manager' do
before do
Sidekiq.redis {|c| c.flushdb }
end
def new_manager(opts)
Sidekiq::Manager.new(opts)
end
it 'creates N processor instances' do
mgr = new_manager(options)
assert_equal options[:concurrency], mgr.workers.size
end
it 'shuts down the system' do
mgr = new_manager(options)
mgr.stop(::Process.clock_gettime(::Process::CLOCK_MONOTONIC))
end
it 'throws away dead processors' do
mgr = new_manager(options)
init_size = mgr.workers.size
processor = mgr.workers.first
begin
mgr.processor_died(processor, 'ignored')
assert_equal init_size, mgr.workers.size
refute mgr.workers.include?(processor)
ensure
mgr.workers.each {|p| p.terminate(true) }
end
end
it 'does not support invalid concurrency' do
assert_raises(ArgumentError) { new_manager(concurrency: 0) }
assert_raises(ArgumentError) { new_manager(concurrency: -1) }
end
def options
{ :concurrency => 3, :queues => ['default'] }
end
describe Sidekiq::Manager do
before do
Sidekiq.redis {|c| c.flushdb }
end
def new_manager(opts)
Sidekiq::Manager.new(opts)
end
it 'creates N processor instances' do
mgr = new_manager(options)
assert_equal options[:concurrency], mgr.workers.size
end
it 'shuts down the system' do
mgr = new_manager(options)
mgr.stop(::Process.clock_gettime(::Process::CLOCK_MONOTONIC))
end
it 'throws away dead processors' do
mgr = new_manager(options)
init_size = mgr.workers.size
processor = mgr.workers.first
begin
mgr.processor_died(processor, 'ignored')
assert_equal init_size, mgr.workers.size
refute mgr.workers.include?(processor)
ensure
mgr.workers.each {|p| p.terminate(true) }
end
end
it 'does not support invalid concurrency' do
assert_raises(ArgumentError) { new_manager(concurrency: 0) }
assert_raises(ArgumentError) { new_manager(concurrency: -1) }
end
def options
{ :concurrency => 3, :queues => ['default'] }
end
end

View file

@ -3,121 +3,119 @@ require_relative 'helper'
require 'sidekiq/middleware/chain'
require 'sidekiq/processor'
class TestMiddleware < Minitest::Test
describe 'middleware chain' do
before do
$errors = []
describe Sidekiq::Middleware do
before do
$errors = []
end
class CustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
class CustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
it 'supports custom middleware' do
chain = Sidekiq::Middleware::Chain.new
chain.add CustomMiddleware, 1, []
assert_equal CustomMiddleware, chain.entries.last.klass
end
class CustomWorker
$recorder = []
include Sidekiq::Worker
def perform(recorder)
$recorder << ['work_performed']
end
end
class NonYieldingMiddleware
def call(*args)
end
end
class AnotherCustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
class YetAnotherCustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
it 'executes middleware in the proper order' do
msg = Sidekiq.dump_json({ 'class' => CustomWorker.to_s, 'args' => [$recorder] })
Sidekiq.server_middleware do |chain|
# should only add once, second should replace the first
2.times { |i| chain.add CustomMiddleware, i.to_s, $recorder }
chain.insert_before CustomMiddleware, AnotherCustomMiddleware, '2', $recorder
chain.insert_after AnotherCustomMiddleware, YetAnotherCustomMiddleware, '3', $recorder
end
boss = Minitest::Mock.new
boss.expect(:options, {:queues => ['default'] }, [])
boss.expect(:options, {:queues => ['default'] }, [])
boss.expect(:options, {:queues => ['default'] }, [])
processor = Sidekiq::Processor.new(boss)
boss.expect(:processor_done, nil, [processor])
processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
assert_equal %w(2 before 3 before 1 before work_performed 1 after 3 after 2 after), $recorder.flatten
end
it 'correctly replaces middleware when using middleware with options in the initializer' do
chain = Sidekiq::Middleware::Chain.new
chain.add NonYieldingMiddleware
chain.add NonYieldingMiddleware, {:foo => 5}
assert_equal 1, chain.count
end
it 'correctly prepends middleware' do
chain = Sidekiq::Middleware::Chain.new
chain_entries = chain.entries
chain.add CustomMiddleware
chain.prepend YetAnotherCustomMiddleware
assert_equal YetAnotherCustomMiddleware, chain_entries.first.klass
assert_equal CustomMiddleware, chain_entries.last.klass
end
it 'allows middleware to abruptly stop processing rest of chain' do
recorder = []
chain = Sidekiq::Middleware::Chain.new
chain.add NonYieldingMiddleware
chain.add CustomMiddleware, 1, recorder
final_action = nil
chain.invoke { final_action = true }
assert_nil final_action
assert_equal [], recorder
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
describe 'i18n' do
it 'supports custom middleware' do
chain = Sidekiq::Middleware::Chain.new
chain.add CustomMiddleware, 1, []
assert_equal CustomMiddleware, chain.entries.last.klass
end
class CustomWorker
$recorder = []
include Sidekiq::Worker
def perform(recorder)
$recorder << ['work_performed']
end
end
class NonYieldingMiddleware
def call(*args)
end
end
class AnotherCustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
class YetAnotherCustomMiddleware
def initialize(name, recorder)
@name = name
@recorder = recorder
end
def call(*args)
@recorder << [@name, 'before']
yield
@recorder << [@name, 'after']
end
end
it 'executes middleware in the proper order' do
msg = Sidekiq.dump_json({ 'class' => CustomWorker.to_s, 'args' => [$recorder] })
Sidekiq.server_middleware do |chain|
# should only add once, second should replace the first
2.times { |i| chain.add CustomMiddleware, i.to_s, $recorder }
chain.insert_before CustomMiddleware, AnotherCustomMiddleware, '2', $recorder
chain.insert_after AnotherCustomMiddleware, YetAnotherCustomMiddleware, '3', $recorder
end
boss = Minitest::Mock.new
boss.expect(:options, {:queues => ['default'] }, [])
boss.expect(:options, {:queues => ['default'] }, [])
boss.expect(:options, {:queues => ['default'] }, [])
processor = Sidekiq::Processor.new(boss)
boss.expect(:processor_done, nil, [processor])
processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', msg))
assert_equal %w(2 before 3 before 1 before work_performed 1 after 3 after 2 after), $recorder.flatten
end
it 'correctly replaces middleware when using middleware with options in the initializer' do
chain = Sidekiq::Middleware::Chain.new
chain.add NonYieldingMiddleware
chain.add NonYieldingMiddleware, {:foo => 5}
assert_equal 1, chain.count
end
it 'correctly prepends middleware' do
chain = Sidekiq::Middleware::Chain.new
chain_entries = chain.entries
chain.add CustomMiddleware
chain.prepend YetAnotherCustomMiddleware
assert_equal YetAnotherCustomMiddleware, chain_entries.first.klass
assert_equal CustomMiddleware, chain_entries.last.klass
end
it 'allows middleware to abruptly stop processing rest of chain' do
recorder = []
chain = Sidekiq::Middleware::Chain.new
chain.add NonYieldingMiddleware
chain.add CustomMiddleware, 1, recorder
final_action = nil
chain.invoke { final_action = true }
assert_nil final_action
assert_equal [], recorder
end
describe 'I18n' do
before do
require 'i18n'
I18n.enforce_available_locales = false

View file

@ -4,362 +4,360 @@ require 'sidekiq/fetch'
require 'sidekiq/cli'
require 'sidekiq/processor'
class TestProcessor < Minitest::Test
TestException = Class.new(StandardError)
TEST_EXCEPTION = TestException.new("kerboom!")
describe Sidekiq::Processor do
TestProcessorException = Class.new(StandardError)
TEST_PROC_EXCEPTION = TestProcessorException.new("kerboom!")
describe 'processor' do
before do
$invokes = 0
@mgr = Minitest::Mock.new
@mgr.expect(:options, {:queues => ['default']})
@mgr.expect(:options, {:queues => ['default']})
@mgr.expect(:options, {:queues => ['default']})
@processor = ::Sidekiq::Processor.new(@mgr)
before do
$invokes = 0
@mgr = Minitest::Mock.new
@mgr.expect(:options, {:queues => ['default']})
@mgr.expect(:options, {:queues => ['default']})
@mgr.expect(:options, {:queues => ['default']})
@processor = ::Sidekiq::Processor.new(@mgr)
end
class MockWorker
include Sidekiq::Worker
def perform(args)
raise TEST_PROC_EXCEPTION if args.to_s == 'boom'
args.pop if args.is_a? Array
$invokes += 1
end
end
class MockWorker
include Sidekiq::Worker
def perform(args)
raise TEST_EXCEPTION if args.to_s == 'boom'
args.pop if args.is_a? Array
$invokes += 1
end
end
def work(msg, queue='queue:default')
Sidekiq::BasicFetch::UnitOfWork.new(queue, msg)
end
def work(msg, queue='queue:default')
Sidekiq::BasicFetch::UnitOfWork.new(queue, msg)
end
it 'processes as expected' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
@processor.process(work(msg))
assert_equal 1, $invokes
end
it 'processes as expected' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
it 'executes a worker as expected' do
worker = Minitest::Mock.new
worker.expect(:perform, nil, [1, 2, 3])
@processor.execute_job(worker, [1, 2, 3])
end
it 're-raises exceptions after handling' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
re_raise = false
begin
@processor.process(work(msg))
assert_equal 1, $invokes
flunk "Expected exception"
rescue TestProcessorException
re_raise = true
end
it 'executes a worker as expected' do
worker = Minitest::Mock.new
worker.expect(:perform, nil, [1, 2, 3])
@processor.execute_job(worker, [1, 2, 3])
assert_equal 0, $invokes
assert re_raise, "does not re-raise exceptions after handling"
end
it 'does not modify original arguments' do
msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
msgstr = Sidekiq.dump_json(msg)
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work(msgstr))
assert_equal [['myarg']], msg['args']
end
describe 'exception handling' do
let(:errors) { [] }
let(:error_handler) do
proc do |exception, context|
errors << { exception: exception, context: context }
end
end
it 're-raises exceptions after handling' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
re_raise = false
before do
Sidekiq.error_handlers << error_handler
end
after do
Sidekiq.error_handlers.pop
end
it 'handles invalid JSON' do
ds = Sidekiq::DeadSet.new
ds.clear
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
msg = Sidekiq.dump_json(job_hash)
job = work(msg[0...-2])
ds = Sidekiq::DeadSet.new
assert_equal 0, ds.size
begin
@processor.process(work(msg))
flunk "Expected exception"
rescue TestException
re_raise = true
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue JSON::ParserError
end
assert_equal 0, $invokes
assert re_raise, "does not re-raise exceptions after handling"
assert_equal 1, ds.size
end
it 'does not modify original arguments' do
msg = { 'class' => MockWorker.to_s, 'args' => [['myarg']] }
msgstr = Sidekiq.dump_json(msg)
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work(msgstr))
assert_equal [['myarg']], msg['args']
it 'handles exceptions raised by the job' do
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'], 'jid' => '123987123' }
msg = Sidekiq.dump_json(job_hash)
job = work(msg)
begin
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue TestProcessorException
end
assert_equal 1, errors.count
assert_instance_of TestProcessorException, errors.first[:exception]
assert_equal msg, errors.first[:context][:jobstr]
assert_equal job_hash['jid'], errors.first[:context][:job]['jid']
end
describe 'exception handling' do
let(:errors) { [] }
let(:error_handler) do
proc do |exception, context|
errors << { exception: exception, context: context }
it 'handles exceptions raised by the reloader' do
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
msg = Sidekiq.dump_json(job_hash)
@processor.instance_variable_set(:'@reloader', proc { raise TEST_PROC_EXCEPTION })
job = work(msg)
begin
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue TestProcessorException
end
assert_equal 1, errors.count
assert_instance_of TestProcessorException, errors.first[:exception]
assert_equal msg, errors.first[:context][:jobstr]
assert_equal job_hash, errors.first[:context][:job]
end
it 'handles exceptions raised during fetch' do
fetch_stub = lambda { raise StandardError, "fetch exception" }
# swallow logging because actually care about the added exception handler
capture_logging do
@processor.instance_variable_get('@strategy').stub(:retrieve_work, fetch_stub) do
@processor.process_one
end
end
before do
Sidekiq.error_handlers << error_handler
assert_instance_of StandardError, errors.last[:exception]
end
end
describe 'acknowledgement' do
class ExceptionRaisingMiddleware
def initialize(raise_before_yield, raise_after_yield, skip)
@raise_before_yield = raise_before_yield
@raise_after_yield = raise_after_yield
@skip = skip
end
after do
Sidekiq.error_handlers.pop
end
it 'handles invalid JSON' do
ds = Sidekiq::DeadSet.new
ds.clear
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
msg = Sidekiq.dump_json(job_hash)
job = work(msg[0...-2])
ds = Sidekiq::DeadSet.new
assert_equal 0, ds.size
begin
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue JSON::ParserError
end
assert_equal 1, ds.size
end
it 'handles exceptions raised by the job' do
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'], 'jid' => '123987123' }
msg = Sidekiq.dump_json(job_hash)
job = work(msg)
begin
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue TestException
end
assert_equal 1, errors.count
assert_instance_of TestException, errors.first[:exception]
assert_equal msg, errors.first[:context][:jobstr]
assert_equal job_hash['jid'], errors.first[:context][:job]['jid']
end
it 'handles exceptions raised by the reloader' do
job_hash = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
msg = Sidekiq.dump_json(job_hash)
@processor.instance_variable_set(:'@reloader', proc { raise TEST_EXCEPTION })
job = work(msg)
begin
@processor.instance_variable_set(:'@job', job)
@processor.process(job)
rescue TestException
end
assert_equal 1, errors.count
assert_instance_of TestException, errors.first[:exception]
assert_equal msg, errors.first[:context][:jobstr]
assert_equal job_hash, errors.first[:context][:job]
end
it 'handles exceptions raised during fetch' do
fetch_stub = lambda { raise StandardError, "fetch exception" }
# swallow logging because actually care about the added exception handler
capture_logging do
@processor.instance_variable_get('@strategy').stub(:retrieve_work, fetch_stub) do
@processor.process_one
end
end
assert_instance_of StandardError, errors.last[:exception]
def call(worker, item, queue)
raise TEST_PROC_EXCEPTION if @raise_before_yield
yield unless @skip
raise TEST_PROC_EXCEPTION if @raise_after_yield
end
end
describe 'acknowledgement' do
class ExceptionRaisingMiddleware
def initialize(raise_before_yield, raise_after_yield, skip)
@raise_before_yield = raise_before_yield
@raise_after_yield = raise_after_yield
@skip = skip
end
let(:raise_before_yield) { false }
let(:raise_after_yield) { false }
let(:skip_job) { false }
let(:worker_args) { ['myarg'] }
let(:work) { MiniTest::Mock.new }
def call(worker, item, queue)
raise TEST_EXCEPTION if @raise_before_yield
yield unless @skip
raise TEST_EXCEPTION if @raise_after_yield
end
before do
work.expect(:queue_name, 'queue:default')
work.expect(:job, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
Sidekiq.server_middleware do |chain|
chain.prepend ExceptionRaisingMiddleware, raise_before_yield, raise_after_yield, skip_job
end
end
let(:raise_before_yield) { false }
let(:raise_after_yield) { false }
let(:skip_job) { false }
let(:worker_args) { ['myarg'] }
let(:work) { MiniTest::Mock.new }
before do
work.expect(:queue_name, 'queue:default')
work.expect(:job, Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => worker_args }))
Sidekiq.server_middleware do |chain|
chain.prepend ExceptionRaisingMiddleware, raise_before_yield, raise_after_yield, skip_job
end
after do
Sidekiq.server_middleware do |chain|
chain.remove ExceptionRaisingMiddleware
end
work.verify
end
after do
Sidekiq.server_middleware do |chain|
chain.remove ExceptionRaisingMiddleware
end
work.verify
end
describe 'middleware throws an exception before processing the work' do
let(:raise_before_yield) { true }
describe 'middleware throws an exception before processing the work' do
let(:raise_before_yield) { true }
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestException
end
end
end
describe 'middleware throws an exception after processing the work' do
let(:raise_after_yield) { true }
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestException
end
end
end
describe 'middleware decides to skip work' do
let(:skip_job) { true }
it 'acks the job' do
work.expect(:acknowledge, nil)
@mgr.expect(:processor_done, nil, [@processor])
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestProcessorException
end
end
end
describe 'worker raises an exception' do
let(:worker_args) { ['boom'] }
describe 'middleware throws an exception after processing the work' do
let(:raise_after_yield) { true }
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestException
end
end
end
describe 'everything goes well' do
it 'acks the job' do
work.expect(:acknowledge, nil)
@mgr.expect(:processor_done, nil, [@processor])
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestProcessorException
end
end
end
describe 'retry' do
class ArgsMutatingServerMiddleware
def call(worker, item, queue)
item['args'] = item['args'].map do |arg|
arg.to_sym if arg.is_a?(String)
end
yield
end
describe 'middleware decides to skip work' do
let(:skip_job) { true }
it 'acks the job' do
work.expect(:acknowledge, nil)
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work)
end
end
class ArgsMutatingClientMiddleware
def call(worker, item, queue, redis_pool)
item['args'] = item['args'].map do |arg|
arg.to_s if arg.is_a?(Symbol)
end
yield
end
end
describe 'worker raises an exception' do
let(:worker_args) { ['boom'] }
before do
Sidekiq.server_middleware do |chain|
chain.prepend ArgsMutatingServerMiddleware
end
Sidekiq.client_middleware do |chain|
chain.prepend ArgsMutatingClientMiddleware
end
end
after do
Sidekiq.server_middleware do |chain|
chain.remove ArgsMutatingServerMiddleware
end
Sidekiq.client_middleware do |chain|
chain.remove ArgsMutatingClientMiddleware
end
end
describe 'middleware mutates the job args and then fails' do
it 'requeues with original arguments' do
job_data = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
retry_stub_called = false
retry_stub = lambda { |worker, msg, queue, exception|
retry_stub_called = true
assert_equal 'boom', msg['args'].first
}
@processor.instance_variable_get('@retrier').stub(:attempt_retry, retry_stub) do
msg = Sidekiq.dump_json(job_data)
begin
@processor.process(work(msg))
flunk "Expected exception"
rescue TestException
end
end
assert retry_stub_called
it 'acks the job' do
work.expect(:acknowledge, nil)
begin
@processor.process(work)
flunk "Expected #process to raise exception"
rescue TestProcessorException
end
end
end
describe 'stats' do
before do
Sidekiq.redis {|c| c.flushdb }
end
describe 'when successful' do
let(:processed_today_key) { "stat:processed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
def successful_job
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work(msg))
end
it 'increments processed stat' do
Sidekiq::Processor::PROCESSED.reset
successful_job
assert_equal 1, Sidekiq::Processor::PROCESSED.reset
end
end
describe 'when failed' do
let(:failed_today_key) { "stat:failed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
def failed_job
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
begin
@processor.process(work(msg))
rescue TestException
end
end
it 'increments failed stat' do
Sidekiq::Processor::FAILURE.reset
failed_job
assert_equal 1, Sidekiq::Processor::FAILURE.reset
end
end
end
describe 'custom job logger class' do
class CustomJobLogger
def call(item, queue)
yield
rescue Exception
raise
end
end
before do
@mgr = Minitest::Mock.new
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@processor = ::Sidekiq::Processor.new(@mgr)
end
it 'is called instead default Sidekiq::JobLogger' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
@processor.process(work(msg))
assert_equal 1, $invokes
@mgr.verify
describe 'everything goes well' do
it 'acks the job' do
work.expect(:acknowledge, nil)
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work)
end
end
end
describe 'retry' do
class ArgsMutatingServerMiddleware
def call(worker, item, queue)
item['args'] = item['args'].map do |arg|
arg.to_sym if arg.is_a?(String)
end
yield
end
end
class ArgsMutatingClientMiddleware
def call(worker, item, queue, redis_pool)
item['args'] = item['args'].map do |arg|
arg.to_s if arg.is_a?(Symbol)
end
yield
end
end
before do
Sidekiq.server_middleware do |chain|
chain.prepend ArgsMutatingServerMiddleware
end
Sidekiq.client_middleware do |chain|
chain.prepend ArgsMutatingClientMiddleware
end
end
after do
Sidekiq.server_middleware do |chain|
chain.remove ArgsMutatingServerMiddleware
end
Sidekiq.client_middleware do |chain|
chain.remove ArgsMutatingClientMiddleware
end
end
describe 'middleware mutates the job args and then fails' do
it 'requeues with original arguments' do
job_data = { 'class' => MockWorker.to_s, 'args' => ['boom'] }
retry_stub_called = false
retry_stub = lambda { |worker, msg, queue, exception|
retry_stub_called = true
assert_equal 'boom', msg['args'].first
}
@processor.instance_variable_get('@retrier').stub(:attempt_retry, retry_stub) do
msg = Sidekiq.dump_json(job_data)
begin
@processor.process(work(msg))
flunk "Expected exception"
rescue TestProcessorException
end
end
assert retry_stub_called
end
end
end
describe 'stats' do
before do
Sidekiq.redis {|c| c.flushdb }
end
describe 'when successful' do
let(:processed_today_key) { "stat:processed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
def successful_job
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
@mgr.expect(:processor_done, nil, [@processor])
@processor.process(work(msg))
end
it 'increments processed stat' do
Sidekiq::Processor::PROCESSED.reset
successful_job
assert_equal 1, Sidekiq::Processor::PROCESSED.reset
end
end
describe 'when failed' do
let(:failed_today_key) { "stat:failed:#{Time.now.utc.strftime("%Y-%m-%d")}" }
def failed_job
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['boom'] })
begin
@processor.process(work(msg))
rescue TestProcessorException
end
end
it 'increments failed stat' do
Sidekiq::Processor::FAILURE.reset
failed_job
assert_equal 1, Sidekiq::Processor::FAILURE.reset
end
end
end
describe 'custom job logger class' do
class CustomJobLogger
def call(item, queue)
yield
rescue Exception
raise
end
end
before do
@mgr = Minitest::Mock.new
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@mgr.expect(:options, {:queues => ['default'], :job_logger => CustomJobLogger})
@processor = ::Sidekiq::Processor.new(@mgr)
end
it 'is called instead default Sidekiq::JobLogger' do
msg = Sidekiq.dump_json({ 'class' => MockWorker.to_s, 'args' => ['myarg'] })
@processor.process(work(msg))
assert_equal 1, $invokes
@mgr.verify
end
end
end

View file

@ -1,22 +1,13 @@
# frozen_string_literal: true
require_relative 'helper'
require 'active_job'
$HAS_AJ = true
begin
require 'active_job'
rescue LoadError
$HAS_AJ = false
end
class TestRails < Minitest::Test
describe 'ActiveJob' do
it 'does not allow Sidekiq::Worker in AJ::Base classes' do
ex = assert_raises ArgumentError do
c = Class.new(ActiveJob::Base)
c.send(:include, Sidekiq::Worker)
end
assert_includes ex.message, "cannot include"
end if $HAS_AJ
describe 'ActiveJob' do
it 'does not allow Sidekiq::Worker in AJ::Base classes' do
ex = assert_raises ArgumentError do
c = Class.new(ActiveJob::Base)
c.send(:include, Sidekiq::Worker)
end
assert_includes ex.message, "cannot include"
end
end

View file

@ -3,8 +3,8 @@
require_relative 'helper'
require 'sidekiq/cli'
class TestRedisConnection < Minitest::Test
describe ".create" do
describe Sidekiq::RedisConnection do
describe "create" do
before do
Sidekiq.options = Sidekiq::DEFAULTS.dup
@old = ENV['REDIS_URL']

View file

@ -4,7 +4,7 @@ require_relative 'helper'
require 'sidekiq/scheduled'
require 'sidekiq/job_retry'
class TestRetry < Minitest::Test
describe Sidekiq::JobRetry do
describe 'middleware' do
class SomeWorker
include Sidekiq::Worker

View file

@ -2,179 +2,177 @@
require_relative 'helper'
require 'sidekiq/job_retry'
class TestRetryExhausted < Minitest::Test
describe 'sidekiq_retries_exhausted' do
class NewWorker
include Sidekiq::Worker
describe 'sidekiq_retries_exhausted' do
class NewWorker
include Sidekiq::Worker
sidekiq_class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
sidekiq_class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
sidekiq_retries_exhausted do |job, e|
self.exhausted_called = true
self.exhausted_job = job
self.exhausted_exception = e
sidekiq_retries_exhausted do |job, e|
self.exhausted_called = true
self.exhausted_job = job
self.exhausted_exception = e
end
end
class OldWorker
include Sidekiq::Worker
sidekiq_class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
sidekiq_retries_exhausted do |job|
self.exhausted_called = true
self.exhausted_job = job
end
end
def cleanup
[NewWorker, OldWorker].each do |worker_class|
worker_class.exhausted_called = nil
worker_class.exhausted_job = nil
worker_class.exhausted_exception = nil
end
end
before do
cleanup
end
after do
cleanup
end
def new_worker
@new_worker ||= NewWorker.new
end
def old_worker
@old_worker ||= OldWorker.new
end
def handler(options={})
@handler ||= Sidekiq::JobRetry.new(options)
end
def job(options={})
@job ||= {'class' => 'Bob', 'args' => [1, 2, 'foo']}.merge(options)
end
it 'does not run exhausted block when job successful on first run' do
handler.local(new_worker, job('retry' => 2), 'default') do
# successful
end
refute NewWorker.exhausted_called
end
it 'does not run exhausted block when job successful on last retry' do
handler.local(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
# successful
end
refute NewWorker.exhausted_called
end
it 'does not run exhausted block when retries not exhausted yet' do
assert_raises RuntimeError do
handler.local(new_worker, job('retry' => 1), 'default') do
raise 'kerblammo!'
end
end
class OldWorker
include Sidekiq::Worker
refute NewWorker.exhausted_called
end
sidekiq_class_attribute :exhausted_called, :exhausted_job, :exhausted_exception
sidekiq_retries_exhausted do |job|
self.exhausted_called = true
self.exhausted_job = job
end
end
def cleanup
[NewWorker, OldWorker].each do |worker_class|
worker_class.exhausted_called = nil
worker_class.exhausted_job = nil
worker_class.exhausted_exception = nil
end
end
before do
cleanup
end
after do
cleanup
end
def new_worker
@new_worker ||= NewWorker.new
end
def old_worker
@old_worker ||= OldWorker.new
end
def handler(options={})
@handler ||= Sidekiq::JobRetry.new(options)
end
def job(options={})
@job ||= {'class' => 'Bob', 'args' => [1, 2, 'foo']}.merge(options)
end
it 'does not run exhausted block when job successful on first run' do
handler.local(new_worker, job('retry' => 2), 'default') do
# successful
end
refute NewWorker.exhausted_called
end
it 'does not run exhausted block when job successful on last retry' do
it 'runs exhausted block when retries exhausted' do
assert_raises RuntimeError do
handler.local(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
# successful
raise 'kerblammo!'
end
refute NewWorker.exhausted_called
end
it 'does not run exhausted block when retries not exhausted yet' do
assert_raises RuntimeError do
handler.local(new_worker, job('retry' => 1), 'default') do
raise 'kerblammo!'
end
assert NewWorker.exhausted_called
end
it 'passes job and exception to retries exhausted block' do
raised_error = assert_raises RuntimeError do
handler.local(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert new_worker.exhausted_called
assert_equal raised_error.message, new_worker.exhausted_job['error_message']
assert_equal raised_error, new_worker.exhausted_exception
end
it 'passes job to retries exhausted block' do
raised_error = assert_raises RuntimeError do
handler.local(old_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert old_worker.exhausted_called
assert_equal raised_error.message, old_worker.exhausted_job['error_message']
assert_nil new_worker.exhausted_exception
end
it 'allows a global default handler' do
begin
class Foobar
include Sidekiq::Worker
end
refute NewWorker.exhausted_called
end
it 'runs exhausted block when retries exhausted' do
assert_raises RuntimeError do
handler.local(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
exhausted_job = nil
exhausted_exception = nil
Sidekiq.default_retries_exhausted = lambda do |job, ex|
exhausted_job = job
exhausted_exception = ex
end
assert NewWorker.exhausted_called
end
it 'passes job and exception to retries exhausted block' do
f = Foobar.new
raised_error = assert_raises RuntimeError do
handler.local(new_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
handler.local(f, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert new_worker.exhausted_called
assert_equal raised_error.message, new_worker.exhausted_job['error_message']
assert_equal raised_error, new_worker.exhausted_exception
assert exhausted_job
assert_equal raised_error, exhausted_exception
ensure
Sidekiq.default_retries_exhausted = nil
end
end
it 'passes job to retries exhausted block' do
it 'allows global failure handlers' do
begin
class Foobar
include Sidekiq::Worker
end
exhausted_job = nil
exhausted_exception = nil
Sidekiq.death_handlers.clear
Sidekiq.death_handlers << proc do |job, ex|
exhausted_job = job
exhausted_exception = ex
end
f = Foobar.new
raised_error = assert_raises RuntimeError do
handler.local(old_worker, job('retry_count' => 0, 'retry' => 1), 'default') do
handler.local(f, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert old_worker.exhausted_called
assert_equal raised_error.message, old_worker.exhausted_job['error_message']
assert_nil new_worker.exhausted_exception
end
it 'allows a global default handler' do
begin
class Foobar
include Sidekiq::Worker
end
exhausted_job = nil
exhausted_exception = nil
Sidekiq.default_retries_exhausted = lambda do |job, ex|
exhausted_job = job
exhausted_exception = ex
end
f = Foobar.new
raised_error = assert_raises RuntimeError do
handler.local(f, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert exhausted_job
assert_equal raised_error, exhausted_exception
ensure
Sidekiq.default_retries_exhausted = nil
end
end
it 'allows global failure handlers' do
begin
class Foobar
include Sidekiq::Worker
end
exhausted_job = nil
exhausted_exception = nil
Sidekiq.death_handlers.clear
Sidekiq.death_handlers << proc do |job, ex|
exhausted_job = job
exhausted_exception = ex
end
f = Foobar.new
raised_error = assert_raises RuntimeError do
handler.local(f, job('retry_count' => 0, 'retry' => 1), 'default') do
raise 'kerblammo!'
end
end
raised_error = raised_error.cause
assert exhausted_job
assert_equal raised_error, exhausted_exception
ensure
Sidekiq.death_handlers.clear
end
assert exhausted_job
assert_equal raised_error, exhausted_exception
ensure
Sidekiq.death_handlers.clear
end
end
end

View file

@ -2,7 +2,7 @@
require_relative 'helper'
require 'sidekiq/scheduled'
class TestScheduled < Minitest::Test
describe Sidekiq::Scheduled do
class ScheduledWorker
include Sidekiq::Worker
def perform(x)
@ -24,14 +24,14 @@ class TestScheduled < Minitest::Test
@poller = Sidekiq::Scheduled::Poller.new
end
class Stopper
class MyStopper
def call(worker_class, job, queue, r)
yield if job['args'].first.odd?
end
end
it 'executes client middleware' do
Sidekiq.client_middleware.add Stopper
Sidekiq.client_middleware.add MyStopper
begin
@retry.schedule (Time.now - 60).to_f, @error_1
@retry.schedule (Time.now - 60).to_f, @error_2
@ -45,7 +45,7 @@ class TestScheduled < Minitest::Test
assert_equal 0, Sidekiq::Queue.new("queue_5").size
assert_equal 1, Sidekiq::Queue.new("queue_6").size
ensure
Sidekiq.client_middleware.remove Stopper
Sidekiq.client_middleware.remove MyStopper
end
end

View file

@ -3,9 +3,9 @@ require_relative 'helper'
require 'sidekiq/scheduled'
require 'active_support/core_ext/integer/time'
class TestScheduling < Minitest::Test
describe 'job scheduling' do
describe 'middleware' do
class ScheduledWorker
class SomeScheduledWorker
include Sidekiq::Worker
sidekiq_options :queue => :custom_queue
def perform(x)
@ -23,25 +23,25 @@ class TestScheduling < Minitest::Test
assert_equal 0, ss.size
assert ScheduledWorker.perform_in(600, 'mike')
assert SomeScheduledWorker.perform_in(600, 'mike')
assert_equal 1, ss.size
assert ScheduledWorker.perform_in(1.month, 'mike')
assert SomeScheduledWorker.perform_in(1.month, 'mike')
assert_equal 2, ss.size
assert ScheduledWorker.perform_in(5.days.from_now, 'mike')
assert SomeScheduledWorker.perform_in(5.days.from_now, 'mike')
assert_equal 3, ss.size
q = Sidekiq::Queue.new("custom_queue")
qs = q.size
assert ScheduledWorker.perform_in(-300, 'mike')
assert SomeScheduledWorker.perform_in(-300, 'mike')
assert_equal 3, ss.size
assert_equal qs+1, q.size
assert Sidekiq::Client.push_bulk('class' => ScheduledWorker, 'args' => [['mike'], ['mike']], 'at' => 600)
assert Sidekiq::Client.push_bulk('class' => SomeScheduledWorker, 'args' => [['mike'], ['mike']], 'at' => 600)
assert_equal 5, ss.size
assert ScheduledWorker.perform_in(TimeDuck.new, 'samwise')
assert SomeScheduledWorker.perform_in(TimeDuck.new, 'samwise')
assert_equal 6, ss.size
end
@ -49,7 +49,7 @@ class TestScheduling < Minitest::Test
ss = Sidekiq::ScheduledSet.new
ss.clear
assert ScheduledWorker.perform_in(1.month, 'mike')
assert SomeScheduledWorker.perform_in(1.month, 'mike')
job = ss.first
assert job['created_at']
refute job['enqueued_at']

View file

@ -2,7 +2,7 @@
require_relative 'helper'
require 'sidekiq/cli'
class TestSidekiq < Minitest::Test
describe Sidekiq do
describe 'json processing' do
it 'handles json' do
assert_equal({"foo" => "bar"}, Sidekiq.load_json("{\"foo\":\"bar\"}"))

View file

@ -20,8 +20,8 @@ def output(section = 'all')
end
end
class TestSidekiqctl < Minitest::Test
describe 'sidekiqctl status' do
describe Sidekiqctl do
describe 'status' do
describe 'version' do
it 'displays the current Sidekiq version' do
assert_includes output, "Sidekiq #{Sidekiq::VERSION}"

View file

@ -1,83 +1,81 @@
# frozen_string_literal: true
require_relative 'helper'
class TestTesting < Minitest::Test
describe 'sidekiq testing' do
describe 'require/load sidekiq/testing.rb' do
before do
require 'sidekiq/testing'
end
after do
Sidekiq::Testing.disable!
end
it 'enables fake testing' do
Sidekiq::Testing.fake!
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.fake?
refute Sidekiq::Testing.inline?
end
it 'enables fake testing in a block' do
Sidekiq::Testing.disable!
assert Sidekiq::Testing.disabled?
refute Sidekiq::Testing.fake?
Sidekiq::Testing.fake! do
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.fake?
refute Sidekiq::Testing.inline?
end
refute Sidekiq::Testing.enabled?
refute Sidekiq::Testing.fake?
end
it 'disables testing in a block' do
Sidekiq::Testing.fake!
assert Sidekiq::Testing.fake?
Sidekiq::Testing.disable! do
refute Sidekiq::Testing.fake?
assert Sidekiq::Testing.disabled?
end
assert Sidekiq::Testing.fake?
assert Sidekiq::Testing.enabled?
end
describe 'Sidekiq::Testing' do
describe 'require/load sidekiq/testing.rb' do
before do
require 'sidekiq/testing'
end
describe 'require/load sidekiq/testing/inline.rb' do
before do
require 'sidekiq/testing/inline'
after do
Sidekiq::Testing.disable!
end
it 'enables fake testing' do
Sidekiq::Testing.fake!
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.fake?
refute Sidekiq::Testing.inline?
end
it 'enables fake testing in a block' do
Sidekiq::Testing.disable!
assert Sidekiq::Testing.disabled?
refute Sidekiq::Testing.fake?
Sidekiq::Testing.fake! do
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.fake?
refute Sidekiq::Testing.inline?
end
after do
Sidekiq::Testing.disable!
refute Sidekiq::Testing.enabled?
refute Sidekiq::Testing.fake?
end
it 'disables testing in a block' do
Sidekiq::Testing.fake!
assert Sidekiq::Testing.fake?
Sidekiq::Testing.disable! do
refute Sidekiq::Testing.fake?
assert Sidekiq::Testing.disabled?
end
it 'enables inline testing' do
Sidekiq::Testing.inline!
assert Sidekiq::Testing.fake?
assert Sidekiq::Testing.enabled?
end
end
describe 'require/load sidekiq/testing/inline.rb' do
before do
require 'sidekiq/testing/inline'
end
after do
Sidekiq::Testing.disable!
end
it 'enables inline testing' do
Sidekiq::Testing.inline!
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.inline?
refute Sidekiq::Testing.fake?
end
it 'enables inline testing in a block' do
Sidekiq::Testing.disable!
assert Sidekiq::Testing.disabled?
refute Sidekiq::Testing.fake?
Sidekiq::Testing.inline! do
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.inline?
refute Sidekiq::Testing.fake?
end
it 'enables inline testing in a block' do
Sidekiq::Testing.disable!
assert Sidekiq::Testing.disabled?
refute Sidekiq::Testing.fake?
Sidekiq::Testing.inline! do
assert Sidekiq::Testing.enabled?
assert Sidekiq::Testing.inline?
end
refute Sidekiq::Testing.enabled?
refute Sidekiq::Testing.inline?
refute Sidekiq::Testing.fake?
end
refute Sidekiq::Testing.enabled?
refute Sidekiq::Testing.inline?
refute Sidekiq::Testing.fake?
end
end

View file

@ -1,275 +1,273 @@
# frozen_string_literal: true
require_relative 'helper'
class TestFake < Minitest::Test
describe 'sidekiq testing' do
class PerformError < RuntimeError; end
describe 'Sidekiq::Testing.fake' do
class PerformError < RuntimeError; end
class DirectWorker
include Sidekiq::Worker
def perform(a, b)
a + b
end
class DirectWorker
include Sidekiq::Worker
def perform(a, b)
a + b
end
end
class EnqueuedWorker
include Sidekiq::Worker
def perform(a, b)
a + b
end
class EnqueuedWorker
include Sidekiq::Worker
def perform(a, b)
a + b
end
end
class StoredWorker
include Sidekiq::Worker
def perform(error)
raise PerformError if error
class StoredWorker
include Sidekiq::Worker
def perform(error)
raise PerformError if error
end
end
before do
require 'sidekiq/testing'
Sidekiq::Testing.fake!
EnqueuedWorker.jobs.clear
DirectWorker.jobs.clear
end
after do
Sidekiq::Testing.disable!
Sidekiq::Queues.clear_all
end
it 'stubs the async call' do
assert_equal 0, DirectWorker.jobs.size
assert DirectWorker.perform_async(1, 2)
assert_in_delta Time.now.to_f, DirectWorker.jobs.last['enqueued_at'], 0.1
assert_equal 1, DirectWorker.jobs.size
assert DirectWorker.perform_in(10, 1, 2)
refute DirectWorker.jobs.last['enqueued_at']
assert_equal 2, DirectWorker.jobs.size
assert DirectWorker.perform_at(10, 1, 2)
assert_equal 3, DirectWorker.jobs.size
assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.1
end
describe 'delayed' do
require 'action_mailer'
class FooMailer < ActionMailer::Base
def bar(str)
str
end
end
before do
require 'sidekiq/testing'
Sidekiq::Testing.fake!
EnqueuedWorker.jobs.clear
DirectWorker.jobs.clear
Sidekiq::Extensions.enable_delay!
end
after do
Sidekiq::Testing.disable!
Sidekiq::Queues.clear_all
it 'stubs the delay call on mailers' do
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
FooMailer.delay.bar('hello!')
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
end
it 'stubs the async call' do
assert_equal 0, DirectWorker.jobs.size
assert DirectWorker.perform_async(1, 2)
assert_in_delta Time.now.to_f, DirectWorker.jobs.last['enqueued_at'], 0.1
assert_equal 1, DirectWorker.jobs.size
assert DirectWorker.perform_in(10, 1, 2)
refute DirectWorker.jobs.last['enqueued_at']
assert_equal 2, DirectWorker.jobs.size
assert DirectWorker.perform_at(10, 1, 2)
assert_equal 3, DirectWorker.jobs.size
assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.1
end
describe 'delayed' do
require 'action_mailer'
class FooMailer < ActionMailer::Base
def bar(str)
str
end
end
before do
Sidekiq::Extensions.enable_delay!
end
it 'stubs the delay call on mailers' do
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
FooMailer.delay.bar('hello!')
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
end
class Something
def self.foo(x)
end
end
it 'stubs the delay call on classes' do
assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size
Something.delay.foo(Date.today)
assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size
class Something
def self.foo(x)
end
end
it 'stubs the enqueue call' do
assert_equal 0, EnqueuedWorker.jobs.size
assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2)
assert_equal 1, EnqueuedWorker.jobs.size
it 'stubs the delay call on classes' do
assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size
Something.delay.foo(Date.today)
assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size
end
end
it 'stubs the enqueue_to call' do
assert_equal 0, EnqueuedWorker.jobs.size
assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2)
assert_equal 1, Sidekiq::Queues['someq'].size
it 'stubs the enqueue call' do
assert_equal 0, EnqueuedWorker.jobs.size
assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2)
assert_equal 1, EnqueuedWorker.jobs.size
end
it 'stubs the enqueue_to call' do
assert_equal 0, EnqueuedWorker.jobs.size
assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2)
assert_equal 1, Sidekiq::Queues['someq'].size
end
it 'executes all stored jobs' do
assert StoredWorker.perform_async(false)
assert StoredWorker.perform_async(true)
assert_equal 2, StoredWorker.jobs.size
assert_raises PerformError do
StoredWorker.drain
end
assert_equal 0, StoredWorker.jobs.size
end
it 'executes all stored jobs' do
assert StoredWorker.perform_async(false)
assert StoredWorker.perform_async(true)
assert_equal 2, StoredWorker.jobs.size
assert_raises PerformError do
StoredWorker.drain
end
assert_equal 0, StoredWorker.jobs.size
class SpecificJidWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform(worker_jid)
return unless worker_jid == self.jid
self.class.count += 1
end
end
class SpecificJidWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform(worker_jid)
return unless worker_jid == self.jid
self.class.count += 1
it 'execute only jobs with assigned JID' do
4.times do |i|
jid = SpecificJidWorker.perform_async(nil)
if i % 2 == 0
SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"]
else
SpecificJidWorker.jobs[-1]["args"] = [jid]
end
end
it 'execute only jobs with assigned JID' do
4.times do |i|
jid = SpecificJidWorker.perform_async(nil)
if i % 2 == 0
SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"]
else
SpecificJidWorker.jobs[-1]["args"] = [jid]
end
end
SpecificJidWorker.perform_one
assert_equal 0, SpecificJidWorker.count
SpecificJidWorker.perform_one
assert_equal 0, SpecificJidWorker.count
SpecificJidWorker.perform_one
assert_equal 1, SpecificJidWorker.count
SpecificJidWorker.perform_one
assert_equal 1, SpecificJidWorker.count
SpecificJidWorker.drain
assert_equal 2, SpecificJidWorker.count
end
SpecificJidWorker.drain
assert_equal 2, SpecificJidWorker.count
end
it 'round trip serializes the job arguments' do
assert StoredWorker.perform_async(:mike)
job = StoredWorker.jobs.first
assert_equal "mike", job['args'].first
StoredWorker.clear
end
it 'round trip serializes the job arguments' do
assert StoredWorker.perform_async(:mike)
job = StoredWorker.jobs.first
assert_equal "mike", job['args'].first
StoredWorker.clear
end
it 'perform_one runs only one job' do
DirectWorker.perform_async(1, 2)
DirectWorker.perform_async(3, 4)
assert_equal 2, DirectWorker.jobs.size
it 'perform_one runs only one job' do
DirectWorker.perform_async(1, 2)
DirectWorker.perform_async(3, 4)
assert_equal 2, DirectWorker.jobs.size
DirectWorker.perform_one
assert_equal 1, DirectWorker.jobs.size
DirectWorker.clear
end
it 'perform_one raise error upon empty queue' do
DirectWorker.clear
assert_raises Sidekiq::EmptyQueueError do
DirectWorker.perform_one
assert_equal 1, DirectWorker.jobs.size
DirectWorker.clear
end
end
it 'perform_one raise error upon empty queue' do
DirectWorker.clear
assert_raises Sidekiq::EmptyQueueError do
DirectWorker.perform_one
end
class FirstWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform
self.class.count += 1
end
end
class FirstWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform
self.class.count += 1
end
class SecondWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform
self.class.count += 1
end
end
class SecondWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
self.count = 0
def perform
self.class.count += 1
end
end
class ThirdWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
def perform
FirstWorker.perform_async
SecondWorker.perform_async
end
end
it 'clears jobs across all workers' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
class ThirdWorker
include Sidekiq::Worker
sidekiq_class_attribute :count
def perform
FirstWorker.perform_async
SecondWorker.perform_async
assert_equal 1, FirstWorker.jobs.size
assert_equal 1, SecondWorker.jobs.size
Sidekiq::Worker.clear_all
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
end
end
it 'drains jobs across all workers' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
it 'clears jobs across all workers' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
FirstWorker.perform_async
SecondWorker.perform_async
FirstWorker.perform_async
SecondWorker.perform_async
assert_equal 1, FirstWorker.jobs.size
assert_equal 1, SecondWorker.jobs.size
assert_equal 1, FirstWorker.jobs.size
assert_equal 1, SecondWorker.jobs.size
Sidekiq::Worker.clear_all
Sidekiq::Worker.drain_all
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
end
assert_equal 1, FirstWorker.count
assert_equal 1, SecondWorker.count
end
it 'drains jobs across all workers' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
it 'drains jobs across all workers even when workers create new jobs' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, ThirdWorker.jobs.size
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
FirstWorker.perform_async
SecondWorker.perform_async
ThirdWorker.perform_async
assert_equal 1, FirstWorker.jobs.size
assert_equal 1, SecondWorker.jobs.size
assert_equal 1, ThirdWorker.jobs.size
Sidekiq::Worker.drain_all
Sidekiq::Worker.drain_all
assert_equal 0, FirstWorker.jobs.size
assert_equal 0, SecondWorker.jobs.size
assert_equal 0, ThirdWorker.jobs.size
assert_equal 1, FirstWorker.count
assert_equal 1, SecondWorker.count
end
assert_equal 1, FirstWorker.count
assert_equal 1, SecondWorker.count
end
it 'drains jobs across all workers even when workers create new jobs' do
Sidekiq::Worker.jobs.clear
FirstWorker.count = 0
SecondWorker.count = 0
it 'drains jobs of workers with symbolized queue names' do
Sidekiq::Worker.jobs.clear
assert_equal 0, ThirdWorker.jobs.size
AltQueueWorker.perform_async(5,6)
assert_equal 1, AltQueueWorker.jobs.size
assert_equal 0, FirstWorker.count
assert_equal 0, SecondWorker.count
Sidekiq::Worker.drain_all
assert_equal 0, AltQueueWorker.jobs.size
end
ThirdWorker.perform_async
it 'can execute a job' do
DirectWorker.execute_job(DirectWorker.new, [2, 3])
end
assert_equal 1, ThirdWorker.jobs.size
Sidekiq::Worker.drain_all
assert_equal 0, ThirdWorker.jobs.size
assert_equal 1, FirstWorker.count
assert_equal 1, SecondWorker.count
end
it 'drains jobs of workers with symbolized queue names' do
Sidekiq::Worker.jobs.clear
AltQueueWorker.perform_async(5,6)
assert_equal 1, AltQueueWorker.jobs.size
Sidekiq::Worker.drain_all
assert_equal 0, AltQueueWorker.jobs.size
end
it 'can execute a job' do
DirectWorker.execute_job(DirectWorker.new, [2, 3])
end
describe 'queue testing' do

View file

@ -1,93 +1,91 @@
# frozen_string_literal: true
require_relative 'helper'
class TestInline < Minitest::Test
describe 'sidekiq inline testing' do
class InlineError < RuntimeError; end
class ParameterIsNotString < RuntimeError; end
describe 'Sidekiq::Testing.inline' do
class InlineError < RuntimeError; end
class ParameterIsNotString < RuntimeError; end
class InlineWorker
include Sidekiq::Worker
def perform(pass)
raise ArgumentError, "no jid" unless jid
raise InlineError unless pass
class InlineWorker
include Sidekiq::Worker
def perform(pass)
raise ArgumentError, "no jid" unless jid
raise InlineError unless pass
end
end
class InlineWorkerWithTimeParam
include Sidekiq::Worker
def perform(time)
raise ParameterIsNotString unless time.is_a?(String) || time.is_a?(Numeric)
end
end
before do
require 'sidekiq/testing/inline'
Sidekiq::Testing.inline!
end
after do
Sidekiq::Testing.disable!
end
it 'stubs the async call when in testing mode' do
assert InlineWorker.perform_async(true)
assert_raises InlineError do
InlineWorker.perform_async(false)
end
end
describe 'delay' do
require 'action_mailer'
class InlineFooMailer < ActionMailer::Base
def bar(str)
raise InlineError
end
end
class InlineWorkerWithTimeParam
include Sidekiq::Worker
def perform(time)
raise ParameterIsNotString unless time.is_a?(String) || time.is_a?(Numeric)
class InlineFooModel
def self.bar(str)
raise InlineError
end
end
before do
require 'sidekiq/testing/inline'
Sidekiq::Testing.inline!
Sidekiq::Extensions.enable_delay!
end
after do
Sidekiq::Testing.disable!
end
it 'stubs the async call when in testing mode' do
assert InlineWorker.perform_async(true)
it 'stubs the delay call on mailers' do
assert_raises InlineError do
InlineWorker.perform_async(false)
InlineFooMailer.delay.bar('three')
end
end
describe 'delay' do
require 'action_mailer'
class InlineFooMailer < ActionMailer::Base
def bar(str)
raise InlineError
end
end
class InlineFooModel
def self.bar(str)
raise InlineError
end
end
before do
Sidekiq::Extensions.enable_delay!
end
it 'stubs the delay call on mailers' do
assert_raises InlineError do
InlineFooMailer.delay.bar('three')
end
end
it 'stubs the delay call on models' do
assert_raises InlineError do
InlineFooModel.delay.bar('three')
end
end
end
it 'stubs the enqueue call when in testing mode' do
assert Sidekiq::Client.enqueue(InlineWorker, true)
it 'stubs the delay call on models' do
assert_raises InlineError do
Sidekiq::Client.enqueue(InlineWorker, false)
InlineFooModel.delay.bar('three')
end
end
it 'stubs the push_bulk call when in testing mode' do
assert Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [true]]})
assert_raises InlineError do
Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [false]]})
end
end
it 'should relay parameters through json' do
assert Sidekiq::Client.enqueue(InlineWorkerWithTimeParam, Time.now.to_f)
end
end
it 'stubs the enqueue call when in testing mode' do
assert Sidekiq::Client.enqueue(InlineWorker, true)
assert_raises InlineError do
Sidekiq::Client.enqueue(InlineWorker, false)
end
end
it 'stubs the push_bulk call when in testing mode' do
assert Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [true]]})
assert_raises InlineError do
Sidekiq::Client.push_bulk({'class' => InlineWorker, 'args' => [[true], [false]]})
end
end
it 'should relay parameters through json' do
assert Sidekiq::Client.enqueue(InlineWorkerWithTimeParam, Time.now.to_f)
end
end

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ require_relative 'helper'
require 'sidekiq/web'
class TestWebHelpers < Minitest::Test
raise 'boom'
class Helpers
include Sidekiq::WebHelpers