adsp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +1 -0
  3. data/LICENSE +21 -0
  4. data/README.md +300 -0
  5. data/lib/adsp/error.rb +14 -0
  6. data/lib/adsp/file.rb +76 -0
  7. data/lib/adsp/option.rb +51 -0
  8. data/lib/adsp/stream/abstract.rb +206 -0
  9. data/lib/adsp/stream/delegates.rb +39 -0
  10. data/lib/adsp/stream/raw/abstract.rb +69 -0
  11. data/lib/adsp/stream/raw/compressor.rb +110 -0
  12. data/lib/adsp/stream/raw/decompressor.rb +80 -0
  13. data/lib/adsp/stream/raw/native_compressor.rb +58 -0
  14. data/lib/adsp/stream/raw/native_decompressor.rb +44 -0
  15. data/lib/adsp/stream/reader.rb +234 -0
  16. data/lib/adsp/stream/reader_helpers.rb +219 -0
  17. data/lib/adsp/stream/stat.rb +80 -0
  18. data/lib/adsp/stream/writer.rb +206 -0
  19. data/lib/adsp/stream/writer_helpers.rb +102 -0
  20. data/lib/adsp/string.rb +58 -0
  21. data/lib/adsp/validation.rb +46 -0
  22. data/lib/adsp/version.rb +7 -0
  23. data/lib/adsp.rb +8 -0
  24. data/test/common.rb +108 -0
  25. data/test/coverage_helper.rb +18 -0
  26. data/test/file.test.rb +120 -0
  27. data/test/minitest.rb +20 -0
  28. data/test/mock/common.rb +57 -0
  29. data/test/mock/file.rb +60 -0
  30. data/test/mock/stream/raw/compressor.rb +20 -0
  31. data/test/mock/stream/raw/decompressor.rb +20 -0
  32. data/test/mock/stream/raw/native_compressor.rb +82 -0
  33. data/test/mock/stream/raw/native_decompressor.rb +70 -0
  34. data/test/mock/stream/reader.rb +18 -0
  35. data/test/mock/stream/writer.rb +18 -0
  36. data/test/mock/string.rb +44 -0
  37. data/test/option.rb +66 -0
  38. data/test/stream/abstract.rb +125 -0
  39. data/test/stream/minitar.test.rb +50 -0
  40. data/test/stream/raw/abstract.rb +45 -0
  41. data/test/stream/raw/compressor.test.rb +166 -0
  42. data/test/stream/raw/decompressor.test.rb +166 -0
  43. data/test/stream/reader.test.rb +643 -0
  44. data/test/stream/reader_helpers.test.rb +421 -0
  45. data/test/stream/writer.test.rb +610 -0
  46. data/test/stream/writer_helpers.test.rb +267 -0
  47. data/test/string.test.rb +95 -0
  48. data/test/validation.rb +71 -0
  49. data/test/version.test.rb +18 -0
  50. metadata +274 -0
