stalk_climber 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,196 +1,289 @@
1
1
  require 'test_helper'
2
- require 'json'
3
2
 
4
- class Job < Test::Unit::TestCase
3
+ class Job < StalkClimber::TestCase
5
4
 
6
- def setup
5
+ setup do
7
6
  @connection = StalkClimber::Connection.new('localhost:11300')
8
7
  @job = seed_jobs(1).first
9
8
  end
10
9
 
11
10
 
12
- def test_body_performs_peek_and_parses_json
13
- body = {'test' => true}.to_json
11
+ context 'beaneater integration' do
14
12
 
15
- @job.connection.expects(:transmit).returns({
16
- :body => body,
17
- })
18
- assert_equal body, @job.body
13
+ should 'derive from Beaneater::Job' do
14
+ assert_kind_of Beaneater::Job, @job
15
+ end
19
16
 
20
- @job.connection.expects(:transmit).never
21
- assert_equal body, @job.body
22
17
  end
23
18
 
24
19
 
25
- def test_connection_stored_with_instance
26
- assert @job.instance_variable_get(:@connection)
27
- assert @job.connection
28
- end
20
+ context '#body' do
29
21
 
22
+ should 'perform peek and set/return body' do
23
+ body = "test #{Time.now.to_i}"
30
24
 
31
- def test_delete
32
- assert @job.delete
33
- assert_raise Beaneater::NotFoundError do
34
- @connection.transmit("peek #{@job.id}")
25
+ @job.connection.expects(:transmit).returns({
26
+ :body => body,
27
+ })
28
+ assert_equal body, @job.body
29
+
30
+ @job.connection.expects(:transmit).never
31
+ assert_equal body, @job.body
35
32
  end
36
- refute @job.instance_variable_get(:@body)
37
- refute @job.instance_variable_get(:@stats)
38
- assert_equal 'DELETED', @job.instance_variable_get(:@status)
33
+
39
34
  end
40
35
 
41
36
 
42
- def test_exists?
43
- assert @job.exists?
37
+ context '#connection' do
38
+
39
+ should 'set connection instance variable to connection' do
40
+ assert @job.instance_variable_get(:@connection)
41
+ assert @job.connection
42
+ end
44
43
 
45
- @job.delete
46
- refute @job.exists?
47
44
  end
48
45
 
49
46
 
50
- def test_initialize_with_peek_response
51
- job = StalkClimber::Job.new(@connection.transmit("peek #{@job.id}"))
52
- @connection.expects(:transmit).never
53
- assert_equal @connection, job.connection
54
- assert_equal @job.id, job.id
55
- assert_equal 'FOUND', job.instance_variable_get(:@status)
56
- assert_equal('{}', job.body)
57
- refute job.instance_variable_get(:@stats)
58
- end
47
+ context '#delete' do
59
48
 
49
+ should 'delete the job' do
50
+ assert_equal 'DELETED', @job.delete[:status]
51
+ assert_raises Beaneater::NotFoundError do
52
+ @connection.transmit("peek #{@job.id}")
53
+ end
54
+ refute @job.instance_variable_get(:@body)
55
+ refute @job.instance_variable_get(:@stats)
56
+ assert_equal 'DELETED', @job.instance_variable_get(:@status)
57
+ end
58
+
59
+
60
+ should 'not clear job instance variables if delete fails' do
61
+ client = Beaneater::Connection.new('localhost:11300')
62
+ tube_name = SecureRandom.uuid
63
+ client.transmit("use #{tube_name}")
64
+ client.transmit("watch #{tube_name}")
65
+ client.transmit('ignore default')
66
+ job = client.transmit(StalkClimber::Connection::PROBE_TRANSMISSION)
67
+ @job = StalkClimber::Job.new(@connection.transmit("stats-job #{job[:id]}"))
68
+ client.transmit('reserve')
69
+ assert_raises Beaneater::NotFoundError do
70
+ @job.delete
71
+ end
72
+ assert @job.instance_variable_get(:@stats), 'Expected stats instance variable to still exist after failed deletion'
73
+ client.transmit("delete #{job[:id]}")
74
+ end
60
75
 
