diff-lcs 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +42 -0
- data/Install +6 -0
- data/README +77 -0
- data/Rakefile +103 -0
- data/bin/htmldiff +111 -0
- data/bin/ldiff +45 -0
- data/lib/diff/lcs.rb +1105 -0
- data/lib/diff/lcs/array.rb +21 -0
- data/lib/diff/lcs/block.rb +51 -0
- data/lib/diff/lcs/callbacks.rb +322 -0
- data/lib/diff/lcs/change.rb +169 -0
- data/lib/diff/lcs/hunk.rb +257 -0
- data/lib/diff/lcs/ldiff.rb +226 -0
- data/lib/diff/lcs/string.rb +19 -0
- data/tests/00test.rb +626 -0
- metadata +66 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
#! /usr/env/bin ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2004 Austin Ziegler <diff-lcs@halostatue.ca>
|
4
|
+
# adapted from:
|
5
|
+
# Algorithm::Diff (Perl) by Ned Konz <perl@bike-nomad.com>
|
6
|
+
# Smalltalk by Mario I. Wolczko <mario@wolczko.com>
|
7
|
+
# implements McIlroy-Hunt diff algorithm
|
8
|
+
#
|
9
|
+
# This program is free software. It may be redistributed and/or modified under
|
10
|
+
# the terms of the GPL version 2 (or later), the Perl Artistic licence, or the
|
11
|
+
# Ruby licence.
|
12
|
+
#
|
13
|
+
# $Id: string.rb,v 1.3 2004/08/08 20:33:09 austin Exp $
|
14
|
+
#++
|
15
|
+
# Includes Diff::LCS into String.
|
16
|
+
|
17
|
+
class String
|
18
|
+
include Diff::LCS
|
19
|
+
end
|
data/tests/00test.rb
ADDED
@@ -0,0 +1,626 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
|
4
|
+
|
5
|
+
require 'diff/lcs'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'pp'
|
8
|
+
require 'diff/lcs/array'
|
9
|
+
|
10
|
+
module Diff::LCS::Tests
|
11
|
+
def __format_diffs(diffs)
|
12
|
+
diffs.map do |e|
|
13
|
+
if e.kind_of?(Array)
|
14
|
+
e.map { |f| f.to_a.join }.join(", ")
|
15
|
+
else
|
16
|
+
e.to_a.join
|
17
|
+
end
|
18
|
+
end.join("; ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def __map_diffs(diffs, klass = Diff::LCS::ContextChange)
|
22
|
+
diffs.map do |chunks|
|
23
|
+
if klass == Diff::LCS::ContextChange
|
24
|
+
klass.from_a(chunks)
|
25
|
+
else
|
26
|
+
chunks.map { |changes| klass.from_a(changes) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def __simple_callbacks
|
32
|
+
callbacks = Object.new
|
33
|
+
class << callbacks
|
34
|
+
attr_reader :matched_a
|
35
|
+
attr_reader :matched_b
|
36
|
+
attr_reader :discards_a
|
37
|
+
attr_reader :discards_b
|
38
|
+
attr_reader :done_a
|
39
|
+
attr_reader :done_b
|
40
|
+
|
41
|
+
def reset
|
42
|
+
@matched_a = []
|
43
|
+
@matched_b = []
|
44
|
+
@discards_a = []
|
45
|
+
@discards_b = []
|
46
|
+
@done_a = []
|
47
|
+
@done_b = []
|
48
|
+
end
|
49
|
+
|
50
|
+
def match(event)
|
51
|
+
@matched_a << event.old_element
|
52
|
+
@matched_b << event.new_element
|
53
|
+
end
|
54
|
+
|
55
|
+
def discard_b(event)
|
56
|
+
@discards_b << event.new_element
|
57
|
+
end
|
58
|
+
|
59
|
+
def discard_a(event)
|
60
|
+
@discards_a << event.old_element
|
61
|
+
end
|
62
|
+
|
63
|
+
def finished_a(event)
|
64
|
+
@done_a << [event.old_element, event.old_position]
|
65
|
+
end
|
66
|
+
|
67
|
+
def finished_b(event)
|
68
|
+
@done_b << [event.new_element, event.new_position]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
callbacks.reset
|
72
|
+
callbacks
|
73
|
+
end
|
74
|
+
|
75
|
+
def __balanced_callback
|
76
|
+
cb = Object.new
|
77
|
+
class << cb
|
78
|
+
attr_reader :result
|
79
|
+
|
80
|
+
def reset
|
81
|
+
@result = ""
|
82
|
+
end
|
83
|
+
|
84
|
+
def match(event)
|
85
|
+
@result << "M#{event.old_position}#{event.new_position} "
|
86
|
+
end
|
87
|
+
|
88
|
+
def discard_a(event)
|
89
|
+
@result << "DA#{event.old_position}#{event.new_position} "
|
90
|
+
end
|
91
|
+
|
92
|
+
def discard_b(event)
|
93
|
+
@result << "DB#{event.old_position}#{event.new_position} "
|
94
|
+
end
|
95
|
+
|
96
|
+
def change(event)
|
97
|
+
@result << "C#{event.old_position}#{event.new_position} "
|
98
|
+
end
|
99
|
+
end
|
100
|
+
cb.reset
|
101
|
+
cb
|
102
|
+
end
|
103
|
+
|
104
|
+
def setup
|
105
|
+
@seq1 = %w(a b c e h j l m n p)
|
106
|
+
@seq2 = %w(b c d e f j k l m r s t)
|
107
|
+
|
108
|
+
@correct_lcs = %w(b c e j l m)
|
109
|
+
|
110
|
+
@skipped_seq1 = 'a h n p'
|
111
|
+
@skipped_seq2 = 'd f k r s t'
|
112
|
+
|
113
|
+
correct_diff = [
|
114
|
+
[ [ '-', 0, 'a' ] ],
|
115
|
+
[ [ '+', 2, 'd' ] ],
|
116
|
+
[ [ '-', 4, 'h' ],
|
117
|
+
[ '+', 4, 'f' ] ],
|
118
|
+
[ [ '+', 6, 'k' ] ],
|
119
|
+
[ [ '-', 8, 'n' ],
|
120
|
+
[ '-', 9, 'p' ],
|
121
|
+
[ '+', 9, 'r' ],
|
122
|
+
[ '+', 10, 's' ],
|
123
|
+
[ '+', 11, 't' ] ] ]
|
124
|
+
@correct_diff = __map_diffs(correct_diff, Diff::LCS::Change)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class TestLCS < Test::Unit::TestCase
|
129
|
+
include Diff::LCS::Tests
|
130
|
+
|
131
|
+
def test_lcs
|
132
|
+
res = ares = bres = nil
|
133
|
+
assert_nothing_raised { res = Diff::LCS.__lcs(@seq1, @seq2) }
|
134
|
+
# The result of the LCS (less the +nil+ values) must be as long as the
|
135
|
+
# correct result.
|
136
|
+
assert_equal(res.compact.size, @correct_lcs.size)
|
137
|
+
res.each_with_index { |ee, ii| assert(ee.nil? || (@seq1[ii] == @seq2[ee])) }
|
138
|
+
assert_nothing_raised { ares = (0...res.size).map { |ii| res[ii] ? @seq1[ii] : nil } }
|
139
|
+
assert_nothing_raised { bres = (0...res.size).map { |ii| res[ii] ? @seq2[res[ii]] : nil } }
|
140
|
+
assert_equal(@correct_lcs, ares.compact)
|
141
|
+
assert_equal(@correct_lcs, bres.compact)
|
142
|
+
assert_nothing_raised { res = Diff::LCS.LCS(@seq1, @seq2) }
|
143
|
+
assert_equal(res.compact, @correct_lcs)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class TestSequences < Test::Unit::TestCase
|
148
|
+
include Diff::LCS::Tests
|
149
|
+
|
150
|
+
def test_sequences
|
151
|
+
callbacks = nil
|
152
|
+
assert_nothing_raised do
|
153
|
+
callbacks = __simple_callbacks
|
154
|
+
class << callbacks
|
155
|
+
undef :finished_a
|
156
|
+
undef :finished_b
|
157
|
+
end
|
158
|
+
Diff::LCS.traverse_sequences(@seq1, @seq2, callbacks)
|
159
|
+
end
|
160
|
+
assert_equal(@correct_lcs.size, callbacks.matched_a.size)
|
161
|
+
assert_equal(@correct_lcs.size, callbacks.matched_b.size)
|
162
|
+
assert_equal(@skipped_seq1, callbacks.discards_a.join(" "))
|
163
|
+
assert_equal(@skipped_seq2, callbacks.discards_b.join(" "))
|
164
|
+
assert_nothing_raised do
|
165
|
+
callbacks = __simple_callbacks
|
166
|
+
Diff::LCS.traverse_sequences(@seq1, @seq2, callbacks)
|
167
|
+
end
|
168
|
+
assert_equal(@correct_lcs.size, callbacks.matched_a.size)
|
169
|
+
assert_equal(@correct_lcs.size, callbacks.matched_b.size)
|
170
|
+
assert_equal(@skipped_seq1, callbacks.discards_a.join(" "))
|
171
|
+
assert_equal(@skipped_seq2, callbacks.discards_b.join(" "))
|
172
|
+
assert_equal(9, callbacks.done_a[0][1])
|
173
|
+
assert_nil(callbacks.done_b[0])
|
174
|
+
|
175
|
+
# seqw = %w(abcd efgh ijkl mnopqrstuvwxyz)
|
176
|
+
# assert_nothing_raised do
|
177
|
+
# callbacks = __simple_callbacks
|
178
|
+
# class << callbacks
|
179
|
+
# undef :finished_a
|
180
|
+
# undef :finished_b
|
181
|
+
# end
|
182
|
+
# Diff::LCS.traverse_sequences(seqw, [], callbacks)
|
183
|
+
# end
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_diff
|
187
|
+
diff = nil
|
188
|
+
assert_nothing_raised { diff = Diff::LCS.diff(@seq1, @seq2) }
|
189
|
+
assert_equal(__format_diffs(@correct_diff), __format_diffs(diff))
|
190
|
+
assert_equal(@correct_diff, diff)
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_diff_empty
|
194
|
+
seqw = %w(abcd efgh ijkl mnopqrstuvwxyz)
|
195
|
+
correct_diff = [
|
196
|
+
[ [ '-', 0, 'abcd' ],
|
197
|
+
[ '-', 1, 'efgh' ],
|
198
|
+
[ '-', 2, 'ijkl' ],
|
199
|
+
[ '-', 3, 'mnopqrstuvwxyz' ] ] ]
|
200
|
+
diff = nil
|
201
|
+
|
202
|
+
assert_nothing_raised { diff = Diff::LCS.diff(seqw, []) }
|
203
|
+
assert_equal(__format_diffs(correct_diff), __format_diffs(diff))
|
204
|
+
|
205
|
+
correct_diff = [
|
206
|
+
[ [ '+', 0, 'abcd' ],
|
207
|
+
[ '+', 1, 'efgh' ],
|
208
|
+
[ '+', 2, 'ijkl' ],
|
209
|
+
[ '+', 3, 'mnopqrstuvwxyz' ] ] ]
|
210
|
+
assert_nothing_raised { diff = Diff::LCS.diff([], seqw) }
|
211
|
+
assert_equal(__format_diffs(correct_diff), __format_diffs(diff))
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class TestBalanced < Test::Unit::TestCase
|
216
|
+
include Diff::LCS::Tests
|
217
|
+
|
218
|
+
def test_sdiff_a
|
219
|
+
sdiff = nil
|
220
|
+
seq1 = %w(abc def yyy xxx ghi jkl)
|
221
|
+
seq2 = %w(abc dxf xxx ghi jkl)
|
222
|
+
correct_sdiff = [
|
223
|
+
[ '=', [ 0, 'abc' ], [ 0, 'abc' ] ],
|
224
|
+
[ '!', [ 1, 'def' ], [ 1, 'dxf' ] ],
|
225
|
+
[ '-', [ 2, 'yyy' ], [ 2, nil ] ],
|
226
|
+
[ '=', [ 3, 'xxx' ], [ 2, 'xxx' ] ],
|
227
|
+
[ '=', [ 4, 'ghi' ], [ 3, 'ghi' ] ],
|
228
|
+
[ '=', [ 5, 'jkl' ], [ 4, 'jkl' ] ] ]
|
229
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
230
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
231
|
+
assert_equal(correct_sdiff, sdiff)
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_sdiff_b
|
235
|
+
sdiff = nil
|
236
|
+
correct_sdiff = [
|
237
|
+
[ '-', [ 0, 'a' ], [ 0, nil ] ],
|
238
|
+
[ '=', [ 1, 'b' ], [ 0, 'b' ] ],
|
239
|
+
[ '=', [ 2, 'c' ], [ 1, 'c' ] ],
|
240
|
+
[ '+', [ 3, nil ], [ 2, 'd' ] ],
|
241
|
+
[ '=', [ 3, 'e' ], [ 3, 'e' ] ],
|
242
|
+
[ '!', [ 4, 'h' ], [ 4, 'f' ] ],
|
243
|
+
[ '=', [ 5, 'j' ], [ 5, 'j' ] ],
|
244
|
+
[ '+', [ 6, nil ], [ 6, 'k' ] ],
|
245
|
+
[ '=', [ 6, 'l' ], [ 7, 'l' ] ],
|
246
|
+
[ '=', [ 7, 'm' ], [ 8, 'm' ] ],
|
247
|
+
[ '!', [ 8, 'n' ], [ 9, 'r' ] ],
|
248
|
+
[ '!', [ 9, 'p' ], [ 10, 's' ] ],
|
249
|
+
[ '+', [ 10, nil ], [ 11, 't' ] ] ]
|
250
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
251
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(@seq1, @seq2) }
|
252
|
+
assert_equal(correct_sdiff, sdiff)
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_sdiff_c
|
256
|
+
sdiff = nil
|
257
|
+
seq1 = %w(a b c d e)
|
258
|
+
seq2 = %w(a e)
|
259
|
+
correct_sdiff = [
|
260
|
+
[ '=', [ 0, 'a' ], [ 0, 'a' ] ],
|
261
|
+
[ '-', [ 1, 'b' ], [ 1, nil ] ],
|
262
|
+
[ '-', [ 2, 'c' ], [ 1, nil ] ],
|
263
|
+
[ '-', [ 3, 'd' ], [ 1, nil ] ],
|
264
|
+
[ '=', [ 4, 'e' ], [ 1, 'e' ] ] ]
|
265
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
266
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
267
|
+
assert_equal(correct_sdiff, sdiff)
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_sdiff_d
|
271
|
+
sdiff = nil
|
272
|
+
seq1 = %w(a e)
|
273
|
+
seq2 = %w(a b c d e)
|
274
|
+
correct_sdiff = [
|
275
|
+
[ '=', [ 0, 'a' ], [ 0, 'a' ] ],
|
276
|
+
[ '+', [ 1, nil ], [ 1, 'b' ] ],
|
277
|
+
[ '+', [ 1, nil ], [ 2, 'c' ] ],
|
278
|
+
[ '+', [ 1, nil ], [ 3, 'd' ] ],
|
279
|
+
[ '=', [ 1, 'e' ], [ 4, 'e' ] ] ]
|
280
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
281
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
282
|
+
assert_equal(correct_sdiff, sdiff)
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_sdiff_e
|
286
|
+
sdiff = nil
|
287
|
+
seq1 = %w(v x a e)
|
288
|
+
seq2 = %w(w y a b c d e)
|
289
|
+
correct_sdiff = [
|
290
|
+
[ '!', [ 0, 'v' ], [ 0, 'w' ] ],
|
291
|
+
[ '!', [ 1, 'x' ], [ 1, 'y' ] ],
|
292
|
+
[ '=', [ 2, 'a' ], [ 2, 'a' ] ],
|
293
|
+
[ '+', [ 3, nil ], [ 3, 'b' ] ],
|
294
|
+
[ '+', [ 3, nil ], [ 4, 'c' ] ],
|
295
|
+
[ '+', [ 3, nil ], [ 5, 'd' ] ],
|
296
|
+
[ '=', [ 3, 'e' ], [ 6, 'e' ] ] ]
|
297
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
298
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
299
|
+
assert_equal(correct_sdiff, sdiff)
|
300
|
+
end
|
301
|
+
|
302
|
+
def test_sdiff_f
|
303
|
+
sdiff = nil
|
304
|
+
seq1 = %w(x a e)
|
305
|
+
seq2 = %w(a b c d e)
|
306
|
+
correct_sdiff = [
|
307
|
+
[ '-', [ 0, 'x' ], [ 0, nil ] ],
|
308
|
+
[ '=', [ 1, 'a' ], [ 0, 'a' ] ],
|
309
|
+
[ '+', [ 2, nil ], [ 1, 'b' ] ],
|
310
|
+
[ '+', [ 2, nil ], [ 2, 'c' ] ],
|
311
|
+
[ '+', [ 2, nil ], [ 3, 'd' ] ],
|
312
|
+
[ '=', [ 2, 'e' ], [ 4, 'e' ] ] ]
|
313
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
314
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
315
|
+
assert_equal(correct_sdiff, sdiff)
|
316
|
+
end
|
317
|
+
|
318
|
+
def test_sdiff_g
|
319
|
+
sdiff = nil
|
320
|
+
seq1 = %w(a e)
|
321
|
+
seq2 = %w(x a b c d e)
|
322
|
+
correct_sdiff = [
|
323
|
+
[ '+', [ 0, nil ], [ 0, 'x' ] ],
|
324
|
+
[ '=', [ 0, 'a' ], [ 1, 'a' ] ],
|
325
|
+
[ '+', [ 1, nil ], [ 2, 'b' ] ],
|
326
|
+
[ '+', [ 1, nil ], [ 3, 'c' ] ],
|
327
|
+
[ '+', [ 1, nil ], [ 4, 'd' ] ],
|
328
|
+
[ '=', [ 1, 'e' ], [ 5, 'e' ] ] ]
|
329
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
330
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
331
|
+
assert_equal(correct_sdiff, sdiff)
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_sdiff_h
|
335
|
+
sdiff = nil
|
336
|
+
seq1 = %w(a e v)
|
337
|
+
seq2 = %w(x a b c d e w x)
|
338
|
+
correct_sdiff = [
|
339
|
+
[ '+', [ 0, nil ], [ 0, 'x' ] ],
|
340
|
+
[ '=', [ 0, 'a' ], [ 1, 'a' ] ],
|
341
|
+
[ '+', [ 1, nil ], [ 2, 'b' ] ],
|
342
|
+
[ '+', [ 1, nil ], [ 3, 'c' ] ],
|
343
|
+
[ '+', [ 1, nil ], [ 4, 'd' ] ],
|
344
|
+
[ '=', [ 1, 'e' ], [ 5, 'e' ] ],
|
345
|
+
[ '!', [ 2, 'v' ], [ 6, 'w' ] ],
|
346
|
+
[ '+', [ 3, nil ], [ 7, 'x' ] ] ]
|
347
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
348
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
349
|
+
assert_equal(correct_sdiff, sdiff)
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_sdiff_i
|
353
|
+
sdiff = nil
|
354
|
+
seq1 = %w()
|
355
|
+
seq2 = %w(a b c)
|
356
|
+
correct_sdiff = [
|
357
|
+
[ '+', [ 0, nil ], [ 0, 'a' ] ],
|
358
|
+
[ '+', [ 0, nil ], [ 1, 'b' ] ],
|
359
|
+
[ '+', [ 0, nil ], [ 2, 'c' ] ] ]
|
360
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
361
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
362
|
+
assert_equal(correct_sdiff, sdiff)
|
363
|
+
end
|
364
|
+
|
365
|
+
def test_sdiff_j
|
366
|
+
sdiff = nil
|
367
|
+
seq1 = %w(a b c)
|
368
|
+
seq2 = %w()
|
369
|
+
correct_sdiff = [
|
370
|
+
[ '-', [ 0, 'a' ], [ 0, nil ] ],
|
371
|
+
[ '-', [ 1, 'b' ], [ 0, nil ] ],
|
372
|
+
[ '-', [ 2, 'c' ], [ 0, nil ] ] ]
|
373
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
374
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
375
|
+
assert_equal(correct_sdiff, sdiff)
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_sdiff_k
|
379
|
+
sdiff = nil
|
380
|
+
seq1 = %w(a b c)
|
381
|
+
seq2 = %w(1)
|
382
|
+
correct_sdiff = [
|
383
|
+
[ '!', [ 0, 'a' ], [ 0, '1' ] ],
|
384
|
+
[ '-', [ 1, 'b' ], [ 1, nil ] ],
|
385
|
+
[ '-', [ 2, 'c' ], [ 1, nil ] ] ]
|
386
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
387
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
388
|
+
assert_equal(correct_sdiff, sdiff)
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_sdiff_l
|
392
|
+
sdiff = nil
|
393
|
+
seq1 = %w(a b c)
|
394
|
+
seq2 = %w(c)
|
395
|
+
correct_sdiff = [
|
396
|
+
[ '-', [ 0, 'a' ], [ 0, nil ] ],
|
397
|
+
[ '-', [ 1, 'b' ], [ 0, nil ] ],
|
398
|
+
[ '=', [ 2, 'c' ], [ 0, 'c' ] ]
|
399
|
+
]
|
400
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
401
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
402
|
+
assert_equal(correct_sdiff, sdiff)
|
403
|
+
end
|
404
|
+
|
405
|
+
def test_sdiff_m
|
406
|
+
sdiff = nil
|
407
|
+
seq1 = %w(abcd efgh ijkl mnop)
|
408
|
+
seq2 = []
|
409
|
+
correct_sdiff = [
|
410
|
+
[ '-', [ 0, 'abcd' ], [ 0, nil ] ],
|
411
|
+
[ '-', [ 1, 'efgh' ], [ 0, nil ] ],
|
412
|
+
[ '-', [ 2, 'ijkl' ], [ 0, nil ] ],
|
413
|
+
[ '-', [ 3, 'mnop' ], [ 0, nil ] ]
|
414
|
+
]
|
415
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
416
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
417
|
+
assert_equal(correct_sdiff, sdiff)
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_sdiff_n
|
421
|
+
sdiff = nil
|
422
|
+
seq1 = []
|
423
|
+
seq2 = %w(abcd efgh ijkl mnop)
|
424
|
+
correct_sdiff = [
|
425
|
+
[ '+', [ 0, nil ], [ 0, 'abcd' ] ],
|
426
|
+
[ '+', [ 0, nil ], [ 1, 'efgh' ] ],
|
427
|
+
[ '+', [ 0, nil ], [ 2, 'ijkl' ] ],
|
428
|
+
[ '+', [ 0, nil ], [ 3, 'mnop' ] ]
|
429
|
+
]
|
430
|
+
correct_sdiff = __map_diffs(correct_sdiff)
|
431
|
+
assert_nothing_raised { sdiff = Diff::LCS.sdiff(seq1, seq2) }
|
432
|
+
assert_equal(correct_sdiff, sdiff)
|
433
|
+
end
|
434
|
+
|
435
|
+
def test_balanced_a
|
436
|
+
seq1 = %w(a b c)
|
437
|
+
seq2 = %w(a x c)
|
438
|
+
callback = nil
|
439
|
+
assert_nothing_raised { callback = __balanced_callback }
|
440
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
441
|
+
assert_equal("M00 C11 M22 ", callback.result)
|
442
|
+
end
|
443
|
+
|
444
|
+
def test_balanced_b
|
445
|
+
seq1 = %w(a b c)
|
446
|
+
seq2 = %w(a x c)
|
447
|
+
callback = nil
|
448
|
+
assert_nothing_raised do
|
449
|
+
callback = __balanced_callback
|
450
|
+
class << callback
|
451
|
+
undef change
|
452
|
+
end
|
453
|
+
end
|
454
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
455
|
+
assert_equal("M00 DA11 DB21 M22 ", callback.result)
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_balanced_c
|
459
|
+
seq1 = %w(a x y c)
|
460
|
+
seq2 = %w(a v w c)
|
461
|
+
callback = nil
|
462
|
+
assert_nothing_raised { callback = __balanced_callback }
|
463
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
464
|
+
assert_equal("M00 C11 C22 M33 ", callback.result)
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_balanced_d
|
468
|
+
seq1 = %w(x y c)
|
469
|
+
seq2 = %w(v w c)
|
470
|
+
callback = nil
|
471
|
+
assert_nothing_raised { callback = __balanced_callback }
|
472
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
473
|
+
assert_equal("C00 C11 M22 ", callback.result)
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_balanced_e
|
477
|
+
seq1 = %w(a x y z)
|
478
|
+
seq2 = %w(b v w)
|
479
|
+
callback = nil
|
480
|
+
assert_nothing_raised { callback = __balanced_callback }
|
481
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
482
|
+
assert_equal("C00 C11 C22 DA33 ", callback.result)
|
483
|
+
end
|
484
|
+
|
485
|
+
def test_balanced_f
|
486
|
+
seq1 = %w(a z)
|
487
|
+
seq2 = %w(a)
|
488
|
+
callback = nil
|
489
|
+
assert_nothing_raised { callback = __balanced_callback }
|
490
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
491
|
+
assert_equal("M00 DA11 ", callback.result)
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_balanced_g
|
495
|
+
seq1 = %w(z a)
|
496
|
+
seq2 = %w(a)
|
497
|
+
callback = nil
|
498
|
+
assert_nothing_raised { callback = __balanced_callback }
|
499
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
500
|
+
assert_equal("DA00 M10 ", callback.result)
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_balanced_h
|
504
|
+
seq1 = %w(a b c)
|
505
|
+
seq2 = %w(x y z)
|
506
|
+
callback = nil
|
507
|
+
assert_nothing_raised { callback = __balanced_callback }
|
508
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
509
|
+
assert_equal("C00 C11 C22 ", callback.result)
|
510
|
+
end
|
511
|
+
|
512
|
+
def test_balanced_i
|
513
|
+
seq1 = %w(abcd efgh ijkl mnopqrstuvwxyz)
|
514
|
+
seq2 = []
|
515
|
+
callback = nil
|
516
|
+
assert_nothing_raised { callback = __balanced_callback }
|
517
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
518
|
+
assert_equal("DA00 DA10 DA20 DA30 ", callback.result)
|
519
|
+
end
|
520
|
+
|
521
|
+
def test_balanced_j
|
522
|
+
seq1 = []
|
523
|
+
seq2 = %w(abcd efgh ijkl mnopqrstuvwxyz)
|
524
|
+
callback = nil
|
525
|
+
assert_nothing_raised { callback = __balanced_callback }
|
526
|
+
assert_nothing_raised { Diff::LCS.traverse_balanced(seq1, seq2, callback) }
|
527
|
+
assert_equal("DB00 DB01 DB02 DB03 ", callback.result)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
class TestPatching < Test::Unit::TestCase
|
532
|
+
include Diff::LCS::Tests
|
533
|
+
|
534
|
+
def test_patch_diff
|
535
|
+
ps = ms1 = ms2 = ms3 = nil
|
536
|
+
assert_nothing_raised do
|
537
|
+
ps = Diff::LCS.diff(@seq1, @seq2)
|
538
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
539
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
540
|
+
ms3 = Diff::LCS.patch(@seq2, ps)
|
541
|
+
end
|
542
|
+
assert_equal(@seq2, ms1)
|
543
|
+
assert_equal(@seq1, ms2)
|
544
|
+
assert_equal(@seq1, ms3)
|
545
|
+
assert_nothing_raised do
|
546
|
+
ps = Diff::LCS.diff(@seq1, @seq2, Diff::LCS::ContextDiffCallbacks)
|
547
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
548
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
549
|
+
ms2 = Diff::LCS.patch(@seq2, ps)
|
550
|
+
end
|
551
|
+
assert_equal(@seq2, ms1)
|
552
|
+
assert_equal(@seq1, ms2)
|
553
|
+
assert_equal(@seq1, ms3)
|
554
|
+
assert_nothing_raised do
|
555
|
+
ps = Diff::LCS.diff(@seq1, @seq2, Diff::LCS::SDiffCallbacks)
|
556
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
557
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
558
|
+
ms3 = Diff::LCS.patch(@seq2, ps)
|
559
|
+
end
|
560
|
+
assert_equal(@seq2, ms1)
|
561
|
+
assert_equal(@seq1, ms2)
|
562
|
+
assert_equal(@seq1, ms3)
|
563
|
+
end
|
564
|
+
|
565
|
+
# Tests patch bug #891:
|
566
|
+
# http://rubyforge.org/tracker/?func=detail&atid=407&aid=891&group_id=84
|
567
|
+
def test_patch_bug891
|
568
|
+
s1 = s2 = s3 = s4 = s5 = ps = nil
|
569
|
+
assert_nothing_raised do
|
570
|
+
s1 = %w{a b c d e f g h i j k }
|
571
|
+
s2 = %w{a b c d D e f g h i j k }
|
572
|
+
ps = Diff::LCS::diff(s1, s2)
|
573
|
+
s3 = Diff::LCS.patch(s1, ps, :patch)
|
574
|
+
ps = Diff::LCS::diff(s1, s2, Diff::LCS::ContextDiffCallbacks)
|
575
|
+
s4 = Diff::LCS.patch(s1, ps, :patch)
|
576
|
+
ps = Diff::LCS::diff(s1, s2, Diff::LCS::SDiffCallbacks)
|
577
|
+
s5 = Diff::LCS.patch(s1, ps, :patch)
|
578
|
+
end
|
579
|
+
assert_equal(s2, s3)
|
580
|
+
assert_equal(s2, s4)
|
581
|
+
assert_equal(s2, s5)
|
582
|
+
|
583
|
+
assert_nothing_raised do
|
584
|
+
ps = Diff::LCS::sdiff(s1, s2)
|
585
|
+
s3 = Diff::LCS.patch(s1, ps, :patch)
|
586
|
+
ps = Diff::LCS::diff(s1, s2, Diff::LCS::ContextDiffCallbacks)
|
587
|
+
s4 = Diff::LCS.patch(s1, ps, :patch)
|
588
|
+
ps = Diff::LCS::diff(s1, s2, Diff::LCS::DiffCallbacks)
|
589
|
+
s5 = Diff::LCS.patch(s1, ps, :patch)
|
590
|
+
end
|
591
|
+
assert_equal(s2, s3)
|
592
|
+
assert_equal(s2, s4)
|
593
|
+
assert_equal(s2, s5)
|
594
|
+
end
|
595
|
+
|
596
|
+
def test_patch_sdiff
|
597
|
+
ps = ms1 = ms2 = ms3 = nil
|
598
|
+
assert_nothing_raised do
|
599
|
+
ps = Diff::LCS.sdiff(@seq1, @seq2)
|
600
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
601
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
602
|
+
ms3 = Diff::LCS.patch(@seq2, ps)
|
603
|
+
end
|
604
|
+
assert_equal(@seq2, ms1)
|
605
|
+
assert_equal(@seq1, ms2)
|
606
|
+
assert_equal(@seq1, ms3)
|
607
|
+
assert_nothing_raised do
|
608
|
+
ps = Diff::LCS.sdiff(@seq1, @seq2, Diff::LCS::ContextDiffCallbacks)
|
609
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
610
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
611
|
+
ms3 = Diff::LCS.patch(@seq2, ps)
|
612
|
+
end
|
613
|
+
assert_equal(@seq2, ms1)
|
614
|
+
assert_equal(@seq1, ms2)
|
615
|
+
assert_equal(@seq1, ms3)
|
616
|
+
assert_nothing_raised do
|
617
|
+
ps = Diff::LCS.sdiff(@seq1, @seq2, Diff::LCS::DiffCallbacks)
|
618
|
+
ms1 = Diff::LCS.patch(@seq1, ps)
|
619
|
+
ms2 = Diff::LCS.patch(@seq2, ps, :unpatch)
|
620
|
+
ms3 = Diff::LCS.patch(@seq2, ps)
|
621
|
+
end
|
622
|
+
assert_equal(@seq2, ms1)
|
623
|
+
assert_equal(@seq1, ms2)
|
624
|
+
assert_equal(@seq1, ms3)
|
625
|
+
end
|
626
|
+
end
|