adsp 1.0.2 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/{test → lib/adsp/test}/common.rb +4 -1
  3. data/{test → lib/adsp/test}/coverage_helper.rb +0 -0
  4. data/lib/adsp/test/file.rb +120 -0
  5. data/{test → lib/adsp/test}/minitest.rb +1 -0
  6. data/{test → lib/adsp/test}/mock/common.rb +1 -0
  7. data/{test → lib/adsp/test}/mock/file.rb +1 -0
  8. data/{test → lib/adsp/test}/mock/stream/raw/compressor.rb +1 -0
  9. data/{test → lib/adsp/test}/mock/stream/raw/decompressor.rb +1 -0
  10. data/{test → lib/adsp/test}/mock/stream/raw/native_compressor.rb +1 -0
  11. data/{test → lib/adsp/test}/mock/stream/raw/native_decompressor.rb +1 -0
  12. data/{test → lib/adsp/test}/mock/stream/reader.rb +1 -0
  13. data/{test → lib/adsp/test}/mock/stream/writer.rb +1 -0
  14. data/{test → lib/adsp/test}/mock/string.rb +1 -0
  15. data/{test → lib/adsp/test}/option.rb +1 -0
  16. data/{test → lib/adsp/test}/stream/abstract.rb +1 -0
  17. data/lib/adsp/test/stream/minitar.rb +50 -0
  18. data/{test → lib/adsp/test}/stream/raw/abstract.rb +1 -0
  19. data/lib/adsp/test/stream/raw/compressor.rb +165 -0
  20. data/lib/adsp/test/stream/raw/decompressor.rb +165 -0
  21. data/lib/adsp/test/stream/reader.rb +642 -0
  22. data/lib/adsp/test/stream/reader_helpers.rb +421 -0
  23. data/lib/adsp/test/stream/writer.rb +609 -0
  24. data/lib/adsp/test/stream/writer_helpers.rb +267 -0
  25. data/lib/adsp/test/string.rb +95 -0
  26. data/{test → lib/adsp/test}/validation.rb +7 -0
  27. data/lib/adsp/test/version.rb +18 -0
  28. data/lib/adsp/version.rb +1 -1
  29. data/test/file.test.rb +3 -116
  30. data/test/stream/minitar.test.rb +3 -46
  31. data/test/stream/raw/compressor.test.rb +3 -162
  32. data/test/stream/raw/decompressor.test.rb +3 -162
  33. data/test/stream/reader.test.rb +3 -639
  34. data/test/stream/reader_helpers.test.rb +3 -417
  35. data/test/stream/writer.test.rb +3 -606
  36. data/test/stream/writer_helpers.test.rb +3 -263
  37. data/test/string.test.rb +3 -91
  38. data/test/version.test.rb +3 -14
  39. metadata +28 -19
@@ -1,643 +1,7 @@
1
1
  # Abstract data stream processor.
2
2
  # Copyright (c) 2021 AUTHORS, MIT License.
3
3
 
4
- require "set"
5
- require "socket"
6
- require "stringio"
4
+ require "adsp/test/minitest"
5
+ require "adsp/test/stream/reader"
7
6
 
