adsp 1.0.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.
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