diff-lcs 1.1.3 → 1.2.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.
@@ -1,18 +1,4 @@
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$
14
- #++
15
- # Includes Diff::LCS into String.
1
+ # -*- ruby encoding: utf-8 -*-
16
2
 
17
3
  class String
18
4
  include Diff::LCS
@@ -0,0 +1,65 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Diff::LCS::Change do
6
+ describe "an add" do
7
+ subject { described_class.new('+', 0, 'element') }
8
+ it { should_not be_deleting }
9
+ it { should be_adding }
10
+ it { should_not be_unchanged }
11
+ it { should_not be_changed }
12
+ it { should_not be_finished_a }
13
+ it { should_not be_finished_b }
14
+ end
15
+
16
+ describe "a delete" do
17
+ subject { described_class.new('-', 0, 'element') }
18
+ it { should be_deleting }
19
+ it { should_not be_adding }
20
+ it { should_not be_unchanged }
21
+ it { should_not be_changed }
22
+ it { should_not be_finished_a }
23
+ it { should_not be_finished_b }
24
+ end
25
+
26
+ describe "an unchanged" do
27
+ subject { described_class.new('=', 0, 'element') }
28
+ it { should_not be_deleting }
29
+ it { should_not be_adding }
30
+ it { should be_unchanged }
31
+ it { should_not be_changed }
32
+ it { should_not be_finished_a }
33
+ it { should_not be_finished_b }
34
+ end
35
+
36
+ describe "a changed" do
37
+ subject { described_class.new('!', 0, 'element') }
38
+ it { should_not be_deleting }
39
+ it { should_not be_adding }
40
+ it { should_not be_unchanged }
41
+ it { should be_changed }
42
+ it { should_not be_finished_a }
43
+ it { should_not be_finished_b }
44
+ end
45
+
46
+ describe "a finished_a" do
47
+ subject { described_class.new('>', 0, 'element') }
48
+ it { should_not be_deleting }
49
+ it { should_not be_adding }
50
+ it { should_not be_unchanged }
51
+ it { should_not be_changed }
52
+ it { should be_finished_a }
53
+ it { should_not be_finished_b }
54
+ end
55
+
56
+ describe "a finished_b" do
57
+ subject { described_class.new('<', 0, 'element') }
58
+ it { should_not be_deleting }
59
+ it { should_not be_adding }
60
+ it { should_not be_unchanged }
61
+ it { should_not be_changed }
62
+ it { should_not be_finished_a }
63
+ it { should be_finished_b }
64
+ end
65
+ end
@@ -30,6 +30,12 @@ describe "Diff::LCS.diff" do
30
30
  correct_diff.each { |hunk| hunk.each { |change| change[0] = '+' } }
31
31
  change_diff(correct_diff).should == diff
32
32
  end
33
- end
34
33
 
35
- # vim: ft=ruby
34
+ it "should return an empty diff with (hello, hello)" do
35
+ Diff::LCS.diff(hello, hello).should == []
36
+ end
37
+
38
+ it "should return an empty diff with (hello_ary, hello_ary)" do
39
+ Diff::LCS.diff(hello_ary, hello_ary).should == []
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe "Diff::LCS Issues" do
6
+ include Diff::LCS::SpecHelper::Matchers
7
+
8
+ it "should not fail to provide a simple patchset (issue 1)" do
9
+ s1, s2 = *%W(aX bXaX)
10
+ correct_forward_diff = [
11
+ [ [ '+', 0, 'b' ],
12
+ [ '+', 1, 'X' ] ],
13
+ ]
14
+
15
+ diff_s1_s2 = Diff::LCS.diff(s1, s2)
16
+ change_diff(correct_forward_diff).should == diff_s1_s2
17
+ expect do
18
+ Diff::LCS.patch(s1, diff_s1_s2).should == s2
19
+ end.to_not raise_error(RuntimeError, /provided patchset/)
20
+ expect do
21
+ Diff::LCS.patch(s2, diff_s1_s2).should == s1
22
+ end.to_not raise_error(RuntimeError, /provided patchset/)
23
+ end
24
+ end
@@ -2,11 +2,11 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe "Diff::LCS.LCS and Diff::LCS.__lcs" do
5
+ describe "Diff::LCS::Internals.lcs" do
6
6
  include Diff::LCS::SpecHelper::Matchers
7
7
 
