stalk_climber 0.0.6 → 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.
@@ -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