beaneater 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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