1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
5 require "arvados/collection"
6 require "minitest/autorun"
9 class CollectionTest < Minitest::Test
12 TWO_BY_TWO_BLOCKS = SDKFixtures.random_blocks(2, 9)
13 TWO_BY_TWO_MANIFEST_A =
14 [". #{TWO_BY_TWO_BLOCKS.first} 0:5:f1 5:4:f2\n",
15 "./s1 #{TWO_BY_TWO_BLOCKS.last} 0:5:f1 5:4:f3\n"]
16 TWO_BY_TWO_MANIFEST_S = TWO_BY_TWO_MANIFEST_A.join("")
19 ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+9", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb+9", "cccccccccccccccccccccccccccccccc+9", "dddddddddddddddddddddddddddddddd+9", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee+9"]
24 def test_empty_construction
25 coll = Arv::Collection.new
26 assert_equal("", coll.manifest_text)
29 def test_successful_construction
30 [:SIMPLEST_MANIFEST, :MULTIBLOCK_FILE_MANIFEST, :MULTILEVEL_MANIFEST].
31 each do |manifest_name|
32 manifest_text = SDKFixtures.const_get(manifest_name)
33 coll = Arv::Collection.new(manifest_text)
34 assert_equal(manifest_text, coll.manifest_text,
35 "did not get same manifest back out from #{manifest_name}")
39 def test_non_manifest_construction_error
40 ["word", ". abc def", ". #{random_block} 0:", ". / !"].each do |m_text|
41 assert_raises(ArgumentError,
42 "built collection from manifest #{m_text.inspect}") do
43 Arv::Collection.new(m_text)
48 def test_file_directory_conflict_construction_error
49 assert_raises(ArgumentError) do
50 Arv::Collection.new(NAME_CONFLICT_MANIFEST)
54 def test_no_implicit_normalization
55 coll = Arv::Collection.new(NONNORMALIZED_MANIFEST)
56 assert_equal(NONNORMALIZED_MANIFEST, coll.manifest_text)
61 def test_non_posix_path_handling
62 m_text = "./.. #{random_block(9)} 0:5:. 5:4:..\n"
63 coll = Arv::Collection.new(m_text.dup)
65 assert_equal(m_text, coll.manifest_text)
68 def test_escaping_through_normalization
69 coll = Arv::Collection.new(MANY_ESCAPES_MANIFEST)
71 # The result should simply duplicate the file spec.
72 # The source file spec has an unescaped backslash in it.
73 # It's OK for the Collection class to properly escape that.
74 expect_text = MANY_ESCAPES_MANIFEST.sub(/ \d+:\d+:\S+/) do |file_spec|
75 file_spec.gsub(/([^\\])(\\[^\\\d])/, '\1\\\\\2')
77 assert_equal(expect_text, coll.manifest_text)
80 def test_concatenation_with_locator_overlap(over_index=0)
81 blocks = random_blocks(4, 2)
82 blocks_s = blocks.join(" ")
83 coll = Arv::Collection.new(". %s 0:8:file\n. %s 0:4:file\n" %
84 [blocks_s, blocks[over_index, 2].join(" ")])
86 assert_equal(". #{blocks_s} 0:8:file #{over_index * 2}:4:file\n",
90 def test_concatenation_with_middle_locator_overlap
91 test_concatenation_with_locator_overlap(1)
94 def test_concatenation_with_end_locator_overlap
95 test_concatenation_with_locator_overlap(2)
98 def test_concatenation_with_partial_locator_overlap
99 blocks = random_blocks(3, 3)
100 coll = Arv::Collection
101 .new(". %s 0:6:overlap\n. %s 0:6:overlap\n" %
102 [blocks[0, 2].join(" "), blocks[1, 2].join(" ")])
104 assert_equal(". #{blocks.join(' ')} 0:6:overlap 3:6:overlap\n",
110 coll = Arv::Collection.new(". #{block} 0:0:f2 0:0:f1\n")
112 assert_equal(". #{block} 0:0:f1 0:0:f2\n", coll.manifest_text)
115 def test_normalization_file_spans_two_whole_blocks(file_specs="0:10:f1",
117 blocks = random_blocks(num_blocks, 5)
118 m_text = ". #{blocks.join(' ')} #{file_specs}\n"
119 coll = Arv::Collection.new(m_text.dup)
121 assert_equal(m_text, coll.manifest_text)
124 def test_normalization_file_fits_beginning_block
125 test_normalization_file_spans_two_whole_blocks("0:7:f1")
128 def test_normalization_file_fits_end_block
129 test_normalization_file_spans_two_whole_blocks("3:7:f1")
132 def test_normalization_file_spans_middle
133 test_normalization_file_spans_two_whole_blocks("3:5:f1")
136 def test_normalization_file_spans_three_whole_blocks
137 test_normalization_file_spans_two_whole_blocks("0:15:f1", 3)
140 def test_normalization_file_skips_bytes
141 test_normalization_file_spans_two_whole_blocks("0:3:f1 5:5:f1")
144 def test_normalization_file_inserts_bytes
145 test_normalization_file_spans_two_whole_blocks("0:3:f1 5:3:f1 3:2:f1")
148 def test_normalization_file_duplicates_bytes
149 test_normalization_file_spans_two_whole_blocks("2:3:f1 2:3:f1", 1)
152 def test_normalization_handles_duplicate_locator
153 blocks = random_blocks(2, 5)
154 coll = Arv::Collection.new(". %s %s 1:8:f1 11:8:f1\n" %
155 [blocks.join(" "), blocks.reverse.join(" ")])
157 assert_equal(". #{blocks.join(' ')} #{blocks[0]} 1:8:f1 6:8:f1\n",
163 def test_simple_file_copy
164 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
165 coll.cp_r("./simple.txt", "./new")
166 assert_equal(SIMPLEST_MANIFEST.sub(" 0:9:", " 0:9:new 0:9:"),
170 def test_copy_file_into_other_stream(target="./s1/f2", basename="f2")
171 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
172 coll.cp_r("./f2", target)
173 expected = "%s./s1 %s 0:5:f1 14:4:%s 5:4:f3\n" %
174 [TWO_BY_TWO_MANIFEST_A.first,
175 TWO_BY_TWO_BLOCKS.reverse.join(" "), basename]
176 assert_equal(expected, coll.manifest_text)
179 def test_implicit_copy_file_into_other_stream
180 test_copy_file_into_other_stream("./s1")
183 def test_copy_file_into_other_stream_with_new_name
184 test_copy_file_into_other_stream("./s1/f2a", "f2a")
187 def test_copy_file_over_in_other_stream(target="./s1/f1")
188 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
189 coll.cp_r("./f1", target)
190 expected = "%s./s1 %s 0:5:f1 14:4:f3\n" %
191 [TWO_BY_TWO_MANIFEST_A.first, TWO_BY_TWO_BLOCKS.join(" ")]
192 assert_equal(expected, coll.manifest_text)
195 def test_implicit_copy_file_over_in_other_stream
196 test_copy_file_over_in_other_stream("./s1")
199 def test_simple_stream_copy
200 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
201 coll.cp_r("./s1", "./sNew")
202 new_line = TWO_BY_TWO_MANIFEST_A.last.sub("./s1 ", "./sNew ")
203 assert_equal(TWO_BY_TWO_MANIFEST_S + new_line, coll.manifest_text)
206 def test_copy_stream_into_other_stream(target="./dir2/subdir",
208 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
209 coll.cp_r("./dir1/subdir", target)
210 new_line = MULTILEVEL_MANIFEST.lines[4].sub("./dir1/subdir ",
211 "./dir2/#{basename} ")
212 assert_equal(MULTILEVEL_MANIFEST + new_line, coll.manifest_text)
215 def test_implicit_copy_stream_into_other_stream
216 test_copy_stream_into_other_stream("./dir2")
219 def test_copy_stream_into_other_stream_with_new_name
220 test_copy_stream_into_other_stream("./dir2/newsub", "newsub")
223 def test_copy_stream_over_empty_stream
224 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
225 (1..3).each do |file_num|
226 coll.rm("./dir0/subdir/file#{file_num}")
228 coll.cp_r("./dir1/subdir", "./dir0")
229 expected = MULTILEVEL_MANIFEST.lines
230 expected[2] = expected[4].sub("./dir1/", "./dir0/")
231 assert_equal(expected.join(""), coll.manifest_text)
234 def test_copy_stream_over_file_raises_ENOTDIR(source="./s1", target="./f2")
235 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
236 assert_raises(Errno::ENOTDIR) do
237 coll.cp_r(source, target)
241 def test_copy_file_under_file_raises_ENOTDIR
242 test_copy_stream_over_file_raises_ENOTDIR("./f1", "./f2/newfile")
245 def test_copy_stream_over_nonempty_stream_merges_and_overwrites
246 blocks = random_blocks(3, 9)
248 ["./subdir #{blocks[0]} 0:1:s1 1:2:zero\n",
249 "./zdir #{blocks[1]} 0:9:zfile\n",
250 "./zdir/subdir #{blocks[2]} 0:1:s2 1:2:zero\n"]
251 coll = Arv::Collection.new(manifest_a.join(""))
252 coll.cp_r("./subdir", "./zdir")
253 manifest_a[2] = "./zdir/subdir %s %s 0:1:s1 9:1:s2 1:2:zero\n" %
254 [blocks[0], blocks[2]]
255 assert_equal(manifest_a.join(""), coll.manifest_text)
258 def test_copy_stream_into_substream(source="./dir1",
259 target="./dir1/subdir/dir1")
260 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
261 coll.cp_r(source, target)
262 expected = MULTILEVEL_MANIFEST.lines.flat_map do |line|
263 [line, line.gsub(/^#{Regexp.escape(source)}([\/ ])/, "#{target}\\1")].uniq
265 assert_equal(expected.sort.join(""), coll.manifest_text)
269 test_copy_stream_into_substream(".", "./root")
272 def test_adding_to_root_after_copy
273 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
274 coll.cp_r(".", "./root")
275 src_coll = Arv::Collection.new(COLON_FILENAME_MANIFEST)
276 coll.cp_r("./file:test.txt", ".", src_coll)
277 got_lines = coll.manifest_text.lines
278 assert_equal(2, got_lines.size)
279 assert_match(/^\. \S{33,} \S{33,} 0:9:file:test\.txt 9:9:simple\.txt\n/,
281 assert_equal(SIMPLEST_MANIFEST.sub(". ", "./root "), got_lines.last)
284 def test_copy_chaining
285 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
286 coll.cp_r("./simple.txt", "./a").cp_r("./a", "./b")
287 assert_equal(SIMPLEST_MANIFEST.sub(" 0:9:", " 0:9:a 0:9:b 0:9:"),
291 def prep_two_collections_for_copy(src_stream, dst_stream)
292 blocks = random_blocks(2, 8)
293 src_text = "#{src_stream} #{blocks.first} 0:8:f1\n"
294 dst_text = "#{dst_stream} #{blocks.last} 0:8:f2\n"
295 return [blocks, src_text, dst_text,
296 Arv::Collection.new(src_text.dup),
297 Arv::Collection.new(dst_text.dup)]
300 def test_copy_file_from_other_collection(src_stream=".", dst_stream="./s1")
301 blocks, src_text, dst_text, src_coll, dst_coll =
302 prep_two_collections_for_copy(src_stream, dst_stream)
303 dst_coll.cp_r("#{src_stream}/f1", dst_stream, src_coll)
304 assert_equal("#{dst_stream} #{blocks.join(' ')} 0:8:f1 8:8:f2\n",
305 dst_coll.manifest_text)
306 assert_equal(src_text, src_coll.manifest_text)
309 def test_copy_file_from_other_collection_to_root
310 test_copy_file_from_other_collection("./s1", ".")
313 def test_copy_stream_from_other_collection
314 blocks, src_text, dst_text, src_coll, dst_coll =
315 prep_two_collections_for_copy("./s2", "./s1")
316 dst_coll.cp_r("./s2", "./s1", src_coll)
317 assert_equal(dst_text + src_text.sub("./s2 ", "./s1/s2 "),
318 dst_coll.manifest_text)
319 assert_equal(src_text, src_coll.manifest_text)
322 def test_copy_stream_from_other_collection_to_root
323 blocks, src_text, dst_text, src_coll, dst_coll =
324 prep_two_collections_for_copy("./s1", ".")
325 dst_coll.cp_r("./s1", ".", src_coll)
326 assert_equal(dst_text + src_text, dst_coll.manifest_text)
327 assert_equal(src_text, src_coll.manifest_text)
330 def test_copy_stream_contents
331 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
332 coll.cp_r("./dir0/subdir/", "./dir1/subdir")
333 expect_lines = MULTILEVEL_MANIFEST.lines
334 expect_lines[4] = expect_lines[2].sub("./dir0/", "./dir1/")
335 assert_equal(expect_lines.join(""), coll.manifest_text)
338 def test_copy_file_into_new_stream_with_implicit_filename
339 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
340 coll.cp_r("./simple.txt", "./new/")
341 assert_equal(SIMPLEST_MANIFEST + SIMPLEST_MANIFEST.sub(". ", "./new "),
345 def test_copy_file_into_new_stream_with_explicit_filename
346 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
347 coll.cp_r("./simple.txt", "./new/newfile.txt")
348 new_line = SIMPLEST_MANIFEST.sub(". ", "./new ").sub(":simple", ":newfile")
349 assert_equal(SIMPLEST_MANIFEST + new_line, coll.manifest_text)
352 def test_copy_stream_contents_into_root
353 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
354 coll.cp_r("./s1/", ".")
355 assert_equal(". %s 0:5:f1 14:4:f2 5:4:f3\n%s" %
356 [TWO_BY_TWO_BLOCKS.reverse.join(" "),
357 TWO_BY_TWO_MANIFEST_A.last],
361 def test_copy_root_contents_into_stream
362 # This is especially fun, because we're copying a parent into its child.
363 # Make sure that happens depth-first.
364 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
365 coll.cp_r("./", "./s1")
366 assert_equal("%s./s1 %s 0:5:f1 5:4:f2 14:4:f3\n%s" %
367 [TWO_BY_TWO_MANIFEST_A.first, TWO_BY_TWO_BLOCKS.join(" "),
368 TWO_BY_TWO_MANIFEST_A.last.sub("./s1 ", "./s1/s1 ")],
372 def test_copy_stream_contents_across_collections
373 block = random_block(8)
374 src_coll = Arv::Collection.new("./s1 #{block} 0:8:f1\n")
375 dst_coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
376 dst_coll.cp_r("./s1/", "./s1", src_coll)
377 assert_equal("%s./s1 %s %s 0:8:f1 13:4:f3\n" %
378 [TWO_BY_TWO_MANIFEST_A.first, block, TWO_BY_TWO_BLOCKS.last],
379 dst_coll.manifest_text)
382 def test_copy_root_contents_across_collections
383 block = random_block(8)
384 src_coll = Arv::Collection.new(". #{block} 0:8:f1\n")
385 dst_coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
386 dst_coll.cp_r("./", ".", src_coll)
387 assert_equal(". %s %s 0:8:f1 13:4:f2\n%s" %
388 [block, TWO_BY_TWO_BLOCKS.first, TWO_BY_TWO_MANIFEST_A.last],
389 dst_coll.manifest_text)
392 def test_copy_root_into_empty_collection
393 block = random_block(8)
394 src_coll = Arv::Collection.new(". #{block} 0:8:f1\n")
395 dst_coll = Arv::Collection.new()
396 dst_coll.cp_r("./", ".", src_coll)
397 assert_equal(". %s 0:8:f1\n" %
399 dst_coll.manifest_text)
402 def test_copy_with_repeated_blocks
403 blocks = abcde_blocks
404 src_coll = Arv::Collection.new(". #{blocks[0]} #{blocks[1]} #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} #{blocks[3]} #{blocks[4]} 27:27:f1\n")
405 dst_coll = Arv::Collection.new()
406 dst_coll.cp_r("f1", "./", src_coll)
407 toks = dst_coll.manifest_text.split(" ")
408 assert_equal(". #{blocks[0]} #{blocks[1]} #{blocks[2]} 0:27:f1\n", dst_coll.manifest_text, "mangled by cp_r")
411 def test_copy_with_repeated_split_blocks
412 blocks = abcde_blocks
413 src_coll = Arv::Collection.new(". #{blocks[0]} #{blocks[1]} #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} #{blocks[3]} #{blocks[4]} 20:27:f1\n")
414 dst_coll = Arv::Collection.new()
416 assert_equal(". #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} 2:27:f1\n", src_coll.manifest_text, "mangled by normalize()")
417 dst_coll.cp_r("f1", "./", src_coll)
418 toks = dst_coll.manifest_text.split(" ")
419 assert_equal(". #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} 2:27:f1\n", dst_coll.manifest_text, "mangled by cp_r")
422 def test_copy_empty_source_path_raises_ArgumentError(src="", dst="./s1")
423 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
424 assert_raises(ArgumentError) do
429 def test_copy_empty_destination_path_raises_ArgumentError
430 test_copy_empty_source_path_raises_ArgumentError(".", "")
435 def test_each_file_path
436 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
441 coll.each_file_path { |path| result << path }
443 assert_equal(["./f1", "./f2", "./s1/f1", "./s1/f3"], result.sort)
446 def test_each_file_path_without_block
447 test_each_file_path { |coll| coll.each_file_path.to_a }
450 def test_each_file_path_empty_collection
451 assert_empty(Arv::Collection.new.each_file_path.to_a)
454 def test_each_file_path_after_collection_emptied
455 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
456 coll.rm("simple.txt")
457 assert_empty(coll.each_file_path.to_a)
460 def test_each_file_path_deduplicates_manifest_listings
461 coll = Arv::Collection.new(MULTIBLOCK_FILE_MANIFEST)
462 assert_equal(["./repfile", "./s1/repfile", "./s1/uniqfile",
463 "./uniqfile", "./uniqfile2"],
464 coll.each_file_path.to_a.sort)
469 def test_exist(test_method=:assert, path="f2")
470 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
471 send(test_method, coll.exist?(path))
474 def test_file_not_exist
475 test_exist(:refute, "f3")
478 def test_stream_exist
479 test_exist(:assert, "s1")
482 def test_file_inside_stream_exist
483 test_exist(:assert, "s1/f1")
486 def test_path_inside_stream_not_exist
487 test_exist(:refute, "s1/f2")
490 def test_path_under_file_not_exist
491 test_exist(:refute, "f2/nonexistent")
494 def test_deep_substreams_not_exist
495 test_exist(:refute, "a/b/c/d/e/f/g")
500 def test_simple_file_rename
501 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
502 coll.rename("./simple.txt", "./new")
503 assert_equal(SIMPLEST_MANIFEST.sub(":simple.txt", ":new"),
507 def test_rename_file_into_other_stream(target="./s1/f2", basename="f2")
508 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
509 coll.rename("./f2", target)
510 expected = ". %s 0:5:f1\n./s1 %s 0:5:f1 14:4:%s 5:4:f3\n" %
511 [TWO_BY_TWO_BLOCKS.first,
512 TWO_BY_TWO_BLOCKS.reverse.join(" "), basename]
513 assert_equal(expected, coll.manifest_text)
516 def test_implicit_rename_file_into_other_stream
517 test_rename_file_into_other_stream("./s1")
520 def test_rename_file_into_other_stream_with_new_name
521 test_rename_file_into_other_stream("./s1/f2a", "f2a")
524 def test_rename_file_over_in_other_stream(target="./s1/f1")
525 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
526 coll.rename("./f1", target)
527 expected = ". %s 5:4:f2\n./s1 %s 0:5:f1 14:4:f3\n" %
528 [TWO_BY_TWO_BLOCKS.first, TWO_BY_TWO_BLOCKS.join(" ")]
529 assert_equal(expected, coll.manifest_text)
532 def test_implicit_rename_file_over_in_other_stream
533 test_rename_file_over_in_other_stream("./s1")
536 def test_simple_stream_rename
537 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
538 coll.rename("./s1", "./newS")
539 assert_equal(TWO_BY_TWO_MANIFEST_S.sub("\n./s1 ", "\n./newS "),
543 def test_rename_stream_into_other_stream(target="./dir2/subdir",
545 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
546 coll.rename("./dir1/subdir", target)
547 expected = MULTILEVEL_MANIFEST.lines
548 replaced_line = expected.delete_at(4)
549 expected << replaced_line.sub("./dir1/subdir ", "./dir2/#{basename} ")
550 assert_equal(expected.join(""), coll.manifest_text)
553 def test_implicit_rename_stream_into_other_stream
554 test_rename_stream_into_other_stream("./dir2")
557 def test_rename_stream_into_other_stream_with_new_name
558 test_rename_stream_into_other_stream("./dir2/newsub", "newsub")
561 def test_rename_stream_over_empty_stream
562 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
563 (1..3).each do |file_num|
564 coll.rm("./dir0/subdir/file#{file_num}")
566 coll.rename("./dir1/subdir", "./dir0")
567 expected = MULTILEVEL_MANIFEST.lines
568 expected[2] = expected.delete_at(4).sub("./dir1/", "./dir0/")
569 assert_equal(expected.sort.join(""), coll.manifest_text)
572 def test_rename_stream_over_file_raises_ENOTDIR
573 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
574 assert_raises(Errno::ENOTDIR) do
575 coll.rename("./s1", "./f2")
579 def test_rename_stream_over_nonempty_stream_raises_ENOTEMPTY
580 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
581 assert_raises(Errno::ENOTEMPTY) do
582 coll.rename("./dir1/subdir", "./dir0")
586 def test_rename_stream_into_substream(source="./dir1",
587 target="./dir1/subdir/dir1")
588 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
589 coll.rename(source, target)
590 assert_equal(MULTILEVEL_MANIFEST.gsub(/^#{Regexp.escape(source)}([\/ ])/m,
596 test_rename_stream_into_substream(".", "./root")
599 def test_adding_to_root_after_rename
600 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
601 coll.rename(".", "./root")
602 src_coll = Arv::Collection.new(SIMPLEST_MANIFEST)
603 coll.cp_r("./simple.txt", ".", src_coll)
604 assert_equal(SIMPLEST_MANIFEST + SIMPLEST_MANIFEST.sub(". ", "./root "),
608 def test_rename_chaining
609 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
610 coll.rename("./simple.txt", "./x").rename("./x", "./simple.txt")
611 assert_equal(SIMPLEST_MANIFEST, coll.manifest_text)
616 def test_simple_remove
617 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S.dup)
619 assert_equal(TWO_BY_TWO_MANIFEST_S.sub(" 5:4:f2", ""), coll.manifest_text)
622 def empty_stream_and_assert(expect_index=0)
623 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
625 assert_equal(TWO_BY_TWO_MANIFEST_A[expect_index], coll.manifest_text)
628 def test_remove_all_files_in_substream
629 empty_stream_and_assert do |coll|
635 def test_remove_all_files_in_root_stream
636 empty_stream_and_assert(1) do |coll|
642 def test_chaining_removes
643 empty_stream_and_assert do |coll|
644 coll.rm("./s1/f1").rm("./s1/f3")
648 def test_remove_last_file
649 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
650 coll.rm("./simple.txt")
651 assert_equal("", coll.manifest_text)
654 def test_remove_nonexistent_file_raises_ENOENT(path="./NoSuchFile",
656 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
657 assert_raises(Errno::ENOENT) do
658 coll.send(method, path)
662 def test_remove_from_nonexistent_stream_raises_ENOENT
663 test_remove_nonexistent_file_raises_ENOENT("./NoSuchStream/simple.txt")
666 def test_remove_stream_raises_EISDIR(path="./s1")
667 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
668 assert_raises(Errno::EISDIR) do
673 def test_remove_root_raises_EISDIR
674 test_remove_stream_raises_EISDIR(".")
677 def test_remove_empty_string_raises_ArgumentError
678 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
679 assert_raises(ArgumentError) do
686 def test_recursive_remove
687 empty_stream_and_assert do |coll|
692 def test_recursive_remove_on_files
693 empty_stream_and_assert do |coll|
699 def test_recursive_remove_root
700 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
702 assert_equal("", coll.manifest_text)
705 def test_rm_r_nonexistent_file_raises_ENOENT(path="./NoSuchFile")
706 test_remove_nonexistent_file_raises_ENOENT("./NoSuchFile", :rm_r)
709 def test_rm_r_from_nonexistent_stream_raises_ENOENT
710 test_remove_nonexistent_file_raises_ENOENT("./NoSuchStream/file", :rm_r)
713 def test_rm_r_empty_string_raises_ArgumentError
714 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
715 assert_raises(ArgumentError) do
722 def test_new_collection_unmodified(*args)
723 coll = Arv::Collection.new(*args)
724 yield coll if block_given?
725 refute(coll.modified?)
728 def test_collection_unmodified_after_instantiation
729 test_new_collection_unmodified(SIMPLEST_MANIFEST)
732 def test_collection_unmodified_after_mark
733 test_new_collection_unmodified(SIMPLEST_MANIFEST) do |coll|
734 coll.cp_r("./simple.txt", "./copy")
739 def check_collection_modified
740 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
742 assert(coll.modified?)
745 def test_collection_modified_after_copy
746 check_collection_modified do |coll|
747 coll.cp_r("./simple.txt", "./copy")
751 def test_collection_modified_after_remove
752 check_collection_modified do |coll|
753 coll.rm("./simple.txt")
757 def test_collection_modified_after_rename
758 check_collection_modified do |coll|
759 coll.rename("./simple.txt", "./newname")