Skip to content
Permalink
Browse files
Use mock redis.
This will help out with mocking Redis for our new tests, and
makes our tests a teeny bit faster.

Fixes #886
  • Loading branch information
yaauie authored and steveklabnik committed Apr 9, 2013
1 parent 55d54cd commit 06de642abaeec446d17c440aed60d3ef04e3ca8d
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 52 deletions.
@@ -22,6 +22,8 @@ Gem::Specification.new do |s|
s.add_dependency "json"
s.add_dependency "mono_logger", "~> 1.0"

s.add_development_dependency "mock_redis", " ~> 0.7.0"

s.description = %s{
Resque is a Redis-backed Ruby library for creating background jobs,
placing those jobs on multiple queues, and processing them later.}
@@ -36,19 +36,29 @@
end
end

require 'mock_redis'
puts "Using a mock Redis"
r = MockRedis.new :host => "localhost", :port => 9736, :db => 0
$mock_redis = Redis::Namespace.new :resque, :redis => r

# this gets set up based on the two keys below
$real_reids = nil

if ENV.key? 'RESQUE_DISTRIBUTED'
require 'redis/distributed'
puts "Starting redis for testing at localhost:9736 and localhost:9737..."
`redis-server #{$dir}/redis-test.conf`
`redis-server #{$dir}/redis-test-cluster.conf`
r = Redis::Distributed.new(['redis://localhost:9736', 'redis://localhost:9737'])
Resque.redis = Redis::Namespace.new :resque, :redis => r
$real_redis = Redis::Namespace.new :resque, :redis => r
else
puts "Starting redis for testing at localhost:9736..."
`redis-server #{$dir}/redis-test.conf`
Resque.redis = 'localhost:9736'
$real_redis = 'localhost:9736'
end

Resque.redis = $mock_redis

class DummyLogger
attr_reader :messages

@@ -15,21 +15,38 @@

@worker = Resque::Worker.new(:jobs, test_options)
Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
Resque::Worker.__send__(:public, :pause_processing)
Resque::Worker.__send__(:public, :will_fork?)
Resque::Worker.__send__(:public, :reserve)
end

it "can fail jobs" do
Resque::Job.create(:jobs, BadJob)
@worker.work
assert_equal 1, Resque::Failure.count
# This test forks, so we will use the real redis
Resque.redis = $real_redis
Resque.redis.flushall

begin
Resque::Job.create(:jobs, BadJob)
@worker.work
assert_equal 1, Resque::Failure.count
ensure
Resque.redis = $mock_redis
end
end

it "failed jobs report exception and message" do
Resque::Job.create(:jobs, BadJobWithSyntaxError)
@worker.work
assert_equal('SyntaxError', Resque::Failure.all['exception'])
assert_equal('Extra Bad job!', Resque::Failure.all['error'])
# we fork, so let's use real redis
Resque.redis = $real_redis
Resque.redis.flushall

begin
Resque::Job.create(:jobs, BadJobWithSyntaxError)
@worker.work
assert_equal('SyntaxError', Resque::Failure.all['exception'])
assert_equal('Extra Bad job!', Resque::Failure.all['error'])
ensure
Resque.redis = $mock_redis
end
end

it "unavailable job definition reports exception and message" do
@@ -163,28 +180,52 @@ def self.perform
end

it "can peek at failed jobs" do
10.times { Resque::Job.create(:jobs, BadJob) }
@worker.work
assert_equal 10, Resque::Failure.count
# This test forks so we'll use the real redis
Resque.redis = $real_redis
Resque.redis.flushall

assert_equal 10, Resque::Failure.all(0, 20).size
begin
10.times { Resque::Job.create(:jobs, BadJob) }
@worker.work
assert_equal 10, Resque::Failure.count

assert_equal 10, Resque::Failure.all(0, 20).size
ensure
Resque.redis = $mock_redis
end
end

it "can clear failed jobs" do
Resque::Job.create(:jobs, BadJob)
@worker.work
assert_equal 1, Resque::Failure.count
Resque::Failure.clear
assert_equal 0, Resque::Failure.count
# This test forks so we'll use the real redis
Resque.redis = $real_redis
Resque.redis.flushall

begin
Resque::Job.create(:jobs, BadJob)
@worker.work
assert_equal 1, Resque::Failure.count
Resque::Failure.clear
assert_equal 0, Resque::Failure.count
ensure
Resque.redis = $mock_redis
end
end