8
- it "should return the correct raw values from Diff::LCS.__lcs" do
9
- res = Diff::LCS.__lcs(seq1, seq2)
8
+ it "should return a meaningful LCS array with (seq1, seq2)" do
9
+ res = Diff::LCS::Internals.lcs(seq1, seq2)
10
10
  # The result of the LCS (less the +nil+ values) must be as long as the
11
11
  # correct result.
12
12
  res.compact.size.should == correct_lcs.size
@@ -20,6 +20,18 @@ describe "Diff::LCS.LCS and Diff::LCS.__lcs" do
20
20
  x_seq2.should == correct_lcs
21
21
  end
22
22
 
23
+ it "should return all indexes with (hello, hello)" do
24
+ Diff::LCS::Internals.lcs(hello, hello).should == (0...hello.size).to_a
25
+ end
26
+
27
+ it "should return all indexes with (hello_ary, hello_ary)" do
28
+ Diff::LCS::Internals.lcs(hello_ary, hello_ary).should == (0...hello_ary.size).to_a
29
+ end
30
+ end
31
+
32
+ describe "Diff::LCS.LCS" do
33
+ include Diff::LCS::SpecHelper::Matchers
34
+
23
35
  it "should return the correct compacted values from Diff::LCS.LCS" do
24
36
  res = Diff::LCS.LCS(seq1, seq2)
25
37
  res.should == correct_lcs
@@ -31,6 +43,12 @@ describe "Diff::LCS.LCS and Diff::LCS.__lcs" do
31
43
  res.should == correct_lcs
32
44
  res.compact.should == res
33
45
  end
34
- end
35
46
 
36
- # vim: ft=ruby
47
+ it "should return %W(h e l l o) with (hello, hello)" do
48
+ Diff::LCS.LCS(hello, hello).should == hello.split(//)
49
+ end
50
+
51
+ it "should return hello_ary with (hello_ary, hello_ary)" do
52
+ Diff::LCS.LCS(hello_ary, hello_ary).should == hello_ary
53
+ end
54
+ end
@@ -26,6 +26,16 @@ describe "Diff::LCS.patch" do
26
26
  end
27
27
 
28
28
  describe "using a Diff::LCS.diff patchset" do
29
+ describe "an empty patchset returns the source" do
30
+ it "works on a string (hello)" do
31
+ Diff::LCS::patch(hello, Diff::LCS.diff(hello, hello)).should == hello
32
+ end
33
+
34
+ it "works on an array %W(h e l l o)" do
35
+ Diff::LCS::patch(hello_ary, Diff::LCS.diff(hello_ary, hello_ary)).should == hello_ary
36
+ end
37
+ end
38
+
29
39
  describe "with default diff callbacks (DiffCallbacks)" do
30
40
  describe "forward (s1 -> s2)" do
31
41
  it_has_behavior "patch sequences correctly" do
@@ -90,6 +100,16 @@ describe "Diff::LCS.patch" do
90
100
  end
91
101
 
92
102
  describe "using a Diff::LCS.sdiff patchset" do
103
+ describe "an empty patchset returns the source" do
104
+ it "works on a string (hello)" do
105
+ Diff::LCS::patch(hello, Diff::LCS.sdiff(hello, hello)).should == hello
106
+ end
107
+
108
+ it "works on an array %W(h e l l o)" do
109
+ Diff::LCS::patch(hello_ary, Diff::LCS.sdiff(hello_ary, hello_ary)).should == hello_ary
110
+ end
111
+ end
112
+
93
113
  describe "with default diff callbacks (DiffCallbacks)" do
94
114
  describe "forward (s1 -> s2)" do
95
115
  it_has_behavior "patch sequences correctly" do
@@ -169,15 +189,16 @@ describe "Diff::LCS.patch" do
169
189
  @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1)
170
190
  end
171
191
 
172
- it "does not autodiscover s1 to s2 patches" do
173
- # It should, but it doesn't.
192
+ it "should autodiscover s1 to s2 patches" do
174
193
  expect do
175
194
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
176
- end.to raise_error(RuntimeError, /provided patchset/)
195
+ end.to_not raise_error(RuntimeError, /provided patchset/)
196
+ end
177
197
 
198
+ it "should autodiscover s2 to s1 patches" do
178
199
  expect do
179
200
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
180
- end.to raise_error(RuntimeError, /provided patchset/)
201
+ end.to_not raise_error(RuntimeError, /provided patchset/)
181
202
  end
182
203
 
183
204
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -206,15 +227,16 @@ describe "Diff::LCS.patch" do
206
227
  @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::ContextDiffCallbacks)