61
- def test_initialize_with_put_response
62
- @connection.expects(:transmit).never
63
- assert @job.id
64
- assert_equal @connection, @job.connection
65
- assert_equal 'INSERTED', @job.instance_variable_get(:@status)
66
- refute @job.instance_variable_get(:@body)
67
- refute @job.instance_variable_get(:@stats)
68
76
  end
69
77
 
70
78
 
71
- def test_initialize_with_stats_response
72
- job = StalkClimber::Job.new(@connection.transmit("stats-job #{@job.id}"))
73
- @connection.expects(:transmit).never
74
- assert_equal @job.id, job.id
75
- assert_equal @connection, job.connection
76
- assert_equal 'OK', job.instance_variable_get(:@status)
77
- assert job.stats
78
- assert job.instance_variable_get(:@stats)
79
- refute job.instance_variable_get(:@body)
80
- StalkClimber::Job::STATS_ATTRIBUTES.each do |method_name|
81
- assert job.send(method_name)
79
+ context '#exists?' do
80
+
81
+
82
+ should 'verify the job exists' do
83
+ assert @job.exists?
84
+
85
+ @job.delete
86
+ refute @job.exists?
82
87
  end
88
+
83
89
  end
84
90
 
85
91
 
86
- def test_initialize_with_stats_attribute_methods_return_correct_values
87
- stats_body = {
88
- 'age' => 3,
89
- 'buries' => 0,
90
- 'delay' => 0,
91
- 'id' => 4412,
92
- 'kicks' => 0,
93
- 'pri' => 4294967295,
94
- 'releases' => 0,
95
- 'reserves' => 0,
96
- 'state' => 'ready',
97
- 'time-left' => 0,
98
- 'timeouts' => 0,
99
- 'ttr' => 300,
100
- 'tube' => 'default',
101
- }
102
- stats_response = {
103
- :body => stats_body,
104
- :connection => @connection,
105
- :id => 149,
106
- :status => 'OK',
107
- }
108
- job = StalkClimber::Job.new(stats_response)
109
- StalkClimber::Job::STATS_ATTRIBUTES.each do |method_name|
110
- assert_equal stats_body[method_name], job.send(method_name), "Expected #{stats_body[method_name.to_sym]} for #{method_name}, got #{job.send(method_name)}"
92
+ context '#initialize' do
93
+
94
+ should 'support initialization with peek response' do
95
+ job = StalkClimber::Job.new(@connection.transmit("peek #{@job.id}"))
96
+ @connection.expects(:transmit).never
97
+ assert_equal @connection, job.connection
98
+ assert_equal @job.id, job.id
99
+ assert_equal 'FOUND', job.instance_variable_get(:@status)
100
+ assert_equal('{}', job.body)
101
+ refute job.instance_variable_get(:@stats)
102
+ end
103
+
104
+
105
+ should 'support initialization with put response' do
106
+ @connection.expects(:transmit).never
107
+ assert @job.id
108
+ assert_equal @connection, @job.connection
109
+ assert_equal 'INSERTED', @job.instance_variable_get(:@status)
110
+ refute @job.instance_variable_get(:@body)
111
+ refute @job.instance_variable_get(:@stats)
112
+ end
113
+
114
+
115
+ should 'support initialization with stats response' do
116
+ job = StalkClimber::Job.new(@connection.transmit("stats-job #{@job.id}"))
117
+ @connection.expects(:transmit).never
118
+ assert_equal @job.id, job.id
119
+ assert_equal @connection, job.connection
120
+ assert_equal 'OK', job.instance_variable_get(:@status)
121
+ assert job.stats(false)
122
+ assert job.instance_variable_get(:@stats)
123
+ refute job.instance_variable_get(:@body)
124
+ StalkClimber::Job::CACHED_ATTRIBUTES.each do |method_name|
125
+ assert job.send(method_name)
126
+ end
127
+ end
128
+
129
+
130
+ should 'support initialization with reserve response' do
131
+ job = StalkClimber::Job.new(@connection.transmit('reserve'))
132
+ @connection.expects(:transmit).never
133
+ assert_equal @connection, job.connection
134
+ assert job.id
135
+ assert_equal 'RESERVED', job.instance_variable_get(:@status)
136
+ assert_equal('{}', job.body)
137
+ refute job.instance_variable_get(:@stats)
111
138
  end