data/test/option.rb ADDED
@@ -0,0 +1,66 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require "ocg"
5
+ require "adsp/option"
6
+
7
+ require_relative "validation"
8
+
9
+ module ADSP
10
+ module Test
11
+ module Option
12
+ private_class_method def self.get_common_invalid_options(buffer_length_names, &block)
13
+ Validation::INVALID_HASHES.each(&block)
14
+
15
+ buffer_length_names.each do |name|
16
+ (Validation::INVALID_NOT_NEGATIVE_INTEGERS - [nil]).each do |invalid_integer|
17
+ yield({ name => invalid_integer })
18
+ end
19
+ end
20
+ end
21
+
22
+ def self.get_invalid_compressor_options(buffer_length_names, &block)
23
+ get_common_invalid_options buffer_length_names, &block
24
+ end
25
+
26
+ def self.get_invalid_decompressor_options(buffer_length_names, &block)
27
+ get_common_invalid_options buffer_length_names, &block
28
+ end
29
+
30
+ # -----
31
+
32
+ # "0" means default buffer length.
33
+ BUFFER_LENGTHS = [
34
+ 0,
35
+ 2
36
+ ]
37
+ .freeze
38
+
39
+ BOOLS = [
40
+ true,
41
+ false
42
+ ]
43
+ .freeze
44
+
45
+ private_class_method def self.get_buffer_length_option_generator(buffer_length_names)
46
+ OCG.new(
47
+ buffer_length_names.to_h { |name| [name, self::BUFFER_LENGTHS] }
48
+ )
49
+ end
50
+
51
+ def self.get_compressor_options_generator(buffer_length_names)
52
+ get_buffer_length_option_generator buffer_length_names
53
+ end
54
+
55
+ def self.get_compatible_decompressor_options(compressor_options, buffer_length_name_mapping, &_block)
56
+ decompressor_options = {}
57
+
58
+ buffer_length_name_mapping.each do |compressor_name, decompressor_name|
59
+ decompressor_options[decompressor_name] = compressor_options[compressor_name]
60
+ end
61
+
62
+ yield decompressor_options
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,125 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require "fcntl"
5
+ require "stringio"
6
+
7
+ require_relative "../common"
8
+ require_relative "../minitest"
9
+ require_relative "../validation"
10
+
11
+ module ADSP
12
+ module Test
13
+ module Stream
14
+ class Abstract < Minitest::Test
15
+ SOURCE_PATH = Common::SOURCE_PATH
16
+
17
+ def test_invalid_initialize
18
+ (Validation::INVALID_STRINGS - [nil] + Validation::INVALID_ENCODINGS).each do |invalid_encoding|
19
+ assert_raises ValidateError do
20
+ target.new ::StringIO.new, {}, :external_encoding => invalid_encoding
21
+ end
22
+
23
+ assert_raises ValidateError do
24
+ target.new ::StringIO.new, {}, :internal_encoding => invalid_encoding
25
+ end
26
+ end
27
+
28
+ (Validation::INVALID_HASHES - [nil]).each do |invalid_hash|
29
+ assert_raises ValidateError do
30
+ target.new ::StringIO.new, {}, :transcode_options => invalid_hash
31
+ end
32
+ end
33
+ end
34
+
35
+ def test_invalid_set_encoding
36
+ instance = target.new ::StringIO.new
37
+
38
+ (Validation::INVALID_STRINGS - [nil] + Validation::INVALID_ENCODINGS).each do |invalid_encoding|
39
+ assert_raises ValidateError do
40
+ instance.set_encoding invalid_encoding
41
+ end
42
+
43
+ assert_raises ValidateError do
44
+ instance.set_encoding ::Encoding::BINARY, invalid_encoding
45
+ end
46
+ end
47
+
48
+ Validation::INVALID_ENCODINGS.each do |invalid_encoding|
49
+ assert_raises ValidateError do
50
+ instance.set_encoding "#{::Encoding::BINARY}:#{invalid_encoding}"
51
+ end
52
+
53
+ assert_raises ValidateError do
54
+ instance.set_encoding "#{invalid_encoding}:#{::Encoding::BINARY}"
55
+ end
56
+ end
57
+
58
+ (Validation::INVALID_HASHES - [nil]).each do |invalid_hash|
59
+ assert_raises ValidateError do
60
+ instance.set_encoding ::Encoding::BINARY, ::Encoding::BINARY, invalid_hash
61
+ end
62
+
63
+ assert_raises ValidateError do
64
+ instance.set_encoding "#{::Encoding::BINARY}:#{::Encoding::BINARY}", invalid_hash
65
+ end
66
+ end
67
+ end
68
+
69
+ def test_to_io
70
+ instance = target.new ::StringIO.new
71
+ assert_equal instance, instance.to_io
72
+ end
73
+
74
+ def test_io_delegates
75
+ ::File.open SOURCE_PATH, "wb+" do |file|
76
+ instance = target.new file
77
+
78
+ instance.autoclose = true
79
+ assert_predicate instance, :autoclose?
80
+
81
+ instance.binmode
82
+ assert_predicate instance, :binmode
83
+
84
+ instance.close_on_exec = true
85
+ assert_predicate instance, :close_on_exec?
86
+
87
+ # Fcntl is not available on windows.
88
+ if Fcntl.const_defined? :F_GETFL
89
+ stats = instance.fcntl Fcntl::F_GETFL, 0
90
+ refute_nil stats
91
+ end
92
+
93
+ instance.fdatasync
94
+
95
+ fd = instance.fileno
96
+ refute_nil fd
97
+
98
+ refute_predicate instance, :isatty
99
+ assert_nil instance.pid
100
+
101
+ instance.sync = true
102
+ assert_predicate instance, :sync
103
+
104
+ refute_nil instance.to_i
105
+ refute_predicate instance, :tty?
106
+ end
107
+ end
108
+
109
+ def test_stat
110
+ instance = target.new $stdout
111
+
112
+ refute_predicate instance.stat, :file?
113
+ refute_predicate instance.stat, :pipe?
114
+ refute_predicate instance.stat, :socket?
115
+ end
116
+
117
+ # -----
118
+
119
+ protected def target
120
+ self.class::Target
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,50 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require "minitar"
5
+
6
+ require_relative "../common"
7
+ require_relative "../minitest"
8
+ require_relative "../mock/stream/reader"
9
+ require_relative "../mock/stream/writer"
10
+
11
+ module ADSP
12
+ module Test
13
+ module Stream
14
+ class MinitarTest < Minitest::Test
15
+ Reader = Mock::Stream::Reader
16
+ Writer = Mock::Stream::Writer
17
+
18
+ ARCHIVE_PATH = Common::ARCHIVE_PATH
19
+ LARGE_TEXTS = Common::LARGE_TEXTS
20
+
21
+ def test_tar
22
+ Common.parallel LARGE_TEXTS do |text, worker_index|
23
+ archive_path = Common.get_path ARCHIVE_PATH, worker_index
24
+
25
+ Writer.open archive_path do |writer|
26
+ Minitar::Writer.open writer do |tar|
27
+ tar.add_file_simple "file", :data => text
28
+ end
29
+ end
30
+
31
+ Reader.open archive_path do |reader|
32
+ Minitar::Reader.open reader do |tar|
33
+ tar.each_entry do |entry|
34
+ assert_equal "file", entry.name
35
+
36
+ decompressed_text = entry.read
37
+ decompressed_text.force_encoding text.encoding
38
+
39
+ assert_equal text, decompressed_text
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ Minitest << MinitarTest
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require_relative "../../minitest"
5
+ require_relative "../../validation"
6
+
7
+ module ADSP
8
+ module Test
9
+ module Stream
10
+ module Raw
11
+ class Abstract < Minitest::Test
12
+ NOOP_PROC = Validation::NOOP_PROC
13
+
14
+ def test_invalid_flush
15
+ instance = target.new
16
+
17
+ assert_raises ValidateError do
18
+ instance.flush
19
+ end
20
+
21
+ instance.close(&NOOP_PROC)
22
+
23
+ assert_raises UsedAfterCloseError do
24
+ instance.flush(&NOOP_PROC)
25
+ end
26
+ end
27
+
28
+ def test_invalid_close
29
+ instance = target.new
30
+
31
+ assert_raises ValidateError do
32
+ instance.close
33
+ end
34
+ end
35
+
36
+ # -----
37
+
38
+ protected def target
39
+ self.class::Target
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,166 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require_relative "abstract"
5
+ require_relative "../../common"
6
+ require_relative "../../minitest"
7
+ require_relative "../../mock/stream/raw/compressor"
8
+ require_relative "../../mock/string"
9
+ require_relative "../../option"
10
+ require_relative "../../validation"
11
+
12
+ module ADSP
13
+ module Test
14
+ module Stream
15
+ module Raw
16
+ class Compressor < Abstract
17
+ Target = Mock::Stream::Raw::Compressor
18
+ String = Mock::String
19
+
20
+ TEXTS = Common::TEXTS
21
+ LARGE_TEXTS = Common::LARGE_TEXTS
22
+ PORTION_LENGTHS = Common::PORTION_LENGTHS
23
+ LARGE_PORTION_LENGTHS = Common::LARGE_PORTION_LENGTHS
24
+
25
+ BUFFER_LENGTH_NAMES = %i[destination_buffer_length].freeze
26
+ BUFFER_LENGTH_MAPPING = { :destination_buffer_length => :destination_buffer_length }.freeze
27
+
28
+ def test_invalid_initialize
29
+ get_invalid_compressor_options do |invalid_options|
30
+ assert_raises ValidateError do
31
+ Target.new invalid_options
32
+ end
33
+ end
34
+ end
35
+
36
+ def test_invalid_write
37
+ compressor = Target.new
38
+
39
+ Validation::INVALID_STRINGS.each do |invalid_string|
40
+ assert_raises ValidateError do
41
+ compressor.write invalid_string, &NOOP_PROC
42
+ end
43
+ end
44
+
45
+ assert_raises ValidateError do
46
+ compressor.write ""
47
+ end
48
+
49
+ compressor.close(&NOOP_PROC)
50
+
51
+ assert_raises UsedAfterCloseError do
52
+ compressor.write "", &NOOP_PROC
53
+ end
54
+ end
55
+
56
+ def test_texts
57
+ parallel_compressor_options do |compressor_options|
58
+ TEXTS.each do |text|
59
+ PORTION_LENGTHS.each do |portion_length|
60
+ compressed_buffer = ::StringIO.new
61
+ compressed_buffer.set_encoding ::Encoding::BINARY
62
+
63
+ writer = proc { |portion| compressed_buffer << portion }
64
+ compressor = Target.new compressor_options
65
+
66
+ begin
67
+ source = "".b
68
+ text_offset = 0
69
+ index = 0
70
+
71
+ loop do
72
+ portion = text.byteslice text_offset, portion_length
73
+ break if portion.nil?
74
+
75
+ text_offset += portion_length
76
+ source << portion
77
+
78
+ bytes_written = compressor.write source, &writer
79
+ source = source.byteslice bytes_written, source.bytesize - bytes_written
80
+
81
+ compressor.flush(&writer) if index.even?
82
+ index += 1
83
+ end
84
+
85
+ ensure
86
+ refute_predicate compressor, :closed?
87
+ compressor.close(&writer)
88
+ assert_predicate compressor, :closed?
89
+ end
90
+
91
+ compressed_text = compressed_buffer.string
92
+
93
+ get_compatible_decompressor_options compressor_options do |decompressor_options|
94
+ decompressed_text = String.decompress compressed_text, decompressor_options
95
+ decompressed_text.force_encoding text.encoding
96
+
97
+ assert_equal text, decompressed_text
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def test_large_texts
105
+ options_generator = OCG.new(
106
+ :text => LARGE_TEXTS,
107
+ :portion_length => LARGE_PORTION_LENGTHS
108
+ )
109
+
110
+ Common.parallel_options options_generator do |options|
111
+ text = options[:text]
112
+ portion_length = options[:portion_length]
113
+
114
+ compressed_buffer = ::StringIO.new
115
+ compressed_buffer.set_encoding ::Encoding::BINARY
116
+
117
+ writer = proc { |portion| compressed_buffer << portion }
118
+ compressor = Target.new
119
+
120
+ begin
121
+ source = "".b
122
+ text_offset = 0
123
+
124
+ loop do
125
+ portion = text.byteslice text_offset, portion_length
126
+ break if portion.nil?
127
+
128
+ text_offset += portion_length
129
+ source << portion
130
+
131
+ bytes_written = compressor.write source, &writer
132
+ source = source.byteslice bytes_written, source.bytesize - bytes_written
133
+ end
134
+ ensure
135
+ compressor.close(&writer)
136
+ end
137
+
138
+ compressed_text = compressed_buffer.string
139
+
140
+ decompressed_text = String.decompress compressed_text
141
+ decompressed_text.force_encoding text.encoding
142
+
143
+ assert_equal text, decompressed_text
144
+ end
145
+ end
146
+
147
+ # -----
148
+
149
+ def get_invalid_compressor_options(&block)
150
+ Option.get_invalid_compressor_options BUFFER_LENGTH_NAMES, &block
151
+ end
152
+
153
+ def parallel_compressor_options(&block)
154
+ Common.parallel_options Option.get_compressor_options_generator(BUFFER_LENGTH_NAMES), &block
155
+ end
156
+
157
+ def get_compatible_decompressor_options(compressor_options, &block)
158
+ Option.get_compatible_decompressor_options compressor_options, BUFFER_LENGTH_MAPPING, &block
159
+ end
160
+ end
161
+
162
+ Minitest << Compressor
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,166 @@
1
+ # Abstract data stream processor.
2
+ # Copyright (c) 2021 AUTHORS, MIT License.
3
+
4
+ require_relative "abstract"
5
+ require_relative "../../common"
6
+ require_relative "../../minitest"
7
+ require_relative "../../mock/stream/raw/decompressor"
8
+ require_relative "../../mock/string"
9
+ require_relative "../../option"
10
+ require_relative "../../validation"
11
+
12
+ module ADSP
13
+ module Test
14
+ module Stream
15
+ module Raw
16
+ class Decompressor < Abstract
17
+ Target = Mock::Stream::Raw::Decompressor
18
+ String = Mock::String
19
+
20
+ TEXTS = Common::TEXTS
21
+ LARGE_TEXTS = Common::LARGE_TEXTS
22
+ PORTION_LENGTHS = Common::PORTION_LENGTHS
23
+ LARGE_PORTION_LENGTHS = Common::LARGE_PORTION_LENGTHS
24
+
25
+ BUFFER_LENGTH_NAMES = %i[destination_buffer_length].freeze
26
+ BUFFER_LENGTH_MAPPING = { :destination_buffer_length => :destination_buffer_length }.freeze
27
+
28
+ def test_invalid_initialize
29
+ get_invalid_decompressor_options do |invalid_options|
30
+ assert_raises ValidateError do
31
+ Target.new invalid_options
32
+ end
33
+ end
34
+ end
35
+
36
+ def test_invalid_read
37
+ decompressor = Target.new
38
+
39
+ Validation::INVALID_STRINGS.each do |invalid_string|
40
+ assert_raises ValidateError do
41
+ decompressor.read invalid_string, &NOOP_PROC
42
+ end
43
+ end
44
+
45
+ assert_raises ValidateError do
46
+ decompressor.read ""
47
+ end
48
+
49
+ decompressor.close(&NOOP_PROC)
50
+
51
+ assert_raises UsedAfterCloseError do
52
+ decompressor.read "", &NOOP_PROC
53
+ end
54
+ end
55
+
56
+ def test_texts
57
+ parallel_compressor_options do |compressor_options|
58
+ TEXTS.each do |text|
59
+ compressed_text = String.compress text, compressor_options
60
+
61
+ PORTION_LENGTHS.each do |portion_length|
62
+ get_compatible_decompressor_options compressor_options do |decompressor_options|
63
+ decompressed_buffer = ::StringIO.new
64
+ decompressed_buffer.set_encoding ::Encoding::BINARY
65
+
66
+ writer = proc { |portion| decompressed_buffer << portion }
67
+ decompressor = Target.new decompressor_options
68
+
69
+ begin
70
+ source = "".b
71
+ compressed_text_offset = 0
72
+ index = 0
73
+
74
+ loop do
75
+ portion = compressed_text.byteslice compressed_text_offset, portion_length
76
+ break if portion.nil?
77
+
78
+ compressed_text_offset += portion_length
79
+ source << portion
80
+
81
+ bytes_read = decompressor.read source, &writer
82
+ source = source.byteslice bytes_read, source.bytesize - bytes_read
83
+
84
+ decompressor.flush(&writer) if index.even?
85
+ index += 1
86
+ end
87
+
88
+ ensure
89
+ refute_predicate decompressor, :closed?
90
+ decompressor.close(&writer)
91
+ assert_predicate decompressor, :closed?
92
+ end
93
+
94
+ decompressed_text = decompressed_buffer.string
95
+ decompressed_text.force_encoding text.encoding
96
+
97
+ assert_equal text, decompressed_text
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def test_large_texts
105
+ options_generator = OCG.new(
106
+ :text => LARGE_TEXTS,
107
+ :portion_length => LARGE_PORTION_LENGTHS
108
+ )
109
+
110
+ Common.parallel_options options_generator do |options|
111
+ text = options[:text]
112
+ portion_length = options[:portion_length]
113
+
114
+ compressed_text = String.compress text
115
+
116
+ decompressed_buffer = ::StringIO.new
117
+ decompressed_buffer.set_encoding ::Encoding::BINARY
118
+
119
+ writer = proc { |portion| decompressed_buffer << portion }
120
+ decompressor = Target.new
121
+
122
+ begin
123
+ source = "".b
124
+ compressed_text_offset = 0
125
+
126
+ loop do
127
+ portion = compressed_text.byteslice compressed_text_offset, portion_length
128
+ break if portion.nil?
129
+
130
+ compressed_text_offset += portion_length
131
+ source << portion
132
+
133
+ bytes_read = decompressor.read source, &writer
134
+ source = source.byteslice bytes_read, source.bytesize - bytes_read
135
+ end
136
+ ensure
137
+ decompressor.close(&writer)
138
+ end
139
+
140
+ decompressed_text = decompressed_buffer.string
141
+ decompressed_text.force_encoding text.encoding
142
+
143
+ assert_equal text, decompressed_text
144
+ end
145
+ end
146
+
147
+ # -----
148
+
149
+ def get_invalid_decompressor_options(&block)
150
+ Option.get_invalid_decompressor_options BUFFER_LENGTH_NAMES, &block
151
+ end
152
+
153
+ def parallel_compressor_options(&block)
154
+ Common.parallel_options Option.get_compressor_options_generator(BUFFER_LENGTH_NAMES), &block
155
+ end
156
+
157
+ def get_compatible_decompressor_options(compressor_options, &block)
158
+ Option.get_compatible_decompressor_options compressor_options, BUFFER_LENGTH_MAPPING, &block
159
+ end
160
+ end
161
+
162
+ Minitest << Decompressor
163
+ end
164
+ end
165
+ end
166
+ end