207
228
  end
208
229
 
209
- it "does not autodiscover s1 to s2 patches" do
210
- # It should, but it doesn't.
230
+ it "should autodiscover s1 to s2 patches" do
211
231
  expect do
212
232
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
213
- end.to raise_error(RuntimeError, /provided patchset/)
233
+ end.to_not raise_error(RuntimeError, /provided patchset/)
234
+ end
214
235
 
236
+ it "should autodiscover s2 to s1 patches" do
215
237
  expect do
216
238
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
217
- end.to raise_error(RuntimeError, /provided patchset/)
239
+ end.to_not raise_error(RuntimeError, /provided patchset/)
218
240
  end
219
241
 
220
242
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -243,15 +265,16 @@ describe "Diff::LCS.patch" do
243
265
  @patch_set_s2_s1 = Diff::LCS.diff(@s2, @s1, Diff::LCS::SDiffCallbacks)
244
266
  end
245
267
 
246
- it "does not autodiscover s1 to s2 patches" do
247
- # It should, but it doesn't.
268
+ it "should autodiscover s1 to s2 patches" do
248
269
  expect do
249
270
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
250
- end.to raise_error(RuntimeError, /provided patchset/)
271
+ end.to_not raise_error(RuntimeError, /provided patchset/)
272
+ end
251
273
 
274
+ it "should autodiscover s2 to s1 patches" do
252
275
  expect do
253
276
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
254
- end.to raise_error(RuntimeError, /provided patchset/)
277
+ end.to_not raise_error(RuntimeError, /provided patchset/)
255
278
  end
256
279
 
257
280
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -280,15 +303,16 @@ describe "Diff::LCS.patch" do
280
303
  @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1)
281
304
  end
282
305
 
283
- it "does not autodiscover s1 to s2 patches" do
284
- # It should, but it doesn't.
306
+ it "should autodiscover s1 to s2 patches" do
285
307
  expect do
286
308
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
287
- end.to raise_error(RuntimeError, /provided patchset/)
309
+ end.to_not raise_error(RuntimeError, /provided patchset/)
310
+ end
288
311
 
312
+ it "should autodiscover s2 to s1 patches" do
289
313
  expect do
290
314
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
291
- end.to raise_error(RuntimeError, /provided patchset/)
315
+ end.to_not raise_error(RuntimeError, /provided patchset/)
292
316
  end
293
317
 
294
318
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -296,7 +320,7 @@ describe "Diff::LCS.patch" do
296
320
  Diff::LCS.patch(@s2, @patch_set_s1_s2).should == @s1
297
321
  end
298
322
 
299
- it "should correctly patch left-to-right (explicit patch)" do
323
+ it "should correctly patch left-to-right (explicit patch)", :only => true do
300
324
  Diff::LCS.patch(@s1, @patch_set_s1_s2, :patch).should == @s2
301
325
  Diff::LCS.patch(@s2, @patch_set_s2_s1, :patch).should == @s1
302
326
  Diff::LCS.patch!(@s1, @patch_set_s1_s2).should == @s2
@@ -317,15 +341,16 @@ describe "Diff::LCS.patch" do
317
341
  @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::ContextDiffCallbacks)
318
342
  end
319
343
 
320
- it "does not autodiscover s1 to s2 patches" do
321
- # It should, but it doesn't.
344
+ it "should autodiscover s1 to s2 patches" do
322
345
  expect do
323
346
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
324
- end.to raise_error(RuntimeError, /provided patchset/)
347
+ end.to_not raise_error(RuntimeError, /provided patchset/)
348
+ end
325
349
 
350
+ it "should autodiscover s2 to s1 patches" do
326
351
  expect do
327
352
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
328
- end.to raise_error(RuntimeError, /provided patchset/)
353
+ end.to_not raise_error(RuntimeError, /provided patchset/)
329
354
  end
330
355
 
331
356
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -354,15 +379,16 @@ describe "Diff::LCS.patch" do
354
379
  @patch_set_s2_s1 = Diff::LCS.sdiff(@s2, @s1, Diff::LCS::DiffCallbacks)
355
380
  end
356
381
 
357
- it "does not autodiscover s1 to s2 patches" do
358
- # It should, but it doesn't.
382
+ it "should autodiscover s1 to s2 patches" do
359
383
  expect do
360
384
  Diff::LCS.patch(@s1, @patch_set_s1_s2).should == @s2
