summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorAustin Ziegler <austin@halostatue.ca>2011-07-31 03:39:42 -0400
committerAustin Ziegler <austin@halostatue.ca>2011-07-31 03:39:42 -0400
commit2276593be732e5c91cac144d1fad0310e072613b (patch)
treeecb9e96942c3cf0990b8ff288c0af2f0b02e1653 /spec
parent743cff65ed6826c48b967c3064783809da7bc1b7 (diff)
downloaddiff-lcs-2276593be732e5c91cac144d1fad0310e072613b.tar.gz
Convert to RSpec
Diffstat (limited to 'spec')
-rw-r--r--spec/diff_lcs_balanced_spec.rb169
-rw-r--r--spec/diff_lcs_diff_spec.rb33
-rw-r--r--spec/diff_lcs_lcs_spec.rb36
-rw-r--r--spec/diff_lcs_patch_spec.rb428
-rw-r--r--spec/diff_lcs_sdiff_spec.rb180
-rw-r--r--spec/diff_lcs_sequences_spec.rb83
-rw-r--r--spec/spec_helper.rb270
7 files changed, 1199 insertions, 0 deletions
diff --git a/spec/diff_lcs_balanced_spec.rb b/spec/diff_lcs_balanced_spec.rb
new file mode 100644
index 0000000..36e11c9
--- /dev/null
+++ b/spec/diff_lcs_balanced_spec.rb
@@ -0,0 +1,169 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.traverse_balanced should traverse sequences correctly" do
+ include Diff::LCS::SpecHelper::Matchers
+
+ def reverse(change_result)
+ new_result = []
+ change_result.each { |line|
+ line = [ line[0], line[2], line[1] ]
+ case line[0]
+ when '<'
+ line[0] = '>'
+ when '>'
+ line[0] = '<'
+ end
+ new_result << line
+ }
+ new_result.sort_by { |line| line[1] }
+ end
+
+ def no_change(change_result)
+ new_result = []
+ change_result.each { |line|
+ case line[0]
+ when '!'
+ new_result << [ '<', line[1], line[2] ]
+ new_result << [ '>', line[1] + 1, line[2] ]
+ else
+ new_result << line
+ end
+ }
+ new_result
+ end
+
+ def traverse(s1, s2, callback_type)
+ callback = __send__(callback_type)
+ Diff::LCS.traverse_balanced(s1, s2, callback)
+ callback
+ end
+
+ def do_balanced_traversal(s1, s2, result)
+ balanced_s1_s2 = traverse(s1, s2, :balanced_callback)
+ balanced_s2_s1 = traverse(s2, s1, :balanced_callback)
+ balanced_s1_s2_no_change = traverse(s1, s2, :balanced_callback_no_change)
+ balanced_s2_s1_no_change = traverse(s2, s1, :balanced_callback_no_change)
+
+ balanced_s1_s2.result.should == result
+ balanced_s2_s1.result.should == reverse(result)
+
+ balanced_s1_s2_no_change.result.should == no_change(result)
+ balanced_s2_s1_no_change.result.should == no_change(reverse(result))
+ end
+
+ it "sequence-a" do
+ s1 = %w(a b c)
+ s2 = %w(a x c)
+
+ result = [
+ [ '=', 0, 0 ],
+ [ '!', 1, 1 ],
+ [ '=', 2, 2 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-b" do
+ s1 = %w(a x y c)
+ s2 = %w(a v w c)
+
+ result = [
+ [ '=', 0, 0 ],
+ [ '!', 1, 1 ],
+ [ '!', 2, 2 ],
+ [ '=', 3, 3 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-c" do
+ s1 = %w(x y c)
+ s2 = %w(v w c)
+ result = [
+ [ '!', 0, 0 ],
+ [ '!', 1, 1 ],
+ [ '=', 2, 2 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-d" do
+ s1 = %w(a x y z)
+ s2 = %w(b v w)
+ result = [
+ [ '!', 0, 0 ],
+ [ '!', 1, 1 ],
+ [ '!', 2, 2 ],
+ [ '<', 3, 3 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-e" do
+ s1 = %w(a z)
+ s2 = %w(a)
+ result = [
+ [ '=', 0, 0 ],
+ [ '<', 1, 1 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-f" do
+ s1 = %w(z a)
+ s2 = %w(a)
+ result = [
+ [ '<', 0, 0 ],
+ [ '=', 1, 0 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-g" do
+ s1 = %w(a b c)
+ s2 = %w(x y z)
+ result = [
+ [ '!', 0, 0 ],
+ [ '!', 1, 1 ],
+ [ '!', 2, 2 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-h" do
+ s1 = %w(abcd efgh ijkl mnopqrstuvwxyz)
+ s2 = []
+ result = [
+ [ '<', 0, 0 ],
+ [ '<', 1, 0 ],
+ [ '<', 2, 0 ],
+ [ '<', 3, 0 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+
+ it "sequence-i" do
+ s1 = []
+ s2 = %w(abcd efgh ijkl mnopqrstuvwxyz)
+ result = [
+ [ '>', 0, 0 ],
+ [ '>', 0, 1 ],
+ [ '>', 0, 2 ],
+ [ '>', 0, 3 ]
+ ]
+
+ do_balanced_traversal(s1, s2, result)
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/diff_lcs_diff_spec.rb b/spec/diff_lcs_diff_spec.rb
new file mode 100644
index 0000000..43ea5c7
--- /dev/null
+++ b/spec/diff_lcs_diff_spec.rb
@@ -0,0 +1,33 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.diff" do
+ include Diff::LCS::SpecHelper::Matchers
+
+ it "should correctly diff the sequences" do
+ diff_s1_s2 = Diff::LCS.diff(seq1, seq2)
+ diff_s2_s1 = Diff::LCS.diff(seq2, seq1)
+
+ change_diff(correct_forward_diff).should == diff_s1_s2
+ change_diff(correct_backward_diff).should == diff_s2_s1
+ end
+
+ it "should correctly diff against an empty sequence" do
+ diff = Diff::LCS.diff(word_sequence, [])
+ correct_diff = [
+ [ [ '-', 0, 'abcd' ],
+ [ '-', 1, 'efgh' ],
+ [ '-', 2, 'ijkl' ],
+ [ '-', 3, 'mnopqrstuvwxyz' ] ]
+ ]
+
+ change_diff(correct_diff).should == diff
+
+ diff = Diff::LCS.diff([], word_sequence)
+ correct_diff.each { |hunk| hunk.each { |change| change[0] = '+' } }
+ change_diff(correct_diff).should == diff
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/diff_lcs_lcs_spec.rb b/spec/diff_lcs_lcs_spec.rb
new file mode 100644
index 0000000..c95ba61
--- /dev/null
+++ b/spec/diff_lcs_lcs_spec.rb
@@ -0,0 +1,36 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.LCS and Diff::LCS.__lcs" do
+ include Diff::LCS::SpecHelper::Matchers
+
+ it "should return the correct raw values from Diff::LCS.__lcs" do
+ res = Diff::LCS.__lcs(seq1, seq2)
+ # The result of the LCS (less the +nil+ values) must be as long as the
+ # correct result.
+ res.compact.size.should == correct_lcs.size
+ res.should correctly_map_sequence(seq1).to_other_sequence(seq2)
+
+ # Compact these transformations and they should be the correct LCS.
+ x_seq1 = (0...res.size).map { |ix| res[ix] ? seq1[ix] : nil }.compact
+ x_seq2 = (0...res.size).map { |ix| res[ix] ? seq2[res[ix]] : nil }.compact
+
+ x_seq1.should == correct_lcs
+ x_seq2.should == correct_lcs
+ end
+
+ it "should return the correct compacted values from Diff::LCS.LCS" do
+ res = Diff::LCS.LCS(seq1, seq2)
+ res.should == correct_lcs
+ res.compact.should == res
+ end
+
+ it "should be transitive" do
+ res = Diff::LCS.LCS(seq2, seq1)
+ res.should == correct_lcs
+ res.compact.should == res
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/diff_lcs_patch_spec.rb b/spec/diff_lcs_patch_spec.rb
new file mode 100644
index 0000000..7e480e0
--- /dev/null
+++ b/spec/diff_lcs_patch_spec.rb
@@ -0,0 +1,428 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.patch" do
+ include Diff::LCS::SpecHelper::Matchers
+
+ describe "using a Diff::LCS.diff patchset" do
+ describe "with default diff callbacks (DiffCallbacks)" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(seq1, seq2)
+ @patch_set_s2_s1 = Diff::LCS.diff(seq2, seq1)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+
+ describe "with context diff callbacks (ContextDiffCallbacks)" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(seq1, seq2, Diff::LCS::ContextDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.diff(seq2, seq1, Diff::LCS::ContextDiffCallbacks)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+
+ describe "with sdiff callbacks (SDiffCallbacks)" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(seq1, seq2, Diff::LCS::SDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.diff(seq2, seq1, Diff::LCS::SDiffCallbacks)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+ end
+
+ describe "using a Diff::LCS.sdiff patchset" do
+ describe "with default diff callbacks (DiffCallbacks)" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::DiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(seq2, seq1, Diff::LCS::DiffCallbacks)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+
+ describe "with context diff callbacks (ContextDiffCallbacks)" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(seq1, seq2, Diff::LCS::ContextDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(seq2, seq1, Diff::LCS::ContextDiffCallbacks)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+
+ describe "with sdiff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(seq1, seq2)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(seq2, seq1)
+ end
+
+ it "should correctly patch left-to-right (patch autodiscovery)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(seq1, @patch_set_s1_s2, :patch).should == seq2
+ Diff::LCS.patch(seq2, @patch_set_s2_s1, :patch).should == seq1
+ Diff::LCS.patch!(seq1, @patch_set_s1_s2).should == seq2
+ Diff::LCS.patch!(seq2, @patch_set_s2_s1).should == seq1
+ end
+
+ it "should correctly patch right-to-left (unpatch autodiscovery)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1).should == seq2
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(seq2, @patch_set_s1_s2, :unpatch).should == seq1
+ Diff::LCS.patch(seq1, @patch_set_s2_s1, :unpatch).should == seq2
+ Diff::LCS.unpatch!(seq2, @patch_set_s1_s2).should == seq1
+ Diff::LCS.unpatch!(seq1, @patch_set_s2_s1).should == seq2
+ end
+ end
+ end
+
+ describe "fix bug 891: patchsets do not contain the last equal part" do
+ before(:each) do
+ @s1 = %w(a b c d e f g h i j k)
+ @s2 = %w(a b c d D e f g h i j k)
+ end
+
+ describe "using Diff::LCS.diff with default diff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2)
+ @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+
+ describe "using Diff::LCS.diff with context diff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2, Diff::LCS::ContextDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::ContextDiffCallbacks)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+
+ describe "using Diff::LCS.diff with sdiff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.diff(@s1, @s2, Diff::LCS::SDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::SDiffCallbacks)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+
+ describe "using Diff::LCS.sdiff with default sdiff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+
+ describe "using Diff::LCS.sdiff with context diff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2, Diff::LCS::ContextDiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::ContextDiffCallbacks)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+
+ describe "using Diff::LCS.xdiff with default diff callbacks" do
+ before(:each) do
+ @patch_set_s1_s2 = Diff::LCS.sdiff(@s1, @s2, Diff::LCS::DiffCallbacks)
+ @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::DiffCallbacks)
+ end
+
+ it "does not autodiscover s1 to s2 patches" do
+ # It should, but it doesn't.
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+
+ expect do
+ Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
+ end.to raise_error(RuntimeError, /provided patchset/)
+ end
+
+ it "should autodiscover s2 to s1 the left-to-right patches" do
+ Diff::LCS.patch(@s2, @patch_set_s2_s1).should == @s1
+ Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
+ end
+
+ it "should correctly patch left-to-right (explicit patch)" do
+ Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
+ Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
+ Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
+ Diff::LCS.patch!(@s2, @patch_set_s2_s1).should == @s1
+ end
+
+ it "should correctly patch right-to-left (explicit unpatch)" do
+ Diff::LCS.patch(@s2, @patch_set_s1_s2, :unpatch).should == @s1
+ Diff::LCS.patch(@s1, @patch_set_s2_s1, :unpatch).should == @s2
+ Diff::LCS.unpatch!(@s2, @patch_set_s1_s2).should == @s1
+ Diff::LCS.unpatch!(@s1, @patch_set_s2_s1).should == @s2
+ end
+ end
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/diff_lcs_sdiff_spec.rb b/spec/diff_lcs_sdiff_spec.rb
new file mode 100644
index 0000000..b6a3f10
--- /dev/null
+++ b/spec/diff_lcs_sdiff_spec.rb
@@ -0,0 +1,180 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.sdiff should compare sequences correctly" do
+ include Diff::LCS::SpecHelper::Matchers
+
+ def do_sdiff_comparison(s1, s2, forward_sdiff)
+ sdiff_s1_s2 = Diff::LCS.sdiff(s1, s2)
+ sdiff_s2_s1 = Diff::LCS.sdiff(s2, s1)
+
+ sdiff_s1_s2.should == context_diff(forward_sdiff)
+ sdiff_s2_s1.should == context_diff(reverse_sdiff(forward_sdiff))
+ end
+
+ it "sequence-a" do
+ do_sdiff_comparison(seq1, seq2, correct_forward_sdiff)
+ end
+
+ it "sequence-b" do
+ s1 = %w(abc def yyy xxx ghi jkl)
+ s2 = %w(abc dxf xxx ghi jkl)
+ forward_sdiff = [
+ [ '=', [ 0, 'abc' ], [ 0, 'abc' ] ],
+ [ '!', [ 1, 'def' ], [ 1, 'dxf' ] ],
+ [ '-', [ 2, 'yyy' ], [ 2, nil ] ],
+ [ '=', [ 3, 'xxx' ], [ 2, 'xxx' ] ],
+ [ '=', [ 4, 'ghi' ], [ 3, 'ghi' ] ],
+ [ '=', [ 5, 'jkl' ], [ 4, 'jkl' ] ]
+ ]
+
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-c" do
+ s1 = %w(a b c d e)
+ s2 = %w(a e)
+ forward_sdiff = [
+ [ '=', [ 0, 'a' ], [ 0, 'a' ] ],
+ [ '-', [ 1, 'b' ], [ 1, nil ] ],
+ [ '-', [ 2, 'c' ], [ 1, nil ] ],
+ [ '-', [ 3, 'd' ], [ 1, nil ] ],
+ [ '=', [ 4, 'e' ], [ 1, 'e' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-d" do
+ s1 = %w(a e)
+ s2 = %w(a b c d e)
+ forward_sdiff = [
+ [ '=', [ 0, 'a' ], [ 0, 'a' ] ],
+ [ '+', [ 1, nil ], [ 1, 'b' ] ],
+ [ '+', [ 1, nil ], [ 2, 'c' ] ],
+ [ '+', [ 1, nil ], [ 3, 'd' ] ],
+ [ '=', [ 1, 'e' ], [ 4, 'e' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-e" do
+ s1 = %w(v x a e)
+ s2 = %w(w y a b c d e)
+ forward_sdiff = [
+ [ '!', [ 0, 'v' ], [ 0, 'w' ] ],
+ [ '!', [ 1, 'x' ], [ 1, 'y' ] ],
+ [ '=', [ 2, 'a' ], [ 2, 'a' ] ],
+ [ '+', [ 3, nil ], [ 3, 'b' ] ],
+ [ '+', [ 3, nil ], [ 4, 'c' ] ],
+ [ '+', [ 3, nil ], [ 5, 'd' ] ],
+ [ '=', [ 3, 'e' ], [ 6, 'e' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-f" do
+ s1 = %w(x a e)
+ s2 = %w(a b c d e)
+ forward_sdiff = [
+ [ '-', [ 0, 'x' ], [ 0, nil ] ],
+ [ '=', [ 1, 'a' ], [ 0, 'a' ] ],
+ [ '+', [ 2, nil ], [ 1, 'b' ] ],
+ [ '+', [ 2, nil ], [ 2, 'c' ] ],
+ [ '+', [ 2, nil ], [ 3, 'd' ] ],
+ [ '=', [ 2, 'e' ], [ 4, 'e' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-g" do
+ s1 = %w(a e)
+ s2 = %w(x a b c d e)
+ forward_sdiff = [
+ [ '+', [ 0, nil ], [ 0, 'x' ] ],
+ [ '=', [ 0, 'a' ], [ 1, 'a' ] ],
+ [ '+', [ 1, nil ], [ 2, 'b' ] ],
+ [ '+', [ 1, nil ], [ 3, 'c' ] ],
+ [ '+', [ 1, nil ], [ 4, 'd' ] ],
+ [ '=', [ 1, 'e' ], [ 5, 'e' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-h" do
+ s1 = %w(a e v)
+ s2 = %w(x a b c d e w x)
+ forward_sdiff = [
+ [ '+', [ 0, nil ], [ 0, 'x' ] ],
+ [ '=', [ 0, 'a' ], [ 1, 'a' ] ],
+ [ '+', [ 1, nil ], [ 2, 'b' ] ],
+ [ '+', [ 1, nil ], [ 3, 'c' ] ],
+ [ '+', [ 1, nil ], [ 4, 'd' ] ],
+ [ '=', [ 1, 'e' ], [ 5, 'e' ] ],
+ [ '!', [ 2, 'v' ], [ 6, 'w' ] ],
+ [ '+', [ 3, nil ], [ 7, 'x' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-i" do
+ s1 = %w()
+ s2 = %w(a b c)
+ forward_sdiff = [
+ [ '+', [ 0, nil ], [ 0, 'a' ] ],
+ [ '+', [ 0, nil ], [ 1, 'b' ] ],
+ [ '+', [ 0, nil ], [ 2, 'c' ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-j" do
+ s1 = %w(a b c)
+ s2 = %w()
+ forward_sdiff = [
+ [ '-', [ 0, 'a' ], [ 0, nil ] ],
+ [ '-', [ 1, 'b' ], [ 0, nil ] ],
+ [ '-', [ 2, 'c' ], [ 0, nil ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-k" do
+ s1 = %w(a b c)
+ s2 = %w(1)
+ forward_sdiff = [
+ [ '!', [ 0, 'a' ], [ 0, '1' ] ],
+ [ '-', [ 1, 'b' ], [ 1, nil ] ],
+ [ '-', [ 2, 'c' ], [ 1, nil ] ] ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-l" do
+ s1 = %w(a b c)
+ s2 = %w(c)
+ forward_sdiff = [
+ [ '-', [ 0, 'a' ], [ 0, nil ] ],
+ [ '-', [ 1, 'b' ], [ 0, nil ] ],
+ [ '=', [ 2, 'c' ], [ 0, 'c' ] ]
+ ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-m" do
+ s1 = %w(abcd efgh ijkl mnop)
+ s2 = []
+ forward_sdiff = [
+ [ '-', [ 0, 'abcd' ], [ 0, nil ] ],
+ [ '-', [ 1, 'efgh' ], [ 0, nil ] ],
+ [ '-', [ 2, 'ijkl' ], [ 0, nil ] ],
+ [ '-', [ 3, 'mnop' ], [ 0, nil ] ]
+ ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+
+ it "sequence-n" do
+ s1 = []
+ s2 = %w(abcd efgh ijkl mnop)
+ forward_sdiff = [
+ [ '+', [ 0, nil ], [ 0, 'abcd' ] ],
+ [ '+', [ 0, nil ], [ 1, 'efgh' ] ],
+ [ '+', [ 0, nil ], [ 2, 'ijkl' ] ],
+ [ '+', [ 0, nil ], [ 3, 'mnop' ] ]
+ ]
+ do_sdiff_comparison(s1, s2, forward_sdiff)
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/diff_lcs_sequences_spec.rb b/spec/diff_lcs_sequences_spec.rb
new file mode 100644
index 0000000..c7a5558
--- /dev/null
+++ b/spec/diff_lcs_sequences_spec.rb
@@ -0,0 +1,83 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'spec_helper'
+
+describe "Diff::LCS.traverse_sequences" do
+ describe "callback with no finishers" do
+ before(:each) do
+ @callback_s1_s2 = simple_callback_no_finishers
+ Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2)
+
+ @callback_s2_s1 = simple_callback_no_finishers
+ Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1)
+ end
+
+ it "should have the correct LCS result on left-matches" do
+ @callback_s1_s2.matched_a.should == correct_lcs
+ @callback_s2_s1.matched_a.should == correct_lcs
+ end
+
+ it "should have the correct LCS result on right-matches" do
+ @callback_s1_s2.matched_b.should == correct_lcs
+ @callback_s2_s1.matched_b.should == correct_lcs
+ end
+
+ it "should have the correct skipped sequences for the left sequence" do
+ @callback_s1_s2.discards_a.should == skipped_seq1
+ @callback_s2_s1.discards_a.should == skipped_seq2
+ end
+
+ it "should have the correct skipped sequences for the right sequence" do
+ @callback_s1_s2.discards_b.should == skipped_seq2
+ @callback_s2_s1.discards_b.should == skipped_seq1
+ end
+
+ it "should not have anything done markers from the left or right sequences" do
+ @callback_s1_s2.done_a.should be_empty
+ @callback_s1_s2.done_b.should be_empty
+ @callback_s2_s1.done_a.should be_empty
+ @callback_s2_s1.done_b.should be_empty
+ end
+ end
+
+ describe "callback with finisher" do
+ before(:each) do
+ @callback_s1_s2 = simple_callback
+ Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2)
+ @callback_s2_s1 = simple_callback
+ Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1)
+ end
+
+ it "should have the correct LCS result on left-matches" do
+ @callback_s1_s2.matched_a.should == correct_lcs
+ @callback_s2_s1.matched_a.should == correct_lcs
+ end
+
+ it "should have the correct LCS result on right-matches" do
+ @callback_s1_s2.matched_b.should == correct_lcs
+ @callback_s2_s1.matched_b.should == correct_lcs
+ end
+
+ it "should have the correct skipped sequences for the left sequence" do
+ @callback_s1_s2.discards_a.should == skipped_seq1
+ @callback_s2_s1.discards_a.should == skipped_seq2
+ end
+
+ it "should have the correct skipped sequences for the right sequence" do
+ @callback_s1_s2.discards_b.should == skipped_seq2
+ @callback_s2_s1.discards_b.should == skipped_seq1
+ end
+
+ it "should have done markers differently-sized sequences" do
+ @callback_s1_s2.done_a.should == [[ "p", 9, "s", 10 ]]
+ @callback_s1_s2.done_b.should be_empty
+
+ # 20110731 I don't yet understand why this particular behaviour
+ # isn't transitive.
+ @callback_s2_s1.done_a.should be_empty
+ @callback_s2_s1.done_b.should be_empty
+ end
+ end
+end
+
+# vim: ft=ruby
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..1c934e7
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,270 @@
+# -*- ruby encoding: utf-8 -*-
+
+require 'rubygems'
+require 'bundler'
+
+require 'pathname'
+
+file = Pathname.new(__FILE__).expand_path
+path = file.parent
+parent = path.parent
+
+$:.unshift parent.join('lib')
+
+require 'diff-lcs'
+
+module Diff::LCS::SpecHelper
+ def seq1
+ %w(a b c e h j l m n p)
+ end
+
+ def skipped_seq1
+ %w(a h n p)
+ end
+
+ def seq2
+ %w(b c d e f j k l m r s t)
+ end
+
+ def skipped_seq2
+ %w(d f k r s t)
+ end
+
+ def word_sequence
+ %w(abcd efgh ijkl mnopqrstuvwxyz)
+ end
+
+ def correct_lcs
+ %w(b c e j l m)
+ end
+
+ def correct_forward_diff
+ [
+ [ [ '-', 0, 'a' ] ],
+ [ [ '+', 2, 'd' ] ],
+ [ [ '-', 4, 'h' ],
+ [ '+', 4, 'f' ] ],
+ [ [ '+', 6, 'k' ] ],
+ [ [ '-', 8, 'n' ],
+ [ '-', 9, 'p' ],
+ [ '+', 9, 'r' ],
+ [ '+', 10, 's' ],
+ [ '+', 11, 't' ] ]
+ ]
+ end
+
+ def correct_backward_diff
+ [
+ [ [ '+', 0, 'a' ] ],
+ [ [ '-', 2, 'd' ] ],
+ [ [ '-', 4, 'f' ],
+ [ '+', 4, 'h' ] ],
+ [ [ '-', 6, 'k' ] ],
+ [
+ [ '-', 9, 'r' ],
+ [ '-', 10, 's' ],
+ [ '+', 8, 'n' ],
+ [ '-', 11, 't' ],
+ [ '+', 9, 'p' ] ]
+ ]
+ end
+
+ def correct_forward_sdiff
+ [
+ [ '-', [ 0, 'a' ], [ 0, nil ] ],
+ [ '=', [ 1, 'b' ], [ 0, 'b' ] ],
+ [ '=', [ 2, 'c' ], [ 1, 'c' ] ],
+ [ '+', [ 3, nil ], [ 2, 'd' ] ],
+ [ '=', [ 3, 'e' ], [ 3, 'e' ] ],
+ [ '!', [ 4, 'h' ], [ 4, 'f' ] ],
+ [ '=', [ 5, 'j' ], [ 5, 'j' ] ],
+ [ '+', [ 6, nil ], [ 6, 'k' ] ],
+ [ '=', [ 6, 'l' ], [ 7, 'l' ] ],
+ [ '=', [ 7, 'm' ], [ 8, 'm' ] ],
+ [ '!', [ 8, 'n' ], [ 9, 'r' ] ],
+ [ '!', [ 9, 'p' ], [ 10, 's' ] ],
+ [ '+', [ 10, nil ], [ 11, 't' ] ]
+ ]
+ end
+
+ def reverse_sdiff(forward_sdiff)
+ forward_sdiff.map { |line|
+ line[1], line[2] = line[2], line[1]
+ case line[0]
+ when '-' then line[0] = '+'
+ when '+' then line[0] = '-'
+ end
+ line
+ }
+ end
+
+ def change_diff(diff)
+ map_diffs(diff, Diff::LCS::Change)
+ end
+
+ def context_diff(diff)
+ map_diffs(diff, Diff::LCS::ContextChange)
+ end
+
+ def format_diffs(diffs)
+ diffs.map do |e|
+ if e.kind_of?(Array)
+ e.map { |f| f.to_a.join }.join(", ")
+ else
+ e.to_a.join
+ end
+ end.join("\n")
+ end
+
+ def map_diffs(diffs, klass = Diff::LCS::ContextChange)
+ diffs.map do |chunks|
+ if klass == Diff::LCS::ContextChange
+ klass.from_a(chunks)
+ else
+ chunks.map { |changes| klass.from_a(changes) }
+ end
+ end
+ end
+
+ def simple_callback
+ callbacks = Object.new
+ class << callbacks
+ attr_reader :matched_a
+ attr_reader :matched_b
+ attr_reader :discards_a
+ attr_reader :discards_b
+ attr_reader :done_a
+ attr_reader :done_b
+
+ def reset
+ @matched_a = []
+ @matched_b = []
+ @discards_a = []
+ @discards_b = []
+ @done_a = []
+ @done_b = []
+ end
+
+ def match(event)
+ @matched_a << event.old_element
+ @matched_b << event.new_element
+ end
+
+ def discard_b(event)
+ @discards_b << event.new_element
+ end
+
+ def discard_a(event)
+ @discards_a << event.old_element
+ end
+
+ def finished_a(event)
+ @done_a << [event.old_element, event.old_position,
+ event.new_element, event.new_position]
+ end
+
+ def finished_b(event)
+ p "called #finished_b"
+ @done_b << [event.old_element, event.old_position,
+ event.new_element, event.new_position]
+ end
+ end
+ callbacks.reset
+ callbacks
+ end
+
+ def simple_callback_no_finishers
+ simple = simple_callback
+ class << simple
+ undef :finished_a
+ undef :finished_b
+ end
+ simple
+ end
+
+ def balanced_callback
+ cb = Object.new
+ class << cb
+ attr_reader :result
+
+ def reset
+ @result = []
+ end
+
+ def match(event)
+ @result << [ "=", event.old_position, event.new_position ]
+ end
+
+ def discard_a(event)
+ @result << [ "<", event.old_position, event.new_position ]
+ end
+
+ def discard_b(event)
+ @result << [ ">", event.old_position, event.new_position ]
+ end
+
+ def change(event)
+ @result << [ "!", event.old_position, event.new_position ]
+ end
+ end
+ cb.reset
+ cb
+ end
+
+ def balanced_callback_no_change
+ balanced = balanced_callback
+ class << balanced
+ undef :change
+ end
+ balanced
+ end
+
+ module Matchers
+ extend RSpec::Matchers::DSL
+
+ matcher :be_nil_or_match_values do |ii, s1, s2|
+ match do |ee|
+ ee.should satisfy { |vee| vee.nil? || s1[ii] == s2[ee] }
+ end
+ end
+
+ matcher :correctly_map_sequence do |s1|
+ match do |actual|
+ actual.each_with_index { |ee, ii|
+ ee.should be_nil_or_match_values(ii, s1, @s2)
+ }
+ end
+
+ chain :to_other_sequence do |s2|
+ @s2 = s2
+ end
+ end
+ end
+end
+
+RSpec.configure do |conf|
+ conf.include Diff::LCS::SpecHelper
+end
+
+
+=begin
+RSpec::Matchers.define :be_a_multiple_of do |expected|
+ match do |actual|
+ actual % expected == 0
+ end
+
+ failure_message_for_should do |actual|
+ "expected that #{actual} would be a multiple of #{expected}"
+ end
+
+ failure_message_for_should_not do |actual|
+ "expected that #{actual} would not be a multiple of #{expected}"
+ end
+
+ description do
+ "be multiple of #{expected}"
+ end
+end
+=end
+
+# vim: ft=ruby