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_range_edge_cases
41 ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:file1\n",
42 ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:file1 0:0:file2\n",
43 ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:file1 0:0:file1\n",
44 ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:file1 0:0:file2 0:0:file1\n",
45 ". 0cc175b9c0f1b6a831c399e269772661+1 0:0:file1 1:0:file2 1:0:file1\n",
47 coll = Arv::Collection.new(txt)
49 assert_match(/ 0:0:file1/, coll.manifest_text)
52 ". d41d8cd98f00b204e9800998ecf8427e+0 1:0:file1\n",
53 ". 0cc175b9c0f1b6a831c399e269772661+1 0:0:file1 2:0:file2 1:0:file1\n",
55 assert_raises(RangeError) do
56 coll = Arv::Collection.new(txt)
62 def test_non_manifest_construction_error
63 ["word", ". abc def", ". #{random_block} 0:", ". / !"].each do |m_text|
64 assert_raises(ArgumentError,
65 "built collection from manifest #{m_text.inspect}") do
66 Arv::Collection.new(m_text)
71 def test_file_directory_conflict_construction_error
72 assert_raises(ArgumentError) do
73 Arv::Collection.new(NAME_CONFLICT_MANIFEST)
77 def test_no_implicit_normalization
78 coll = Arv::Collection.new(NONNORMALIZED_MANIFEST)
79 assert_equal(NONNORMALIZED_MANIFEST, coll.manifest_text)
84 def test_non_posix_path_handling
85 m_text = "./.. #{random_block(9)} 0:5:. 5:4:..\n"
86 coll = Arv::Collection.new(m_text.dup)
88 assert_equal(m_text, coll.manifest_text)
91 def test_escaping_through_normalization
92 coll = Arv::Collection.new(MANY_ESCAPES_MANIFEST)
94 # The result should simply duplicate the file spec.
95 # The source file spec has an unescaped backslash in it.
96 # It's OK for the Collection class to properly escape that.
97 expect_text = MANY_ESCAPES_MANIFEST.sub(/ \d+:\d+:\S+/) do |file_spec|
98 file_spec.gsub(/([^\\])(\\[^\\\d])/, '\1\\\\\2')
100 assert_equal(expect_text, coll.manifest_text)
103 def test_concatenation_with_locator_overlap(over_index=0)
104 blocks = random_blocks(4, 2)
105 blocks_s = blocks.join(" ")
106 coll = Arv::Collection.new(". %s 0:8:file\n. %s 0:4:file\n" %
107 [blocks_s, blocks[over_index, 2].join(" ")])
109 assert_equal(". #{blocks_s} 0:8:file #{over_index * 2}:4:file\n",
113 def test_concatenation_with_middle_locator_overlap
114 test_concatenation_with_locator_overlap(1)
117 def test_concatenation_with_end_locator_overlap
118 test_concatenation_with_locator_overlap(2)
121 def test_concatenation_with_partial_locator_overlap
122 blocks = random_blocks(3, 3)
123 coll = Arv::Collection
124 .new(". %s 0:6:overlap\n. %s 0:6:overlap\n" %
125 [blocks[0, 2].join(" "), blocks[1, 2].join(" ")])
127 assert_equal(". #{blocks.join(' ')} 0:6:overlap 3:6:overlap\n",
133 coll = Arv::Collection.new(". #{block} 0:0:f2 0:0:f1\n")
135 assert_equal(". #{block} 0:0:f1 0:0:f2\n", coll.manifest_text)
138 def test_normalization_file_spans_two_whole_blocks(file_specs="0:10:f1",
140 blocks = random_blocks(num_blocks, 5)
141 m_text = ". #{blocks.join(' ')} #{file_specs}\n"
142 coll = Arv::Collection.new(m_text.dup)
144 assert_equal(m_text, coll.manifest_text)
147 def test_normalization_file_fits_beginning_block
148 test_normalization_file_spans_two_whole_blocks("0:7:f1")
151 def test_normalization_file_fits_end_block
152 test_normalization_file_spans_two_whole_blocks("3:7:f1")
155 def test_normalization_file_spans_middle
156 test_normalization_file_spans_two_whole_blocks("3:5:f1")
159 def test_normalization_file_spans_three_whole_blocks
160 test_normalization_file_spans_two_whole_blocks("0:15:f1", 3)
163 def test_normalization_file_skips_bytes
164 test_normalization_file_spans_two_whole_blocks("0:3:f1 5:5:f1")
167 def test_normalization_file_inserts_bytes
168 test_normalization_file_spans_two_whole_blocks("0:3:f1 5:3:f1 3:2:f1")
171 def test_normalization_file_duplicates_bytes
172 test_normalization_file_spans_two_whole_blocks("2:3:f1 2:3:f1", 1)
175 def test_normalization_handles_duplicate_locator
176 blocks = random_blocks(2, 5)
177 coll = Arv::Collection.new(". %s %s 1:8:f1 11:8:f1\n" %
178 [blocks.join(" "), blocks.reverse.join(" ")])
180 assert_equal(". #{blocks.join(' ')} #{blocks[0]} 1:8:f1 6:8:f1\n",
186 def test_simple_file_copy
187 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
188 coll.cp_r("./simple.txt", "./new")
189 assert_equal(SIMPLEST_MANIFEST.sub(" 0:9:", " 0:9:new 0:9:"),
193 def test_copy_file_into_other_stream(target="./s1/f2", basename="f2")
194 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
195 coll.cp_r("./f2", target)
196 expected = "%s./s1 %s 0:5:f1 14:4:%s 5:4:f3\n" %
197 [TWO_BY_TWO_MANIFEST_A.first,
198 TWO_BY_TWO_BLOCKS.reverse.join(" "), basename]
199 assert_equal(expected, coll.manifest_text)
202 def test_implicit_copy_file_into_other_stream
203 test_copy_file_into_other_stream("./s1")
206 def test_copy_file_into_other_stream_with_new_name
207 test_copy_file_into_other_stream("./s1/f2a", "f2a")
210 def test_copy_file_over_in_other_stream(target="./s1/f1")
211 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
212 coll.cp_r("./f1", target)
213 expected = "%s./s1 %s 0:5:f1 14:4:f3\n" %
214 [TWO_BY_TWO_MANIFEST_A.first, TWO_BY_TWO_BLOCKS.join(" ")]
215 assert_equal(expected, coll.manifest_text)
218 def test_implicit_copy_file_over_in_other_stream
219 test_copy_file_over_in_other_stream("./s1")
222 def test_simple_stream_copy
223 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
224 coll.cp_r("./s1", "./sNew")
225 new_line = TWO_BY_TWO_MANIFEST_A.last.sub("./s1 ", "./sNew ")
226 assert_equal(TWO_BY_TWO_MANIFEST_S + new_line, coll.manifest_text)
229 def test_copy_stream_into_other_stream(target="./dir2/subdir",
231 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
232 coll.cp_r("./dir1/subdir", target)
233 new_line = MULTILEVEL_MANIFEST.lines[4].sub("./dir1/subdir ",
234 "./dir2/#{basename} ")
235 assert_equal(MULTILEVEL_MANIFEST + new_line, coll.manifest_text)
238 def test_implicit_copy_stream_into_other_stream
239 test_copy_stream_into_other_stream("./dir2")
242 def test_copy_stream_into_other_stream_with_new_name
243 test_copy_stream_into_other_stream("./dir2/newsub", "newsub")
246 def test_copy_stream_over_empty_stream
247 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
248 (1..3).each do |file_num|
249 coll.rm("./dir0/subdir/file#{file_num}")
251 coll.cp_r("./dir1/subdir", "./dir0")
252 expected = MULTILEVEL_MANIFEST.lines
253 expected[2] = expected[4].sub("./dir1/", "./dir0/")
254 assert_equal(expected.join(""), coll.manifest_text)
257 def test_copy_stream_over_file_raises_ENOTDIR(source="./s1", target="./f2")
258 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
259 assert_raises(Errno::ENOTDIR) do
260 coll.cp_r(source, target)
264 def test_copy_file_under_file_raises_ENOTDIR
265 test_copy_stream_over_file_raises_ENOTDIR("./f1", "./f2/newfile")
268 def test_copy_stream_over_nonempty_stream_merges_and_overwrites
269 blocks = random_blocks(3, 9)
271 ["./subdir #{blocks[0]} 0:1:s1 1:2:zero\n",
272 "./zdir #{blocks[1]} 0:9:zfile\n",
273 "./zdir/subdir #{blocks[2]} 0:1:s2 1:2:zero\n"]
274 coll = Arv::Collection.new(manifest_a.join(""))
275 coll.cp_r("./subdir", "./zdir")
276 manifest_a[2] = "./zdir/subdir %s %s 0:1:s1 9:1:s2 1:2:zero\n" %
277 [blocks[0], blocks[2]]
278 assert_equal(manifest_a.join(""), coll.manifest_text)
281 def test_copy_stream_into_substream(source="./dir1",
282 target="./dir1/subdir/dir1")
283 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
284 coll.cp_r(source, target)
285 expected = MULTILEVEL_MANIFEST.lines.flat_map do |line|
286 [line, line.gsub(/^#{Regexp.escape(source)}([\/ ])/, "#{target}\\1")].uniq
288 assert_equal(expected.sort.join(""), coll.manifest_text)
292 test_copy_stream_into_substream(".", "./root")
295 def test_adding_to_root_after_copy
296 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
297 coll.cp_r(".", "./root")
298 src_coll = Arv::Collection.new(COLON_FILENAME_MANIFEST)
299 coll.cp_r("./file:test.txt", ".", src_coll)
300 got_lines = coll.manifest_text.lines
301 assert_equal(2, got_lines.size)
302 assert_match(/^\. \S{33,} \S{33,} 0:9:file:test\.txt 9:9:simple\.txt\n/,
304 assert_equal(SIMPLEST_MANIFEST.sub(". ", "./root "), got_lines.last)
307 def test_copy_chaining
308 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
309 coll.cp_r("./simple.txt", "./a").cp_r("./a", "./b")
310 assert_equal(SIMPLEST_MANIFEST.sub(" 0:9:", " 0:9:a 0:9:b 0:9:"),
314 def prep_two_collections_for_copy(src_stream, dst_stream)
315 blocks = random_blocks(2, 8)
316 src_text = "#{src_stream} #{blocks.first} 0:8:f1\n"
317 dst_text = "#{dst_stream} #{blocks.last} 0:8:f2\n"
318 return [blocks, src_text, dst_text,
319 Arv::Collection.new(src_text.dup),
320 Arv::Collection.new(dst_text.dup)]
323 def test_copy_file_from_other_collection(src_stream=".", dst_stream="./s1")
324 blocks, src_text, dst_text, src_coll, dst_coll =
325 prep_two_collections_for_copy(src_stream, dst_stream)
326 dst_coll.cp_r("#{src_stream}/f1", dst_stream, src_coll)
327 assert_equal("#{dst_stream} #{blocks.join(' ')} 0:8:f1 8:8:f2\n",
328 dst_coll.manifest_text)
329 assert_equal(src_text, src_coll.manifest_text)
332 def test_copy_file_from_other_collection_to_root
333 test_copy_file_from_other_collection("./s1", ".")
336 def test_copy_stream_from_other_collection
337 blocks, src_text, dst_text, src_coll, dst_coll =
338 prep_two_collections_for_copy("./s2", "./s1")
339 dst_coll.cp_r("./s2", "./s1", src_coll)
340 assert_equal(dst_text + src_text.sub("./s2 ", "./s1/s2 "),
341 dst_coll.manifest_text)
342 assert_equal(src_text, src_coll.manifest_text)
345 def test_copy_stream_from_other_collection_to_root
346 blocks, src_text, dst_text, src_coll, dst_coll =
347 prep_two_collections_for_copy("./s1", ".")
348 dst_coll.cp_r("./s1", ".", src_coll)
349 assert_equal(dst_text + src_text, dst_coll.manifest_text)
350 assert_equal(src_text, src_coll.manifest_text)
353 def test_copy_stream_contents
354 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
355 coll.cp_r("./dir0/subdir/", "./dir1/subdir")
356 expect_lines = MULTILEVEL_MANIFEST.lines
357 expect_lines[4] = expect_lines[2].sub("./dir0/", "./dir1/")
358 assert_equal(expect_lines.join(""), coll.manifest_text)
361 def test_copy_file_into_new_stream_with_implicit_filename
362 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
363 coll.cp_r("./simple.txt", "./new/")
364 assert_equal(SIMPLEST_MANIFEST + SIMPLEST_MANIFEST.sub(". ", "./new "),
368 def test_copy_file_into_new_stream_with_explicit_filename
369 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
370 coll.cp_r("./simple.txt", "./new/newfile.txt")
371 new_line = SIMPLEST_MANIFEST.sub(". ", "./new ").sub(":simple", ":newfile")
372 assert_equal(SIMPLEST_MANIFEST + new_line, coll.manifest_text)
375 def test_copy_stream_contents_into_root
376 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
377 coll.cp_r("./s1/", ".")
378 assert_equal(". %s 0:5:f1 14:4:f2 5:4:f3\n%s" %
379 [TWO_BY_TWO_BLOCKS.reverse.join(" "),
380 TWO_BY_TWO_MANIFEST_A.last],
384 def test_copy_root_contents_into_stream
385 # This is especially fun, because we're copying a parent into its child.
386 # Make sure that happens depth-first.
387 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
388 coll.cp_r("./", "./s1")
389 assert_equal("%s./s1 %s 0:5:f1 5:4:f2 14:4:f3\n%s" %
390 [TWO_BY_TWO_MANIFEST_A.first, TWO_BY_TWO_BLOCKS.join(" "),
391 TWO_BY_TWO_MANIFEST_A.last.sub("./s1 ", "./s1/s1 ")],
395 def test_copy_stream_contents_across_collections
396 block = random_block(8)
397 src_coll = Arv::Collection.new("./s1 #{block} 0:8:f1\n")
398 dst_coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
399 dst_coll.cp_r("./s1/", "./s1", src_coll)
400 assert_equal("%s./s1 %s %s 0:8:f1 13:4:f3\n" %
401 [TWO_BY_TWO_MANIFEST_A.first, block, TWO_BY_TWO_BLOCKS.last],
402 dst_coll.manifest_text)
405 def test_copy_root_contents_across_collections
406 block = random_block(8)
407 src_coll = Arv::Collection.new(". #{block} 0:8:f1\n")
408 dst_coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
409 dst_coll.cp_r("./", ".", src_coll)
410 assert_equal(". %s %s 0:8:f1 13:4:f2\n%s" %
411 [block, TWO_BY_TWO_BLOCKS.first, TWO_BY_TWO_MANIFEST_A.last],
412 dst_coll.manifest_text)
415 def test_copy_root_into_empty_collection
416 block = random_block(8)
417 src_coll = Arv::Collection.new(". #{block} 0:8:f1\n")
418 dst_coll = Arv::Collection.new()
419 dst_coll.cp_r("./", ".", src_coll)
420 assert_equal(". %s 0:8:f1\n" %
422 dst_coll.manifest_text)
425 def test_copy_with_repeated_blocks
426 blocks = abcde_blocks
427 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")
428 dst_coll = Arv::Collection.new()
429 dst_coll.cp_r("f1", "./", src_coll)
430 assert_equal(". #{blocks[0]} #{blocks[1]} #{blocks[2]} 0:27:f1\n", dst_coll.manifest_text, "mangled by cp_r")
433 def test_copy_with_repeated_split_blocks
434 blocks = abcde_blocks
435 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")
436 dst_coll = Arv::Collection.new()
438 assert_equal(". #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} 2:27:f1\n", src_coll.manifest_text, "mangled by normalize()")
439 dst_coll.cp_r("f1", "./", src_coll)
440 assert_equal(". #{blocks[2]} #{blocks[0]} #{blocks[1]} #{blocks[2]} 2:27:f1\n", dst_coll.manifest_text, "mangled by cp_r")
443 def test_copy_empty_source_path_raises_ArgumentError(src="", dst="./s1")
444 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
445 assert_raises(ArgumentError) do
450 def test_copy_empty_destination_path_raises_ArgumentError
451 test_copy_empty_source_path_raises_ArgumentError(".", "")
456 def test_each_file_path
457 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
462 coll.each_file_path { |path| result << path }
464 assert_equal(["./f1", "./f2", "./s1/f1", "./s1/f3"], result.sort)
467 def test_each_file_path_without_block
468 test_each_file_path { |coll| coll.each_file_path.to_a }
471 def test_each_file_path_empty_collection
472 assert_empty(Arv::Collection.new.each_file_path.to_a)
475 def test_each_file_path_after_collection_emptied
476 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
477 coll.rm("simple.txt")
478 assert_empty(coll.each_file_path.to_a)
481 def test_each_file_path_deduplicates_manifest_listings
482 coll = Arv::Collection.new(MULTIBLOCK_FILE_MANIFEST)
483 assert_equal(["./repfile", "./s1/repfile", "./s1/uniqfile",
484 "./uniqfile", "./uniqfile2"],
485 coll.each_file_path.to_a.sort)
490 def test_exist(test_method=:assert, path="f2")
491 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
492 send(test_method, coll.exist?(path))
495 def test_file_not_exist
496 test_exist(:refute, "f3")
499 def test_stream_exist
500 test_exist(:assert, "s1")
503 def test_file_inside_stream_exist
504 test_exist(:assert, "s1/f1")
507 def test_path_inside_stream_not_exist
508 test_exist(:refute, "s1/f2")
511 def test_path_under_file_not_exist
512 test_exist(:refute, "f2/nonexistent")
515 def test_deep_substreams_not_exist
516 test_exist(:refute, "a/b/c/d/e/f/g")
521 def test_simple_file_rename
522 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
523 coll.rename("./simple.txt", "./new")
524 assert_equal(SIMPLEST_MANIFEST.sub(":simple.txt", ":new"),
528 def test_rename_file_into_other_stream(target="./s1/f2", basename="f2")
529 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
530 coll.rename("./f2", target)
531 expected = ". %s 0:5:f1\n./s1 %s 0:5:f1 14:4:%s 5:4:f3\n" %
532 [TWO_BY_TWO_BLOCKS.first,
533 TWO_BY_TWO_BLOCKS.reverse.join(" "), basename]
534 assert_equal(expected, coll.manifest_text)
537 def test_implicit_rename_file_into_other_stream
538 test_rename_file_into_other_stream("./s1")
541 def test_rename_file_into_other_stream_with_new_name
542 test_rename_file_into_other_stream("./s1/f2a", "f2a")
545 def test_rename_file_over_in_other_stream(target="./s1/f1")
546 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
547 coll.rename("./f1", target)
548 expected = ". %s 5:4:f2\n./s1 %s 0:5:f1 14:4:f3\n" %
549 [TWO_BY_TWO_BLOCKS.first, TWO_BY_TWO_BLOCKS.join(" ")]
550 assert_equal(expected, coll.manifest_text)
553 def test_implicit_rename_file_over_in_other_stream
554 test_rename_file_over_in_other_stream("./s1")
557 def test_simple_stream_rename
558 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
559 coll.rename("./s1", "./newS")
560 assert_equal(TWO_BY_TWO_MANIFEST_S.sub("\n./s1 ", "\n./newS "),
564 def test_rename_stream_into_other_stream(target="./dir2/subdir",
566 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
567 coll.rename("./dir1/subdir", target)
568 expected = MULTILEVEL_MANIFEST.lines
569 replaced_line = expected.delete_at(4)
570 expected << replaced_line.sub("./dir1/subdir ", "./dir2/#{basename} ")
571 assert_equal(expected.join(""), coll.manifest_text)
574 def test_implicit_rename_stream_into_other_stream
575 test_rename_stream_into_other_stream("./dir2")
578 def test_rename_stream_into_other_stream_with_new_name
579 test_rename_stream_into_other_stream("./dir2/newsub", "newsub")
582 def test_rename_stream_over_empty_stream
583 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
584 (1..3).each do |file_num|
585 coll.rm("./dir0/subdir/file#{file_num}")
587 coll.rename("./dir1/subdir", "./dir0")
588 expected = MULTILEVEL_MANIFEST.lines
589 expected[2] = expected.delete_at(4).sub("./dir1/", "./dir0/")
590 assert_equal(expected.sort.join(""), coll.manifest_text)
593 def test_rename_stream_over_file_raises_ENOTDIR
594 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
595 assert_raises(Errno::ENOTDIR) do
596 coll.rename("./s1", "./f2")
600 def test_rename_stream_over_nonempty_stream_raises_ENOTEMPTY
601 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
602 assert_raises(Errno::ENOTEMPTY) do
603 coll.rename("./dir1/subdir", "./dir0")
607 def test_rename_stream_into_substream(source="./dir1",
608 target="./dir1/subdir/dir1")
609 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
610 coll.rename(source, target)
611 assert_equal(MULTILEVEL_MANIFEST.gsub(/^#{Regexp.escape(source)}([\/ ])/m,
617 test_rename_stream_into_substream(".", "./root")
620 def test_adding_to_root_after_rename
621 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
622 coll.rename(".", "./root")
623 src_coll = Arv::Collection.new(SIMPLEST_MANIFEST)
624 coll.cp_r("./simple.txt", ".", src_coll)
625 assert_equal(SIMPLEST_MANIFEST + SIMPLEST_MANIFEST.sub(". ", "./root "),
629 def test_rename_chaining
630 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
631 coll.rename("./simple.txt", "./x").rename("./x", "./simple.txt")
632 assert_equal(SIMPLEST_MANIFEST, coll.manifest_text)
637 def test_simple_remove
638 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S.dup)
640 assert_equal(TWO_BY_TWO_MANIFEST_S.sub(" 5:4:f2", ""), coll.manifest_text)
643 def empty_stream_and_assert(expect_index=0)
644 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
646 assert_equal(TWO_BY_TWO_MANIFEST_A[expect_index], coll.manifest_text)
649 def test_remove_all_files_in_substream
650 empty_stream_and_assert do |coll|
656 def test_remove_all_files_in_root_stream
657 empty_stream_and_assert(1) do |coll|
663 def test_chaining_removes
664 empty_stream_and_assert do |coll|
665 coll.rm("./s1/f1").rm("./s1/f3")
669 def test_remove_last_file
670 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
671 coll.rm("./simple.txt")
672 assert_equal("", coll.manifest_text)
675 def test_remove_nonexistent_file_raises_ENOENT(path="./NoSuchFile",
677 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
678 assert_raises(Errno::ENOENT) do
679 coll.send(method, path)
683 def test_remove_from_nonexistent_stream_raises_ENOENT
684 test_remove_nonexistent_file_raises_ENOENT("./NoSuchStream/simple.txt")
687 def test_remove_stream_raises_EISDIR(path="./s1")
688 coll = Arv::Collection.new(TWO_BY_TWO_MANIFEST_S)
689 assert_raises(Errno::EISDIR) do
694 def test_remove_root_raises_EISDIR
695 test_remove_stream_raises_EISDIR(".")
698 def test_remove_empty_string_raises_ArgumentError
699 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
700 assert_raises(ArgumentError) do
707 def test_recursive_remove
708 empty_stream_and_assert do |coll|
713 def test_recursive_remove_on_files
714 empty_stream_and_assert do |coll|
720 def test_recursive_remove_root
721 coll = Arv::Collection.new(MULTILEVEL_MANIFEST)
723 assert_equal("", coll.manifest_text)
726 def test_rm_r_nonexistent_file_raises_ENOENT(path="./NoSuchFile")
727 test_remove_nonexistent_file_raises_ENOENT("./NoSuchFile", :rm_r)
730 def test_rm_r_from_nonexistent_stream_raises_ENOENT
731 test_remove_nonexistent_file_raises_ENOENT("./NoSuchStream/file", :rm_r)
734 def test_rm_r_empty_string_raises_ArgumentError
735 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
736 assert_raises(ArgumentError) do
743 def test_new_collection_unmodified(*args)
744 coll = Arv::Collection.new(*args)
745 yield coll if block_given?
746 refute(coll.modified?)
749 def test_collection_unmodified_after_instantiation
750 test_new_collection_unmodified(SIMPLEST_MANIFEST)
753 def test_collection_unmodified_after_mark
754 test_new_collection_unmodified(SIMPLEST_MANIFEST) do |coll|
755 coll.cp_r("./simple.txt", "./copy")
760 def check_collection_modified
761 coll = Arv::Collection.new(SIMPLEST_MANIFEST)
763 assert(coll.modified?)
766 def test_collection_modified_after_copy
767 check_collection_modified do |coll|
768 coll.cp_r("./simple.txt", "./copy")
772 def test_collection_modified_after_remove
773 check_collection_modified do |coll|
774 coll.rm("./simple.txt")
778 def test_collection_modified_after_rename
779 check_collection_modified do |coll|
780 coll.rename("./simple.txt", "./newname")