361
- end.to raise_error(RuntimeError, /provided patchset/)
385
+ end.to_not raise_error(RuntimeError, /provided patchset/)
386
+ end
362
387
 
388
+ it "should autodiscover s2 to s1 patches" do
363
389
  expect do
364
390
  Diff::LCS.patch(@s1, @patch_set_s2_s1).should == @s2
365
- end.to raise_error(RuntimeError, /provided patchset/)
391
+ end.to_not raise_error(RuntimeError, /provided patchset/)
366
392
  end
367
393
 
368
394
  it "should autodiscover s2 to s1 the left-to-right patches" do
@@ -386,5 +412,3 @@ describe "Diff::LCS.patch" do
386
412
  end
387
413
  end
388
414
  end
389
-
390
- # vim: ft=ruby
@@ -200,5 +200,3 @@ describe "Diff::LCS.sdiff" do
200
200
  it_has_behavior "compare sequences correctly"
201
201
  end
202
202
  end
203
-
204
- # vim: ft=ruby
@@ -12,6 +12,14 @@ $:.unshift parent.join('lib')
12
12
  require 'diff-lcs'
13
13
 
14
14
  module Diff::LCS::SpecHelper
15
+ def hello
16
+ "hello"
17
+ end
18
+
19
+ def hello_ary
20
+ %W(h e l l o)
21
+ end
22
+
15
23
  def seq1
16
24
  %w(a b c e h j l m n p)
17
25
  end
@@ -159,7 +167,6 @@ module Diff::LCS::SpecHelper
159
167
  new_result
160
168
  end
161
169
 
162
-
163
170
  def simple_callback
164
171
  callbacks = Object.new
165
172
  class << callbacks
@@ -279,6 +286,5 @@ end
279
286
  RSpec.configure do |conf|
280
287
  conf.include Diff::LCS::SpecHelper
281
288
  conf.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:'
289
+ conf.filter_run_excluding :broken => true
282
290
  end
283
-
284
- # vim: ft=ruby
@@ -29,6 +29,32 @@ describe "Diff::LCS.traverse_balanced" do
29
29
  end
30
30
  end
31
31
 
32
+ describe "identical string sequences ('abc')" do
33
+ s1 = s2 = "abc"
34
+
35
+ result = [
36
+ [ '=', 0, 0 ],
37
+ [ '=', 1, 1 ],
38
+ [ '=', 2, 2 ]
39
+ ]
40
+
41
+ it_has_behavior "with a #change callback", s1, s2, result
42
+ it_has_behavior "without a #change callback", s1, s2, result
43
+ end
44
+
45
+ describe "identical array sequences %w(a b c)" do
46
+ s1 = s2 = %w(a b c)
47
+
48
+ result = [
49
+ [ '=', 0, 0 ],
50
+ [ '=', 1, 1 ],
51
+ [ '=', 2, 2 ]
52
+ ]
53
+
54
+ it_has_behavior "with a #change callback", s1, s2, result
55
+ it_has_behavior "without a #change callback", s1, s2, result
56
+ end
57
+
32
58
  describe "sequences %w(a b c) & %w(a x c)" do
33
59
  s1 = %w(a b c)
34
60
  s2 = %w(a x c)
@@ -282,5 +308,3 @@ describe "Diff::LCS.traverse_balanced" do
282
308
  it_has_behavior "without a #change callback", s1, s2, result
283
309
  end
284
310
  end
285
-
286
- # vim: ft=ruby
@@ -4,39 +4,97 @@ require 'spec_helper'
4
4
 
5
5
  describe "Diff::LCS.traverse_sequences" do
6
6
  describe "callback with no finishers" do
