backburner 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ $backburner_sum = 0
4
+ $backburner_numbers = []
5
+
6
+ class TestBackburnerJob
7
+ include Backburner::Queue
8
+ queue "test.jobber"
9
+
10
+ def self.perform(value, number)
11
+ $backburner_sum += value
12
+ $backburner_numbers << number
13
+ end
14
+ end
15
+
16
+ describe "Backburner module" do
17
+ before { Backburner.default_queues.clear }
18
+
19
+ describe "for enqueue method" do
20
+ before do
21
+ Backburner.enqueue TestBackburnerJob, 5, 6
22
+ Backburner.enqueue TestBackburnerJob, 15, 10
23
+ silenced(2) do
24
+ worker = Backburner::Worker.new('test.jobber')
25
+ worker.prepare
26
+ 2.times { worker.work_one_job }
27
+ end
28
+ end
29
+
30
+ it "can run jobs using #run method" do
31
+ assert_equal 20, $backburner_sum
32
+ assert_same_elements [6, 10], $backburner_numbers
33
+ end
34
+ end # enqueue
35
+
36
+ describe "for work method" do
37
+ it "invokes worker start" do
38
+ Backburner::Worker.expects(:start).with(["foo", "bar"])
39
+ Backburner.work("foo", "bar")
40
+ end
41
+
42
+ it "invokes worker start with no args" do
43
+ Backburner::Worker.expects(:start).with([])
44
+ Backburner.work
45
+ end
46
+ end # work!
47
+
48
+ describe "for configuration" do
49
+ it "remembers the tube_namespace" do
50
+ assert_equal "demo.test", Backburner.configuration.tube_namespace
51
+ end
52
+ end # configuration
53
+
54
+ describe "for default_queues" do
55
+ it "supports assignment" do
56
+ Backburner.default_queues << "foo"
57
+ Backburner.default_queues << "bar"
58
+ assert_same_elements ["foo", "bar"], Backburner.default_queues
59
+ end
60
+ end
61
+ end # Backburner
@@ -0,0 +1,35 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Connection class" do
4
+ describe "for initialize" do
5
+ before do
6
+ @connection = Backburner::Connection.new("beanstalk://localhost")
7
+ end
8
+
9
+ it "should store url in accessor" do
10
+ assert_equal "beanstalk://localhost", @connection.url
11
+ end
12
+
13
+ it "should setup beanstalk connection" do
14
+ assert_kind_of Beanstalk::Pool, @connection.beanstalk
15
+ end
16
+ end # initialize
17
+
18
+ describe "for bad uri" do
19
+ it "should raise a BadUrl" do
20
+ assert_raises(Backburner::Connection::BadURL) {
21
+ @connection = Backburner::Connection.new("fake://foo")
22
+ }
23
+ end
24
+ end
25
+
26
+ describe "for delegated methods" do
27
+ before do
28
+ @connection = Backburner::Connection.new("beanstalk://localhost")
29
+ end
30
+
31
+ it "delegate methods to beanstalk connection" do
32
+ assert_equal "localhost:11300", @connection.list_tubes.keys.first
33
+ end
34
+ end # delegator
35
+ end # Connection
@@ -0,0 +1,79 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Helpers module" do
4
+ include Backburner::Helpers
5
+
6
+ describe "for classify method" do
7
+ it "should support simple classify" do
8
+ assert_equal "FooBarBaz", classify("foo-bar-baz")
9
+ end
10
+
11
+ it "should not affect existing classified strings" do
12
+ assert_equal "Foo::BarBaz", classify("Foo::BarBaz")
13
+ end
14
+ end # classify
15
+
16
+ describe "for constantize method" do
17
+ it "should constantize known constant" do
18
+ assert_equal Backburner, constantize("Backburner")
19
+ end
20
+
21
+ it "should properly report when constant is undefined" do
22
+ assert_raises(NameError) { constantize("FakeObject") }
23
+ end
24
+ end # constantize
25
+
26
+ describe "for dasherize method" do
27
+ it "should not harm existing dashed names" do
28
+ assert_equal "foo/bar-baz", dasherize("foo/bar-baz")
29
+ end
30
+
31
+ it "should properly convert simple names to dashes" do
32
+ assert_equal "foo-bar", dasherize("FooBar")
33
+ end
34
+
35
+ it "should properly convert class to dash with namespace" do
36
+ assert_equal "foo/bar-baz", dasherize("Foo::BarBaz")
37
+ end
38
+ end # dasherize
39
+
40
+ describe "for exception_message method" do
41
+ it "prints out message about failure" do
42
+ output = exception_message(RuntimeError.new("test"))
43
+ assert_match /Exception RuntimeError/, output
44
+ end
45
+ end # exception_message
46
+
47
+ describe "for tube_namespace" do
48
+ before { Backburner.expects(:configuration).returns(stub(:tube_namespace => "test.foo.job")) }
49
+
50
+ it "accesses correct value" do
51
+ assert_equal "test.foo.job", tube_namespace
52
+ end
53
+ end # tube_namespace
54
+
55
+ describe "for expand_tube_name method" do
56
+ before { Backburner.expects(:configuration).returns(stub(:tube_namespace => "test.foo.job.")) }
57
+
58
+ it "supports base strings" do
59
+ assert_equal "test.foo.job.email/send-news", expand_tube_name("email/send_news")
60
+ end # simple string
61
+
62
+ it "supports qualified strings" do
63
+ assert_equal "test.foo.job.email/send-news", expand_tube_name("test.foo.job.email/send_news")
64
+ end # qualified string
65
+
66
+ it "supports base symbols" do
67
+ assert_equal "test.foo.job.email/send-news", expand_tube_name(:"email/send_news")
68
+ end # symbols
69
+
70
+ it "supports queue names" do
71
+ test = stub(:queue => "email/send_news")
72
+ assert_equal "test.foo.job.email/send-news", expand_tube_name(test)
73
+ end # queue names
74
+
75
+ it "supports class names" do
76
+ assert_equal "test.foo.job.runtime-error", expand_tube_name(RuntimeError)
77
+ end # class names
78
+ end # expand_tube_name
79
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ describe "Backburner::Logger module" do
4
+ include Backburner::Logger
5
+
6
+ describe "for log method" do
7
+ it "prints out to std out" do
8
+ output = capture_stdout { log("foo") }
9
+ assert_equal "foo\n", output
10
+ end
11
+ end # log
12
+
13
+ describe "for log_error method" do
14
+ it "prints out to std err" do
15
+ output = capture_stdout { log_error("bar") }
16
+ assert_equal "bar\n", output
17
+ end
18
+ end # log_error
19
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class TestObj
4
+ include Backburner::Performable
5
+ ID = 56
6
+ def id; ID; end
7
+ def self.find(id); TestObj.new if id == ID; end
8
+ def foo(state, state2); "bar #{state} #{state2}"; end
9
+ def self.bar(state, state2); "baz #{state} #{state2}"; end
10
+ end
11
+
12
+ describe "Backburner::Performable module" do
13
+ after { ENV["TEST"] = nil }
14
+
15
+ describe "for async instance method" do
16
+ it "should invoke worker enqueue" do
17
+ Backburner::Worker.expects(:enqueue).with(TestObj, [56, :foo, true, false], has_entries(:pri => 5000, :queue => "foo"))
18
+ TestObj.new.async(:pri => 5000, :queue => "foo").foo(true, false)
19
+ end
20
+ end # async instance
21
+
22
+ describe "for async class method" do
23
+ it "should invoke worker enqueue" do
24
+ Backburner::Worker.expects(:enqueue).with(TestObj, [nil, :bar, true, false], has_entries(:pri => 5000, :queue => "foo"))
25
+ TestObj.async(:pri => 5000, :queue => "foo").bar(true, false)
26
+ end
27
+ end # async class
28
+
29
+ describe "for perform class method" do
30
+ it "should work for instance" do
31
+ assert_equal "bar true false", TestObj.perform(TestObj::ID, :foo, true, false)
32
+ end # instance
33
+
34
+ it "should work for class level" do
35
+ assert_equal "baz false true", TestObj.perform(nil, :bar, false, true)
36
+ end # class
37
+ end # perform
38
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ module NestedDemo
4
+ class TestJobA; include Backburner::Queue; end
5
+ class TestJobB; include Backburner::Queue; end
6
+ end
7
+
8
+ describe "Backburner::Queue module" do
9
+ describe "contains known_queue_classes" do
10
+ it "has all defined known queues" do
11
+ assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobA
12
+ assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobB
13
+ end
14
+ end
15
+
16
+ describe "for queue method accessor" do
17
+ it "should return the queue name" do
18
+ assert_equal "nested-demo/test-job-a", NestedDemo::TestJobA.queue
19
+ end
20
+ end # queue_name
21
+
22
+ describe "for queue assignment method" do
23
+ it "should allow queue name to be assigned" do
24
+ NestedDemo::TestJobB.queue("nested/job")
25
+ assert_equal "nested/job", NestedDemo::TestJobB.queue
26
+ end
27
+ end # queue
28
+ end # Backburner::Queue
@@ -0,0 +1,93 @@
1
+ require 'rubygems'
2
+ require 'tempfile'
3
+ require 'minitest/autorun'
4
+ require 'mocha'
5
+ $:.unshift File.expand_path("../../lib")
6
+ require 'backburner'
7
+
8
+ # Configure Backburner
9
+ Backburner.configure do |config|
10
+ config.beanstalk_url = "beanstalk://localhost"
11
+ config.tube_namespace = "demo.test"
12
+ end
13
+
14
+ ## Kernel Extensions
15
+ require 'stringio'
16
+
17
+ module Kernel
18
+ # Redirect standard out, standard error and the buffered logger for sprinkle to StringIO
19
+ # capture_stdout { any_commands; you_want } => "all output from the commands"
20
+ def capture_stdout
21
+ return yield if ENV['DEBUG'] # Skip if debug mode
22
+
23
+ out = StringIO.new
24
+ $stdout = out
25
+ $stderr = out
26
+ yield
27
+ return out.string
28
+ ensure
29
+ $stdout = STDOUT
30
+ $stderr = STDERR
31
+ end
32
+ end
33
+
34
+ class User
35
+ attr_accessor :id, :name
36
+
37
+ def initialize(id, name)
38
+ @id, @name = id, name
39
+ end
40
+ end
41
+
42
+ class MiniTest::Spec
43
+ class << self
44
+ alias :should :it
45
+ alias :context :describe
46
+ end
47
+ alias :assert_no_match :refute_match
48
+ alias :assert_not_nil :refute_nil
49
+ alias :assert_not_equal :refute_equal
50
+
51
+ # assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
52
+ def assert_same_elements(a1, a2, msg = nil)
53
+ [:select, :inject, :size].each do |m|
54
+ [a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
55
+ end
56
+
57
+ assert a1h = a1.inject({}) { |h,e| h[e] ||= a1.select { |i| i == e }.size; h }
58
+ assert a2h = a2.inject({}) { |h,e| h[e] ||= a2.select { |i| i == e }.size; h }
59
+
60
+ assert_equal(a1h, a2h, msg)
61
+ end
62
+
63
+ # assert_contains(['a', '1'], /\d/) => passes
64
+ # assert_contains(['a', '1'], 'a') => passes
65
+ # assert_contains(['a', '1'], /not there/) => fails
66
+ def assert_contains(collection, x, extra_msg = "")
67
+ collection = [collection] unless collection.is_a?(Array)
68
+ msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
69
+ case x
70
+ when Regexp
71
+ assert(collection.detect { |e| e =~ x }, msg)
72
+ else
73
+ assert(collection.include?(x), msg)
74
+ end
75
+ end
76
+
77
+ # silenced(5) { ... }
78
+ def silenced(time=3, &block)
79
+ Timeout::timeout(time) { capture_stdout(&block) }
80
+ end
81
+
82
+ # pop_one_job(tube_name)
83
+ def pop_one_job(tube_name)
84
+ connection = Backburner::Worker.connection
85
+ tube_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
86
+ connection.watch(tube_name)
87
+ connection.list_tubes_watched.each do |server, tubes|
88
+ tubes.each { |tube| connection.ignore(tube) unless tube == tube_name }
89
+ end
90
+ silenced(3) { @res = connection.reserve }
91
+ return @res, JSON.parse(@res.body)
92
+ end
93
+ end # MiniTest::Spec
@@ -0,0 +1,163 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ $worker_test_count = 0
4
+
5
+ class TestJob
6
+ include Backburner::Queue
7
+ def self.perform(x, y); $worker_test_count += x + y; end
8
+ end
9
+
10
+ class TestAsyncJob
11
+ include Backburner::Performable
12
+ def self.foo(x, y); $worker_test_count = x * y; end
13
+ end
14
+
15
+ describe "Backburner::Worker module" do
16
+ before { Backburner.default_queues.clear }
17
+
18
+ describe "for enqueue class method" do
19
+ it "should support enqueuing job" do
20
+ Backburner::Worker.enqueue TestJob, [3, 4], :ttr => 100
21
+ job, body = pop_one_job("test-job")
22
+ assert_equal "TestJob", body["class"]
23
+ assert_equal [3, 4], body["args"]
24
+ assert_equal 100, job.ttr
25
+ assert_equal Backburner.configuration.default_priority, job.pri
26
+ end # simple
27
+
28
+ it "should support enqueuing job with custom queue" do
29
+ Backburner::Worker.enqueue TestJob, [6, 7], :queue => "test.bar", :pri => 5000
30
+ job, body = pop_one_job("test.bar")
31
+ assert_equal "TestJob", body["class"]
32
+ assert_equal [6, 7], body["args"]
33
+ assert_equal 0, job.delay
34
+ assert_equal 5000, job.pri
35
+ assert_equal Backburner.configuration.respond_timeout, job.ttr
36
+ end # custom
37
+
38
+ it "should support async job" do
39
+ TestAsyncJob.async(:ttr => 100, :queue => "bar.baz.foo").foo(10, 5)
40
+ job, body = pop_one_job("bar.baz.foo")
41
+ assert_equal "TestAsyncJob", body["class"]
42
+ assert_equal [nil, "foo", 10, 5], body["args"]
43
+ assert_equal 100, job.ttr
44
+ assert_equal Backburner.configuration.default_priority, job.pri
45
+ end # async
46
+ end # enqueue
47
+
48
+ describe "for start class method" do
49
+ it "should initialize and start the worker instance" do
50
+ ech = stub
51
+ Backburner::Worker.expects(:new).with("foo").returns(ech)
52
+ ech.expects(:start)
53
+ Backburner::Worker.start("foo")
54
+ end
55
+ end # start
56
+
57
+ describe "for connection class method" do
58
+ it "should return the beanstalk connection" do
59
+ assert_equal "beanstalk://localhost", Backburner::Worker.connection.url
60
+ assert_kind_of Beanstalk::Pool, Backburner::Worker.connection.beanstalk
61
+ end
62
+ end # connection
63
+
64
+ describe "for tube_names accessor" do
65
+ it "supports retrieving tubes" do
66
+ worker = Backburner::Worker.new(["foo", "bar"])
67
+ assert_equal ["foo", "bar"], worker.tube_names
68
+ end
69
+
70
+ it "supports single tube array arg" do
71
+ worker = Backburner::Worker.new([["foo", "bar"]])
72
+ assert_equal ["foo", "bar"], worker.tube_names
73
+ end
74
+
75
+ it "supports empty nil array arg" do
76
+ worker = Backburner::Worker.new([nil])
77
+ assert_equal nil, worker.tube_names
78
+ end
79
+
80
+ it "supports single tube arg" do
81
+ worker = Backburner::Worker.new("foo")
82
+ assert_equal ["foo"], worker.tube_names
83
+ end
84
+
85
+ it "supports empty array arg" do
86
+ worker = Backburner::Worker.new([])
87
+ assert_equal nil, worker.tube_names
88
+ end
89
+
90
+ it "supports nil arg" do
91
+ worker = Backburner::Worker.new(nil)
92
+ assert_equal nil, worker.tube_names
93
+ end
94
+ end # tube_names
95
+
96
+ describe "for prepare method" do
97
+ it "should watch specified tubes" do
98
+ worker = Backburner::Worker.new(["foo", "bar"])
99
+ out = capture_stdout { worker.prepare }
100
+ assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
101
+ assert_same_elements ["demo.test.foo", "demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
102
+ assert_match /demo\.test\.foo/, out
103
+ end # multiple
104
+
105
+ it "should watch single tube" do
106
+ worker = Backburner::Worker.new("foo")
107
+ out = capture_stdout { worker.prepare }
108
+ assert_equal ["demo.test.foo"], worker.tube_names
109
+ assert_same_elements ["demo.test.foo"], Backburner::Worker.connection.list_tubes_watched.values.first
110
+ assert_match /demo\.test\.foo/, out
111
+ end # single
112
+
113
+ it "should respect default_queues settings" do
114
+ Backburner.default_queues.concat(["foo", "bar"])
115
+ worker = Backburner::Worker.new
116
+ out = capture_stdout { worker.prepare }
117
+ assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
118
+ assert_same_elements ["demo.test.foo", "demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
119
+ assert_match /demo\.test\.foo/, out
120
+ end
121
+
122
+ it "should assign based on all tubes" do
123
+ Backburner::Worker.any_instance.expects(:all_existing_queues).once.returns("bar")
124
+ worker = Backburner::Worker.new
125
+ out = capture_stdout { worker.prepare }
126
+ assert_equal ["demo.test.bar"], worker.tube_names
127
+ assert_same_elements ["demo.test.bar"], Backburner::Worker.connection.list_tubes_watched.values.first
128
+ assert_match /demo\.test\.bar/, out
129
+ end # all assign
130
+
131
+ it "should properly retrieve all tubes" do
132
+ worker = Backburner::Worker.new
133
+ out = capture_stdout { worker.prepare }
134
+ assert_contains worker.tube_names, "demo.test.test-job"
135
+ assert_contains Backburner::Worker.connection.list_tubes_watched.values.first, "demo.test.test-job"
136
+ assert_match /demo\.test\.test-job/, out
137
+ end # all read
138
+ end # prepare
139
+
140
+ describe "for work_one_job method" do
141
+ it "should work an enqueued job" do
142
+ $worker_test_count = 0
143
+ Backburner::Worker.enqueue TestJob, [1, 2], :queue => "foo.bar"
144
+ silenced(2) do
145
+ worker = Backburner::Worker.new('foo.bar')
146
+ worker.prepare
147
+ worker.work_one_job
148
+ end
149
+ assert_equal 3, $worker_test_count
150
+ end
151
+
152
+ it "should work for an async job" do
153
+ $worker_test_count = 0
154
+ TestAsyncJob.async(:queue => "bar.baz").foo(3, 5)
155
+ silenced(2) do
156
+ worker = Backburner::Worker.new('bar.baz')
157
+ worker.prepare
158
+ worker.work_one_job
159
+ end
160
+ assert_equal 15, $worker_test_count
161
+ end
162
+ end # work_one_job
163
+ end # Backburner::Worker