source: valtobtest/subversion-1.6.2/subversion/bindings/swig/ruby/test/test_fs.rb @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 15.3 KB
Line 
1require "my-assertions"
2require "util"
3require "time"
4require "md5"
5
6require "svn/core"
7require "svn/fs"
8require "svn/repos"
9require "svn/client"
10
11class SvnFsTest < Test::Unit::TestCase
12  include SvnTestUtil
13
14  def setup
15    setup_basic
16  end
17
18  def teardown
19    teardown_basic
20  end
21
22  def test_version
23    assert_equal(Svn::Core.subr_version, Svn::Fs.version)
24  end
25
26  def assert_create
27    path = File.join(@tmp_path, "fs")
28    fs_type = Svn::Fs::TYPE_FSFS
29    config = {Svn::Fs::CONFIG_FS_TYPE => fs_type}
30
31    assert(!File.exist?(path))
32    fs = nil
33    callback = Proc.new do |fs|
34      assert(File.exist?(path))
35      assert_equal(fs_type, Svn::Fs.type(path))
36      fs.set_warning_func do |err|
37        p err
38        abort
39      end
40      assert_equal(path, fs.path)
41    end
42    yield(:create, [path, config], callback)
43
44    assert(fs.closed?)
45    assert_raises(Svn::Error::FsAlreadyClose) do
46      fs.path
47    end
48
49    yield(:delete, [path])
50    assert(!File.exist?(path))
51  end
52
53  def test_create
54    assert_create do |method, args, callback|
55      Svn::Fs.__send__(method, *args, &callback)
56    end
57  end
58
59  def test_create_for_backward_compatibility
60    assert_create do |method, args, callback|
61      Svn::Fs::FileSystem.__send__(method, *args, &callback)
62    end
63  end
64
65  def assert_hotcopy
66    log = "sample log"
67    file = "hello.txt"
68    path = File.join(@wc_path, file)
69    FileUtils.touch(path)
70
71    rev = nil
72
73    backup_path = make_context(log) do |ctx|
74      ctx.add(path)
75      commit_info = ctx.commit(@wc_path)
76      rev = commit_info.revision
77
78      assert_equal(log, ctx.log_message(path, rev))
79
80      backup_path = File.join(@tmp_path, "back")
81    end
82
83    fs_path = @fs.path
84    @fs.close
85    @fs = nil
86    @repos.close
87    @repos = nil
88
89    FileUtils.mv(fs_path, backup_path)
90    FileUtils.mkdir_p(fs_path)
91
92    make_context(log) do |ctx|
93      assert_raises(Svn::Error::RaLocalReposOpenFailed) do
94        ctx.log_message(path, rev)
95      end
96
97      yield(backup_path, fs_path)
98      assert_equal(log, ctx.log_message(path, rev))
99    end
100  end
101
102  def test_hotcopy
103    assert_hotcopy do |src, dest|
104      Svn::Fs.hotcopy(src, dest)
105    end
106  end
107
108  def test_hotcopy_for_backward_compatibility
109    assert_hotcopy do |src, dest|
110      Svn::Fs::FileSystem.hotcopy(src, dest)
111    end
112  end
113
114  def test_root
115    log = "sample log"
116    file = "sample.txt"
117    src = "sample source"
118    path_in_repos = "/#{file}"
119    path = File.join(@wc_path, file)
120
121    assert_nil(@fs.root.name)
122    assert_equal(Svn::Core::INVALID_REVNUM, @fs.root.base_revision)
123
124    make_context(log) do |ctx|
125      FileUtils.touch(path)
126      ctx.add(path)
127      rev1 = ctx.commit(@wc_path).revision
128      file_id1 = @fs.root.node_id(path_in_repos)
129
130      assert_equal(rev1, @fs.root.revision)
131      assert_equal(Svn::Core::NODE_FILE, @fs.root.check_path(path_in_repos))
132      assert(@fs.root.file?(path_in_repos))
133      assert(!@fs.root.dir?(path_in_repos))
134
135      assert_equal([path_in_repos], @fs.root.paths_changed.keys)
136      info = @fs.root.paths_changed[path_in_repos]
137      assert(info.text_mod?)
138      assert(info.add?)
139
140      File.open(path, "w") {|f| f.print(src)}
141      rev2 = ctx.commit(@wc_path).revision
142      file_id2 = @fs.root.node_id(path_in_repos)
143
144      assert_equal(src, @fs.root.file_contents(path_in_repos){|f| f.read})
145      assert_equal(src.length, @fs.root.file_length(path_in_repos))
146      assert_equal(MD5.new(src).hexdigest,
147                   @fs.root.file_md5_checksum(path_in_repos))
148
149      assert_equal([path_in_repos], @fs.root.paths_changed.keys)
150      info = @fs.root.paths_changed[path_in_repos]
151      assert(info.text_mod?)
152      assert(info.modify?)
153
154      assert_equal([path_in_repos, rev2],
155                   @fs.root.node_history(file).location)
156      assert_equal([path_in_repos, rev2],
157                   @fs.root.node_history(file).prev.location)
158      assert_equal([path_in_repos, rev1],
159                   @fs.root.node_history(file).prev.prev.location)
160
161      assert(!@fs.root.dir?(path_in_repos))
162      assert(@fs.root.file?(path_in_repos))
163
164      assert(file_id1.related?(file_id2))
165      assert_equal(1, file_id1.compare(file_id2))
166      assert_equal(1, file_id2.compare(file_id1))
167
168      assert_equal(rev2, @fs.root.node_created_rev(path_in_repos))
169      assert_equal(path_in_repos, @fs.root.node_created_path(path_in_repos))
170
171      assert_raises(Svn::Error::FsNotTxnRoot) do
172        @fs.root.set_node_prop(path_in_repos, "name", "value")
173      end
174    end
175  end
176
177  def test_transaction
178    log = "sample log"
179    file = "sample.txt"
180    src = "sample source"
181    path_in_repos = "/#{file}"
182    path = File.join(@wc_path, file)
183    prop_name = "prop"
184    prop_value = "value"
185
186    make_context(log) do |ctx|
187      File.open(path, "w") {|f| f.print(src)}
188      ctx.add(path)
189      ctx.commit(@wc_path)
190    end
191
192    assert_raises(Svn::Error::FsNoSuchTransaction) do
193      @fs.open_txn("NOT-EXIST")
194    end
195
196    start_time = Time.now
197    txn1 = @fs.transaction
198    assert_equal([Svn::Core::PROP_REVISION_DATE], txn1.proplist.keys)
199    assert_instance_of(Time, txn1.proplist[Svn::Core::PROP_REVISION_DATE])
200    date = txn1.prop(Svn::Core::PROP_REVISION_DATE)
201
202    # Subversion's clock is more precise than Ruby's on
203    # Windows.  So this test can fail intermittently because
204    # the begin and end of the range are the same (to 3
205    # decimal places), but the time from Subversion has 6
206    # decimal places so it looks like it's not in the range.
207    # So we just add a smidgen to the end of the Range.
208    assert_operator(start_time..(Time.now + 0.001), :include?, date)
209    txn1.set_prop(Svn::Core::PROP_REVISION_DATE, nil)
210    assert_equal([], txn1.proplist.keys)
211    assert_equal(youngest_rev, txn1.base_revision)
212    assert(txn1.root.txn_root?)
213    assert(!txn1.root.revision_root?)
214    assert_equal(txn1.name, txn1.root.name)
215    assert_equal(txn1.base_revision, txn1.root.base_revision)
216
217    @fs.transaction do |txn|
218      assert_nothing_raised do
219        @fs.open_txn(txn.name)
220      end
221      txn2 = txn
222    end
223
224    txn3 = @fs.transaction
225
226    assert_equal([txn1.name, txn3.name].sort, @fs.transactions.sort)
227    @fs.purge_txn(txn3.name)
228    assert_equal([txn1.name].sort, @fs.transactions.sort)
229
230    @fs.transaction do |txn|
231      assert(@fs.transactions.include?(txn.name))
232      txn.abort
233      assert(!@fs.transactions.include?(txn.name))
234    end
235
236    txn4 = @fs.transaction
237    assert_equal({}, txn1.root.node_proplist(path_in_repos))
238    assert_nil(txn1.root.node_prop(path_in_repos, prop_name))
239    txn1.root.set_node_prop(path_in_repos, prop_name, prop_value)
240    assert_equal(prop_value, txn1.root.node_prop(path_in_repos, prop_name))
241    assert_equal({prop_name => prop_value},
242                 txn1.root.node_proplist(path_in_repos))
243    assert(txn1.root.props_changed?(path_in_repos, txn4.root, path_in_repos))
244    assert(!txn1.root.props_changed?(path_in_repos, txn1.root, path_in_repos))
245    txn1.root.set_node_prop(path_in_repos, prop_name, nil)
246    assert_nil(txn1.root.node_prop(path_in_repos, prop_name))
247    assert_equal({}, txn1.root.node_proplist(path_in_repos))
248  end
249
250  def test_operation
251    log = "sample log"
252    file = "sample.txt"
253    file2 = "sample2.txt"
254    file3 = "sample3.txt"
255    dir = "sample"
256    src = "sample source"
257    path_in_repos = "/#{file}"
258    path2_in_repos = "/#{file2}"
259    path3_in_repos = "/#{file3}"
260    dir_path_in_repos = "/#{dir}"
261    path = File.join(@wc_path, file)
262    path2 = File.join(@wc_path, file2)
263    path3 = File.join(@wc_path, file3)
264    dir_path = File.join(@wc_path, dir)
265    token = @fs.generate_lock_token
266    make_context(log) do |ctx|
267
268      @fs.transaction do |txn|
269        txn.root.make_file(file)
270        txn.root.make_dir(dir)
271      end
272      ctx.up(@wc_path)
273      assert(File.exist?(path))
274      assert(File.directory?(dir_path))
275
276      @fs.transaction do |txn|
277        txn.root.copy(file2, @fs.root, file)
278        txn.root.delete(file)
279        txn.abort
280      end
281      ctx.up(@wc_path)
282      assert(File.exist?(path))
283      assert(!File.exist?(path2))
284
285      @fs.transaction do |txn|
286        txn.root.copy(file2, @fs.root, file)
287        txn.root.delete(file)
288      end
289      ctx.up(@wc_path)
290      assert(!File.exist?(path))
291      assert(File.exist?(path2))
292
293      prev_root = @fs.root(youngest_rev - 1)
294      assert(!prev_root.contents_changed?(file, @fs.root, file2))
295      File.open(path2, "w") {|f| f.print(src)}
296      ctx.ci(@wc_path)
297      assert(prev_root.contents_changed?(file, @fs.root, file2))
298
299      txn1 = @fs.transaction
300      access = Svn::Fs::Access.new(@author)
301      @fs.access = access
302      @fs.access.add_lock_token(token)
303      assert_equal([], @fs.get_locks(file2))
304      lock = @fs.lock(file2)
305      assert_equal(lock.token, @fs.get_lock(file2).token)
306      assert_equal([lock.token],
307                   @fs.get_locks(file2).collect{|l| l.token})
308      @fs.unlock(file2, lock.token)
309      assert_equal([], @fs.get_locks(file2))
310
311      entries = @fs.root.dir_entries("/")
312      assert_equal([file2, dir].sort, entries.keys.sort)
313      assert_equal(@fs.root.node_id(path2_in_repos).to_s,
314                   entries[file2].id.to_s)
315      assert_equal(@fs.root.node_id(dir_path_in_repos).to_s,
316                   entries[dir].id.to_s)
317
318      @fs.transaction do |txn|
319        prev_root = @fs.root(youngest_rev - 2)
320        txn.root.revision_link(prev_root, file)
321      end
322      ctx.up(@wc_path)
323      assert(File.exist?(path))
324
325      closest_root, closet_path = @fs.root.closest_copy(file2)
326      assert_equal(path2_in_repos, closet_path)
327    end
328  end
329
330  def test_delta(use_deprecated_api=false)
331    log = "sample log"
332    file = "source.txt"
333    src = "a\nb\nc\nd\ne\n"
334    modified = "A\nb\nc\nd\nE\n"
335    result = "a\n\n\n\ne\n"
336    expected = "A\n\n\n\nE\n"
337    path_in_repos = "/#{file}"
338    path = File.join(@wc_path, file)
339
340    make_context(log) do |ctx|
341
342      File.open(path, "w") {|f| f.print(src)}
343      ctx.add(path)
344      rev1 = ctx.ci(@wc_path).revision
345
346      File.open(path, "w") {|f| f.print(modified)}
347      @fs.transaction do |txn|
348        checksum = MD5.new(normalize_line_break(result)).hexdigest
349        stream = txn.root.apply_text(path_in_repos, checksum)
350        stream.write(normalize_line_break(result))
351        stream.close
352      end
353      ctx.up(@wc_path)
354      assert_equal(expected, File.open(path){|f| f.read})
355
356      rev2 = ctx.ci(@wc_path).revision
357      if use_deprecated_api
358        stream = @fs.root(rev2).file_delta_stream(@fs.root(rev1),
359                                                  path_in_repos,
360                                                  path_in_repos)
361      else
362        stream = @fs.root(rev1).file_delta_stream(path_in_repos,
363                                                  @fs.root(rev2),
364                                                  path_in_repos)
365      end
366
367      data = ''
368      stream.each{|w| data << w.new_data}
369      assert_equal(normalize_line_break(expected), data)
370
371      File.open(path, "w") {|f| f.print(src)}
372      rev3 = ctx.ci(@wc_path).revision
373
374      File.open(path, "w") {|f| f.print(modified)}
375      @fs.transaction do |txn|
376        base_checksum = MD5.new(normalize_line_break(src)).hexdigest
377        checksum = MD5.new(normalize_line_break(result)).hexdigest
378        handler = txn.root.apply_textdelta(path_in_repos,
379                                           base_checksum, checksum)
380        assert_raises(Svn::Error::ChecksumMismatch) do
381          handler.call(nil)
382        end
383      end
384    end
385  end
386
387  def test_delta_with_deprecated_api
388    test_delta(true)
389  end
390
391  def test_prop
392    log = "sample log"
393    make_context(log) do |ctx|
394      ctx.checkout(@repos_uri, @wc_path)
395      ctx.mkdir(["#{@wc_path}/new_dir"])
396
397      start_time = Time.now
398      info = ctx.commit([@wc_path])
399
400      assert_equal(@author, info.author)
401      assert_equal(@fs.youngest_rev, info.revision)
402      assert_operator(start_time..(Time.now), :include?, info.date)
403
404      assert_equal(@author, @fs.prop(Svn::Core::PROP_REVISION_AUTHOR))
405      assert_equal(log, @fs.prop(Svn::Core::PROP_REVISION_LOG))
406      assert_equal([
407                     Svn::Core::PROP_REVISION_AUTHOR,
408                     Svn::Core::PROP_REVISION_DATE,
409                     Svn::Core::PROP_REVISION_LOG,
410                   ].sort,
411                   @fs.proplist.keys.sort)
412      @fs.set_prop(Svn::Core::PROP_REVISION_LOG, nil)
413      assert_nil(@fs.prop(Svn::Core::PROP_REVISION_LOG))
414      assert_equal([
415                     Svn::Core::PROP_REVISION_AUTHOR,
416                     Svn::Core::PROP_REVISION_DATE,
417                   ].sort,
418                   @fs.proplist.keys.sort)
419    end
420  end
421
422  def assert_recover
423    path = File.join(@tmp_path, "fs")
424    fs_type = Svn::Fs::TYPE_FSFS
425    config = {Svn::Fs::CONFIG_FS_TYPE => fs_type}
426
427    yield(:create, [path, config])
428
429    assert_nothing_raised do
430      yield(:recover, [path], Proc.new{})
431    end
432  end
433
434  def test_recover_for_backward_compatibility
435    assert_recover do |method, args, block|
436      Svn::Fs::FileSystem.__send__(method, *args, &block)
437    end
438  end
439
440  def test_recover
441    assert_recover do |method, args, block|
442      Svn::Fs.__send__(method, *args, &block)
443    end
444  end
445
446  def test_deleted_revision
447    file = "file"
448    log = "sample log"
449    path = File.join(@wc_path, file)
450    path_in_repos = "/#{file}"
451    make_context(log) do |ctx|
452
453      FileUtils.touch(path)
454      ctx.add(path)
455      rev1 = ctx.ci(@wc_path).revision
456
457      ctx.rm_f(path)
458      rev2 = ctx.ci(@wc_path).revision
459
460      FileUtils.touch(path)
461      ctx.add(path)
462      rev3 = ctx.ci(@wc_path).revision
463
464      ctx.rm_f(path)
465      rev4 = ctx.ci(@wc_path).revision
466
467      assert_equal(Svn::Core::INVALID_REVNUM,
468                   @fs.deleted_revision(path_in_repos, 0, rev4))
469      assert_equal(rev2, @fs.deleted_revision(path_in_repos, rev1, rev4))
470      assert_equal(Svn::Core::INVALID_REVNUM,
471                   @fs.deleted_revision(path_in_repos, rev2, rev4))
472      assert_equal(rev4, @fs.deleted_revision(path_in_repos, rev3, rev4))
473      assert_equal(Svn::Core::INVALID_REVNUM,
474                   @fs.deleted_revision(path_in_repos, rev4, rev4))
475    end
476  end
477
478  def test_mergeinfo
479    log = "sample log"
480    file = "sample.txt"
481    src = "sample\n"
482    trunk = File.join(@wc_path, "trunk")
483    branch = File.join(@wc_path, "branch")
484    trunk_path = File.join(trunk, file)
485    branch_path = File.join(branch, file)
486    trunk_in_repos = "/trunk"
487    branch_in_repos = "/branch"
488
489    make_context(log) do |ctx|
490      ctx.mkdir(trunk, branch)
491      File.open(trunk_path, "w") {}
492      File.open(branch_path, "w") {}
493      ctx.add(trunk_path)
494      ctx.add(branch_path)
495      rev1 = ctx.commit(@wc_path).revision
496
497      File.open(branch_path, "w") {|f| f.print(src)}
498      rev2 = ctx.commit(@wc_path).revision
499
500      assert_equal({}, @fs.root.mergeinfo(trunk_in_repos))
501      ctx.merge(branch, rev1, branch, rev2, trunk)
502      assert_equal({}, @fs.root.mergeinfo(trunk_in_repos))
503
504      rev3 = ctx.commit(@wc_path).revision
505      mergeinfo = Svn::Core::MergeInfo.parse("#{branch_in_repos}:2")
506      assert_equal({trunk_in_repos => mergeinfo},
507                   @fs.root.mergeinfo(trunk_in_repos))
508
509      ctx.rm(branch_path)
510      rev4 = ctx.commit(@wc_path).revision
511
512      ctx.merge(branch, rev3, branch, rev4, trunk)
513      assert(!File.exist?(trunk_path))
514      rev5 = ctx.commit(@wc_path).revision
515      assert_equal({trunk_in_repos => Svn::Core::MergeInfo.parse("#{branch_in_repos}:2,4")},
516                   @fs.root.mergeinfo(trunk_in_repos))
517    end
518  end
519end
Note: See TracBrowser for help on using the repository browser.