require "util"
require "stringio"
require 'md5'
require 'tempfile'
require "svn/info"
class SvnDeltaTest < Test::Unit::TestCase
include SvnTestUtil
def setup
setup_basic
end
def teardown
teardown_basic
end
def test_version
assert_equal(Svn::Core.subr_version, Svn::Delta.version)
end
def test_txdelta_window
s = ("a\nb\nc\nd\ne" + "\n" * 100) * 1000
t = ("a\nb\nX\nd\ne" + "\n" * 100) * 1000
source = StringIO.new(s)
target = StringIO.new(t)
stream = Svn::Delta::TextDeltaStream.new(source, target)
assert_nil(stream.md5_digest)
stream.each do |window|
window.ops.each do |op|
op_size = op.offset + op.length
case op.action_code
when Svn::Delta::TXDELTA_SOURCE
assert_operator(op_size, :<=, window.sview_len)
when Svn::Delta::TXDELTA_NEW
assert_operator(op_size, :<=, window.new_data.length)
when Svn::Delta::TXDELTA_TARGET
assert_operator(op_size, :<=, window.tview_len)
else
flunk
end
end
end
assert_equal(MD5.new(t).hexdigest, stream.md5_digest)
end
def test_txdelta_window_compose
s = ("a\nb\nc\nd\ne" + "\n" * 100) * 1000
t = ("a\nb\nX\nd\ne" + "\n" * 100) * 1000
source = StringIO.new(s)
target = StringIO.new(t)
stream = Svn::Delta::TextDeltaStream.new(source, target)
composed_window = nil
stream.each do |window|
if composed_window.nil?
composed_window = window
else
composed_window = composed_window.compose(window)
end
end
composed_window.ops.each do |op|
op_size = op.offset + op.length
case op.action_code
when Svn::Delta::TXDELTA_SOURCE
assert_operator(op_size, :<=, composed_window.sview_len)
when Svn::Delta::TXDELTA_NEW
assert_operator(op_size, :<=, composed_window.new_data.length)
when Svn::Delta::TXDELTA_TARGET
assert_operator(op_size, :<=, composed_window.tview_len)
else
flunk
end
end
end
def test_txdelta_apply_instructions
s = ("a\nb\nc\nd\ne" + "\n" * 100) * 1000
t = ("a\nb\nX\nd\ne" + "\n" * 100) * 1000
source = StringIO.new(s)
target = StringIO.new(t)
stream = Svn::Delta::TextDeltaStream.new(source, target)
result = ""
offset = 0
stream.each do |window|
result << window.apply_instructions(s[offset, window.sview_len])
offset += window.sview_len
end
assert_equal(t, result)
end
def test_push_target
source = StringIO.new("abcde")
target_content = "ZZZ" * 100
data = ""
finished = false
handler = Proc.new do |window|
if window
data << window.new_data
else
finished = true
end
end
target = Svn::Delta::TextDeltaStream.push_target(source, &handler)
target.write(target_content)
assert(!finished)
target.close
assert(finished)
assert_equal(target_content, data)
end
def test_apply
source_text = "abcde"
target_text = "abXde"
source = StringIO.new(source_text)
target = StringIO.new(target_text)
stream = Svn::Delta::TextDeltaStream.new(source, target)
apply_source = StringIO.new(source_text)
apply_result = StringIO.new("")
handler, digest = Svn::Delta.apply(apply_source, apply_result)
handler.send(stream)
apply_result.rewind
assert_equal(target_text, apply_result.read)
handler, digest = Svn::Delta.apply(apply_source, apply_result)
handler.send(target_text)
apply_result.rewind
assert_equal(target_text * 2, apply_result.read)
handler, digest = Svn::Delta.apply(apply_source, apply_result)
handler.send(StringIO.new(target_text))
apply_result.rewind
assert_equal(target_text * 3, apply_result.read)
end
def test_svndiff
source_text = "abcde"
target_text = "abXde"
source = StringIO.new(source_text)
target = StringIO.new(target_text)
stream = Svn::Delta::TextDeltaStream.new(source, target)
output = StringIO.new("")
handler = Svn::Delta.svndiff_handler(output)
Svn::Delta.send(target_text, handler)
output.rewind
result = output.read
assert_match(/\ASVN.*#{target_text}\z/, result)
# skip svndiff window
input = StringIO.new(result[4..-1])
window = Svn::Delta.read_svndiff_window(input, 0)
assert_equal(target_text, window.new_data)
finished = false
data = ""
stream = Svn::Delta.parse_svndiff do |window|
if window
data << window.new_data
else
finished = true
end
end
stream.write(result)
stream.close
assert(finished)
assert_equal(target_text, data)
end
def test_path_driver
editor = Svn::Delta::BaseEditor.new
data = []
callback = Proc.new do |parent_baton, path|
if /\/\z/ =~ path
data << [:dir, path]
parent_baton
else
data << [:file, path]
end
end
Svn::Delta.path_driver(editor, 0, ["/"], &callback)
assert_equal([[:dir, '/']], data)
end
def test_changed
dir = "changed_dir"
dir1 = "changed_dir1"
dir2 = "changed_dir2"
dir_path = File.join(@wc_path, dir)
dir1_path = File.join(@wc_path, dir1)
dir2_path = File.join(@wc_path, dir2)
dir_svn_path = dir
dir1_svn_path = dir1
dir2_svn_path = dir2
log = "added 3 dirs\nanded 5 files"
ctx = make_context(log)
ctx.mkdir([dir_path, dir1_path, dir2_path])
file1 = "changed1.txt"
file2 = "changed2.txt"
file3 = "changed3.txt"
file4 = "changed4.txt"
file5 = "changed5.txt"
file1_path = File.join(@wc_path, file1)
file2_path = File.join(dir_path, file2)
file3_path = File.join(@wc_path, file3)
file4_path = File.join(dir_path, file4)
file5_path = File.join(@wc_path, file5)
file1_svn_path = file1
file2_svn_path = [dir_svn_path, file2].join("/")
file3_svn_path = file3
file4_svn_path = [dir_svn_path, file4].join("/")
file5_svn_path = file5
FileUtils.touch(file1_path)
FileUtils.touch(file2_path)
FileUtils.touch(file3_path)
FileUtils.touch(file4_path)
FileUtils.touch(file5_path)
ctx.add(file1_path)
ctx.add(file2_path)
ctx.add(file3_path)
ctx.add(file4_path)
ctx.add(file5_path)
commit_info = ctx.commit(@wc_path)
first_rev = commit_info.revision
editor = traverse(Svn::Delta::ChangedEditor, commit_info.revision, true)
assert_equal([
file1_svn_path, file2_svn_path,
file3_svn_path, file4_svn_path,
file5_svn_path,
].sort,
editor.added_files)
assert_equal([], editor.updated_files)
assert_equal([], editor.deleted_files)
assert_equal([].sort, editor.updated_dirs)
assert_equal([].sort, editor.deleted_dirs)
assert_equal([
"#{dir_svn_path}/",
"#{dir1_svn_path}/",
"#{dir2_svn_path}/"
].sort,
editor.added_dirs)
log = "deleted 2 dirs\nchanged 3 files\ndeleted 2 files\nadded 3 files"
ctx = make_context(log)
dir3 = "changed_dir3"
dir4 = "changed_dir4"
dir3_path = File.join(dir_path, dir3)
dir4_path = File.join(@wc_path, dir4)
dir3_svn_path = [dir_svn_path, dir3].join("/")
dir4_svn_path = dir4
file6 = "changed6.txt"
file7 = "changed7.txt"
file8 = "changed8.txt"
file9 = "changed9.txt"
file10 = "changed10.txt"
file6_path = File.join(dir_path, file6)
file7_path = File.join(@wc_path, file7)
file8_path = File.join(dir_path, file8)
file9_path = File.join(dir_path, file9)
file10_path = File.join(dir_path, file10)
file6_svn_path = [dir_svn_path, file6].join("/")
file7_svn_path = file7
file8_svn_path = [dir_svn_path, file8].join("/")
file9_svn_path = [dir_svn_path, file9].join("/")
file10_svn_path = [dir_svn_path, file10].join("/")
File.open(file1_path, "w") {|f| f.puts "changed"}
File.open(file2_path, "w") {|f| f.puts "changed"}
File.open(file3_path, "w") {|f| f.puts "changed"}
ctx.rm_f([file4_path, file5_path])
FileUtils.touch(file6_path)
FileUtils.touch(file7_path)
FileUtils.touch(file8_path)
ctx.add(file6_path)
ctx.add(file7_path)
ctx.add(file8_path)
ctx.cp(file1_path, file9_path)
ctx.cp(file2_path, file10_path)
ctx.rm(dir1_path)
ctx.mv(dir2_path, dir3_path)
ctx.cp(dir1_path, dir4_path)
commit_info = ctx.commit(@wc_path)
second_rev = commit_info.revision
editor = traverse(Svn::Delta::ChangedEditor, commit_info.revision, true)
assert_equal([file1_svn_path, file2_svn_path, file3_svn_path].sort,
editor.updated_files)
assert_equal([file4_svn_path, file5_svn_path].sort,
editor.deleted_files)
assert_equal([file6_svn_path, file7_svn_path, file8_svn_path].sort,
editor.added_files)
assert_equal([].sort, editor.updated_dirs)
assert_equal([
[file9_svn_path, file1_svn_path, first_rev],
[file10_svn_path, file2_svn_path, first_rev],
].sort_by{|x| x[0]},
editor.copied_files)
assert_equal([
["#{dir3_svn_path}/", "#{dir2_svn_path}/", first_rev],
["#{dir4_svn_path}/", "#{dir1_svn_path}/", first_rev],
].sort_by{|x| x[0]},
editor.copied_dirs)
assert_equal(["#{dir1_svn_path}/", "#{dir2_svn_path}/"].sort,
editor.deleted_dirs)
assert_equal([].sort, editor.added_dirs)
end
def test_change_prop
prop_name = "prop"
prop_value = "value"
dir = "dir"
dir_path = File.join(@wc_path, dir)
dir_svn_path = dir
log = "added 1 dirs\nanded 2 files"
ctx = make_context(log)
ctx.mkdir([dir_path])
file1 = "file1.txt"
file2 = "file2.txt"
file1_path = File.join(@wc_path, file1)
file2_path = File.join(dir_path, file2)
file1_svn_path = file1
file2_svn_path = [dir_svn_path, file2].join("/")
FileUtils.touch(file1_path)
FileUtils.touch(file2_path)
ctx.add(file1_path)
ctx.add(file2_path)
ctx.propset(prop_name, prop_value, dir_path)
commit_info = ctx.commit(@wc_path)
editor = traverse(Svn::Delta::ChangedDirsEditor, commit_info.revision)
assert_equal(["", dir_svn_path].collect{|path| "#{path}/"}.sort,
editor.changed_dirs)
log = "prop changed"
ctx = make_context(log)
ctx.propdel(prop_name, dir_path)
commit_info = ctx.commit(@wc_path)
editor = traverse(Svn::Delta::ChangedDirsEditor, commit_info.revision)
assert_equal([dir_svn_path].collect{|path| "#{path}/"}.sort,
editor.changed_dirs)
ctx.propset(prop_name, prop_value, file1_path)
commit_info = ctx.commit(@wc_path)
editor = traverse(Svn::Delta::ChangedDirsEditor, commit_info.revision)
assert_equal([""].collect{|path| "#{path}/"}.sort,
editor.changed_dirs)
ctx.propdel(prop_name, file1_path)
ctx.propset(prop_name, prop_value, file2_path)
commit_info = ctx.commit(@wc_path)
editor = traverse(Svn::Delta::ChangedDirsEditor, commit_info.revision)
assert_equal(["", dir_svn_path].collect{|path| "#{path}/"}.sort,
editor.changed_dirs)
end
def test_deep_copy
dir1 = "dir1"
dir2 = "dir2"
dir1_path = File.join(@wc_path, dir1)
dir2_path = File.join(dir1_path, dir2)
dir1_svn_path = dir1
dir2_svn_path = [dir1, dir2].join("/")
log = "added 2 dirs\nanded 3 files"
ctx = make_context(log)
ctx.mkdir([dir1_path, dir2_path])
file1 = "file1.txt"
file2 = "file2.txt"
file3 = "file3.txt"
file1_path = File.join(@wc_path, file1)
file2_path = File.join(dir1_path, file2)
file3_path = File.join(dir2_path, file3)
file1_svn_path = file1
file2_svn_path = [dir1_svn_path, file2].join("/")
file3_svn_path = [dir2_svn_path, file3].join("/")
FileUtils.touch(file1_path)
FileUtils.touch(file2_path)
FileUtils.touch(file3_path)
ctx.add(file1_path)
ctx.add(file2_path)
ctx.add(file3_path)
commit_info = ctx.commit(@wc_path)
first_rev = commit_info.revision
editor = traverse(Svn::Delta::ChangedEditor, commit_info.revision, true)
assert_equal([
file1_svn_path, file2_svn_path,
file3_svn_path,
].sort,
editor.added_files)
assert_equal([].sort, editor.updated_files)
assert_equal([].sort, editor.deleted_files)
assert_equal([].sort, editor.updated_dirs)
assert_equal([].sort, editor.deleted_dirs)
assert_equal([
"#{dir1_svn_path}/",
"#{dir2_svn_path}/",
].sort,
editor.added_dirs)
log = "copied top dir"
ctx = make_context(log)
dir3 = "dir3"
dir3_path = File.join(@wc_path, dir3)
dir3_svn_path = dir3
ctx.cp(dir1_path, dir3_path)
commit_info = ctx.commit(@wc_path)
second_rev = commit_info.revision
editor = traverse(Svn::Delta::ChangedEditor, commit_info.revision, true)
assert_equal([].sort, editor.updated_files)
assert_equal([].sort, editor.deleted_files)
assert_equal([].sort, editor.added_files)
assert_equal([].sort, editor.updated_dirs)
assert_equal([].sort, editor.copied_files)
assert_equal([
["#{dir3_svn_path}/", "#{dir1_svn_path}/", first_rev]
].sort_by{|x| x[0]},
editor.copied_dirs)
assert_equal([].sort, editor.deleted_dirs)
assert_equal([].sort, editor.added_dirs)
end
private
def traverse(editor_class, rev, pass_root=false)
root = @fs.root
base_rev = rev - 1
base_root = @fs.root(base_rev)
if pass_root
editor = editor_class.new(root, base_root)
else
editor = editor_class.new
end
base_root.dir_delta("", "", root, "", editor)
editor
end
end
syntax highlighted by Code2HTML, v. 0.9.1