139
+
140
+
141
+ should 'raise error if initialized with unknown response type' do
142
+ assert_raises RuntimeError do
143
+ StalkClimber::Job.new({:status => 'DELETED'})
144
+ end
145
+ end
146
+
112
147
  end
113
148
 
114
149
 
115
- def test_initialize_with_unknown_status_raises_error
116
- assert_raise RuntimeError do
117
- StalkClimber::Job.new({:status => 'DELETED'})
150
+ context 'stats methods' do
151
+
152
+ should 'initialize stats attributes and attribute methods should return correct values' do
153
+ stats_body = {
154
+ 'age' => 3,
155
+ 'buries' => 0,
156
+ 'delay' => 0,
157
+ 'id' => 4412,
158
+ 'kicks' => 0,
159
+ 'pri' => 4294967295,
160
+ 'releases' => 0,
161
+ 'reserves' => 0,
162
+ 'state' => 'ready',
163
+ 'time-left' => 0,
164
+ 'timeouts' => 0,
165
+ 'ttr' => 300,
166
+ 'tube' => 'default',
167
+ }
168
+ stats_response = {
169
+ :body => stats_body,
170
+ :connection => @connection,
171
+ :id => 149,
172
+ :status => 'OK',
173
+ }
174
+ job = StalkClimber::Job.new(stats_response)
175
+ StalkClimber::Job::CACHED_ATTRIBUTES.each do |method_name|
176
+ assert_equal stats_body[method_name], job.send(method_name), "Expected #{stats_body[method_name]} for #{method_name}, got #{job.send(method_name)}"
177
+ end
178
+ end
179
+
180
+
181
+ should 'be able to force refresh of stats' do
182
+ initial_value = @job.age
183
+ @connection.expects(:transmit).returns({:body => {'age' => initial_value + 100}})
184
+ assert_equal initial_value + 100, @job.age(true)
185
+ end
186
+
187
+
188
+ should 'allow for not refreshing stats' do
189
+ initial_value = @job.age
190
+ @connection.expects(:transmit).never
191
+ assert_equal initial_value, @job.age(false)
118
192
  end
193
+
119
194
  end
120
195
 
121
196
 
122
- def test_stats_attribute_method_can_force_refresh
123
- initial_value = @job.age
124
- @connection.expects(:transmit).returns({:body => {'age' => initial_value + 100}})
125
- assert_equal initial_value + 100, @job.age(true)
197
+ context '#stats' do
198
+
199
+ should 'be able to force refresh' do
200
+ body = {
201
+ 'age'=>3,
202
+ 'buries'=>0,
203
+ 'delay'=>0,
204
+ 'kicks'=>0,
205
+ 'id' => 4412,
206
+ 'pri'=>4294967295,
207
+ 'releases'=>0,
208
+ 'reserves'=>0,
209
+ 'state'=>'ready',
210
+ 'time-left'=>0,
211
+ 'timeouts'=>0,
212
+ 'ttr'=>300,
213
+ 'tube'=>'default',
214
+ }
215
+ stats_1 = {
216
+ :body => {},
217
+ :connection => @connection,
218
+ :id => 149,
219
+ :status => 'OK',
220
+ }
221
+ stats_2 = {
222
+ :body => body,
223
+ :connection => @connection,
224
+ :id => 149,
225
+ :status => 'OK',
226
+ }
227
+ @connection.expects(:transmit).twice.returns(stats_1, stats_2)
228
+ job = StalkClimber::Job.new(@connection.transmit("stats-job #{@job.id}"))
229
+ job.stats
230
+ StalkClimber::Job::CACHED_ATTRIBUTES.each do |method_name|
231
+ assert_equal body[method_name], job.send(method_name), "Expected #{body[method_name.to_sym]} for #{method_name}, got #{job.send(method_name)}"
232
+ end
233
+ end
234
+
235
+
236
+ should 'allow for not refreshing stats' do
237
+ stat = @job.stats
238
+ @job.connection.expects(:transmit).never
239
+ assert_equal stat, @job.stats(false)
240
+ end
241
+
126
242
  end