7
- before(:each) do
8
- @callback_s1_s2 = simple_callback_no_finishers
9
- Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2)
10
-
11
- @callback_s2_s1 = simple_callback_no_finishers
12
- Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1)
7
+ describe "over (seq1, seq2)" do
8
+ before(:each) do
9
+ @callback_s1_s2 = simple_callback_no_finishers
10
+ Diff::LCS.traverse_sequences(seq1, seq2, @callback_s1_s2)
11
+
12
+ @callback_s2_s1 = simple_callback_no_finishers
13
+ Diff::LCS.traverse_sequences(seq2, seq1, @callback_s2_s1)
14
+ end
15
+
16
+ it "should have the correct LCS result on left-matches" do
17
+ @callback_s1_s2.matched_a.should == correct_lcs
18
+ @callback_s2_s1.matched_a.should == correct_lcs
19
+ end
20
+
21
+ it "should have the correct LCS result on right-matches" do
22
+ @callback_s1_s2.matched_b.should == correct_lcs
23
+ @callback_s2_s1.matched_b.should == correct_lcs
24
+ end
25
+
26
+ it "should have the correct skipped sequences with the left sequence" do
27
+ @callback_s1_s2.discards_a.should == skipped_seq1
28
+ @callback_s2_s1.discards_a.should == skipped_seq2
29
+ end
30
+
31
+ it "should have the correct skipped sequences with the right sequence" do
32
+ @callback_s1_s2.discards_b.should == skipped_seq2
33
+ @callback_s2_s1.discards_b.should == skipped_seq1
34
+ end
35
+
36
+ it "should not have anything done markers from the left or right sequences" do
37
+ @callback_s1_s2.done_a.should be_empty
38
+ @callback_s1_s2.done_b.should be_empty
39
+ @callback_s2_s1.done_a.should be_empty
40
+ @callback_s2_s1.done_b.should be_empty
41
+ end
13
42
  end
14
43
 
15
- it "should have the correct LCS result on left-matches" do
16
- @callback_s1_s2.matched_a.should == correct_lcs
17
- @callback_s2_s1.matched_a.should == correct_lcs
18
- end
44
+ describe "over (hello, hello)" do
45
+ before(:each) do
46
+ @callback = simple_callback_no_finishers
47
+ Diff::LCS.traverse_sequences(hello, hello, @callback)
48
+ end
19
49
 
20
- it "should have the correct LCS result on right-matches" do
21
- @callback_s1_s2.matched_b.should == correct_lcs
22
- @callback_s2_s1.matched_b.should == correct_lcs
23
- end
50
+ it "should have the correct LCS result on left-matches" do
51
+ @callback.matched_a.should == hello.split(//)
52
+ end
24
53
 
25
- it "should have the correct skipped sequences for the left sequence" do
26
- @callback_s1_s2.discards_a.should == skipped_seq1
27
- @callback_s2_s1.discards_a.should == skipped_seq2
28
- end
54
+ it "should have the correct LCS result on right-matches" do
55
+ @callback.matched_b.should == hello.split(//)
56
+ end
29
57
 
30
- it "should have the correct skipped sequences for the right sequence" do
31
- @callback_s1_s2.discards_b.should == skipped_seq2
32
- @callback_s2_s1.discards_b.should == skipped_seq1
58
+ it "should have the correct skipped sequences with the left sequence", :only => true do
59
+ @callback.discards_a.should be_empty
60
+ end
61
+
62
+ it "should have the correct skipped sequences with the right sequence" do
63
+ @callback.discards_b.should be_empty
64
+ end
65
+
66
+ it "should not have anything done markers from the left or right sequences" do
67
+ @callback.done_a.should be_empty
68
+ @callback.done_b.should be_empty
69
+ end
33
70
  end
34
71
 
35
- it "should not have anything done markers from the left or right sequences" do
36
- @callback_s1_s2.done_a.should be_empty
37
- @callback_s1_s2.done_b.should be_empty
38
- @callback_s2_s1.done_a.should be_empty
39
- @callback_s2_s1.done_b.should be_empty
72
+ describe "over (hello_ary, hello_ary)" do
73
+ before(:each) do
74
+ @callback = simple_callback_no_finishers
75
+ Diff::LCS.traverse_sequences(hello_ary, hello_ary, @callback)
76
+ end
77
+
78
+ it "should have the correct LCS result on left-matches" do
79
+ @callback.matched_a.should == hello_ary
80
+ end
81
+
82
+ it "should have the correct LCS result on right-matches" do
83
+ @callback.matched_b.should == hello_ary
84
+ end
85
+
86
+ it "should have the correct skipped sequences with the left sequence" do
87
+ @callback.discards_a.should be_empty
88
+ end
89
+
90
+ it "should have the correct skipped sequences with the right sequence" do
91
+ @callback.discards_b.should be_empty
92
+ end
93
+
94
+ it "should not have anything done markers from the left or right sequences" do
95
+ @callback.done_a.should be_empty
96
+ @callback.done_b.should be_empty
97
+ end
40
98
  end
41
99
  end
42
100
 
@@ -79,5 +137,3 @@ describe "Diff::LCS.traverse_sequences" do
79
137
  end
80
138
  end
81
139
  end
82
-
83
- # vim: ft=ruby