kronk 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,589 @@
1
+ require 'test/test_helper'
2
+
3
+ class TestPlayer < Test::Unit::TestCase
4
+
5
+ class MockPipe < StringIO; end
6
+
7
+ class MockOutput < Kronk::Player::Output
8
+ attr_accessor :result_calls
9
+
10
+ def initialize *args
11
+ @result_calls = 0
12
+ super
13
+ end
14
+
15
+ def result kronk, mutex
16
+ mutex.synchronize do
17
+ @result_calls += 1
18
+ end
19
+ end
20
+ end
21
+
22
+ class MockParser
23
+ def self.parse str
24
+ str
25
+ end
26
+ end
27
+
28
+
29
+ def setup
30
+ @io = MockPipe.new
31
+ @parser = MockParser
32
+ @output = MockOutput
33
+ @player = Kronk::Player.new :io => @io,
34
+ :parser => @parser,
35
+ :output => @output
36
+ end
37
+
38
+
39
+ def test_init_defaults
40
+ player = Kronk::Player.new
41
+ assert_equal Kronk::Player::Suite, player.output.class
42
+ assert_equal Kronk::Player::InputReader, player.input.class
43
+ assert_equal Mutex, player.mutex.class
44
+ assert_equal 1, player.concurrency
45
+ assert_nil player.input.io
46
+ assert_nil player.number
47
+ assert player.queue.empty?
48
+ assert player.threads.empty?
49
+ end
50
+
51
+
52
+ def test_init
53
+ assert_equal Kronk::Player::InputReader, @player.input.class
54
+ assert_equal Mutex, @player.mutex.class
55
+ assert_equal @io, @player.input.io
56
+ assert_equal 1, @player.concurrency
57
+ assert_nil @player.number
58
+ assert @player.queue.empty?
59
+ assert @player.threads.empty?
60
+ end
61
+
62
+
63
+ def test_init_opts
64
+ player = Kronk::Player.new :number => 1000,
65
+ :concurrency => 10,
66
+ :output => :stream
67
+
68
+ assert_equal Kronk::Player::Stream, player.output.class
69
+ assert_equal Kronk::Player::RequestParser, player.input.parser
70
+ assert_equal 10, player.concurrency
71
+ assert_equal 1000, player.number
72
+ end
73
+
74
+
75
+ def test_output
76
+ @player.output_from :benchmark
77
+ assert_equal Kronk::Player::Benchmark, @player.output.class
78
+
79
+ @player.output_from :stream
80
+ assert_equal Kronk::Player::Stream, @player.output.class
81
+
82
+ @player.output_from :suite
83
+ assert_equal Kronk::Player::Suite, @player.output.class
84
+
85
+ @player.output_from Kronk::Player::Benchmark
86
+ assert_equal Kronk::Player::Benchmark, @player.output.class
87
+ end
88
+
89
+
90
+ def test_queue_req
91
+ @player.queue_req :first_item
92
+ @player.queue_req :second_item
93
+ assert_equal [:first_item, :second_item], @player.queue
94
+ end
95
+
96
+
97
+ def test_from_io
98
+ @player.from_io "mock"
99
+ assert_equal "mock", @player.input.io
100
+ assert_equal MockParser, @player.input.parser
101
+
102
+ @player.from_io "mock", "mock_parser"
103
+ assert_equal "mock", @player.input.io
104
+ assert_equal "mock_parser", @player.input.parser
105
+ end
106
+
107
+
108
+ def test_output_results
109
+ @player.output.expects(:completed).with().returns "FINISHED"
110
+ assert_equal "FINISHED", @player.output_results
111
+ end
112
+
113
+
114
+ def test_finished_false
115
+ @player.number = nil
116
+
117
+ @player.queue.clear
118
+ @player.count = 2
119
+ @player.input.stubs(:eof?).returns false
120
+ assert !@player.finished?
121
+
122
+ @player.queue << "test"
123
+ @player.count = 2
124
+ @player.input.stubs(:eof?).returns true
125
+ assert !@player.finished?
126
+
127
+ @player.count = 0
128
+ @player.queue.clear
129
+ @player.input.stubs(:eof?).returns true
130
+ assert !@player.finished?
131
+
132
+ @player.count = 4
133
+ @player.queue.clear
134
+ @player.input.stubs(:eof?).returns true
135
+ @player.reader_thread = "mock thread"
136
+ @player.reader_thread.expects(:alive?).returns true
137
+ assert !@player.finished?
138
+
139
+ @player.queue << "test"
140
+ @player.input.stubs(:eof?).returns true
141
+ @player.reader_thread.stubs(:alive?).returns false
142
+ @player.count = 5
143
+ @player.number = 10
144
+ assert !@player.finished?
145
+ end
146
+
147
+
148
+ def test_finished_true
149
+ @player.number = 4
150
+ @player.count = 4
151
+ assert @player.finished?
152
+
153
+ @player.number = nil
154
+ @player.count = 1
155
+ @player.queue.clear
156
+ @player.input.stubs(:eof?).returns true
157
+ @player.reader_thread = "mock thread"
158
+ @player.reader_thread.expects(:alive?).returns false
159
+ assert @player.finished?
160
+
161
+ @player.number = 10
162
+ @player.count = 1
163
+ @player.queue.clear
164
+ @player.input.stubs(:eof?).returns true
165
+ @player.reader_thread.expects(:alive?).returns false
166
+ assert @player.finished?
167
+ end
168
+
169
+
170
+ def test_compare_single
171
+ io1 = StringIO.new(mock_200_response)
172
+ io2 = StringIO.new(mock_302_response)
173
+ expect_compare_output mock_200_response, mock_302_response
174
+
175
+ @player.compare io1, io2
176
+ end
177
+
178
+
179
+ def test_compare
180
+ @player.concurrency = 3
181
+ @player.input.parser = Kronk::Player::RequestParser
182
+ @player.input.io << "/req3\n/req4\n/req5\n"
183
+ @player.input.io.rewind
184
+ @player.input.io.close_write
185
+
186
+ @player.queue.concat [{:uri_suffix => "/req1"}, {:uri_suffix => "/req2"}]
187
+
188
+ part1 = (1..2).map{|n| "/req#{n}"}
189
+ part2 = (3..5).map{|n| "/req#{n}"}
190
+
191
+ part1.each do |path|
192
+ mock_requests "example.com", "beta-example.com",
193
+ :uri_suffix => path,
194
+ :query => "foo=bar"
195
+ end
196
+
197
+ part2.each do |path|
198
+ mock_requests "example.com", "beta-example.com",
199
+ :uri_suffix => path,
200
+ :query => "foo=bar"
201
+ end
202
+
203
+ @player.compare "example.com", "beta-example.com", :query => "foo=bar"
204
+
205
+ assert_equal 5, @player.output.result_calls
206
+ end
207
+
208
+
209
+ def test_request_single
210
+ io = StringIO.new(mock_200_response)
211
+ expect_request_output mock_200_response
212
+
213
+ @player.request io
214
+ end
215
+
216
+
217
+ def test_request
218
+ @player.concurrency = 3
219
+ @player.input.parser = Kronk::Player::RequestParser
220
+ @player.input.io << "/req3\n/req4\n/req5\n"
221
+ @player.input.io.rewind
222
+ @player.input.io.close_write
223
+
224
+ @player.queue.concat [{:uri_suffix => "/req1"}, {:uri_suffix => "/req2"}]
225
+
226
+ part1 = (1..2).map{|n| "/req#{n}"}
227
+ part2 = (3..5).map{|n| "/req#{n}"}
228
+
229
+ part1.each do |path|
230
+ mock_requests "example.com",
231
+ :uri_suffix => path,
232
+ :query => "foo=bar"
233
+ end
234
+
235
+ part2.each do |path|
236
+ mock_requests "example.com",
237
+ :uri_suffix => path,
238
+ :query => "foo=bar"
239
+ end
240
+
241
+ @player.request "example.com", :query => "foo=bar"
242
+
243
+ assert_equal 5, @player.output.result_calls
244
+ end
245
+
246
+
247
+ def test_process_queue_interrupted
248
+ @player.concurrency = 0
249
+
250
+ @player.output.expects :start
251
+ @player.output.expects :completed
252
+
253
+ thread = Thread.new do
254
+ @player.process_queue
255
+ end
256
+
257
+ sleep 0.1
258
+ assert_exit 2 do
259
+ Process.kill 'INT', Process.pid
260
+ end
261
+
262
+ ensure
263
+ thread.kill
264
+ end
265
+
266
+
267
+ def test_process_queue
268
+ @player.concurrency = 10
269
+ requests = (1..20).map{|n| "request #{n}"}
270
+ @player.queue.concat requests.dup
271
+ @player.input.io.close
272
+
273
+ @player.output.expects :start
274
+ @player.output.expects :completed
275
+
276
+ start = Time.now
277
+ processed = []
278
+
279
+ @player.process_queue do |req|
280
+ processed << req
281
+ sleep 0.5
282
+ end
283
+
284
+ time_spent = (Time.now - start).to_i
285
+ assert_equal 1, time_spent
286
+ assert_equal 20, @player.count
287
+ assert @player.queue.empty?, "Expected queue to be empty"
288
+
289
+ processed.sort!{|r1, r2| r1.split.last.to_i <=> r2.split.last.to_i}
290
+ assert_equal requests, processed
291
+ end
292
+
293
+
294
+ def test_process_queue_from_io
295
+ @player.concurrency = 10
296
+ @player.output.expects :start
297
+ @player.output.expects :completed
298
+
299
+ @player.input.parser.stubs(:start_new?).returns true
300
+ @player.input.parser.stubs(:start_new?).with("").returns false
301
+
302
+ processed = []
303
+ start_time = 0
304
+ time_spent = 0
305
+
306
+ requests = (1..20).map{|n| "request #{n}\n"}
307
+ @player.from_io StringIO.new(requests.join)
308
+
309
+ start_time = Time.now
310
+ @player.process_queue do |req|
311
+ processed << req
312
+ sleep 0.5
313
+ end
314
+
315
+ time_spent = (Time.now - start_time).to_i
316
+
317
+ assert_equal 1, time_spent
318
+ assert_equal 20, @player.count
319
+ assert @player.queue.empty?, "Expected queue to be empty"
320
+
321
+ processed.sort! do |r1, r2|
322
+ r1.split.last.strip.to_i <=> r2.split.last.strip.to_i
323
+ end
324
+
325
+ assert_equal requests, processed
326
+ end
327
+
328
+
329
+ def test_single_request_from_io
330
+ @player.input.io = StringIO.new "mock request"
331
+ @player.input.parser.stubs(:start_new?).returns true
332
+ assert @player.single_request?, "Expected player to have one request"
333
+ end
334
+
335
+
336
+ def test_single_request_from_queue
337
+ @player.input.io = nil
338
+ assert @player.single_request?, "Expected player to have one request"
339
+ end
340
+
341
+
342
+ def test_not_single_request
343
+ @player.input.io = nil
344
+ @player.queue.concat Array.new(10, "mock request")
345
+ assert !@player.single_request?, "Expected player to have many requests"
346
+
347
+ @player.input.io = StringIO.new Array.new(5, "mock request").join("\n")
348
+ @player.queue.clear
349
+ @player.input.parser.expects(:start_new?).returns(true)
350
+
351
+ assert !@player.single_request?, "Expected player to have many requests"
352
+ end
353
+
354
+
355
+ def test_try_fill_queue_from_input
356
+ @player.input.stubs(:get_next).returns "mock_request"
357
+
358
+ @player.concurrency = 5
359
+ @player.number = 20
360
+
361
+ thread = @player.try_fill_queue
362
+ assert_equal Thread, thread.class
363
+
364
+ sleep 0.2
365
+ assert_equal Array.new(10, "mock_request"), @player.queue
366
+
367
+ @player.queue.slice!(8)
368
+
369
+ sleep 0.2
370
+ assert_equal Array.new(10, "mock_request"), @player.queue
371
+
372
+ ensure
373
+ thread.kill
374
+ end
375
+
376
+
377
+ def test_try_fill_queue_from_last
378
+ @player.input.stubs(:get_next).returns nil
379
+ @player.input.stubs(:eof?).returns false
380
+
381
+ @player.concurrency = 5
382
+ @player.queue << "mock_request"
383
+
384
+ thread = @player.try_fill_queue
385
+ assert_equal Thread, thread.class
386
+
387
+ sleep 0.2
388
+ assert_equal Array.new(10, "mock_request"), @player.queue
389
+
390
+ @player.queue.slice!(8)
391
+
392
+ sleep 0.2
393
+ assert_equal Array.new(10, "mock_request"), @player.queue
394
+
395
+ ensure
396
+ thread.kill
397
+ end
398
+
399
+
400
+ def test_try_fill_queue_no_input
401
+ @player.input.stubs(:eof?).returns true
402
+
403
+ @player.concurrency = 5
404
+ @player.queue << "mock_request"
405
+
406
+ thread = @player.try_fill_queue
407
+ assert_equal Thread, thread.class
408
+
409
+ sleep 0.2
410
+ assert_equal ["mock_request"], @player.queue
411
+
412
+ ensure
413
+ thread.kill
414
+ end
415
+
416
+
417
+ def test_next_request
418
+ @player.input.expects(:get_next).returns "NEXT ITEM"
419
+ assert_equal "NEXT ITEM", @player.next_request
420
+
421
+ @player.input.expects(:get_next).returns nil
422
+ @player.queue.concat ["FIRST ITEM", "QUEUE REPEAT"]
423
+ assert_equal "QUEUE REPEAT", @player.next_request
424
+
425
+ @player.input.expects(:get_next).returns nil
426
+ @player.queue.clear
427
+ @player.instance_variable_set "@last_req", "LAST REQ"
428
+ assert_equal "LAST REQ", @player.next_request
429
+
430
+ @player.input.expects(:get_next).returns nil
431
+ @player.queue.clear
432
+ @player.instance_variable_set "@last_req", nil
433
+ assert_equal Hash.new, @player.next_request
434
+ end
435
+
436
+
437
+ def test_process_compare
438
+ mock_thread = "mock_thread"
439
+ Thread.expects(:new).twice.yields.returns mock_thread
440
+ mock_thread.expects(:join).twice
441
+
442
+ resp1 = Kronk::Response.new mock_resp("200_response.json")
443
+ resp1.parser = JSON
444
+ resp2 = Kronk::Response.new mock_resp("200_response.txt")
445
+
446
+ req1 = Kronk::Request.new "example.com"
447
+ req2 = Kronk::Request.new "beta-example.com"
448
+
449
+ Kronk::Request.expects(:new).returns req2
450
+ Kronk::Request.expects(:new).returns req1
451
+
452
+ req1.expects(:retrieve).returns resp1
453
+ req2.expects(:retrieve).returns resp2
454
+
455
+ @got_results = nil
456
+
457
+ @player.output.expects(:result).with do |kronk, mutex|
458
+ @got_results = true
459
+ assert_equal @player.mutex, mutex
460
+ assert_equal Kronk::Diff.new(resp1.stringify, resp2.stringify).formatted,
461
+ kronk.diff.formatted
462
+ true
463
+ end
464
+
465
+ @player.process_compare "example.com", "beta-example.com",
466
+ :uri_suffix => "/test", :include_headers => true
467
+
468
+ assert @got_results, "Expected output to get results but didn't"
469
+ end
470
+
471
+
472
+ def test_process_compare_error
473
+ @got_results = []
474
+
475
+ @player.output.expects(:error).times(3).with do |error, kronk, mutex|
476
+ @got_results << error.class
477
+ assert_equal @player.mutex, mutex
478
+ assert_equal Kronk, kronk.class
479
+ true
480
+ end
481
+
482
+ errs = [Kronk::Exception, Kronk::Response::MissingParser, Errno::ECONNRESET]
483
+ errs.each do |eklass|
484
+ Kronk.any_instance.expects(:compare).raises eklass
485
+
486
+ @player.process_compare "example.com", "beta-example.com",
487
+ :uri_suffix => "/test", :include_headers => true
488
+ end
489
+
490
+ assert_equal errs, @got_results, "Expected output to get errors but didn't"
491
+ end
492
+
493
+
494
+ def test_process_compare_error_not_caught
495
+ Kronk.any_instance.expects(:compare).raises RuntimeError
496
+
497
+ assert_raises RuntimeError do
498
+ @player.process_compare "example.com", "beta-example.com",
499
+ :uri_suffix => "/test", :include_headers => true
500
+ end
501
+ end
502
+
503
+
504
+ def test_process_request
505
+ resp = Kronk::Response.new mock_resp("200_response.json")
506
+ resp.parser = JSON
507
+
508
+ req = Kronk::Request.new "example.com"
509
+ req.expects(:retrieve).returns resp
510
+
511
+ Kronk::Request.expects(:new).returns req
512
+
513
+ @got_results = nil
514
+
515
+ @player.output.expects(:result).with do |kronk, mutex|
516
+ @got_results = true
517
+ assert_equal @player.mutex, mutex
518
+ assert_equal resp, kronk.response
519
+ true
520
+ end
521
+
522
+ @player.process_request "example.com",
523
+ :uri_suffix => "/test", :include_headers => true
524
+
525
+ assert @got_results, "Expected output to get results but didn't"
526
+ end
527
+
528
+
529
+ def test_process_request_error
530
+ @got_results = []
531
+
532
+ @player.output.expects(:error).times(3).with do |error, kronk, mutex|
533
+ @got_results << error.class
534
+ assert_equal @player.mutex, mutex
535
+ assert_equal Kronk, kronk.class
536
+ true
537
+ end
538
+
539
+ errs = [Kronk::Exception, Kronk::Response::MissingParser, Errno::ECONNRESET]
540
+ errs.each do |eklass|
541
+ Kronk.any_instance.expects(:retrieve).raises eklass
542
+
543
+ @player.process_request "example.com",
544
+ :uri_suffix => "/test", :include_headers => true
545
+ end
546
+
547
+ assert_equal errs, @got_results, "Expected output to get errors but didn't"
548
+ end
549
+
550
+
551
+ def test_process_request_error_not_caught
552
+ Kronk.any_instance.expects(:retrieve).raises RuntimeError
553
+
554
+ assert_raises RuntimeError do
555
+ @player.process_request "example.com",
556
+ :uri_suffix => "/test", :include_headers => true
557
+ end
558
+ end
559
+
560
+
561
+ private
562
+
563
+ def mock_requests *setup
564
+ resp = []
565
+ req = []
566
+
567
+ opts = setup.length > 1 && Hash === setup.last ?
568
+ setup.delete_at(-1) : Hash.new
569
+
570
+ case setup.first
571
+ when Hash
572
+ hash = setup.first
573
+ req = hash.keys
574
+ resp = req.map{|k| hash[k]}
575
+
576
+ when String
577
+ req = setup
578
+ resp = [mock_resp("200_response.txt")] * setup.length
579
+ end
580
+
581
+ req.each_with_index do |r, i|
582
+ mock_req = "mock request"
583
+ mock_res = Kronk::Response.new resp[i]
584
+ Kronk::Request.stubs(:new).with(req[i], opts).returns mock_req
585
+ mock_req.stubs(:retrieve).returns mock_res
586
+ mock_req.stubs(:uri).returns nil
587
+ end
588
+ end
589
+ end