127
243
 
128
244
 
129
- def test_stats_can_force_a_refresh
130
- body = {
131
- 'age'=>3,
132
- 'buries'=>0,
133
- 'delay'=>0,
134
- 'kicks'=>0,
135
- 'id' => 4412,
136
- 'pri'=>4294967295,
137
- 'releases'=>0,
138
- 'reserves'=>0,
139
- 'state'=>'ready',
140
- 'time-left'=>0,
141
- 'timeouts'=>0,
142
- 'ttr'=>300,
143
- 'tube'=>'default',
144
- }
145
- stats_1 = {
146
- :body => {},
147
- :connection => @connection,
148
- :id => 149,
149
- :status => 'OK',
150
- }
151
- stats_2 = {
152
- :body => body,
153
- :connection => @connection,
154
- :id => 149,
155
- :status => 'OK',
156
- }
157
- @connection.expects(:transmit).twice.returns(stats_1, stats_2)
158
- job = StalkClimber::Job.new(@connection.transmit("stats-job #{@job.id}"))
159
- job.stats(:force_refresh)
160
- StalkClimber::Job::STATS_ATTRIBUTES.each do |method_name|
161
- assert_equal body[method_name], job.send(method_name), "Expected #{body[method_name.to_sym]} for #{method_name}, got #{job.send(method_name)}"
245
+ context '#to_h' do
246
+
247
+ should 'return the expected hash' do
248
+ job_body = "test #{Time.now.to_i}"
249
+ stats_body = {
250
+ 'age' => 3,
251
+ 'body' => job_body, # Will be ignored during job init
252
+ 'buries' => 0,
253
+ 'connection' => @connection, # Will be ignored during job init
254
+ 'delay' => 0,
255
+ 'id' => 4412,
256
+ 'kicks' => 0,
257
+ 'pri' => 4294967295,
258
+ 'releases' => 0,
259
+ 'reserves' => 0,
260
+ 'state' => 'ready',
261
+ 'time-left' => 0,
262
+ 'timeouts' => 0,
263
+ 'ttr' => 300,
264
+ 'tube' => 'default',
265
+ }
266
+ stats_response = {
267
+ :body => stats_body,
268
+ :connection => @connection,
269
+ :id => 149,
270
+ :status => 'OK',
271
+ }
272
+ job = StalkClimber::Job.new(stats_response)
273
+ job.instance_variable_set(:@body, job_body)
274
+ job.connection.expects(:transmit).once.returns(stats_response)
275
+ assert_equal stats_body, job.to_h
162
276
  end
277
+
163
278
  end
164
279
 
