diff-lcs 2.0.0.beta.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -5
  3. data/CODE_OF_CONDUCT.md +152 -114
  4. data/CONTRIBUTING.md +8 -3
  5. data/CONTRIBUTORS.md +19 -9
  6. data/Manifest.txt +88 -70
  7. data/README.md +30 -17
  8. data/Rakefile +90 -22
  9. data/SECURITY.md +3 -12
  10. data/integration/compare/array_diff_spec.rb +10 -0
  11. data/integration/compare/hash_diff_spec.rb +25 -0
  12. data/integration/compare/string_diff_spec.rb +10 -0
  13. data/integration/rspec_differ_spec.rb +26 -0
  14. data/integration/rspec_expectations_spec.rb +32 -0
  15. data/integration/runner +20 -0
  16. data/lib/diff/lcs/change.rb +21 -16
  17. data/lib/diff/lcs/ldiff.rb +9 -4
  18. data/lib/diff/lcs/version.rb +1 -1
  19. data/spec/hunk_spec.rb +32 -34
  20. data/spec/ldiff_spec.rb +7 -7
  21. data/spec/spec_helper.rb +4 -12
  22. data/test/fixtures/ldiff/output.diff-c +7 -0
  23. data/test/fixtures/ldiff/output.diff-u +5 -0
  24. data/test/fixtures/ldiff/output.diff.bin2 +1 -0
  25. data/test/fixtures/ldiff/output.diff.bin2-c +1 -0
  26. data/test/fixtures/ldiff/output.diff.bin2-e +1 -0
  27. data/test/fixtures/ldiff/output.diff.bin2-f +1 -0
  28. data/test/fixtures/ldiff/output.diff.bin2-u +1 -0
  29. data/{spec → test}/fixtures/ldiff/output.diff.chef-c +2 -2
  30. data/test/fixtures/ldiff/output.diff.chef-u +9 -0
  31. data/{spec → test}/fixtures/ldiff/output.diff.chef2-c +2 -2
  32. data/{spec → test}/fixtures/ldiff/output.diff.chef2-u +2 -2
  33. data/test/fixtures/ldiff/output.diff.empty.vs.four_lines-c +9 -0
  34. data/test/fixtures/ldiff/output.diff.empty.vs.four_lines-u +7 -0
  35. data/test/fixtures/ldiff/output.diff.four_lines.vs.empty-c +9 -0
  36. data/test/fixtures/ldiff/output.diff.four_lines.vs.empty-u +7 -0
  37. data/test/fixtures/ldiff/output.diff.issue95_trailing_context-c +9 -0
  38. data/test/fixtures/ldiff/output.diff.issue95_trailing_context-u +6 -0
  39. data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-c +2 -2
  40. data/test/fixtures/ldiff/output.diff.missing_new_line1-u +9 -0
  41. data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-c +2 -2
  42. data/test/fixtures/ldiff/output.diff.missing_new_line2-u +9 -0
  43. data/test/test_block.rb +34 -0
  44. data/test/test_change.rb +234 -0
  45. data/test/test_diff.rb +53 -0
  46. data/test/test_helper.rb +225 -0
  47. data/test/test_hunk.rb +72 -0
  48. data/test/test_issues.rb +168 -0
  49. data/test/test_lcs.rb +47 -0
  50. data/test/test_ldiff.rb +89 -0
  51. data/test/test_patch.rb +362 -0
  52. data/test/test_sdiff.rb +167 -0
  53. data/test/test_traverse_balanced.rb +322 -0
  54. data/test/test_traverse_sequences.rb +187 -0
  55. metadata +136 -105
  56. data/spec/fixtures/ldiff/output.diff-c +0 -7
  57. data/spec/fixtures/ldiff/output.diff-u +0 -5
  58. data/spec/fixtures/ldiff/output.diff.bin2 +0 -1
  59. data/spec/fixtures/ldiff/output.diff.bin2-c +0 -1
  60. data/spec/fixtures/ldiff/output.diff.bin2-e +0 -1
  61. data/spec/fixtures/ldiff/output.diff.bin2-f +0 -1
  62. data/spec/fixtures/ldiff/output.diff.bin2-u +0 -1
  63. data/spec/fixtures/ldiff/output.diff.chef-u +0 -9
  64. data/spec/fixtures/ldiff/output.diff.empty.vs.four_lines-c +0 -9
  65. data/spec/fixtures/ldiff/output.diff.empty.vs.four_lines-u +0 -7
  66. data/spec/fixtures/ldiff/output.diff.four_lines.vs.empty-c +0 -9
  67. data/spec/fixtures/ldiff/output.diff.four_lines.vs.empty-u +0 -7
  68. data/spec/fixtures/ldiff/output.diff.issue95_trailing_context-c +0 -9
  69. data/spec/fixtures/ldiff/output.diff.issue95_trailing_context-u +0 -6
  70. data/spec/fixtures/ldiff/output.diff.missing_new_line1-u +0 -9
  71. data/spec/fixtures/ldiff/output.diff.missing_new_line2-u +0 -9
  72. /data/{spec → test}/fixtures/123_x +0 -0
  73. /data/{spec → test}/fixtures/456_x +0 -0
  74. /data/{spec → test}/fixtures/aX +0 -0
  75. /data/{spec → test}/fixtures/bXaX +0 -0
  76. /data/{spec → test}/fixtures/ds1.csv +0 -0
  77. /data/{spec → test}/fixtures/ds2.csv +0 -0
  78. /data/{spec → test}/fixtures/empty +0 -0
  79. /data/{spec → test}/fixtures/file1.bin +0 -0
  80. /data/{spec → test}/fixtures/file2.bin +0 -0
  81. /data/{spec → test}/fixtures/four_lines +0 -0
  82. /data/{spec → test}/fixtures/four_lines_with_missing_new_line +0 -0
  83. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line1-e +0 -0
  84. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line1-f +0 -0
  85. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line2-e +0 -0
  86. /data/{spec → test}/fixtures/ldiff/diff.missing_new_line2-f +0 -0
  87. /data/{spec → test}/fixtures/ldiff/error.diff.chef-e +0 -0
  88. /data/{spec → test}/fixtures/ldiff/error.diff.chef-f +0 -0
  89. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line1-e +0 -0
  90. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line1-f +0 -0
  91. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line2-e +0 -0
  92. /data/{spec → test}/fixtures/ldiff/error.diff.missing_new_line2-f +0 -0
  93. /data/{spec → test}/fixtures/ldiff/output.diff +0 -0
  94. /data/{spec → test}/fixtures/ldiff/output.diff.bin1 +0 -0
  95. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-c +0 -0
  96. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-e +0 -0
  97. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-f +0 -0
  98. /data/{spec → test}/fixtures/ldiff/output.diff.bin1-u +0 -0
  99. /data/{spec → test}/fixtures/ldiff/output.diff.chef +0 -0
  100. /data/{spec → test}/fixtures/ldiff/output.diff.chef2 +0 -0
  101. /data/{spec → test}/fixtures/ldiff/output.diff.chef2-d +0 -0
  102. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines +0 -0
  103. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines-e +0 -0
  104. /data/{spec → test}/fixtures/ldiff/output.diff.empty.vs.four_lines-f +0 -0
  105. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty +0 -0
  106. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty-e +0 -0
  107. /data/{spec → test}/fixtures/ldiff/output.diff.four_lines.vs.empty-f +0 -0
  108. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context +0 -0
  109. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context-e +0 -0
  110. /data/{spec → test}/fixtures/ldiff/output.diff.issue95_trailing_context-f +0 -0
  111. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1 +0 -0
  112. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-e +0 -0
  113. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line1-f +0 -0
  114. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2 +0 -0
  115. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-e +0 -0
  116. /data/{spec → test}/fixtures/ldiff/output.diff.missing_new_line2-f +0 -0
  117. /data/{spec → test}/fixtures/new-chef +0 -0
  118. /data/{spec → test}/fixtures/new-chef2 +0 -0
  119. /data/{spec → test}/fixtures/old-chef +0 -0
  120. /data/{spec → test}/fixtures/old-chef2 +0 -0
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rubygems"
4
- require "pathname"
5
-
6
- require "psych" if RUBY_VERSION >= "1.9"
3
+ $LOAD_PATH.unshift File.expand_path(__dir__, "../lib")
7
4
 
