bzip2-ffi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,382 @@
1
+ require 'test_helper'
2
+
3
+ class IOTest < Minitest::Test
4
+ class DummyIO
5
+ def initialize
6
+ @closed = false
7
+ end
8
+
9
+ def close
10
+ @closed = true
11
+ end
12
+
13
+ def closed?
14
+ @closed
15
+ end
16
+ end
17
+
18
+ class NoCloseIO
19
+ end
20
+
21
+ class TestIO < Bzip2::FFI::IO
22
+ class << self
23
+ public :new
24
+ public :open
25
+ end
26
+
27
+ public :io
28
+ public :stream
29
+ public :check_closed
30
+ public :check_error
31
+
32
+ def initialize(io, options = {})
33
+ super
34
+
35
+ raise 'test' if options[:test_initialize_raise_exception]
36
+ end
37
+ end
38
+
39
+ def test_autoclose_set_true
40
+ io = TestIO.new(DummyIO.new, autoclose: false)
41
+ assert_equal(false, io.autoclose?)
42
+ io.autoclose = true
43
+ assert_equal(true, io.autoclose?)
44
+ end
45
+
46
+ def test_autoclose_set_truthy
47
+ io = TestIO.new(DummyIO.new, autoclose: false)
48
+ assert_equal(false, io.autoclose?)
49
+ io.autoclose = 'false'
50
+ assert_equal(true, io.autoclose?)
51
+ end
52
+
53
+ def test_autoclose_set_false
54
+ io = TestIO.new(DummyIO.new, autoclose: true)
55
+ assert_equal(true, io.autoclose?)
56
+ io.autoclose = false
57
+ assert_equal(false, io.autoclose?)
58
+ end
59
+
60
+ def test_autoclose_set_not_truthy
61
+ io = TestIO.new(DummyIO.new, autoclose: true)
62
+ assert_equal(true, io.autoclose?)
63
+ io.autoclose = nil
64
+ assert_equal(false, io.autoclose?)
65
+ end
66
+
67
+ def test_autoclose_get_when_closed
68
+ io = TestIO.new(DummyIO.new)
69
+ io.close
70
+ assert_raises(IOError) { io.autoclose? }
71
+ end
72
+
73
+ def test_autoclose_set_when_closed
74
+ io = TestIO.new(DummyIO.new)
75
+ io.close
76
+ assert_raises(IOError) { io.autoclose = true }
77
+ end
78
+
79
+ def test_binmode?
80
+ io = TestIO.new(DummyIO.new)
81
+ assert_equal(true, io.binmode?)
82
+ end
83
+
84
+ def test_binmode_get_when_closed
85
+ io = TestIO.new(DummyIO.new)
86
+ io.close
87
+ assert_raises(IOError) { io.binmode? }
88
+ end
89
+
90
+ def test_binmode
91
+ io = TestIO.new(DummyIO.new)
92
+ assert_same(io, io.binmode)
93
+ assert_equal(true, io.binmode?)
94
+ end
95
+
96
+ def test_binmode_set_when_closed
97
+ io = TestIO.new(DummyIO.new)
98
+ io.close
99
+ assert_raises(IOError) { io.binmode }
100
+ end
101
+
102
+ def test_close_without_autoclose
103
+ dummy_io = DummyIO.new
104
+ io = TestIO.new(dummy_io)
105
+ refute(dummy_io.closed?)
106
+ io.close
107
+ refute(dummy_io.closed?)
108
+ end
109
+
110
+ def test_close_with_autoclose
111
+ dummy_io = DummyIO.new
112
+ io = TestIO.new(dummy_io, autoclose: true)
113
+ refute(dummy_io.closed?)
114
+ io.close
115
+ assert(dummy_io.closed?)
116
+ end
117
+
118
+ def test_close_with_unclosable_and_autoclose
119
+ no_close_io = NoCloseIO.new
120
+ io = TestIO.new(no_close_io, autoclose: true)
121
+ assert_nothing_raised { io.close }
122
+ end
123
+
124
+ def test_close_returns_nil
125
+ io = TestIO.new(DummyIO.new)
126
+ assert_nil(io.close)
127
+ end
128
+
129
+ def test_close_when_closed
130
+ io = TestIO.new(DummyIO.new)
131
+ io.close
132
+ assert_raises(IOError) { io.close }
133
+ end
134
+
135
+ def test_closed
136
+ io = TestIO.new(DummyIO.new)
137
+ assert_equal(false, io.closed?)
138
+ io.close
139
+ assert_equal(true, io.closed?)
140
+ end
141
+
142
+ def test_external_encoding
143
+ io = TestIO.new(DummyIO.new)
144
+ assert_equal(Encoding::ASCII_8BIT, io.external_encoding)
145
+ end
146
+
147
+ def test_external_encoding_when_closed
148
+ io = TestIO.new(DummyIO.new)
149
+ io.close
150
+ assert_raises(IOError) { io.external_encoding }
151
+ end
152
+
153
+ def test_internal_encoding
154
+ io = TestIO.new(DummyIO.new)
155
+ assert_equal(Encoding::ASCII_8BIT, io.internal_encoding)
156
+ end
157
+
158
+ def test_internal_encoding_when_closed
159
+ io = TestIO.new(DummyIO.new)
160
+ io.close
161
+ assert_raises(IOError) { io.internal_encoding }
162
+ end
163
+
164
+ def test_io
165
+ dummy_io = DummyIO.new
166
+ io = TestIO.new(dummy_io)
167
+ assert_same(dummy_io, io.io)
168
+ end
169
+
170
+ def test_initialize_nil_io
171
+ assert_raises(ArgumentError) { TestIO.new }
172
+ end
173
+
174
+ def test_initialize_calls_binmode_on_io
175
+ dummy_io = Minitest::Mock.new
176
+ dummy_io.expect(:binmode, dummy_io)
177
+ TestIO.new(dummy_io)
178
+ assert(dummy_io.verify)
179
+ end
180
+
181
+ def test_initialize_autoclose_default
182
+ io = TestIO.new(DummyIO.new)
183
+ assert_equal(false, io.autoclose?)
184
+ end
185
+
186
+ def test_initialize_autoclose_option
187
+ io = TestIO.new(DummyIO.new, autoclose: true)
188
+ assert_equal(true, io.autoclose?)
189
+ end
190
+
191
+ def test_stream
192
+ io = TestIO.new(DummyIO.new)
193
+ s = io.stream
194
+ refute_nil(s)
195
+ assert_kind_of(Bzip2::FFI::Libbz2::BzStream, s)
196
+ end
197
+
198
+ def test_stream_when_closed
199
+ io = TestIO.new(DummyIO.new)
200
+ io.close
201
+ assert_raises(IOError) { io.stream }
202
+ end
203
+
204
+ def test_check_closed_when_open
205
+ io = TestIO.new(DummyIO.new)
206
+ assert_nothing_raised { io.check_closed }
207
+ end
208
+
209
+ def test_check_closed_when_closed
210
+ io = TestIO.new(DummyIO.new)
211
+ io.close
212
+ e = assert_raises(IOError) { io.check_closed }
213
+ assert_equal('closed stream', e.message)
214
+ end
215
+
216
+ def test_check_error_not_error
217
+ io = TestIO.new(DummyIO.new)
218
+
219
+ (0..4).each do |i|
220
+ assert_equal(i, io.check_error(i))
221
+ end
222
+ end
223
+
224
+ def test_check_error_error
225
+ codes = {
226
+ Bzip2::FFI::Libbz2::BZ_SEQUENCE_ERROR => Bzip2::FFI::Error::SequenceError,
227
+ Bzip2::FFI::Libbz2::BZ_PARAM_ERROR => Bzip2::FFI::Error::ParamError,
228
+ Bzip2::FFI::Libbz2::BZ_MEM_ERROR => Bzip2::FFI::Error::MemoryError,
229
+ Bzip2::FFI::Libbz2::BZ_DATA_ERROR => Bzip2::FFI::Error::DataError,
230
+ Bzip2::FFI::Libbz2::BZ_DATA_ERROR_MAGIC => Bzip2::FFI::Error::MagicDataError,
231
+ Bzip2::FFI::Libbz2::BZ_CONFIG_ERROR => Bzip2::FFI::Error::ConfigError
232
+ }
233
+
234
+ io = TestIO.new(DummyIO.new)
235
+
236
+ codes.each do |code, error_class|
237
+ assert_raises(error_class) { io.check_error(code) }
238
+ end
239
+ end
240
+
241
+ def test_check_error_unexpected
242
+ io = TestIO.new(DummyIO.new)
243
+
244
+ # -6, -7 and -8 are codes that are only raised by the libbz2 high-level
245
+ # interface. Only the low-level interface is used by Bzip2::FFI.
246
+ # -10 is not defined by libbz2.
247
+ [-6, -7, -8, -10].each do |code|
248
+ error = assert_raises(Bzip2::FFI::Error::UnexpectedError) { io.check_error(code) }
249
+ assert_includes(error.message, code.to_s)
250
+ end
251
+ end
252
+
253
+ def test_open_no_block
254
+ dummy_io = DummyIO.new
255
+ io = TestIO.open(dummy_io)
256
+ assert_kind_of(TestIO, io)
257
+ refute(io.closed?)
258
+ assert_equal(false, io.autoclose?)
259
+ assert_same(dummy_io, io.io)
260
+ end
261
+
262
+ def test_open_no_block_options
263
+ dummy_io = DummyIO.new
264
+ io = TestIO.open(dummy_io, autoclose: true)
265
+ assert_kind_of(TestIO, io)
266
+ refute(io.closed?)
267
+ assert_equal(true, io.autoclose?)
268
+ assert_same(dummy_io, io.io)
269
+ end
270
+
271
+ def test_open_no_block_proc
272
+ dummy_io = nil
273
+ io = TestIO.open(-> { dummy_io = DummyIO.new })
274
+ refute_nil(dummy_io)
275
+ assert_same(dummy_io, io.io)
276
+ refute(dummy_io.closed?)
277
+ end
278
+
279
+ def test_open_no_block_proc_closed_on_exception
280
+ dummy_io = nil
281
+
282
+ assert_raises(RuntimeError) do
283
+ TestIO.open(-> { dummy_io = DummyIO.new }, test_initialize_raise_exception: true)
284
+ end
285
+
286
+ refute_nil(dummy_io)
287
+ assert(dummy_io.closed?)
288
+ end
289
+
290
+ def test_open_no_block_proc_closed_on_exception_unless_no_close
291
+ no_close_io = nil
292
+
293
+ assert_raises(RuntimeError) do
294
+ TestIO.open(-> { no_close_io = NoCloseIO.new }, test_initialize_raise_exception: true)
295
+ end
296
+
297
+ refute_nil(no_close_io)
298
+ end
299
+
300
+ def test_open_block
301
+ dummy_io = DummyIO.new
302
+ copy_io = nil
303
+
304
+ res = TestIO.open(dummy_io) do |io|
305
+ assert_kind_of(TestIO, io)
306
+ refute(io.closed?)
307
+ assert_equal(false, io.autoclose?)
308
+ assert_same(dummy_io, io.io)
309
+ copy_io = io
310
+ 42
311
+ end
312
+
313
+ assert(copy_io.closed?)
314
+ assert_equal(42, res)
315
+ end
316
+
317
+ def test_open_block_options
318
+ dummy_io = DummyIO.new
319
+ copy_io = nil
320
+
321
+ res = TestIO.open(dummy_io, autoclose: true) do |io|
322
+ assert_kind_of(TestIO, io)
323
+ refute(io.closed?)
324
+ assert_equal(true, io.autoclose?)
325
+ assert_same(dummy_io, io.io)
326
+ copy_io = io
327
+ 42
328
+ end
329
+
330
+ assert(copy_io.closed?)
331
+ assert_equal(42, res)
332
+ end
333
+
334
+ def test_open_block_closes
335
+ # Shouldn't raise an exception if the block closes the io.
336
+ res = TestIO.open(DummyIO.new) do |io|
337
+ io.close
338
+ :block_closed
339
+ end
340
+
341
+ assert_equal(:block_closed, res)
342
+ end
343
+
344
+ def test_open_block_proc
345
+ dummy_io = nil
346
+
347
+ TestIO.open(-> { dummy_io = DummyIO.new }) do |io|
348
+ refute_nil(dummy_io)
349
+ assert_same(dummy_io, io.io)
350
+ refute(dummy_io.closed?)
351
+ end
352
+ end
353
+
354
+ def test_open_block_proc_closed_on_exception
355
+ dummy_io = nil
356
+
357
+ assert_raises(RuntimeError) do
358
+ TestIO.open(-> { dummy_io = DummyIO.new }, test_initialize_raise_exception: true) do |io|
359
+ flunk('block should not be called')
360
+ end
361
+ end
362
+
363
+ refute_nil(dummy_io)
364
+ assert(dummy_io.closed?)
365
+ end
366
+
367
+ def test_open_block_proc_closed_on_exception_unless_no_close
368
+ no_close_io = nil
369
+
370
+ assert_raises(RuntimeError) do
371
+ TestIO.open(-> { no_close_io = NoCloseIO.new }, test_initialize_raise_exception: true) do |io|
372
+ flunk('block should not be called')
373
+ end
374
+ end
375
+
376
+ refute_nil(no_close_io)
377
+ end
378
+
379
+ def test_open_io_nil
380
+ assert_raises(ArgumentError) { TestIO.open(nil) }
381
+ end
382
+ end
@@ -0,0 +1,498 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'stringio'
4
+ require 'test_helper'
5
+ require 'tmpdir'
6
+
7
+ class ReaderTest < Minitest::Test
8
+ class StringIOWithoutSeek < StringIO
9
+ undef_method :seek
10
+ end
11
+
12
+ def setup
13
+ Bzip2::FFI::Reader.test_after_open_file_raise_exception = false
14
+ end
15
+
16
+ def teardown
17
+ Bzip2::FFI::Reader.test_after_open_file_raise_exception = false
18
+ Bzip2::FFI::Reader.test_after_open_file_last_io = nil
19
+ end
20
+
21
+ def compare_fixture(reader, fixture, read_size = nil, use_outbuf = nil)
22
+ File.open(fixture_path(fixture), 'rb') do |input|
23
+ if read_size
24
+ loop do
25
+ buffer = input.read(read_size)
26
+
27
+ if use_outbuf
28
+ outbuf = 'outbuf'
29
+ decompressed = reader.read(read_size, outbuf)
30
+
31
+ if decompressed
32
+ assert_same(outbuf, decompressed)
33
+ else
34
+ assert_equal('', outbuf)
35
+ end
36
+ else
37
+ decompressed = reader.read(read_size)
38
+ end
39
+
40
+ if buffer
41
+ assert_same(Encoding::ASCII_8BIT, decompressed.encoding)
42
+ assert_equal(buffer, decompressed)
43
+ else
44
+ assert_nil(decompressed)
45
+ break
46
+ end
47
+ end
48
+ else
49
+ buffer = input.read
50
+
51
+ if use_outbuf
52
+ outbuf = 'outbuf'
53
+ decompressed = reader.read(nil, outbuf)
54
+ assert_same(outbuf, decompressed)
55
+ else
56
+ decompressed = reader.read
57
+ end
58
+
59
+ refute_nil(decompressed)
60
+ assert_same(Encoding::ASCII_8BIT, decompressed.encoding)
61
+ assert_equal(buffer, decompressed)
62
+ end
63
+
64
+ assert_nil(reader.read(1))
65
+ assert_equal(0, reader.read.bytesize)
66
+ end
67
+ end
68
+
69
+ def bzip_test(fixture, options = {})
70
+ Dir.mktmpdir('bzip2-ffi-test') do |dir|
71
+ uncompressed = File.join(dir, 'test')
72
+ if fixture
73
+ FileUtils.cp(fixture_path(fixture), uncompressed)
74
+ else
75
+ FileUtils.touch(uncompressed)
76
+ end
77
+
78
+ assert_bzip2_successful(uncompressed)
79
+
80
+ compressed = File.join(dir, "test.bz2")
81
+ assert(File.exist?(compressed))
82
+
83
+ Bzip2::FFI::Reader.open(compressed, options[:reader_options] || {}) do |reader|
84
+ if fixture
85
+ compare_fixture(reader, fixture, options[:read_size], options[:use_outbuf])
86
+ else
87
+ assert_equal(0, reader.read.bytesize)
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ def test_initialize_nil_io
94
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.new(nil) }
95
+ end
96
+
97
+ def test_initialize_io_with_no_read_method
98
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.new(Object.new) }
99
+ end
100
+
101
+ def test_empty
102
+ bzip_test(nil)
103
+ end
104
+
105
+ def test_fixture_text
106
+ [16, 1024, 16384, File.size(fixture_path('lorem.txt')), nil].each do |read_size|
107
+ [false, true].each do |use_outbuf|
108
+ bzip_test('lorem.txt', read_size: read_size, use_outbuf: use_outbuf)
109
+ end
110
+ end
111
+ end
112
+
113
+ def test_fixture_very_compressible
114
+ [16, 1024, 16384, File.size(fixture_path('zero.txt')), nil].each do |read_size|
115
+ [false, true].each do |use_outbuf|
116
+ bzip_test('zero.txt', read_size: read_size, use_outbuf: use_outbuf)
117
+ end
118
+ end
119
+ end
120
+
121
+ def test_fixture_uncompressible
122
+ [16, 1024, 16384, File.size(fixture_path('bzipped')), nil].each do |read_size|
123
+ [false, true].each do |use_outbuf|
124
+ bzip_test('bzipped', read_size: read_size, use_outbuf: use_outbuf)
125
+ end
126
+ end
127
+ end
128
+
129
+ def test_fixture_image
130
+ [16, 1024, 16384, File.size(fixture_path('moon.tiff')), nil].each do |read_size|
131
+ [false, true].each do |use_outbuf|
132
+ bzip_test('moon.tiff', read_size: read_size, use_outbuf: use_outbuf)
133
+ end
134
+ end
135
+ end
136
+
137
+ def test_small
138
+ # Not trivial to check if the value passed has any effect. Just check that
139
+ # there are no failures.
140
+ [false, true].each do |small|
141
+ bzip_test('lorem.txt', reader_options: {small: small})
142
+ end
143
+ end
144
+
145
+ def test_close_mid_read
146
+ Bzip2::FFI::Reader.open(fixture_path('bzipped')) do |reader|
147
+ decompressed = reader.read(1)
148
+ refute_nil(decompressed)
149
+ assert_equal(1, decompressed.bytesize)
150
+ end
151
+ end
152
+
153
+ def test_read_zero_before_eof
154
+ Bzip2::FFI::Reader.open(fixture_path('bzipped')) do |reader|
155
+ decompressed = reader.read(0)
156
+ refute_nil(decompressed)
157
+ assert_equal(0, decompressed.bytesize)
158
+ end
159
+ end
160
+
161
+ def test_read_zero_before_eof_buffer
162
+ Bzip2::FFI::Reader.open(fixture_path('bzipped')) do |reader|
163
+ buffer = 'outbuf'
164
+ decompressed = reader.read(0, buffer)
165
+ assert_same(buffer, decompressed)
166
+ assert_equal(0, decompressed.bytesize)
167
+ end
168
+ end
169
+
170
+ def test_read_zero_after_eof
171
+ Bzip2::FFI::Reader.open(fixture_path('bzipped')) do |reader|
172
+ reader.read
173
+ decompressed = reader.read(0) # would return nil if greater than 0
174
+ refute_nil(decompressed)
175
+ assert_equal(0, decompressed.bytesize)
176
+ end
177
+ end
178
+
179
+ def test_read_zero_after_eof_buffer
180
+ Bzip2::FFI::Reader.open(fixture_path('bzipped')) do |reader|
181
+ reader.read
182
+ buffer = 'outbuf'
183
+ decompressed = reader.read(0, buffer) # would return nil if greater than 0
184
+ assert_same(buffer, decompressed)
185
+ assert_equal(0, decompressed.bytesize)
186
+ end
187
+ end
188
+
189
+ def test_read_after_close_read_all
190
+ File.open(fixture_path('bzipped'), 'rb') do |file|
191
+ reader = Bzip2::FFI::Reader.new(file)
192
+ reader.close
193
+ assert_raises(IOError) { reader.read }
194
+ end
195
+ end
196
+
197
+ def test_read_after_close_read_all_buffer
198
+ File.open(fixture_path('bzipped'), 'rb') do |file|
199
+ reader = Bzip2::FFI::Reader.new(file)
200
+ reader.close
201
+ assert_raises(IOError) { reader.read(nil, '') }
202
+ end
203
+ end
204
+
205
+ def test_read_after_close_read_n
206
+ File.open(fixture_path('bzipped'), 'rb') do |file|
207
+ reader = Bzip2::FFI::Reader.new(file)
208
+ reader.close
209
+ assert_raises(IOError) { reader.read(1) }
210
+ end
211
+ end
212
+
213
+ def test_read_after_close_read_n_buffer
214
+ File.open(fixture_path('bzipped'), 'rb') do |file|
215
+ reader = Bzip2::FFI::Reader.new(file)
216
+ reader.close
217
+ assert_raises(IOError) { reader.read(1, '') }
218
+ end
219
+ end
220
+
221
+ def test_read_after_close_read_zero
222
+ File.open(fixture_path('bzipped'), 'rb') do |file|
223
+ reader = Bzip2::FFI::Reader.new(file)
224
+ reader.close
225
+ assert_raises(IOError) { reader.read(0) }
226
+ end
227
+ end
228
+
229
+ def test_read_after_close_read_zero_buffer
230
+ File.open(fixture_path('bzipped'), 'rb') do |file|
231
+ reader = Bzip2::FFI::Reader.new(file)
232
+ reader.close
233
+ assert_raises(IOError) { reader.read(0, '') }
234
+ end
235
+ end
236
+
237
+ def test_close_returns_nil
238
+ reader = Bzip2::FFI::Reader.new(StringIO.new)
239
+ assert_nil(reader.close)
240
+ end
241
+
242
+ def test_non_bzipped
243
+ Bzip2::FFI::Reader.open(fixture_path('lorem.txt')) do |reader|
244
+ assert_raises(Bzip2::FFI::Error::MagicDataError) { reader.read }
245
+ end
246
+ end
247
+
248
+ def test_truncated_bzip
249
+ [1024, Bzip2::FFI::Reader::READ_BUFFER_SIZE, 8192].each do |size|
250
+ partial = StringIO.new
251
+
252
+ File.open(fixture_path('bzipped'), 'rb') do |input|
253
+ buffer = input.read(size)
254
+ refute_nil(buffer)
255
+ assert_equal(size, buffer.bytesize)
256
+ partial.write(buffer)
257
+ end
258
+
259
+ partial.seek(0)
260
+
261
+ Bzip2::FFI::Reader.open(partial) do |reader|
262
+ assert_raises(Bzip2::FFI::Error::UnexpectedEofError) { reader.read }
263
+ end
264
+ end
265
+ end
266
+
267
+ def test_corrupted_bzip
268
+ corrupted = StringIO.new
269
+
270
+ File.open(fixture_path('bzipped'), 'rb') do |file|
271
+ corrupted.write(file.read)
272
+ end
273
+
274
+ corrupted.seek(4000)
275
+ corrupted.write("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
276
+
277
+ corrupted.seek(0)
278
+
279
+ Bzip2::FFI::Reader.open(corrupted) do |reader|
280
+ assert_raises(Bzip2::FFI::Error::DataError) { reader.read }
281
+ end
282
+ end
283
+
284
+ def test_data_after_compressed
285
+ suffixed = StringIO.new
286
+
287
+ File.open(fixture_path('bzipped'), 'rb') do |file|
288
+ suffixed.write(file.read)
289
+ end
290
+
291
+ suffixed.write('Test')
292
+
293
+ suffixed.seek(0)
294
+
295
+ Bzip2::FFI::Reader.open(suffixed) do |reader|
296
+ assert_equal(65670, reader.read.bytesize)
297
+ assert_nil(reader.read(1))
298
+ assert_equal(0, reader.read.bytesize)
299
+ end
300
+
301
+ assert_equal('Test', suffixed.read)
302
+ end
303
+
304
+ def test_data_after_compressed_no_seek
305
+ suffixed = StringIO.new
306
+
307
+ File.open(fixture_path('bzipped'), 'rb') do |file|
308
+ suffixed.write(file.read)
309
+ end
310
+
311
+ suffixed.write('Test')
312
+
313
+ suffixed.seek(0)
314
+
315
+ class << suffixed
316
+ undef_method :seek
317
+ end
318
+
319
+ Bzip2::FFI::Reader.open(suffixed) do |reader|
320
+ assert_equal(65670, reader.read.bytesize)
321
+ assert_nil(reader.read(1))
322
+ assert_equal(0, reader.read.bytesize)
323
+ end
324
+
325
+ # For this input, the suffix will already have been consumed before the
326
+ # end of the bzip2 stream is reached. There is no seek method, so it is not
327
+ # possible to restore the position to the end of the bzip2 stream.
328
+ assert_equal(0, suffixed.read.bytesize)
329
+ end
330
+
331
+ def test_data_after_compressed_seek_raises_io_error
332
+ suffixed = StringIO.new
333
+
334
+ File.open(fixture_path('bzipped'), 'rb') do |file|
335
+ suffixed.write(file.read)
336
+ end
337
+
338
+ suffixed.write('Test')
339
+
340
+ suffixed.seek(0)
341
+
342
+ def suffixed.seek(amount, whence = IO::SEEK_SET)
343
+ raise IOError, 'Cannot seek'
344
+ end
345
+
346
+ Bzip2::FFI::Reader.open(suffixed) do |reader|
347
+ assert_equal(65670, reader.read.bytesize)
348
+ assert_nil(reader.read(1))
349
+ assert_equal(0, reader.read.bytesize)
350
+ end
351
+
352
+ # For this input, the suffix will already have been consumed before the
353
+ # end of the bzip2 stream is reached. There is no seek method, so it is not
354
+ # possible to restore the position to the end of the bzip2 stream.
355
+ assert_equal(0, suffixed.read.bytesize)
356
+ end
357
+
358
+ def test_finalizer
359
+ # Code coverage will verify that the finalizer was called.
360
+ 10.times { Bzip2::FFI::Reader.new(StringIO.new) }
361
+ GC.start
362
+ end
363
+
364
+ def test_open_io_nil
365
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.open(nil) }
366
+ end
367
+
368
+ def test_open_io_with_no_read_method
369
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.open(Object.new) }
370
+ end
371
+
372
+ def test_open_block_io
373
+ io = StringIO.new
374
+ Bzip2::FFI::Reader.open(io, autoclose: true) do |reader|
375
+ assert_same(io, reader.send(:io))
376
+ assert_equal(true, reader.autoclose?)
377
+ end
378
+ end
379
+
380
+ def test_open_no_block_io
381
+ io = StringIO.new
382
+ reader = Bzip2::FFI::Reader.open(io, autoclose: true)
383
+ begin
384
+ assert_same(io, reader.send(:io))
385
+ assert_equal(true, reader.autoclose?)
386
+ ensure
387
+ reader.close
388
+ end
389
+ end
390
+
391
+ def test_open_block_path
392
+ path = fixture_path('bzipped')
393
+ [path, Pathname.new(path)].each do |path_param|
394
+ Bzip2::FFI::Reader.open(path_param) do |reader|
395
+ io = reader.send(:io)
396
+ assert_kind_of(File, io)
397
+ assert_equal(path, io.path)
398
+ assert_raises(IOError) { io.write('test') }
399
+ assert_nothing_raised { io.read(1) }
400
+ end
401
+ end
402
+ end
403
+
404
+ def test_open_no_block_path
405
+ path = fixture_path('bzipped')
406
+ [path, Pathname.new(path)].each do |path_param|
407
+ reader = Bzip2::FFI::Reader.open(path_param)
408
+ begin
409
+ io = reader.send(:io)
410
+ assert_kind_of(File, io)
411
+ assert_equal(path, io.path)
412
+ assert_raises(IOError) { io.write('test') }
413
+ assert_nothing_raised { io.read(1) }
414
+ ensure
415
+ io.close
416
+ end
417
+ end
418
+ end
419
+
420
+ def test_open_block_path_always_autoclosed
421
+ Bzip2::FFI::Reader.open(fixture_path('bzipped'), autoclose: false) do |reader|
422
+ assert_equal(true, reader.autoclose?)
423
+ end
424
+ end
425
+
426
+ def test_open_no_block_path_always_autoclosed
427
+ reader = Bzip2::FFI::Reader.open(fixture_path('bzipped'), autoclose: false)
428
+ begin
429
+ assert_equal(true, reader.autoclose?)
430
+ ensure
431
+ reader.close
432
+ end
433
+ end
434
+
435
+ def test_open_path_does_not_exist
436
+ Dir.mktmpdir('bzip2-ffi-test') do |dir|
437
+ assert_raises(Errno::ENOENT) { Bzip2::FFI::Reader.open(File.join(dir, 'test')) }
438
+ end
439
+ end
440
+
441
+ def test_open_proc_not_allowed
442
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.open(-> { StringIO.new }) }
443
+ end
444
+
445
+ def test_open_after_open_file_exception_closes_file
446
+ Bzip2::FFI::Reader.test_after_open_file_raise_exception = true
447
+ assert_raises(RuntimeError) { Bzip2::FFI::Reader.open(fixture_path('bzipped')) }
448
+ file = Bzip2::FFI::Reader.test_after_open_file_last_io
449
+ refute_nil(file)
450
+ assert(file.closed?)
451
+ end
452
+
453
+ def test_class_read_initialize_nil_io
454
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.read(nil) }
455
+ end
456
+
457
+ def test_class_read_io_with_no_read_method
458
+ assert_raises(ArgumentError) { Bzip2::FFI::Reader.read(Object.new) }
459
+ end
460
+
461
+ def class_read_test(content)
462
+ Dir.mktmpdir('bzip2-ffi-test') do |dir|
463
+ uncompressed = File.join(dir, 'test')
464
+ File.write(uncompressed, content)
465
+ assert_bzip2_successful(uncompressed)
466
+ compressed = File.join(dir, 'test.bz2')
467
+ result = yield compressed
468
+ assert_equal(content, result)
469
+ assert_same(Encoding::ASCII_8BIT, result.encoding)
470
+ end
471
+ end
472
+
473
+ def test_class_read_io
474
+ class_read_test('test_io') do |compressed|
475
+ File.open(compressed, 'rb') do |file|
476
+ Bzip2::FFI::Reader.read(file, {})
477
+ end
478
+ end
479
+ end
480
+
481
+ def test_class_read_path
482
+ class_read_test('test_path') do |compressed|
483
+ Bzip2::FFI::Reader.read(compressed)
484
+ end
485
+ end
486
+
487
+ def test_class_read_pathname
488
+ class_read_test('test_pathname') do |compressed|
489
+ Bzip2::FFI::Reader.read(Pathname.new(compressed))
490
+ end
491
+ end
492
+
493
+ def test_class_read_path_file_does_not_exist
494
+ Dir.mktmpdir('bzip2-ffi-test') do |dir|
495
+ assert_raises(Errno::ENOENT) { Bzip2::FFI::Reader.read(File.join(dir, 'test')) }
496
+ end
497
+ end
498
+ end