beaneater 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ # test/connection_test.rb
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ describe Beaneater::Connection do
6
+
7
+ describe 'for #new' do
8
+ before do
9
+ @host = 'localhost'
10
+ @bc = Beaneater::Connection.new(@host)
11
+ end
12
+
13
+ it "should store address, host and port" do
14
+ assert_equal 'localhost', @bc.address
15
+ assert_equal 'localhost', @bc.host
16
+ assert_equal 11300, @bc.port
17
+ end
18
+
19
+ it "should init telnet connection" do
20
+ telops = @bc.telnet_connection.instance_variable_get(:@options)
21
+ assert_kind_of Net::Telnet, @bc.telnet_connection
22
+ assert_equal 'localhost', telops["Host"]
23
+ assert_equal 11300, telops["Port"]
24
+ end
25
+
26
+ it "should raise on invalid connection" do
27
+ assert_raises(Beaneater::NotConnected) { Beaneater::Connection.new("localhost:8544") }
28
+ end
29
+ end # new
30
+
31
+ describe 'for #transmit' do
32
+ before do
33
+ @host = 'localhost'
34
+ @bc = Beaneater::Connection.new(@host)
35
+ end
36
+
37
+ it "should return yaml loaded response" do
38
+ res = @bc.transmit 'stats'
39
+ refute_nil res[:body]['current-connections']
40
+ assert_equal 'OK', res[:status]
41
+ end
42
+
43
+ it "should return id" do
44
+ Net::Telnet.any_instance.expects(:cmd).with(has_entries('String' => 'foo')).returns('INSERTED 254')
45
+ res = @bc.transmit 'foo'
46
+ assert_equal '254', res[:id]
47
+ assert_equal 'INSERTED', res[:status]
48
+ end
49
+ end # transmit
50
+
51
+ describe 'for #close' do
52
+ before do
53
+ @host = 'localhost'
54
+ @bc = Beaneater::Connection.new(@host)
55
+ end
56
+
57
+ it "should clear telnet connection" do
58
+ assert_kind_of Net::Telnet, @bc.telnet_connection
59
+ @bc.close
60
+ assert_nil @bc.telnet_connection
61
+ assert_raises(Beaneater::NotConnected) { @bc.transmit 'stats' }
62
+ end
63
+ end # close
64
+ end # Beaneater::Connection
@@ -0,0 +1,26 @@
1
+ # test/connection_test.rb
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ describe "Beaneater::Errors" do
6
+ it 'should raise proper exception for invalid status NOT_FOUND' do
7
+ @klazz = Beaneater::UnexpectedResponse.from_status("NOT_FOUND", "job-stats -1")
8
+ assert_kind_of(Beaneater::NotFoundError, @klazz)
9
+ assert_equal 'job-stats -1', @klazz.cmd
10
+ assert_equal 'NOT_FOUND', @klazz.status
11
+ end
12
+
13
+ it 'should raise proper exception for invalid status BAD_FORMAT' do
14
+ @klazz = Beaneater::UnexpectedResponse.from_status("BAD_FORMAT", "FAKE")
15
+ assert_kind_of(Beaneater::BadFormatError, @klazz)
16
+ assert_equal 'FAKE', @klazz.cmd
17
+ assert_equal 'BAD_FORMAT', @klazz.status
18
+ end
19
+
20
+ it 'should raise proper exception for invalid status DEADLINE_SOON' do
21
+ @klazz = Beaneater::UnexpectedResponse.from_status("DEADLINE_SOON", "reserve 0")
22
+ assert_kind_of(Beaneater::DeadlineSoonError, @klazz)
23
+ assert_equal 'reserve 0', @klazz.cmd
24
+ assert_equal 'DEADLINE_SOON', @klazz.status
25
+ end
26
+ end
data/test/job_test.rb ADDED
@@ -0,0 +1,213 @@
1
+ # test/connection_test.rb
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ describe Beaneater::Job do
6
+ before do
7
+ @pool = Beaneater::Pool.new(['localhost'])
8
+ @tube = @pool.tubes.find 'tube'
9
+ end
10
+
11
+ describe "for #bury" do
12
+ before do
13
+ @time = Time.now.to_i
14
+ @tube.put "foo bury #{@time}", :pri => 5
15
+ end
16
+
17
+ it("should be buried with same pri") do
18
+ job = @tube.reserve
19
+ assert_equal "foo bury #{@time}", job.body
20
+ assert_equal 'reserved', job.stats.state
21
+ job.bury
22
+ assert_equal 'buried', job.stats.state
23
+ assert_equal 5, job.stats.pri
24
+ assert_equal "foo bury #{@time}", @tube.peek(:buried).body
25
+ end
26
+
27
+ it("should be released with new pri") do
28
+ job = @tube.reserve
29
+ assert_equal "foo bury #{@time}", job.body
30
+ assert_equal 'reserved', job.stats.state
31
+ job.bury(:pri => 10)
32
+ assert_equal 'buried', job.stats.state
33
+ assert_equal 10, job.stats.pri
34
+ assert_equal "foo bury #{@time}", @tube.peek(:buried).body
35
+ end
36
+
37
+ it "should not bury if not reserved" do
38
+ job = @tube.peek(:ready)
39
+ assert_raises(Beaneater::JobNotReserved) { job.bury }
40
+ end
41
+
42
+ it "should not bury if reserved and deleted" do
43
+ job = @tube.reserve
44
+ job.delete
45
+ assert_equal false, job.reserved
46
+ assert_raises(Beaneater::NotFoundError) { job.bury }
47
+ end
48
+ end # bury
49
+
50
+ describe "for #release" do
51
+ before do
52
+ @time = Time.now.to_i
53
+ @tube.put "foo release #{@time}", :pri => 5
54
+ end
55
+
56
+ it("should be released with same pri") do
57
+ job = @tube.reserve
58
+ assert_equal "foo release #{@time}", job.body
59
+ assert_equal 'reserved', job.stats.state
60
+ job.release
61
+ assert_equal 'ready', job.stats.state
62
+ assert_equal 5, job.stats.pri
63
+ assert_equal 0, job.stats.delay
64
+ end
65
+
66
+ it("should be released with new pri") do
67
+ job = @tube.reserve
68
+ assert_equal "foo release #{@time}", job.body
69
+ assert_equal 'reserved', job.stats.state
70
+ job.release :pri => 10, :delay => 2
71
+ assert_equal 'delayed', job.stats.state
72
+ assert_equal 10, job.stats.pri
73
+ assert_equal 2, job.stats.delay
74
+ end
75
+
76
+ it "should not released if not reserved" do
77
+ job = @tube.peek(:ready)
78
+ assert_raises(Beaneater::JobNotReserved) { job.release }
79
+ end
80
+
81
+ it "should not release if not reserved and buried" do
82
+ job = @tube.reserve
83
+ job.bury
84
+ assert_raises(Beaneater::JobNotReserved) { job.release }
85
+ end
86
+ end # release
87
+
88
+ describe "for #delete" do
89
+ before do
90
+ @tube.put 'foo'
91
+ end
92
+
93
+ it("should deletable") do
94
+ job = @tube.peek(:ready)
95
+ assert_equal 'foo', job.body
96
+ job.delete
97
+ assert_nil @tube.peek(:ready)
98
+ end
99
+ end # delete
100
+
101
+ describe "for #touch" do
102
+ before do
103
+ @tube.put 'foo touch', :ttr => 1
104
+ end
105
+
106
+ it("should be toucheable") do
107
+ job = @tube.reserve
108
+ assert_equal 'foo touch', job.body
109
+ job.touch
110
+ assert_equal 1, job.stats.reserves
111
+ job.delete
112
+ end
113
+
114
+ it "should not touch if not reserved" do
115
+ job = @tube.peek(:ready)
116
+ assert_raises(Beaneater::JobNotReserved) { job.touch }
117
+ end
118
+
119
+ it "should not touch if not reserved and released" do
120
+ job = @tube.reserve
121
+ job.release
122
+ assert_raises(Beaneater::JobNotReserved) { job.touch }
123
+ end
124
+
125
+ it "should not touch if reserved and deleted" do
126
+ job = @tube.reserve
127
+ job.delete
128
+ assert_raises(Beaneater::NotFoundError) { job.touch }
129
+ end
130
+ end # touch
131
+
132
+ describe "for #kick" do
133
+ before do
134
+ @tube.put 'foo touch', :ttr => 1
135
+ end
136
+
137
+ it("should be toucheable") do
138
+ job = @tube.reserve
139
+ assert_equal 'foo touch', job.body
140
+ job.bury
141
+ assert_equal 1, @tube.stats.current_jobs_buried
142
+ if @pool.stats.version > 1.7
143
+ job.kick
144
+ assert_equal 0, @tube.stats.current_jobs_buried
145
+ assert_equal 1, @tube.stats.current_jobs_ready
146
+ end
147
+ end
148
+ end # kick
149
+
150
+ describe "for #stats" do
151
+ before do
152
+ @tube.put 'foo'
153
+ @job = @tube.peek(:ready)
154
+ end
155
+
156
+ it("should have stats") do
157
+ assert_equal 'tube', @job.stats['tube']
158
+ assert_equal 'ready', @job.stats.state
159
+ end
160
+
161
+ it "should return nil for deleted job with no stats" do
162
+ @job.delete
163
+ assert_raises(Beaneater::NotFoundError) { @job.stats }
164
+ end
165
+ end # stats
166
+
167
+ describe "for #reserved?" do
168
+ before do
169
+ @tube.put 'foo'
170
+ @job = @tube.peek(:ready)
171
+ end
172
+
173
+ it("should have stats") do
174
+ assert_equal false, @job.reserved?
175
+ job = @tube.reserve
176
+ assert_equal job.id, @job.id
177
+ assert_equal true, @job.reserved?
178
+ @job.delete
179
+ assert_raises(Beaneater::NotFoundError) { @job.reserved? }
180
+ end
181
+ end # reserved?
182
+
183
+ describe "for #exists?" do
184
+ before do
185
+ @tube.put 'foo'
186
+ @job = @tube.peek(:ready)
187
+ end
188
+
189
+ it("should exists") { assert @job.exists? }
190
+
191
+ it "should not exist" do
192
+ @job.delete
193
+ assert !@job.exists?
194
+ end
195
+ end # exists?
196
+
197
+ describe "for #tube" do
198
+ before do
199
+ @tube.put 'bar'
200
+ @job = @tube.peek(:ready)
201
+ end
202
+
203
+ it("should have stats") do
204
+ job = @tube.reserve
205
+ assert_equal @tube.name, job.tube
206
+ job.release
207
+ end
208
+ end # tube
209
+
210
+ after do
211
+ cleanup_tubes!(['tube'])
212
+ end
213
+ end # Beaneater::Tubes
data/test/jobs_test.rb ADDED
@@ -0,0 +1,107 @@
1
+ # test/connection_test.rb
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ describe Beaneater::Jobs do
6
+ before do
7
+ @pool = Beaneater::Pool.new(['localhost'])
8
+ @jobs = Beaneater::Jobs.new(@pool)
9
+ @tube = @pool.tubes.find('baz')
10
+ end
11
+
12
+ describe "for #find" do
13
+ before do
14
+ @time = Time.now.to_i
15
+ @tube.put("foo find #{@time}")
16
+ @job = @tube.peek(:ready)
17
+ end
18
+
19
+ it "should return job from id" do
20
+ assert_equal "foo find #{@time}", @jobs.find(@job.id).body
21
+ end
22
+
23
+ it "should return job using peek" do
24
+ assert_equal "foo find #{@time}", @jobs.find(@job.id).body
25
+ end
26
+
27
+ it "should return job using hash syntax" do
28
+ assert_equal "foo find #{@time}", @jobs.find(@job.id).body
29
+ end
30
+
31
+ it "should return nil for invalid id" do
32
+ assert_nil @jobs.find(-1)
33
+ end
34
+ end # find
35
+
36
+ describe "for #register!" do
37
+ before do
38
+ $foo = 0
39
+ @jobs.register('tube', :retry_on => [Timeout::Error]) do |job|
40
+ $foo += 1
41
+ end
42
+ end
43
+
44
+ it "should store processor" do
45
+ assert_equal 'tube', @jobs.processors.keys.first
46
+ assert_equal [Timeout::Error], @jobs.processors.values.first[:retry_on]
47
+ end
48
+
49
+ it "should store block for 'tube'" do
50
+ @jobs.processors['tube'][:block].call nil
51
+ assert_equal 1, $foo
52
+ end
53
+ end # register!
54
+
55
+ describe "for process!" do
56
+ before do
57
+ $foo = []
58
+
59
+ @jobs.register('tube_success', :retry_on => [Timeout::Error]) do |job|
60
+ # p job.body
61
+ $foo << job.body
62
+ raise Beaneater::AbortProcessingError if job.body =~ /abort/
63
+ end
64
+
65
+ @jobs.register('tube_release', :retry_on => [Timeout::Error], :max_retries => 2) do |job|
66
+ $foo << job.body
67
+ raise Timeout::Error
68
+ end
69
+
70
+ @jobs.register('tube_buried') do |job|
71
+ $foo << job.body
72
+ raise RuntimeError
73
+ end
74
+
75
+ cleanup_tubes!(['tube_success', 'tube_release', 'tube_buried'])
76
+
77
+ @pool.tubes.find('tube_success').put("success abort", :pri => 2**31 + 1)
78
+ @pool.tubes.find('tube_success').put("success 2", :pri => 1)
79
+ @pool.tubes.find('tube_release').put("released")
80
+ @pool.tubes.find('tube_buried').put("buried")
81
+
82
+ @jobs.process!(:release_delay => 0)
83
+ end
84
+
85
+ it "should process all jobs" do
86
+ assert_equal ['success 2', 'released', 'released', 'released', 'buried', 'success abort'], $foo
87
+ end
88
+
89
+ it "should clear successful_jobs" do
90
+ assert_equal 0, @pool.tubes.find('tube_success').stats.current_jobs_ready
91
+ assert_equal 1, @pool.tubes.find('tube_success').stats.current_jobs_buried
92
+ assert_equal 0, @pool.tubes.find('tube_success').stats.current_jobs_reserved
93
+ end
94
+
95
+ it "should retry release jobs 2 times" do
96
+ assert_equal 2, @pool.tubes.find('tube_release').peek(:buried).stats.releases
97
+ end
98
+
99
+ it "should bury unexpected exception" do
100
+ assert_equal 1, @pool.tubes.find('tube_buried').stats.current_jobs_buried
101
+ end
102
+ end
103
+
104
+ after do
105
+ cleanup_tubes!(['baz', 'tube_success', 'tube_release', 'tube_buried'])
106
+ end
107
+ end
@@ -0,0 +1,68 @@
1
+ # test/connection_test.rb
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ describe Beaneater::PoolCommand do
6
+
7
+ describe 'for #new' do
8
+ before do
9
+ @pool = stub
10
+ @command = Beaneater::PoolCommand.new(@pool)
11
+ end
12
+
13
+ it "should store pool" do
14
+ assert_equal @pool, @command.pool
15
+ end
16
+ end #new
17
+
18
+ describe 'for #transmit_to_all' do
19
+ describe 'for regular command' do
20
+ before do
21
+ @pool = stub(:transmit_to_all => "OK")
22
+ @command = Beaneater::PoolCommand.new(@pool)
23
+ end
24
+
25
+ it "can run regular command" do
26
+ assert_equal "OK", @command.transmit_to_all("foo")
27
+ end
28
+ end # regular command
29
+
30
+ describe 'for merged command' do
31
+ before do
32
+ @pool = stub(:transmit_to_all => [{ :body => { 'x' => 1, 'version' => 1.1 }}, {:body => { 'x' => 3,'version' => 1.2 }}])
33
+ @command = Beaneater::PoolCommand.new(@pool)
34
+ end
35
+
36
+ it "can run merge command" do
37
+ cmd = @command.transmit_to_all("bar", :merge => true)
38
+ assert_equal 4, cmd[:body]['x']
39
+ assert_equal Set[1.1, 1.2], cmd[:body]['version']
40
+ end
41
+ end # merged command
42
+ end # transmit_to_all
43
+
44
+ describe 'for #method_missing' do
45
+ describe '#transmit_to_rand' do
46
+ before do
47
+ @pool = stub
48
+ @pool.expects(:transmit_to_rand).with('foo').returns('OK')
49
+ @command = Beaneater::PoolCommand.new(@pool)
50
+ end
51
+
52
+ it 'delegates to connection' do
53
+ assert_equal 'OK', @command.transmit_to_rand('foo')
54
+ end
55
+ end # transmit_to_rand
56
+
57
+ describe 'invalid method' do
58
+ before do
59
+ @pool = stub
60
+ @command = Beaneater::PoolCommand.new(@pool)
61
+ end
62
+
63
+ it 'raises no method error' do
64
+ assert_raises(NoMethodError) { @command.foo('foo') }
65
+ end
66
+ end # transmit_to_rand
67
+ end
68
+ end # Beaneater::PoolCommand