require File.dirname(__FILE__) + '/test_helper' context "Resque" do setup do Resque.drop Resque.bypass_queues = false Resque.enable_delay(:delayed) Resque.push(:people, { 'name' => 'chris' }) Resque.push(:people, { 'name' => 'bob' }) Resque.push(:people, { 'name' => 'mark' }) end test "can set a namespace through a url-like string" do assert Resque.mongo assert_equal 'resque', Resque.mongo.name Resque.mongo = 'localhost:27017/namespace' assert_equal 'namespace', Resque.mongo.name end test "can put jobs on a queue" do assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') end test "can grab jobs off a queue" do Resque::Job.create(:jobs, 'some-job', 20, '/tmp') job = Resque.reserve(:jobs) assert_kind_of Resque::Job, job assert_equal SomeJob, job.payload_class assert_equal 20, job.args[0] assert_equal '/tmp', job.args[1] end test "can re-queue jobs" do Resque::Job.create(:jobs, 'some-job', 20, '/tmp') job = Resque.reserve(:jobs) job.recreate assert_equal job, Resque.reserve(:jobs) end test "can put jobs on a queue by way of an ivar" do assert_equal 0, Resque.size(:ivar) assert Resque.enqueue(SomeIvarJob, 20, '/tmp') assert Resque.enqueue(SomeIvarJob, 20, '/tmp') job = Resque.reserve(:ivar) assert_kind_of Resque::Job, job assert_equal SomeIvarJob, job.payload_class assert_equal 20, job.args[0] assert_equal '/tmp', job.args[1] assert Resque.reserve(:ivar) assert_equal nil, Resque.reserve(:ivar) end test "can remove jobs from a queue by way of an ivar" do assert_equal 0, Resque.size(:ivar) assert Resque.enqueue(SomeIvarJob, 20, '/tmp') assert Resque.enqueue(SomeIvarJob, 30, '/tmp') assert Resque.enqueue(SomeIvarJob, 20, '/tmp') assert Resque::Job.create(:ivar, 'blah-job', 20, '/tmp') assert Resque.enqueue(SomeIvarJob, 20, '/tmp') assert_equal 5, Resque.size(:ivar) assert Resque.dequeue(SomeIvarJob, 30, '/tmp') assert_equal 4, Resque.size(:ivar) assert Resque.dequeue(SomeIvarJob) assert_equal 1, Resque.size(:ivar) end test "jobs have a nice #inspect" do assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') job = Resque.reserve(:jobs) assert_equal '(Job{jobs} | SomeJob | [20, "/tmp"])', job.inspect end test "jobs can be destroyed" do assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'BadJob', 30, '/tmp') assert Resque::Job.create(:jobs, 'BadJob', 20, '/tmp') assert_equal 5, Resque.size(:jobs) assert_equal 2, Resque::Job.destroy(:jobs, 'SomeJob') assert_equal 3, Resque.size(:jobs) assert_equal 1, Resque::Job.destroy(:jobs, 'BadJob', 30, '/tmp') assert_equal 2, Resque.size(:jobs) end test "jobs can test for equality" do assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'some-job', 20, '/tmp') assert_equal Resque.reserve(:jobs), Resque.reserve(:jobs) assert Resque::Job.create(:jobs, 'SomeMethodJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs) assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp') assert Resque::Job.create(:jobs, 'SomeJob', 30, '/tmp') assert_not_equal Resque.reserve(:jobs), Resque.reserve(:jobs) end test "can put jobs on a queue by way of a method" do assert_equal 0, Resque.size(:method) assert Resque.enqueue(SomeMethodJob, 20, '/tmp') assert Resque.enqueue(SomeMethodJob, 20, '/tmp') job = Resque.reserve(:method) assert_kind_of Resque::Job, job assert_equal SomeMethodJob, job.payload_class assert_equal 20, job.args[0] assert_equal '/tmp', job.args[1] assert Resque.reserve(:method) assert_equal nil, Resque.reserve(:method) end test "needs to infer a queue with enqueue" do assert_raises Resque::NoQueueError do Resque.enqueue(SomeJob, 20, '/tmp') end end test "can put items on a queue" do assert Resque.push(:people, { 'name' => 'jon' }) end def pop_no_id(queue) item = Resque.pop(queue) item.delete("_id") item end test "can pull items off a queue" do assert_equal('chris', pop_no_id(:people)['name']) assert_equal('bob', pop_no_id(:people)['name']) assert_equal('mark', pop_no_id(:people)['name']) assert_equal nil, Resque.pop(:people) end test "knows how big a queue is" do assert_equal 3, Resque.size(:people) assert_equal('chris', pop_no_id(:people)['name']) assert_equal 2, Resque.size(:people) assert_equal('bob', pop_no_id(:people)['name']) assert_equal('mark', pop_no_id(:people)['name']) assert_equal 0, Resque.size(:people) end test "can peek at a queue" do peek = Resque.peek(:people) peek.delete "_id" assert_equal('chris', peek['name']) assert_equal 3, Resque.size(:people) end test "can peek multiple items on a queue" do assert_equal('bob', Resque.peek(:people, 1, 1)['name']) peek = Resque.peek(:people, 1, 2).map { |hash| { 'name' => hash['name']}} assert_equal([{ 'name' => 'bob' }, { 'name' => 'mark' }], peek) peek = Resque.peek(:people, 0, 2).map { |hash| { 'name' => hash['name']} } assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }], peek) peek = Resque.peek(:people, 0, 3).map { |hash| { 'name' => hash['name']} } assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }, { 'name' => 'mark' }], peek) peek = Resque.peek(:people, 2, 1) assert_equal('mark', peek['name']) assert_equal nil, Resque.peek(:people, 3) assert_equal [], Resque.peek(:people, 3, 2) end test "knows what queues it is managing" do assert_equal %w( people ), Resque.queues Resque.push(:cars, { 'make' => 'bmw' }) assert_equal %w( cars people ), Resque.queues.sort end test "queues are always a list" do Resque.drop assert_equal [], Resque.queues end test "can delete a queue" do Resque.push(:cars, { 'make' => 'bmw' }) assert_equal %w( cars people ), Resque.queues.sort Resque.remove_queue(:people) assert_equal %w( cars ), Resque.queues assert_equal nil, Resque.pop(:people) end test "keeps track of resque keys" do assert Resque.keys.include? 'people' end test "badly wants a class name, too" do assert_raises Resque::NoClassError do Resque::Job.create(:jobs, nil) end end test "keeps stats" do Resque::Job.create(:jobs, SomeJob, 20, '/tmp') Resque::Job.create(:jobs, BadJob) Resque::Job.create(:jobs, GoodJob) Resque::Job.create(:others, GoodJob) Resque::Job.create(:others, GoodJob) stats = Resque.info assert_equal 8, stats[:pending] @worker = Resque::Worker.new(:jobs) @worker.register_worker 2.times { @worker.process } job = @worker.reserve @worker.working_on job stats = Resque.info assert_equal 1, stats[:working] assert_equal 1, stats[:workers] @worker.done_working stats = Resque.info assert_equal 3, stats[:queues] assert_equal 3, stats[:processed] assert_equal 1, stats[:failed] # assert_equal [Resque.redis.respond_to?(:server) ? 'localhost:9736' : 'redis://localhost:9736/0'], stats[:servers] end test "decode bad json" do assert_nil Resque.decode("{\"error\":\"Module not found \\u002\"}") end test "unique jobs are unique" do #does uniqueness work? Resque.enqueue(UniqueJob, {:_id => 'my_id', :arg1=> 'my args1'}) assert_equal(1, Resque.size(:unique)) assert_equal('my args1', Resque.peek(:unique)['args'][0]['arg1']) assert_equal('my_id', Resque.peek(:unique)['args'][0]['_id']) Resque.enqueue(UniqueJob, {:_id => 'my_id', :arg1=> 'my args2'}) assert_equal(1, Resque.size(:unique)) assert_equal('my args2', Resque.peek(:unique)['args'][0]['arg1']) #if I enqueue unique jobs with the same key in 2 queues, do I get 2 jobs? Resque.enqueue(UniqueJob, {:_id => 'my_id3', :arg1=> 'my arg3'}) assert_equal(2, Resque.size(:unique)) Resque.enqueue(OtherUnique, {:_id => 'my_id3', :arg1=> 'my args4'}) #following line fails because :unique and :unique2 are in the same collection #\assert_equal(2, Resque.size(:unique)) assert_equal(1, Resque.size(:unique2)) #can I enqueue normal jobs in the unique queue? Resque.enqueue(NonUnique, {:arg1=> 'my args'}) assert_equal(3, Resque.size(:unique)) Resque.enqueue(NonUnique, {:_id => 'my_id', :_id => 'my_id', :arg1=> 'my args2'}) assert_equal(4, Resque.size(:unique)) #how do unique jobs work without a given _id? Resque.enqueue(UniqueJob, {:arg1=> 'my args3'}) assert_equal(5, Resque.size(:unique)) assert_equal('my args3', Resque.peek(:unique, 4)['args'][0]['arg1']) Resque.enqueue(UniqueJob, {:arg1=> 'my args4'}) assert_equal(6, Resque.size(:unique)) assert_equal('my args4', Resque.peek(:unique, 5)['args'][0]['arg1']) end test "Can bypass queues for testing" do Resque.enqueue(NonUnique, 'test') assert_equal(1, Resque.size(:unique)) Resque.bypass_queues = true Resque.enqueue(NonUnique, 'test') assert_equal(1, Resque.size(:unique)) Resque.bypass_queues = false Resque.enqueue(NonUnique, 'test') assert_equal(2, Resque.size(:unique)) end test "delayed jobs work" do args = { :delay_until => Time.new-1} Resque.enqueue(DelayedJob, args) job = Resque::Job.reserve(:delayed) assert_equal(1, job.args[0].keys.length) assert_equal(args[:delay_until].to_i, job.args[0]["delay_until"].to_i) args[:delay_until] = Time.new + 2 assert_equal(0, Resque.delayed_size(:delayed)) Resque.enqueue(DelayedJob, args) assert_equal(1, Resque.delayed_size(:delayed)) assert_nil Resque.peek(:delayed) assert_nil Resque::Job.reserve(:delayed) sleep 1 assert_nil Resque::Job.reserve(:delayed) sleep 1 assert_equal(DelayedJob, Resque::Job.reserve(:delayed).payload_class) end test "delayed unique jobs modify args in place" do args = { :delay_until => Time.new + 3600, :_id => 'unique'} Resque.enqueue(DelayedJob, args) assert_nil(Resque.peek(:delayed)) args[:delay_until] = Time.new - 1 Resque.enqueue(DelayedJob, args) assert_equal(2, Resque::Job.reserve(:delayed).args[0].keys.count) end test "delayed attribute is ignored when bypassing queues" do Resque.bypass_queues = true args = { :delay_until => Time.new+20} foo = Resque.enqueue(DelayedJob, args) assert_equal(0, Resque.size(:delayed)) assert(args[:delay_until] > Time.new) assert(foo =~ /^delayed job executing/) Resque.bypass_queues = false end test "mixing delay and non-delay is bad" do dargs = { :delay_until => Time.new + 3600} #non-delay into delay assert_raise(Resque::QueueError) do Resque.enqueue(NonDelayedJob, dargs) end #delay into non-delay assert_raise(Resque::QueueError) do Resque.enqueue(MistargetedDelayedJob, dargs) end end test "hydra works" do 20.times do Resque.enqueue(HydraJob, { :one => 'one'}) end assert_equal(0, Resque.size(:hydra)) assert_equal(20, Resque.size(:hydra1)+Resque.size(:hydra0)) assert(0 != Resque.size(:hydra1)) assert(0 != Resque.size(:hydra0)) end test "hydra/unique hashes correctly" do 20.times do Resque.enqueue(UniqueHydraJob, {:_id => 'zomgz', :one => 'one'}) end # 'zomgz'.hash % 100 == 39 assert_equal(1, Resque.size(:hydra39)) Resque.enqueue(UniqueHydraJob, {:_id => '518', :one => 'one'}) assert_equal(2, Resque.size(:hydra39)) end end