165
- def test_to_h_returns_expected_hash
166
- job_body = "test #{Time.now.to_i}"
167
- stats_body = {
168
- 'age' => 3,
169
- 'body' => job_body, # Will be ignored during job init
170
- 'buries' => 0,
171
- :connection => @connection, # Will be ignored during job init
172
- 'delay' => 0,
173
- 'id' => 4412,
174
- 'kicks' => 0,
175
- 'pri' => 4294967295,
176
- 'releases' => 0,
177
- 'reserves' => 0,
178
- 'state' => 'ready',
179
- 'time-left' => 0,
180
- 'timeouts' => 0,
181
- 'ttr' => 300,
182
- 'tube' => 'default',
183
- }
184
- stats_response = {
185
- :body => stats_body,
186
- :connection => @connection,
187
- :id => 149,
188
- :status => 'OK',
189
- }
190
- job = StalkClimber::Job.new(stats_response)
191
- job.instance_variable_set(:@body, job_body)
192
- expected_hash = Hash[stats_body.map { |k, v| [k.to_sym, v] }]
193
- assert_equal expected_hash, job.to_h
280
+
281
+ context '#to_s' do
282
+
283
+ should 'return expected string representation of job' do
284
+ assert_equal "#<StalkClimber::Job id=#{@job.id} body=#{@job.body.inspect}>", @job.to_s
285
+ end
286
+
194
287
  end
195
288
 
196
289
  end
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+
3
+ class JobsTest < StalkClimber::TestCase
4
+
5
+ context '#each' do
6
+
7
+ setup do
8
+ @climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
9
+
10
+ @test_jobs = {}
11
+ @climber.connection_pool.connections.each do |connection|
12
+ @test_jobs[connection.address] = []
13
+ 5.times.to_a.map! do
14
+ @test_jobs[connection.address] << StalkClimber::Job.new(connection.transmit(StalkClimber::Connection::PROBE_TRANSMISSION))
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+ should 'cache jobs for later use' do
21
+ jobs = {}
22
+ @climber.jobs.each do |job|
23
+ jobs[job.connection.address] ||= {}
24
+ jobs[job.connection.address][job.id] = job
25
+ end
26
+
27
+ @climber.expects(:with_job).never
28
+ @climber.jobs.each do |job|
29
+ assert_equal jobs[job.connection.address][job.id], job
30
+ end
31
+
32
+ @climber.connection_pool.connections.each do |connection|
33
+ @test_jobs[connection.address].map(&:delete)
34
+ end
35
+ end
36
+
37
+
38
+ should 'allow breaking from enumeration' do
39
+ begin
40
+ count = 0
41
+ @climber.jobs.each do |job|
42
+ break if 2 == count += 1
43
+ assert(false, "Jobs#each did not break when expected") if count >= 3
44
+ end
45
+ rescue => e
46
+ assert(false, "Breaking from Jobs#each raised #{e.inspect}")
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+
53
+ context '#each_threaded' do
54
+
55
+ should 'work correctly in non-break situations' do
56
+ climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
57
+ test_jobs = {}
58
+ climber.connection_pool.connections.each do |connection|
59
+ test_jobs[connection.address] = []
60
+ 5.times.to_a.map! do
61
+ test_jobs[connection.address] << StalkClimber::Job.new(connection.transmit(StalkClimber::Connection::PROBE_TRANSMISSION))
62
+ end
63
+ end
64
+
65
+ climber.jobs.each_threaded do |job|
66
+ job
67
+ end
68
+
69
+ climber.connection_pool.connections.each do |connection|
70
+ test_jobs[connection.address].map(&:delete)
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+
77
+ context 'enumberable contract' do
78
+
79
+ should 'function correctly as an enumerable' do
80
+ climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
81
+ test_jobs = {}
82
+ climber.connection_pool.connections.each do |connection|
83
+ test_jobs[connection.address] = []
84
+ 5.times.to_a.map! do
85
+ test_jobs[connection.address] << StalkClimber::Job.new(connection.transmit(StalkClimber::Connection::PROBE_TRANSMISSION))
86
+ end
87
+ end
88
+
89
+ # verify enumeration can be short circuited
90
+ climber.jobs.any? do |job|
91
+ true
92
+ end
93
+
94
+ # test normal enumeration
95
+ climber.jobs.all? do |job|
96
+ job
97
+ end
98
+
99
+ climber.connection_pool.connections.each do |connection|
100
+ test_jobs[connection.address].map(&:delete)
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end