multi_zip 0.1.3

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.
@@ -0,0 +1,487 @@
1
+ shared_examples 'zip backend' do |backend_name|
2
+ let(:filename) { archive_fixture_filename }
3
+ subject { MultiZip.new(filename, :backend => backend_name) }
4
+
5
+ before do
6
+ apply_constants(backend_name)
7
+ # subject.backend = backend_name
8
+ end
9
+ after { stash_constants(backend_name) }
10
+
11
+ describe '#read_member' do
12
+ context "backend: #{backend_name}" do
13
+ context 'member found' do
14
+ archive_member_files.each do |member_file|
15
+ it "returns '#{member_file}' as a string" do
16
+ expect(
17
+ subject.read_member(member_file).bytesize
18
+ ).to eq(
19
+ archive_member_size(member_file)
20
+ )
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'member not found' do
26
+ it_behaves_like 'raises MemberNotFoundError', :read_member, 'doesnt_exist'
27
+ end
28
+
29
+ context 'member is a directory' do
30
+ it_behaves_like 'raises MemberNotFoundError', :read_member, archive_member_directories.first
31
+ end
32
+
33
+ context 'archive not found' do
34
+ it_behaves_like 'raises ArchiveNotFoundError', :read_member, archive_member_files.first
35
+ end
36
+
37
+ context 'archive is not a file' do
38
+ it 'raises ArchiveNotFoundError'
39
+ end
40
+
41
+ context 'archive cannot be accessed due to permissions' do
42
+ it 'raises ArchiveNotAccessibleError'
43
+ end
44
+
45
+ context 'invalid or unreadable archive' do
46
+ it_behaves_like 'raises InvalidArchiveError', :read_member, archive_member_files.first
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#read_members' do
52
+ context "backend: #{backend_name}" do
53
+ context 'all members found' do
54
+ it 'returns the member content as an array a string in order of args' do
55
+ extracted_files = subject.read_members(archive_member_files)
56
+
57
+ archive_member_files.each_with_index do |member, i|
58
+ expect(extracted_files[i].bytesize).to eq(archive_member_size(member))
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'one of the members is a directory' do
64
+ it_behaves_like 'raises MemberNotFoundError', :read_members,
65
+ [ archive_member_files.first, archive_member_directories.first ]
66
+ end
67
+
68
+ context 'one of the members is not found' do
69
+ it_behaves_like 'raises MemberNotFoundError', :read_members,
70
+ [ archive_member_files.first, 'doesnt_exist' ]
71
+ end
72
+
73
+ context 'archive not found' do
74
+ it_behaves_like 'raises ArchiveNotFoundError', :read_members, archive_member_files
75
+ end
76
+
77
+ context 'archive is not a file' do
78
+ it 'raises ArchiveNotFoundError'
79
+ end
80
+
81
+ context 'archive cannot be accessed due to permissions' do
82
+ it 'raises ArchiveNotAccessibleError'
83
+ end
84
+
85
+ context 'invalid or unreadable archive' do
86
+ it_behaves_like 'raises InvalidArchiveError', :read_members,
87
+ [ archive_member_files.first, archive_member_directories.first ]
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#extract_member' do
93
+ context "backend: #{backend_name}" do
94
+ let(:tempfile) { Tempfile.new('multi_zip_test') }
95
+
96
+ context 'member found' do
97
+ let!(:extraction_return) { subject.extract_member(archive_member_files.first, tempfile.path) }
98
+ after { tempfile.delete }
99
+ it 'writes the file to the local filesystem' do
100
+ expect(tempfile.size).to eq(archive_member_size(archive_member_files.first))
101
+ end
102
+
103
+ it 'returns the file system path written to' do
104
+ expect(extraction_return).to eq(tempfile.path)
105
+ end
106
+ end
107
+
108
+ context 'member is a directory' do
109
+ it 'raises MemberNotFoundError' do
110
+ expect(
111
+ lambda { subject.extract_member(archive_member_directories.first, tempfile.path) }
112
+ ).to raise_error(MultiZip::MemberNotFoundError)
113
+ end
114
+ end
115
+
116
+ context 'member not found' do
117
+ it 'raises MemberNotFoundError' do
118
+ expect(
119
+ lambda { subject.extract_member('doesnt_exist', tempfile.path) }
120
+ ).to raise_error(MultiZip::MemberNotFoundError)
121
+ end
122
+ end
123
+
124
+ context 'archive not found' do
125
+ it_behaves_like 'raises ArchiveNotFoundError', :extract_member, archive_member_files.first, 'destination'
126
+ end
127
+
128
+ context 'archive is not a file' do
129
+ it 'raises ArchiveNotFoundError'
130
+ end
131
+
132
+ context 'archive cannot be accessed due to permissions' do
133
+ it 'raises ArchiveNotAccessibleError'
134
+ end
135
+
136
+ context 'invalid or unreadable archive' do
137
+ let(:filename) { invalid_archive_fixture_filename }
138
+ it 'raises ArchiveInvalidError' do
139
+ expect(
140
+ lambda { subject.extract_member(archive_member_files.first, tempfile.path) }
141
+ ).to raise_error(MultiZip::InvalidArchiveError)
142
+ end
143
+ end
144
+ end
145
+ end
146
+
147
+ describe '#list_members' do
148
+ context "backend: #{backend_name}" do
149
+ context 'file contains members' do
150
+ it 'returns array member file names' do
151
+ expect(subject.list_members).to eq(archive_member_names)
152
+ end
153
+
154
+ context 'prefix provided' do
155
+ context 'files with that prefix exist' do
156
+ it 'returns only files with that prefix' do
157
+ expect(subject.list_members('dir_1/')).to eq(
158
+ [ 'dir_1/', 'dir_1/file_3.txt' ]
159
+ )
160
+ end
161
+ end
162
+
163
+ context 'no files with that prefix exist' do
164
+ it 'returns empty array' do
165
+ expect(subject.list_members('doesnt_exist/')).to eq( [ ] )
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ context 'contains no members, is empty archive' do
172
+ it 'returns empty array'
173
+ end
174
+
175
+ context 'archive not found' do
176
+ it_behaves_like 'raises ArchiveNotFoundError', :list_members
177
+ end
178
+
179
+ context 'archive is not a file' do
180
+ it 'raises ArchiveNotFoundError'
181
+ end
182
+
183
+ context 'archive cannot be accessed due to permissions' do
184
+ it 'raises ArchiveNotAccessibleError'
185
+ end
186
+
187
+ context 'invalid or unreadable archive' do
188
+ it_behaves_like 'raises InvalidArchiveError', :list_members
189
+ end
190
+ end
191
+ end
192
+
193
+ describe '#member_exists?' do
194
+ context "backend: #{backend_name}" do
195
+ context 'member is a file' do
196
+ it 'returns true if member exists' do
197
+ expect(subject.member_exists?(archive_member_files.first)).to be_truthy
198
+ end
199
+ end
200
+
201
+ context 'member is a directory' do
202
+ it 'returns true if member exists' do
203
+ expect(subject.member_exists?(archive_member_directories.first)).to be_truthy
204
+ end
205
+ end
206
+
207
+ it 'returns false if member does not exist' do
208
+ expect(subject.member_exists?('does_not_exist')).to be_falsey
209
+ end
210
+
211
+ context 'archive not found' do
212
+ it_behaves_like 'raises ArchiveNotFoundError', :member_exists?, archive_member_files.first
213
+ end
214
+
215
+ context 'archive is not a file' do
216
+ it 'raises ArchiveNotFoundError'
217
+ end
218
+
219
+ context 'archive cannot be accessed due to permissions' do
220
+ it 'raises ArchiveNotAccessibleError'
221
+ end
222
+
223
+ context 'invalid or unreadable archive' do
224
+ it_behaves_like 'raises InvalidArchiveError', :member_exists?, archive_member_files.first
225
+ end
226
+ end
227
+ end
228
+
229
+ describe '#write_member' do
230
+ context "backend: #{backend_name}" do
231
+ after { FileUtils.rm(filename) if File.exists?(filename) }
232
+
233
+ let(:filename) { "/tmp/multizip_test.zip" }
234
+ let(:member_file_name) { 'test_member_file' }
235
+ let(:member_file_contents) { 'file contents here' }
236
+
237
+ context 'archive did not exist' do
238
+ before { expect(File.exists?(filename)).to be_falsey }
239
+
240
+ let!(:result) do
241
+ subject.write_member(member_file_name, member_file_contents)
242
+ end
243
+
244
+ it 'archive is created' do
245
+ expect(File.exists?(filename)).to be_truthy
246
+ end
247
+
248
+ context 'member added successfully' do
249
+ it 'returns true' do
250
+ expect(result).to be_truthy
251
+ end
252
+ it 'adds the member to the file' do
253
+ expect(
254
+ subject.read_member(member_file_name)
255
+ ).to eq(
256
+ member_file_contents
257
+ )
258
+ end
259
+ end
260
+
261
+ context 'member not successfully added' do
262
+ it 'raises MemberNotAddedError'
263
+ it 'does not add member to the archive/archive is empty'
264
+ end
265
+ end
266
+
267
+ context 'archive already exists' do
268
+ before do
269
+ FileUtils.cp(archive_fixture_filename, filename)
270
+ expect(File.exists?(filename)).to be_truthy
271
+ end
272
+
273
+ let!(:preexisting_members) { subject.list_members }
274
+
275
+ let!(:result) do
276
+ subject.write_member(member_file_name, member_file_contents)
277
+ end
278
+
279
+ context 'member added successfully' do
280
+ it 'returns true' do
281
+ expect(result).to be_truthy
282
+ end
283
+
284
+ context 'member with that name already exists' do
285
+ let(:member_file_name) { 'mimetype' }
286
+ it 'returns true' do
287
+ expect(result).to be_truthy
288
+ end
289
+ it 'it overwrites the member file name with new data' do
290
+ expect(
291
+ subject.read_member(member_file_name)
292
+ ).to eq(
293
+ member_file_contents
294
+ )
295
+ end
296
+ end
297
+
298
+ it 'adds the member to the file' do
299
+ expect(
300
+ subject.read_member(member_file_name)
301
+ ).to eq(
302
+ member_file_contents
303
+ )
304
+ end
305
+
306
+ it 'does not remove preexisting members' do
307
+ expect(
308
+ subject.list_members - preexisting_members
309
+ ).to eq(
310
+ [ member_file_name ]
311
+ )
312
+ end
313
+ end
314
+
315
+ context 'member not successfully added' do
316
+ it 'raises MemberNotAddedError'
317
+ it 'does not add member to the archive'
318
+ it 'does not remove preexisting members from the archive'
319
+ end
320
+ end
321
+
322
+ context 'archive is not a file' do
323
+ it 'raises ArchiveNotFoundError'
324
+ end
325
+
326
+ context 'archive cannot be accessed due to permissions' do
327
+ it 'raises ArchiveNotAccessibleError'
328
+ end
329
+
330
+ context 'invalid or unreadable archive' do
331
+ it 'raises ArchiveInvalidError'
332
+ end
333
+ end
334
+ end
335
+
336
+ describe '#remove_member' do
337
+ context "backend: #{backend_name}" do
338
+ subject { MultiZip.new(temp_filename, :backend => backend_name) }
339
+
340
+ let(:temp_filename) { "/tmp/multizip_test.zip" }
341
+ let(:member_file_name) { archive_member_files.first }
342
+
343
+ after do
344
+ FileUtils.rm(temp_filename) if File.exists?(temp_filename)
345
+ end
346
+
347
+ context 'archive exists' do
348
+ before do
349
+ FileUtils.cp(filename, temp_filename)
350
+ expect(
351
+ MultiZip.new(temp_filename).member_exists?(member_file_name)
352
+ ).to be_truthy
353
+ end
354
+
355
+ let!(:result) do
356
+ subject.remove_member(member_file_name)
357
+ end
358
+
359
+ context 'member removed successfully' do
360
+ it 'returns true' do
361
+ expect(result).to be_truthy
362
+ end
363
+ it 'removes the member from the file' do
364
+ expect(
365
+ MultiZip.new(temp_filename).member_exists?(member_file_name)
366
+ ).to be_falsey
367
+ end
368
+ it 'does not remove any other members' do
369
+ zip = MultiZip.new(temp_filename)
370
+ (archive_member_files - [member_file_name]).each do |mfn|
371
+ expect(zip.member_exists?(mfn)).to be_truthy
372
+ end
373
+ end
374
+ end
375
+
376
+ context 'member not successfully added' do
377
+ it 'raises MemberNotRemovedError'
378
+ it 'does not remove member from the archive'
379
+ end
380
+ end
381
+
382
+ context 'archive not found' do
383
+ it_behaves_like 'raises ArchiveNotFoundError', :remove_member, archive_member_files.first
384
+ end
385
+
386
+ context 'archive is not a file' do
387
+ it 'raises ArchiveNotFoundError'
388
+ end
389
+
390
+ context 'archive cannot be accessed due to permissions' do
391
+ it 'raises ArchiveNotAccessibleError'
392
+ end
393
+
394
+ context 'invalid or unreadable archive' do
395
+ it 'raises ArchiveInvalidError'
396
+ end
397
+ end
398
+ end
399
+
400
+ describe '#remove_members' do
401
+ context "backend: #{backend_name}" do
402
+ subject { MultiZip.new(temp_filename, :backend => backend_name) }
403
+
404
+ let(:temp_filename) { "/tmp/multizip_test.zip" }
405
+ let(:member_file_names) { archive_member_files[0..1] }
406
+
407
+ after do
408
+ FileUtils.rm(temp_filename) if File.exists?(temp_filename)
409
+ end
410
+
411
+ context 'archive exists' do
412
+ before do
413
+ FileUtils.cp(filename, temp_filename)
414
+ member_file_names.each do |mfn|
415
+ expect(
416
+ MultiZip.new(temp_filename).member_exists?(mfn)
417
+ ).to be_truthy
418
+ end
419
+ end
420
+
421
+ let!(:result) do
422
+ subject.remove_members(member_file_names)
423
+ end
424
+
425
+ context 'members removed successfully' do
426
+ it 'returns true' do
427
+ expect(result).to be_truthy
428
+ end
429
+ it 'removes the members from the file' do
430
+ member_file_names.each do |mfn|
431
+ expect(
432
+ MultiZip.new(temp_filename).member_exists?(mfn)
433
+ ).to be_falsey
434
+ end
435
+ end
436
+ it 'does not remove any other members' do
437
+ zip = MultiZip.new(temp_filename)
438
+ (archive_member_files - member_file_names).each do |mfn|
439
+ expect(zip.member_exists?(mfn)).to be_truthy
440
+ end
441
+ end
442
+ end
443
+
444
+ context 'member not successfully added' do
445
+ it 'raises MemberNotRemovedError'
446
+ it 'does not remove member from the archive'
447
+ end
448
+ end
449
+
450
+ context 'archive not found' do
451
+ it_behaves_like 'raises ArchiveNotFoundError', :remove_members, archive_member_files
452
+ end
453
+
454
+ context 'archive is not a file' do
455
+ it 'raises ArchiveNotFoundError'
456
+ end
457
+
458
+ context 'archive cannot be accessed due to permissions' do
459
+ it 'raises ArchiveNotAccessibleError'
460
+ end
461
+
462
+ context 'invalid or unreadable archive' do
463
+ it 'raises ArchiveInvalidError'
464
+ end
465
+ end
466
+ end
467
+ end
468
+
469
+ shared_examples 'raises MemberNotFoundError' do |*args|
470
+ it 'raises MemberNotFoundError' do
471
+ expect(lambda{ subject.send(args.shift, *args) }).to raise_error(MultiZip::MemberNotFoundError)
472
+ end
473
+ end
474
+
475
+ shared_examples 'raises InvalidArchiveError' do |*args|
476
+ let(:filename) { invalid_archive_fixture_filename }
477
+ it 'raises InvalidArchiveError' do
478
+ expect(lambda{ subject.send(args.shift, *args) }).to raise_error(MultiZip::InvalidArchiveError)
479
+ end
480
+ end
481
+
482
+ shared_examples 'raises ArchiveNotFoundError' do |*args|
483
+ let(:filename) { 'doesnt_exist' }
484
+ it 'raises ArchiveNotFoundError' do
485
+ expect(lambda{ subject.send(args.shift, *args) }).to raise_error(MultiZip::ArchiveNotFoundError)
486
+ end
487
+ end
@@ -0,0 +1 @@
1
+ This is not a valid zip archive.
Binary file
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'backend_shared_example'
3
+
4
+ RSpec.describe MultiZip do
5
+ it_behaves_like 'zip backend', 'archive_zip'
6
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'backend_shared_example'
3
+
4
+ RSpec.describe MultiZip do
5
+ if test_with_rubyzip?
6
+ it_behaves_like 'zip backend', 'rubyzip'
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'backend_shared_example'
3
+
4
+ RSpec.describe MultiZip do
5
+ if test_with_zipruby?
6
+ it_behaves_like 'zip backend', 'zipruby'
7
+ end
8
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe MultiZip do
4
+ let(:filename) { archive_fixture_filename }
5
+ let(:subject) { MultiZip.new(filename) }
6
+
7
+ describe '.new' do
8
+ it 'accepts a block'
9
+ end
10
+
11
+ describe '#backend=' do
12
+ context 'supported backends' do
13
+ before do
14
+ # so we don't get NoSupportedBackendError in subject.
15
+ expect_any_instance_of(MultiZip).to receive(:default_backend)
16
+ end
17
+
18
+ backends_to_test.each do |backend_name|
19
+ it "sets backend to #{backend_name}" do
20
+ subject.backend = backend_name
21
+ expect(subject.backend).to eq(backend_name.to_sym)
22
+ end
23
+ end
24
+ end
25
+
26
+ context 'unknown backend' do
27
+ it 'raises exception' do
28
+ expect(
29
+ lambda { subject.backend = 'unsupported' }
30
+ ).to raise_exception(MultiZip::NoSupportedBackendError)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#backend" do
36
+ context "no backend specified" do
37
+ backends_to_test.each do |gem_name|
38
+ context "#{gem_name} gem has been required" do
39
+ before do
40
+ apply_constants(gem_name)
41
+ end
42
+
43
+ after { stash_constants(gem_name) }
44
+
45
+ it "is :#{gem_name}" do
46
+ expect(subject.backend).to eq(gem_name.to_sym)
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end