diff-lcs 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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