5
+ require "rubygems"
8
6
  require "simplecov"
9
7
  require "simplecov-lcov"
10
8
 
9
+ require "diff/lcs"
10
+
11
11
  SimpleCov::Formatter::LcovFormatter.config do |config|
12
12
  config.report_with_single_file = true
13
13
  config.lcov_file_name = "lcov.info"
@@ -23,12 +23,6 @@ SimpleCov.start "test_frameworks" do
23
23
  ])
24
24
  end
25
25
 
26
- file = Pathname.new(__FILE__).expand_path
27
- path = file.parent
28
- parent = path.parent
29
-
30
- $:.unshift parent.join("lib")
31
-
32
26
  module CaptureSubprocessIO
33
27
  def _synchronize
34
28
  yield
@@ -62,8 +56,6 @@ module CaptureSubprocessIO
62
56
  private :_capture_subprocess_io
63
57
  end
64
58
 
65
- require "diff-lcs"
66
-
67
59
  module Diff::LCS::SpecHelper
68
60
  def hello
69
61
  "hello"
@@ -0,0 +1,7 @@
1
+ *** test/fixtures/aX 2020-06-23 11:15:32.000000000 -0400
2
+ --- test/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400
3
+ ***************
4
+ *** 1 ****
5
+ ! aX
6
+ --- 1 ----
7
+ ! bXaX
@@ -0,0 +1,5 @@
1
+ --- test/fixtures/aX 2020-06-23 11:15:32.000000000 -0400
2
+ +++ test/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400
3
+ @@ -1 +1 @@
4
+ -aX
5
+ +bXaX
@@ -0,0 +1 @@
1
+ Binary files test/fixtures/file1.bin and test/fixtures/file2.bin differ
@@ -0,0 +1 @@
1
+ Binary files test/fixtures/file1.bin and test/fixtures/file2.bin differ
@@ -0,0 +1 @@
1
+ Binary files test/fixtures/file1.bin and test/fixtures/file2.bin differ
@@ -0,0 +1 @@
1
+ Binary files test/fixtures/file1.bin and test/fixtures/file2.bin differ
@@ -0,0 +1 @@
1
+ Binary files test/fixtures/file1.bin and test/fixtures/file2.bin differ
@@ -1,5 +1,5 @@
1
- *** spec/fixtures/old-chef 2020-06-23 23:18:20.000000000 -0400
2
- --- spec/fixtures/new-chef 2020-06-23 23:18:20.000000000 -0400
1
+ *** test/fixtures/old-chef 2020-06-23 23:18:20.000000000 -0400
2
+ --- test/fixtures/new-chef 2020-06-23 23:18:20.000000000 -0400
3
3
  ***************