it "catches exceptional jobs" do
Resque::Job.create(:jobs, BadJob)
Resque::Job.create(:jobs, BadJob)
@worker.process
@worker.process
@worker.process
assert_equal 2, Resque::Failure.count
# This test forks so we'll use the real redis
Resque.redis = $real_redis
Resque.redis.flushall

begin
Resque::Job.create(:jobs, BadJob)
Resque::Job.create(:jobs, BadJob)
@worker.process
@worker.process
@worker.process
assert_equal 2, Resque::Failure.count
ensure
Resque.redis = $mock_redis
end
end

it "strips whitespace from queue names" do
@@ -308,12 +349,20 @@ def self.perform
end

it "fails if a job class has no `perform` method" do
worker = Resque::Worker.new(:perform_less, test_options)
Resque::Job.create(:perform_less, Object)
# This test forks so let's use real redis
Resque.redis = $real_redis
Resque.redis.flushall

assert_equal 0, Resque::Failure.count
worker.work
assert_equal 1, Resque::Failure.count
begin
worker = Resque::Worker.new(:perform_less, test_options)
Resque::Job.create(:perform_less, Object)

assert_equal 0, Resque::Failure.count
worker.work
assert_equal 1, Resque::Failure.count
ensure
Resque.redis = $mock_redis
end
end

it "inserts itself into the 'workers' list on startup" do
@@ -383,10 +432,21 @@ def self.perform
end

it "reserve blocks when the queue is empty" do
worker = Resque::Worker.new(:timeout, test_options)
# due to difference in behavior regarding timeouts, let's
# use real redis
Resque.redis = $real_redis
Resque.redis.flushall

assert_raises Timeout::Error do
Timeout.timeout(1) { worker.reserve(5) }
begin
worker = Resque::Worker.new(:timeout, test_options)

# In MockRedis, this will return nil rather than throwing
# the timeout error.
assert_raises Timeout::Error do
Timeout.timeout(1) { worker.reserve(5) }
end
ensure
Resque.redis = $mock_redis
end
end

@@ -535,17 +595,23 @@ def self.perform
end

it "Will call an after_fork hook after forking" do
# we fork, therefore, real redis
Resque.redis = $real_redis
Resque.redis.flushall

msg = "called!"
Resque.after_fork = Proc.new { Resque.redis.set("after_fork", msg) }
workerA = Resque::Worker.new(:jobs, test_options)
begin
msg = "called!"
Resque.after_fork = Proc.new { Resque.redis.set("after_fork", msg) }
workerA = Resque::Worker.new(:jobs, test_options)

Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
Resque::Job.create(:jobs, SomeJob, 20, '/tmp')

workerA.work
val = Resque.redis.get("after_fork")
assert_equal val, msg
workerA.work
val = Resque.redis.get("after_fork")
assert_equal val, msg
ensure
Resque.redis = $mock_redis
end
end

it "Will not call an after_fork hook when the worker can't fork" do
@@ -657,26 +723,35 @@ class Resque::Worker
end

it "will call before_pause before it is paused" do
before_pause_called = false
captured_worker = nil
# this test is kinda weird and complex, so let's punt
# and use real redis to make sure we don't break stuff
Resque.redis = $real_redis
Resque.redis.flushall

Resque.before_pause do |worker|
before_pause_called = true
captured_worker = worker
end
begin
before_pause_called = false
captured_worker = nil

@worker.pause_processing
Resque.before_pause do |worker|
before_pause_called = true
captured_worker = worker
end

assert !before_pause_called
@worker.pause_processing

t = Thread.start { sleep(0.1); Process.kill('CONT', @worker.pid) }
assert !before_pause_called

@worker.work
t = Thread.start { sleep(0.1); Process.kill('CONT', @worker.pid) }

t.join
@worker.work

assert before_pause_called
assert_equal @worker, captured_worker
t.join

assert before_pause_called
assert_equal @worker, captured_worker
ensure
Resque.redis = $mock_redis
end
end

it "will call after_pause after it is paused" do
@@ -710,6 +785,7 @@ class Resque::Worker
}.each do |scenario,rescue_time|
it "SIGTERM when #{scenario} while catching #{exception}" do
begin
Resque.redis = $real_redis
eval("class LongRunningJob; @@exception = #{exception}; end")
class LongRunningJob
@queue = :long_running_job
@@ -770,6 +846,7 @@ def self.perform( run_time, rescue_time=nil )
ensure
remaining_keys = Resque.redis.keys('sigterm-test:*') || []
Resque.redis.del(*remaining_keys) unless remaining_keys.empty?
Resque.redis = $mock_redis
end
end
end

0 comments on commit 06de642

Please sign in to comment.