8
- require_relative "abstract"
9
- require_relative "../common"
10
- require_relative "../minitest"
11
- require_relative "../option"
12
- require_relative "../validation"
13
- require_relative "../mock/stream/reader"
14
- require_relative "../mock/string"
15
-
16
- module ADSP
17
- module Test
18
- module Stream
19
- class Reader < Abstract
20
- Target = Mock::Stream::Reader
21
- String = Mock::String
22
-
23
- ARCHIVE_PATH = Common::ARCHIVE_PATH
24
- ENCODINGS = Common::ENCODINGS
25
- TRANSCODE_OPTIONS = Common::TRANSCODE_OPTIONS
26
- TEXTS = Common::TEXTS
27
- LARGE_TEXTS = Common::LARGE_TEXTS
28
- PORTION_LENGTHS = Common::PORTION_LENGTHS
29
- LARGE_PORTION_LENGTHS = Common::LARGE_PORTION_LENGTHS
30
-
31
- BUFFER_LENGTH_NAMES = %i[source_buffer_length destination_buffer_length].freeze
32
- BUFFER_LENGTH_MAPPING = {
33
- :source_buffer_length => :destination_buffer_length,
34
- :destination_buffer_length => :source_buffer_length
35
- }
36
- .freeze
37
-
38
- def test_invalid_initialize
39
- get_invalid_decompressor_options do |invalid_options|
40
- assert_raises ValidateError do
41
- target.new ::StringIO.new, invalid_options
42
- end
43
- end
44
-
45
- super
46
- end
47
-
48
- # -- synchronous --
49
-
50
- def test_invalid_read
51
- instance = target.new ::StringIO.new
52
-
53
- (Validation::INVALID_NOT_NEGATIVE_INTEGERS - [nil]).each do |invalid_integer|
54
- assert_raises ValidateError do
55
- instance.read invalid_integer
56
- end
57
- end
58
-
59
- (Validation::INVALID_STRINGS - [nil]).each do |invalid_string|
60
- assert_raises ValidateError do
61
- instance.read nil, invalid_string
62
- end
63
- end
64
-
65
- assert_raises ValidateError do
66
- instance = target.new Validation::StringIOWithoutRead.new
67
- instance.read
68
- end
69
-
70
- assert_raises ValidateError do
71
- instance = target.new Validation::StringIOWithoutEOF.new
72
- instance.read
73
- end
74
- end
75
-
76
- def test_read
77
- parallel_compressor_options do |compressor_options|
78
- TEXTS.each do |text|
79
- archive = get_archive text, compressor_options
80
- prev_result = "".b
81
-
82
- Option::BOOLS.each do |with_buffer|
83
- PORTION_LENGTHS.each do |portion_length|
84
- get_compatible_decompressor_options compressor_options do |decompressor_options|
85
- instance = target.new ::StringIO.new(archive), decompressor_options
86
- decompressed_text = "".b
87
-
88
- begin
89
- result = instance.read 0
90
- assert_equal "", result
91
-
92
- loop do
93
- prev_eof = instance.eof?
94
-
95
- result =
96
- if with_buffer
97
- instance.read portion_length, prev_result
98
- else
99
- instance.read portion_length
100
- end
101
-
102
- if result.nil?
103
- assert_predicate instance, :eof?
104
- break
105
- end
106
-
107
- refute prev_eof unless archive.bytesize.zero?
108
-
109
- assert_equal prev_result, result if with_buffer
110
- decompressed_text << result
111
- end
112
-
113
- assert_equal instance.pos, decompressed_text.bytesize
114
- assert_equal instance.pos, instance.tell
115
- ensure
116
- refute_predicate instance, :closed?
117
- instance.close
118
- assert_predicate instance, :closed?
119
- end
120
-
121
- decompressed_text.force_encoding text.encoding
122
- assert_equal text, decompressed_text
123
- end
124
- end
125
-
126
- get_compatible_decompressor_options compressor_options do |decompressor_options|
127
- instance = target.new ::StringIO.new(archive), decompressor_options
128
- decompressed_text = nil
129
-
130
- begin
131
- prev_eof = instance.eof?
132
-
133
- if with_buffer
134
- decompressed_text = instance.read nil, prev_result
135
- assert_equal prev_result, decompressed_text
136
- else
137
- decompressed_text = instance.read
138
- end
139
-
140
- assert_predicate instance, :eof?
141
- refute prev_eof unless archive.bytesize.zero?
142
-
143
- assert_equal instance.pos, decompressed_text.bytesize
144
- assert_equal instance.pos, instance.tell
145
- ensure
146
- refute_predicate instance, :closed?
147
- instance.close
148
- assert_predicate instance, :closed?
149
- end
150
-
151
- decompressed_text.force_encoding text.encoding
152
- assert_equal text, decompressed_text
153
- end
154
- end
155
- end
156
- end
157
- end
158
-
159
- def test_read_with_large_texts
160
- options_generator = OCG.new(
161
- :text => LARGE_TEXTS,
162
- :with_buffer => Option::BOOLS
163
- )
164
-
165
- Common.parallel_options options_generator do |options|
166
- text = options[:text]
167
- with_buffer = options[:with_buffer]
168
-
169
- archive = get_archive text
170
- prev_result = "".b
171
-
172
- LARGE_PORTION_LENGTHS.each do |portion_length|
173
- instance = target.new ::StringIO.new(archive)
174
- decompressed_text = "".b
175
-
176
- begin
177
- loop do
178
- result =
179
- if with_buffer
180
- instance.read portion_length, prev_result
181
- else
182
- instance.read portion_length
183
- end
184
-
185
- break if result.nil?
186
-
187
- assert_equal prev_result, result if with_buffer
188
- decompressed_text << result
189
- end
190
- ensure
191
- instance.close
192
- end
193
-
194
- decompressed_text.force_encoding text.encoding
195
- assert_equal text, decompressed_text
196
- end
197
-
198
- instance = target.new ::StringIO.new(archive)
199
- decompressed_text = nil
200
-
201
- begin
202
- if with_buffer
203
- decompressed_text = instance.read nil, prev_result
204
- assert_equal prev_result, decompressed_text
205
- else
206
- decompressed_text = instance.read
207
- end
208
- ensure
209
- instance.close
210
- end
211
-
212
- decompressed_text.force_encoding text.encoding
213
- assert_equal text, decompressed_text
214
- end
215
- end
216
-
217
- def test_encoding
218
- parallel_compressor_options do |compressor_options|
219
- TEXTS.each do |text|
220
- external_encoding = text.encoding
221
- archive = get_archive text, compressor_options
222
-
223
- PORTION_LENGTHS.each do |portion_length|
224
- get_compatible_decompressor_options compressor_options do |decompressor_options|
225
- instance = target.new ::StringIO.new(archive), decompressor_options
226
- decompressed_text = "".b
227
-
228
- begin
229
- result = instance.read 0
230
- assert_equal Encoding::BINARY, result.encoding
231
-
232
- loop do
233
- result = instance.read portion_length
234
- break if result.nil?
235
-
236
- assert_equal Encoding::BINARY, result.encoding
237
- decompressed_text << result
238
- end
239
- ensure
240
- instance.close
241
- end
242
-
243
- decompressed_text.force_encoding external_encoding
244
- assert_equal text, decompressed_text
245
- end
246
- end
247
-
248
- # We don't need to transcode between same encodings.
249
- (ENCODINGS - [external_encoding]).each do |internal_encoding|
250
- target_text = text.encode internal_encoding, **TRANSCODE_OPTIONS
251
-
252
- get_compatible_decompressor_options compressor_options do |decompressor_options|
253
- instance = target.new(
254
- ::StringIO.new(archive),
255
- decompressor_options,
256
- :external_encoding => external_encoding,
257
- :internal_encoding => internal_encoding,
258
- :transcode_options => TRANSCODE_OPTIONS
259
- )
260
-
261
- assert_equal external_encoding, instance.external_encoding
262
- assert_equal internal_encoding, instance.internal_encoding
263
- assert_equal TRANSCODE_OPTIONS, instance.transcode_options
264
-
265
- decompressed_text = nil
266
-
267
- begin
268
- instance.set_encoding external_encoding, internal_encoding, TRANSCODE_OPTIONS
269
- assert_equal external_encoding, instance.external_encoding
270
- assert_equal internal_encoding, instance.internal_encoding
271
- assert_equal TRANSCODE_OPTIONS, instance.transcode_options
272
-
273
- decompressed_text = instance.read
274
- assert_equal internal_encoding, decompressed_text.encoding
275
- ensure
276
- instance.close
277
- end
278
-
279
- assert_equal target_text, decompressed_text
280
- assert_predicate target_text, :valid_encoding?
281
- end
282
- end
283
- end
284
- end
285
- end
286
-
287
- def test_rewind
288
- parallel_compressor_options do |compressor_options, worker_index|
289
- archive_path = Common.get_path ARCHIVE_PATH, worker_index
290
-
291
- TEXTS.each do |text|
292
- write_archive archive_path, text, compressor_options
293
-
294
- get_compatible_decompressor_options compressor_options do |decompressor_options|
295
- decompressed_text = nil
296
-
297
- ::File.open archive_path, "rb" do |file|
298
- instance = target.new file, decompressor_options
299
-
300
- begin
301
- result_1 = instance.read
302
-
303
- assert_equal 0, instance.rewind
304
- assert_equal 0, instance.pos
305
- assert_equal instance.pos, instance.tell
306
-
307
- result_2 = instance.read
308
- assert_equal result_1, result_2
309
-
310
- decompressed_text = result_1
311
- ensure
312
- instance.close
313
- end
314
- end
315
-
316
- decompressed_text.force_encoding text.encoding
317
- assert_equal text, decompressed_text
318
- end
319
- end
320
- end
321
- end
322
-
323
- def test_invalid_eof
324
- assert_raises ValidateError do
325
- instance = target.new Validation::StringIOWithoutEOF.new
326
- instance.eof?
327
- end
328
- end
329
-
330
- def test_eof
331
- compressed_text = String.compress "ab"
332
- instance = target.new ::StringIO.new(compressed_text)
333
-
334
- refute_predicate instance, :eof?
335
-
336
- byte = instance.read 1
337
- refute_predicate instance, :eof?
338
- assert_equal "a", byte
339
-
340
- byte = instance.read 1
341
- assert_predicate instance, :eof?
342
- assert_equal "b", byte
343
- end
344
-
345
- # -- asynchronous --
346
-
347
- def test_invalid_readpartial_and_read_nonblock
348
- instance = target.new ::StringIO.new
349
-
350
- Validation::INVALID_NOT_NEGATIVE_INTEGERS.each do |invalid_integer|
351
- assert_raises ValidateError do
352
- instance.readpartial invalid_integer
353
- end
354
- assert_raises ValidateError do
355
- instance.read_nonblock invalid_integer
356
- end
357
- end
358
-
359
- (Validation::INVALID_STRINGS - [nil]).each do |invalid_string|
360
- assert_raises ValidateError do
361
- instance.readpartial 0, invalid_string
362
- end
363
- assert_raises ValidateError do
364
- instance.read_nonblock 0, invalid_string
365
- end
366
- end
367
-
368
- assert_raises ValidateError do
369
- instance = target.new Validation::StringIOWithoutReadpartial.new
370
- instance.readpartial 1
371
- end
372
-
373
- assert_raises ValidateError do
374
- instance = target.new Validation::StringIOWithoutReadNonblock.new
375
- instance.read_nonblock 1
376
- end
377
- end
378
-
379
- def test_readpartial
380
- IO.pipe do |read_io, write_io|
381
- instance = target.new read_io
382
- write_io.close
383
-
384
- assert_raises ::EOFError do
385
- instance.readpartial 1
386
- end
387
- end
388
-
389
- nonblock_server do |server|
390
- parallel_compressor_options do |compressor_options|
391
- TEXTS.each do |text|
392
- PORTION_LENGTHS.each do |portion_length|
393
- Option::BOOLS.each do |with_buffer|
394
- nonblock_test server, text, portion_length, compressor_options do |instance|
395
- prev_result = "".b
396
- decompressed_text = "".b
397
-
398
- loop do
399
- if with_buffer
400
- result = instance.readpartial portion_length, prev_result
401
- assert_equal prev_result, result
402
- else
403
- result = instance.readpartial portion_length
404
- end
405
-
406
- decompressed_text << result
407
- rescue ::EOFError
408
- break
409
- end
410
-
411
- decompressed_text
412
- end
413
- end
414
- end
415
- end
416
- end
417
- end
418
- end
419
-
420
- def test_read_nonblock
421
- IO.pipe do |read_io, write_io|
422
- instance = target.new read_io
423
-
424
- assert_raises ::IO::WaitReadable do
425
- instance.read_nonblock 1
426
- end
427
-
428
- write_io.close
429
-
430
- assert_raises ::EOFError do
431
- instance.read_nonblock 1
432
- end
433
- end
434
-
435
- nonblock_server do |server|
436
- parallel_compressor_options do |compressor_options|
437
- TEXTS.each do |text|
438
- PORTION_LENGTHS.each do |portion_length|
439
- nonblock_test server, text, portion_length, compressor_options do |instance, socket|
440
- decompressed_text = "".b
441
-
442
- loop do
443
- begin
444
- decompressed_text << instance.read_nonblock(portion_length)
445
- rescue ::IO::WaitReadable
446
- socket.wait_readable
447
- retry
448
- rescue ::EOFError
449
- break
450
- end
451
-
452
- begin
453
- decompressed_text << instance.readpartial(portion_length)
454
- rescue ::EOFError
455
- break
456
- end
457
-
458
- result = instance.read portion_length
459
- break if result.nil?
460
-
461
- decompressed_text << result
462
- end
463
-
464
- decompressed_text
465
- end
466
- end
467
- end
468
- end
469
- end
470
- end
471
-
472
- def test_read_nonblock_with_large_texts
473
- nonblock_server do |server|
474
- Common.parallel LARGE_TEXTS do |text|
475
- LARGE_PORTION_LENGTHS.each do |portion_length|
476
- nonblock_test server, text, portion_length do |instance, socket|
477
- decompressed_text = "".b
478
-
479
- loop do
480
- begin
481
- decompressed_text << instance.read_nonblock(portion_length)
482
- rescue ::IO::WaitReadable
483
- socket.wait_readable
484
- retry
485
- rescue ::EOFError
486
- break
487
- end
488
-
489
- begin
490
- decompressed_text << instance.readpartial(portion_length)
491
- rescue ::EOFError
492
- break
493
- end
494
-
495
- result = instance.read portion_length
496
- break if result.nil?
497
-
498
- decompressed_text << result
499
- end
500
-
501
- decompressed_text
502
- end
503
- end
504
- end
505
- end
506
- end
507
-
508
- # -- nonblock test --
509
-
510
- protected def nonblock_server
511
- # Server need just to redirect content for client.
512
-
513
- ::TCPServer.open 0 do |server|
514
- # Server loop will be processed in separate (parent) thread.
515
- # Child threads will be collected for later usage.
516
- child_lock = ::Mutex.new
517
- child_threads = ::Set.new
518
-
519
- parent_thread = ::Thread.new do
520
- loop do
521
- child_thread = ::Thread.start server.accept do |socket|
522
- result = "".b
523
-
524
- # Reading head.
525
- result_size, portion_length = socket.read(16).unpack "QQ"
526
- next if result_size.zero?
527
-
528
- # Reading result.
529
- loop do
530
- begin
531
- result << socket.read_nonblock(portion_length)
532
- rescue ::IO::WaitReadable
533
- socket.wait_readable
534
- retry
535
- end
536
-
537
- break if result.bytesize == result_size
538
- end
539
-
540
- # Writing result.
541
- loop do
542
- begin
543
- bytes_written = socket.write_nonblock result
544
- rescue ::IO::WaitWritable
545
- socket.wait_writable
546
- retry
547
- end
548
-
549
- result = result.byteslice bytes_written, result.bytesize - bytes_written
550
- result_size -= bytes_written
551
-
552
- break if result_size.zero?
553
- end
554
-
555
- ensure
556
- socket.close
557
-
558
- # Removing current child thread.
559
- child_lock.synchronize { child_threads.delete ::Thread.current }
560
- end
561
-
562
- # Adding new child thread.
563
- child_lock.synchronize { child_threads.add child_thread }
564
- end
565
- end
566
-
567
- # Processing client.
568
- begin
569
- yield server
570
- ensure
571
- # We need to kill parent thread when client has finished.
572
- # So server won't be able to create new child threads.
573
- # Than we can join all remaining child threads.
574
- parent_thread.kill.join
575
- child_threads.each(&:join)
576
- end
577
- end
578
- end
579
-
580
- protected def nonblock_test(server, text, portion_length, compressor_options = {}, &_block)
581
- port = server.addr[1]
582
- compressed_text = String.compress text, compressor_options
583
-
584
- processor = proc do |decompressor_options|
585
- decompressed_text = ::TCPSocket.open "localhost", port do |socket|
586
- # Writing head.
587
- head = [compressed_text.bytesize, portion_length].pack "QQ"
588
- socket.write head
589
-
590
- # Writing compressed text.
591
- socket.write compressed_text
592
-
593
- instance = target.new socket, decompressor_options
594
-
595
- begin
596
- yield instance, socket
597
- ensure
598
- instance.close
599
- end
600
- end
601
-
602
- # Testing decompressed text.
603
- decompressed_text.force_encoding text.encoding
604
- assert_equal text, decompressed_text
605
- end
606
-
607
- if compressor_options.empty?
608
- processor.call({})
609
- else
610
- get_compatible_decompressor_options compressor_options do |decompressor_options|
611
- processor.call decompressor_options
612
- end
613
- end
614
- end
615
-
616
- # -----
617
-
618
- protected def get_archive(text, compressor_options = {})
619
- String.compress text, compressor_options
620
- end
621
-
622
- protected def write_archive(archive_path, text, compressor_options = {})
623
- compressed_text = String.compress text, compressor_options
624
- ::File.write archive_path, compressed_text, :mode => "wb"
625
- end
626
-
627
- def get_invalid_decompressor_options(&block)
628
- Option.get_invalid_decompressor_options BUFFER_LENGTH_NAMES, &block
629
- end
630
-
631
- def parallel_compressor_options(&block)
632
- Common.parallel_options Option.get_compressor_options_generator(BUFFER_LENGTH_NAMES), &block
633
- end
634
-
635
- def get_compatible_decompressor_options(compressor_options, &block)
636
- Option.get_compatible_decompressor_options compressor_options, BUFFER_LENGTH_MAPPING, &block
637
- end
638
- end
639
-
640
- Minitest << Reader
641
- end
642
- end
643
- end
7
+ Minitest << ADSP::Test::Stream::Reader