4
4
  *** 1,4 ****
5
5
  {
@@ -0,0 +1,9 @@
1
+ --- test/fixtures/old-chef 2020-06-23 23:18:20.000000000 -0400
2
+ +++ test/fixtures/new-chef 2020-06-23 23:18:20.000000000 -0400
3
+ @@ -1,4 +1,4 @@
4
+ {
5
+ "name": "x",
6
+ - "description": "hi"
7
+ + "description": "lo"
8
+ }
9
+
@@ -1,5 +1,5 @@
1
- *** spec/fixtures/old-chef2 2020-06-30 09:43:35.000000000 -0400
2
- --- spec/fixtures/new-chef2 2020-06-30 09:44:32.000000000 -0400
1
+ *** test/fixtures/old-chef2 2020-06-30 09:43:35.000000000 -0400
2
+ --- test/fixtures/new-chef2 2020-06-30 09:44:32.000000000 -0400
3
3
  ***************
4
4
  *** 1,5 ****
5
5
  recipe[a::default]
@@ -1,5 +1,5 @@
1
- --- spec/fixtures/old-chef2 2020-06-30 09:43:35.000000000 -0400
2
- +++ spec/fixtures/new-chef2 2020-06-30 09:44:32.000000000 -0400
1
+ --- test/fixtures/old-chef2 2020-06-30 09:43:35.000000000 -0400
2
+ +++ test/fixtures/new-chef2 2020-06-30 09:44:32.000000000 -0400
3
3
  @@ -1,5 +1,4 @@
4
4
  recipe[a::default]
5
5
  -recipe[b::default]
@@ -0,0 +1,9 @@
1
+ *** test/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
2
+ --- test/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
3
+ ***************
4
+ *** 0 ****
5
+ --- 1,4 ----
6
+ + one
7
+ + two
8
+ + three
9
+ + four
@@ -0,0 +1,7 @@
1
+ --- test/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
2
+ +++ test/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
3
+ @@ -0,0 +1,4 @@
4
+ +one
5
+ +two
6
+ +three
7
+ +four
@@ -0,0 +1,9 @@
1
+ *** test/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
2
+ --- test/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
3
+ ***************
4
+ *** 1,4 ****
5
+ - one
6
+ - two
7
+ - three
8
+ - four
9
+ --- 0 ----
@@ -0,0 +1,7 @@
1
+ --- test/fixtures/four_lines 2025-01-31 12:13:45.476036544 +0100
2
+ +++ test/fixtures/empty 2025-01-31 12:14:52.856031635 +0100
3
+ @@ -1,4 +0,0 @@
4
+ -one
5
+ -two
6
+ -three
7
+ -four
@@ -0,0 +1,9 @@
1
+ *** test/fixtures/123_x 2025-01-31 17:00:17.070615716 +0100
2
+ --- test/fixtures/456_x 2025-01-31 16:58:26.380624827 +0100
3
+ ***************
4
+ *** 1,2 ****
5
+ ! 123
6
+ x
7
+ --- 1,2 ----
8
+ ! 456
9
+ x
@@ -0,0 +1,6 @@
1
+ --- test/fixtures/123_x 2025-01-31 17:00:17.070615716 +0100
2
+ +++ test/fixtures/456_x 2025-01-31 16:58:26.380624827 +0100
3
+ @@ -1,2 +1,2 @@
4
+ -123
5
+ +456
6
+ x
@@ -1,5 +1,5 @@
1
- *** spec/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
2
- --- spec/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
1
+ *** test/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
2
+ --- test/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
3
3
  ***************
4
4
  *** 1,4 ****
5
5
  one
@@ -0,0 +1,9 @@
1
+ --- test/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
2
+ +++ test/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
3
+ @@ -1,4 +1,4 @@
4
+ one
5
+ two
6
+ three
7
+ -four
8
+ +four
9
+
@@ -1,5 +1,5 @@
1
- *** spec/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
2
- --- spec/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
1
+ *** test/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
2
+ --- test/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
3
3
  ***************
4
4
  *** 1,4 ****
5
5
  one
@@ -0,0 +1,9 @@
1
+ --- test/fixtures/four_lines_with_missing_new_line 2025-01-31 12:17:43.926013315 +0100
2
+ +++ test/fixtures/four_lines 2025-01-31 12:17:43.926013315 +0100
3
+ @@ -1,4 +1,4 @@
4
+ one
5
+ two
6
+ three
7
+ -four
8
+
9
+ +four
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+ require "diff/lcs/block"
5
+
6
+ class TestBlock < Minitest::Test
7
+ include Diff::LCS::TestHelper
8
+
9
+ def test_op_unchanged
10
+ block = Diff::LCS::Block.from_chunk([])
11
+ assert_equal "^", block.op
12
+ end
13
+
14
+ def test_op_delete
15
+ changes = [Diff::LCS::Change.new("-", 0, "a")]
16
+ block = Diff::LCS::Block.from_chunk(changes)
17
+ assert_equal "-", block.op
18
+ end
19
+
20
+ def test_op_insert
21
+ changes = [Diff::LCS::Change.new("+", 0, "a")]
22
+ block = Diff::LCS::Block.from_chunk(changes)
23
+ assert_equal "+", block.op
24
+ end
25
+
26
+ def test_op_conflict
27
+ changes = [
28
+ Diff::LCS::Change.new("-", 0, "a"),
29
+ Diff::LCS::Change.new("+", 0, "b")
30
+ ]
31
+ block = Diff::LCS::Block.from_chunk(changes)
32
+ assert_equal "!", block.op
33
+ end
34
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class TestChange < Minitest::Test
6
+ def test_invalid_change
7
+ assert_raises RuntimeError, /Invalid CHange Action/ do
8
+ change("~", 0, "element")
9
+ end
10
+
11
+ assert_raises RuntimeError, /Invalid Position Type/ do
12
+ change("+", 3.5, "element")
13
+ end
14
+ end
15
+
16
+ def test_from_a
17
+ assert_kind_of Diff::LCS::Change, change_from_a(["+", 0, "element"])
18
+ assert_kind_of Diff::LCS::Change, change_from_a(["+", 0, "element"], Diff::LCS::ContextChange)
19
+ assert_kind_of Diff::LCS::ContextChange,
20
+ change_from_a(["!", [1, "old_element"], [2, "new_element"]])
21
+ assert_kind_of Diff::LCS::ContextChange,
22
+ change_from_a(["!", [1, "old_element"], [2, "new_element"]], Diff::LCS::ContextChange)
23
+
24
+ assert_raises RuntimeError, "Invalid change array format provided." do
25
+ change_from_a(["+", 0])
26
+ end
27
+
28
+ assert_raises RuntimeError, "Invalid change array format provided." do
29
+ change_from_a(["+", 0], Diff::LCS::ContextChange)
30
+ end
31
+ end
32
+
33
+ def test_spaceship_reflexive
34
+ c1 = change("=", 5, "x")
35
+ c2 = change("=", 5, "x")
36
+ assert_equal 0, c1 <=> c2
37
+ end
38
+
39
+ def test_spaceship_position_precedence
40
+ c1 = change("=", 5, "x")
41
+ c2 = change("=", 10, "x")
42
+
43
+ assert_equal(-1, c1 <=> c2)
44
+ assert_equal 1, c2 <=> c1
45
+ end
46
+
47
+ def test_spaceship_action_precedence
48
+ valid_actions.each_cons(2) do |a1, a2|
49
+ c1 = change(a1, 5, "x")
50
+ c2 = change(a2, 5, "x")
51
+
52
+ assert_equal(-1, c1 <=> c2, "#{a1} should sort before #{a2}")
53
+ assert_equal 1, c2 <=> c1
54
+ end
55
+ end
56
+
57
+ def test_spaceship_element_precedence
58
+ c1 = change("=", 5, "a")
59
+ c2 = change("=", 5, "z")
60
+
61
+ assert_equal(-1, c1 <=> c2)
62
+ assert_equal 1, c2 <=> c1
63
+ assert_equal 0, c1 <=> change("=", 5, "a")
64
+ end
65
+
66
+ def test_add
67
+ change = change("+", 0, "element")
68
+
69
+ assert change.adding?
70
+
71
+ refute change.deleting?
72
+ refute change.unchanged?
73
+ refute change.changed?
74
+ refute change.finished_a?
75
+ refute change.finished_b?
76
+ end
77
+
78
+ def test_delete
79
+ change = change("-", 0, "element")
80
+
81
+ assert change.deleting?
82
+
83
+ refute change.adding?
84
+ refute change.unchanged?
85
+ refute change.changed?
86
+ refute change.finished_a?
87
+ refute change.finished_b?
88
+ end
89
+
90
+ def test_unchanged
91
+ change = change("=", 0, "element")
92
+
93
+ assert change.unchanged?
94
+
95
+ refute change.deleting?
96
+ refute change.adding?
97
+ refute change.changed?
98
+ refute change.finished_a?
99
+ refute change.finished_b?
100
+ end
101
+
102
+ def test_changed
103
+ change = change("!", 0, "element")
104
+
105
+ assert change.changed?
106
+
107
+ refute change.deleting?
108
+ refute change.adding?
109
+ refute change.unchanged?
110
+ refute change.finished_a?
111
+ refute change.finished_b?
112
+ end
113
+
114
+ def test_finished_a
115
+ change = change(">", 0, "element")
116
+
117
+ assert change.finished_a?
118
+
119
+ refute change.deleting?
120
+ refute change.adding?
121
+ refute change.unchanged?
122
+ refute change.changed?
123
+ refute change.finished_b?
124
+ end
125
+
126
+ def test_finished_b
127
+ change = change("<", 0, "element")
128
+
129
+ assert change.finished_b?
130
+
131
+ refute change.deleting?
132
+ refute change.adding?
133
+ refute change.unchanged?
134
+ refute change.changed?
135
+ refute change.finished_a?
136
+ end
137
+
138
+ def test_as_array
139
+ action, position, element = change("!", 0, "element")
140
+ assert_equal "!", action
141
+ assert_equal 0, position
142
+ assert_equal "element", element
143
+ end
144
+ end
145
+
146
+ class TestContextChange < Minitest::Test
147
+ private def change(...) = Diff::LCS::ContextChange.new(...)
148
+ private def simplify(...) = Diff::LCS::ContextChange.simplify(change(...))
149
+
150
+ def test_invalid_change
151
+ assert_raises RuntimeError, /Invalid CHange Action/ do
152
+ change("~", 0, "old", 0, "new")
153
+ end
154
+
155
+ assert_raises RuntimeError, /Invalid Position Type/ do
156
+ change("+", 3.5, "old", 0, "new")
157
+ end
158
+
159
+ assert_raises RuntimeError, /Invalid Position Type/ do
160
+ change("+", 0, "old", 3.5, "new")
161
+ end
162
+ end
163
+
164
+ def test_as_array
165
+ action, old, new = change("!", 1, "old_element", 2, "new_element")
166
+
167
+ assert_equal "!", action
168
+ assert_equal [1, "old_element"], old
169
+ assert_equal [2, "new_element"], new
170
+ end
171
+
172
+ def test_spaceship_reflexive
173
+ c1 = change("=", 5, "x", 10, "y")
174
+ c2 = change("=", 5, "x", 10, "y")
175
+ assert_equal 0, c1 <=> c2
176
+ end
177
+
178
+ def test_spaceship_position_precedence
179
+ c1 = change("=", 5, "x", 10, "y")
180
+ c2 = change("=", 15, "x", 10, "y")
181
+
182
+ assert_equal(-1, c1 <=> c2)
183
+ assert_equal 1, c2 <=> c1
184
+
185
+ c1 = change("=", 5, "x", 10, "y")
186
+ c2 = change("=", 5, "x", 20, "y")
187
+
188
+ assert_equal(-1, c1 <=> c2)
189
+ assert_equal 1, c2 <=> c1
190
+ end
191
+
192
+ def test_spaceship_action_precedence
193
+ valid_actions.each_cons(2) do |a1, a2|
194
+ c1 = change(a1, 5, "x", 10, "y")
195
+ c2 = change(a2, 5, "x", 10, "y")
196
+
197
+ assert_equal(-1, c1 <=> c2, "#{a1} should sort before #{a2}")
198
+ assert_equal 1, c2 <=> c1
199
+ end
200
+ end
201
+
202
+ def test_spaceship_element_precedence
203
+ c1 = change("=", 5, "a", 10, "y")
204
+ c2 = change("=", 5, "z", 10, "y")
205
+
206
+ assert_equal(-1, c1 <=> c2, "old_element precedence")
207
+ assert_equal 1, c2 <=> c1
208
+
209
+ c3 = change("=", 5, "x", 10, "a")
210
+ c4 = change("=", 5, "x", 10, "z")
211
+
212
+ assert_equal(-1, c3 <=> c4, "new_element precedence")
213
+ assert_equal 1, c4 <=> c3
214
+ assert_equal 0, c3 <=> Diff::LCS::ContextChange.new("=", 5, "x", 10, "a")
215
+ end
216
+
217
+ def test_simplify
218
+ simplify("-", 5, "old", 10, "new") => {action:, new_element:}
219
+ assert_equal action, "-"
220
+ assert_nil new_element
221
+
222
+ simplify("<", 5, "old", 10, "new") => {action:, new_element:}
223
+ assert_equal action, "-"
224
+ assert_nil new_element
225
+
226
+ simplify("+", 5, "old", 10, "new") => {action:, old_element:}
227
+ assert_equal action, "+"
228
+ assert_nil old_element
229
+
230
+ simplify(">", 5, "old", 10, "new") => {action:, old_element:}
231
+ assert_equal action, "+"
232
+ assert_nil old_element
233
+ end
234
+ end
data/test/test_diff.rb ADDED
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "test_helper"
4
+
5
+ class TestDiff < Minitest::Test
6
+ def test_correctly_diffs_seq1_to_seq2
7
+ assert_equal change_diff(correct_forward_diff), diff(seq1, seq2)
8
+ end
9
+
10
+ def test_correctly_diffs_seq2_to_seq1
11
+ assert_equal change_diff(correct_backward_diff), diff(seq2, seq1)
12
+ end
13
+
14
+ def test_correctly_diffs_against_empty_sequence_forward
15
+ correct_diff = [
16
+ [
17
+ ["-", 0, "abcd"],
18
+ ["-", 1, "efgh"],
19
+ ["-", 2, "ijkl"],
20
+ ["-", 3, "mnopqrstuvwxyz"]
21
+ ]
22
+ ]
23
+
24
+ assert_equal change_diff(correct_diff), diff(word_sequence, [])
25
+ end
26
+
27
+ def test_correctly_diffs_against_empty_sequence_backward
28
+ correct_diff = [
29
+ [
30
+ ["+", 0, "abcd"],
31
+ ["+", 1, "efgh"],
32
+ ["+", 2, "ijkl"],
33
+ ["+", 3, "mnopqrstuvwxyz"]
34
+ ]
35
+ ]
36
+
37
+ assert_equal change_diff(correct_diff), diff([], word_sequence)
38
+ end
39
+
40
+ def test_correctly_diffs_xx_and_xaxb
41
+ left = "xx"
42
+ right = "xaxb"
43
+ assert_equal right, patch(left, diff(left, right))
44
+ end
45
+
46
+ def test_returns_empty_diff_with_hello_hello
47
+ assert_empty diff(hello, hello)
48
+ end
49
+
50
+ def test_returns_empty_diff_with_hello_ary_hello_ary
51
+ assert_empty diff(hello_ary, hello_ary)
52
+ end
53
+ end