diff-lcs 1.4.1 → 1.5.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.
data/lib/diff/lcs.rb CHANGED
@@ -49,7 +49,7 @@ module Diff; end unless defined? Diff # rubocop:disable Style/Documentation
49
49
  # a x b y c z p d q
50
50
  # a b c a x b y c z
51
51
  module Diff::LCS
52
- VERSION = '1.4.1'
52
+ VERSION = '1.5.0'
53
53
  end
54
54
 
55
55
  require 'diff/lcs/callbacks'
@@ -60,6 +60,13 @@ module Diff::LCS # rubocop:disable Style/Documentation
60
60
  # +self+ and +other+. See Diff::LCS#lcs.
61
61
  #
62
62
  # lcs = seq1.lcs(seq2)
63
+ #
64
+ # A note when using objects: Diff::LCS only works properly when each object
65
+ # can be used as a key in a Hash, which typically means that the objects must
66
+ # implement Object#eql? in a way that two identical values compare
67
+ # identically for key purposes. That is:
68
+ #
69
+ # O.new('a').eql?(O.new('a')) == true
63
70
  def lcs(other, &block) #:yields self[i] if there are matched subsequences:
64
71
  Diff::LCS.lcs(self, other, &block)
65
72
  end
@@ -78,14 +85,14 @@ module Diff::LCS # rubocop:disable Style/Documentation
78
85
  # Traverses the discovered longest common subsequences between +self+ and
79
86
  # +other+. See Diff::LCS#traverse_sequences.
80
87
  def traverse_sequences(other, callbacks = nil, &block)
81
- traverse_sequences(self, other, callbacks || Diff::LCS::SequenceCallbacks, &block)
88
+ Diff::LCS.traverse_sequences(self, other, callbacks || Diff::LCS::SequenceCallbacks, &block)
82
89
  end
83
90
 
84
91
  # Traverses the discovered longest common subsequences between +self+ and
85
92
  # +other+ using the alternate, balanced algorithm. See
86
93
  # Diff::LCS#traverse_balanced.
87
94
  def traverse_balanced(other, callbacks = nil, &block)
88
- traverse_balanced(self, other, callbacks || Diff::LCS::BalancedCallbacks, &block)
95
+ Diff::LCS.traverse_balanced(self, other, callbacks || Diff::LCS::BalancedCallbacks, &block)
89
96
  end
90
97
 
91
98
  # Attempts to patch +self+ with the provided +patchset+. A new sequence based
@@ -243,8 +250,9 @@ class << Diff::LCS
243
250
  # advance that arrow and will call <tt>callbacks#discard_a</tt> or
244
251
  # <tt>callbacks#discard_b</tt>, depending on which arrow it advanced. If both
245
252
  # arrows point to elements that are not part of the longest common
246
- # subsequence, then #traverse_sequences will advance one of them and call the
247
- # appropriate callback, but it is not specified which it will call.
253
+ # subsequence, then #traverse_sequences will advance arrow +a+ and call the
254
+ # appropriate callback, then it will advance arrow +b+ and call the appropriate
255
+ # callback.
248
256
  #
249
257
  # The methods for <tt>callbacks#match</tt>, <tt>callbacks#discard_a</tt>, and
250
258
  # <tt>callbacks#discard_b</tt> are invoked with an event comprising the
@@ -285,37 +293,36 @@ class << Diff::LCS
285
293
  b_size = seq2.size
286
294
  ai = bj = 0
287
295
 
288
- (0..matches.size).each do |i|
289
- b_line = matches[i]
290
-
291
- ax = string ? seq1[i, 1] : seq1[i]
292
- bx = string ? seq2[bj, 1] : seq2[bj]
293
-
296
+ matches.each do |b_line|
294
297
  if b_line.nil?
295
- unless ax.nil? or (string and ax.empty?)
296
- event = Diff::LCS::ContextChange.new('-', i, ax, bj, bx)
298
+ unless seq1[ai].nil?
299
+ ax = string ? seq1[ai, 1] : seq1[ai]
300
+ bx = string ? seq2[bj, 1] : seq2[bj]
301
+
302
+ event = Diff::LCS::ContextChange.new('-', ai, ax, bj, bx)
297
303
  event = yield event if block_given?
298
304
  callbacks.discard_a(event)
299
305
  end
300
306
  else
307
+ ax = string ? seq1[ai, 1] : seq1[ai]
308
+
301
309
  loop do
302
310
  break unless bj < b_line
303
311
 
304
312
  bx = string ? seq2[bj, 1] : seq2[bj]
305
- event = Diff::LCS::ContextChange.new('+', i, ax, bj, bx)
313
+ event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
306
314
  event = yield event if block_given?
307
315
  callbacks.discard_b(event)
308
316
  bj += 1
309
317
  end
310
318
  bx = string ? seq2[bj, 1] : seq2[bj]
311
- event = Diff::LCS::ContextChange.new('=', i, ax, bj, bx)
319
+ event = Diff::LCS::ContextChange.new('=', ai, ax, bj, bx)
312
320
  event = yield event if block_given?
313
321
  callbacks.match(event)
314
322
  bj += 1
315
323
  end
316
- ai = i
324
+ ai += 1
317
325
  end
318
- ai += 1
319
326
 
320
327
  # The last entry (if any) processed was a match. +ai+ and +bj+ point just
321
328
  # past the last matching lines in their sequences.
@@ -373,14 +380,14 @@ class << Diff::LCS
373
380
  ai += 1
374
381
  end
375
382
 
376
- next unless bj < b_size
377
-
378
- ax = string ? seq1[ai, 1] : seq1[ai]
379
- bx = string ? seq2[bj, 1] : seq2[bj]
380
- event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
381
- event = yield event if block_given?
382
- callbacks.discard_b(event)
383
- bj += 1
383
+ if bj < b_size
384
+ ax = string ? seq1[ai, 1] : seq1[ai]
385
+ bx = string ? seq2[bj, 1] : seq2[bj]
386
+ event = Diff::LCS::ContextChange.new('+', ai, ax, bj, bx)
387
+ event = yield event if block_given?
388
+ callbacks.discard_b(event)
389
+ bj += 1
390
+ end
384
391
  end
385
392
  end
386
393
 
@@ -1,5 +1,5 @@
1
- *** spec/fixtures/aX 2019-02-01 22:29:34.000000000 -0500
2
- --- spec/fixtures/bXaX 2019-02-01 22:29:43.000000000 -0500
1
+ *** spec/fixtures/aX 2020-06-23 11:15:32.000000000 -0400
2
+ --- spec/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400
3
3
  ***************
4
4
  *** 1 ****
5
5
  ! aX
@@ -1,5 +1,5 @@
1
- --- spec/fixtures/aX 2019-02-01 22:29:34.000000000 -0500
2
- +++ spec/fixtures/bXaX 2019-02-01 22:29:43.000000000 -0500
1
+ --- spec/fixtures/aX 2020-06-23 11:15:32.000000000 -0400
2
+ +++ spec/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400
3
3
  @@ -1 +1 @@
4
4
  -aX
5
5
  +bXaX
@@ -0,0 +1,4 @@
1
+ 3c3
2
+ < "description": "hi"
3
+ ---
4
+ > "description": "lo"
@@ -0,0 +1,15 @@
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
3
+ ***************
4
+ *** 1,4 ****
5
+ {
6
+ "name": "x",
7
+ ! "description": "hi"
8
+ }
9
+
10
+ --- 1,4 ----
11
+ {
12
+ "name": "x",
13
+ ! "description": "lo"
14
+ }
15
+
@@ -0,0 +1,3 @@
1
+ 3c
2
+ "description": "lo"
3
+ .
@@ -0,0 +1,3 @@
1
+ c3
2
+ "description": "lo"
3
+ .
@@ -0,0 +1,9 @@
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
3
+ @@ -1,4 +1,4 @@
4
+ {
5
+ "name": "x",
6
+ - "description": "hi"
7
+ + "description": "lo"
8
+ }
9
+
@@ -0,0 +1,7 @@
1
+ 2d1
2
+ < recipe[b::default]
3
+ 14a14,17
4
+ > recipe[o::new]
5
+ > recipe[p::new]
6
+ > recipe[q::new]
7
+ > recipe[r::new]
@@ -0,0 +1,20 @@
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
3
+ ***************
4
+ *** 1,5 ****
5
+ recipe[a::default]
6
+ - recipe[b::default]
7
+ recipe[c::default]
8
+ recipe[d::default]
9
+ recipe[e::default]
10
+ --- 1,4 ----
11
+ ***************
12
+ *** 12,14 ****
13
+ --- 11,17 ----
14
+ recipe[l::default]
15
+ recipe[m::default]
16
+ recipe[n::default]
17
+ + recipe[o::new]
18
+ + recipe[p::new]
19
+ + recipe[q::new]
20
+ + recipe[r::new]
@@ -0,0 +1,7 @@
1
+ d2
2
+ a14
3
+ recipe[o::new]
4
+ recipe[p::new]
5
+ recipe[q::new]
6
+ recipe[r::new]
7
+ .
@@ -0,0 +1,7 @@
1
+ 14a
2
+ recipe[o::new]
3
+ recipe[p::new]
4
+ recipe[q::new]
5
+ recipe[r::new]
6
+ .
7
+ 2d
@@ -0,0 +1,7 @@
1
+ d2
2
+ a14
3
+ recipe[o::new]
4
+ recipe[p::new]
5
+ recipe[q::new]
6
+ recipe[r::new]
7
+ .
@@ -0,0 +1,16 @@
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
3
+ @@ -1,5 +1,4 @@
4
+ recipe[a::default]
5
+ -recipe[b::default]
6
+ recipe[c::default]
7
+ recipe[d::default]
8
+ recipe[e::default]
9
+ @@ -12,3 +11,7 @@
10
+ recipe[l::default]
11
+ recipe[m::default]
12
+ recipe[n::default]
13
+ +recipe[o::new]
14
+ +recipe[p::new]
15
+ +recipe[q::new]
16
+ +recipe[r::new]
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "x",
3
+ "description": "lo"
4
+ }
@@ -0,0 +1,17 @@
1
+ recipe[a::default]
2
+ recipe[c::default]
3
+ recipe[d::default]
4
+ recipe[e::default]
5
+ recipe[f::default]
6
+ recipe[g::default]
7
+ recipe[h::default]
8
+ recipe[i::default]
9
+ recipe[j::default]
10
+ recipe[k::default]
11
+ recipe[l::default]
12
+ recipe[m::default]
13
+ recipe[n::default]
14
+ recipe[o::new]
15
+ recipe[p::new]
16
+ recipe[q::new]
17
+ recipe[r::new]
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "x",
3
+ "description": "hi"
4
+ }
@@ -0,0 +1,14 @@
1
+ recipe[a::default]
2
+ recipe[b::default]
3
+ recipe[c::default]
4
+ recipe[d::default]
5
+ recipe[e::default]
6
+ recipe[f::default]
7
+ recipe[g::default]
8
+ recipe[h::default]
9
+ recipe[i::default]
10
+ recipe[j::default]
11
+ recipe[k::default]
12
+ recipe[l::default]
13
+ recipe[m::default]
14
+ recipe[n::default]
data/spec/hunk_spec.rb CHANGED
@@ -6,28 +6,39 @@ if String.method_defined?(:encoding)
6
6
  require 'diff/lcs/hunk'
7
7
 
8
8
  describe Diff::LCS::Hunk do
9
- let(:old_data) { ['Tu avec carté {count} itém has'.encode('UTF-16LE')] }
10
- let(:new_data) { ['Tu avec carte {count} item has'.encode('UTF-16LE')] }
9
+ let(:old_data) { ['Tu a un carté avec {count} itéms'.encode('UTF-16LE')] }
10
+ let(:new_data) { ['Tu a un carte avec {count} items'.encode('UTF-16LE')] }
11
11
  let(:pieces) { Diff::LCS.diff old_data, new_data }
12
12
  let(:hunk) { Diff::LCS::Hunk.new(old_data, new_data, pieces[0], 3, 0) }
13
13
 
14
14
  it 'produces a unified diff from the two pieces' do
15
15
  expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
16
16
  @@ -1 +1 @@
17
- -Tu avec carté {count} itém has
18
- +Tu avec carte {count} item has
17
+ -Tu a un carté avec {count} itéms
18
+ +Tu a un carte avec {count} items
19
19
  EXPECTED
20
20
 
21
21
  expect(hunk.diff(:unified)).to eq(expected)
22
22
  end
23
23
 
24
+ it 'produces a unified diff from the two pieces (last entry)' do
25
+ expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
26
+ @@ -1 +1 @@
27
+ -Tu a un carté avec {count} itéms
28
+ +Tu a un carte avec {count} items
29
+ \
30
+ EXPECTED
31
+
32
+ expect(hunk.diff(:unified, true)).to eq(expected)
33
+ end
34
+
24
35
  it 'produces a context diff from the two pieces' do
25
36
  expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
26
37
  ***************
27
38
  *** 1 ****
28
- ! Tu avec carté {count} itém has
39
+ ! Tu a un carté avec {count} itéms
29
40
  --- 1 ----
30
- ! Tu avec carte {count} item has
41
+ ! Tu a un carte avec {count} items
31
42
  EXPECTED
32
43
 
33
44
  expect(hunk.diff(:context)).to eq(expected)
@@ -36,9 +47,9 @@ if String.method_defined?(:encoding)
36
47
  it 'produces an old diff from the two pieces' do
37
48
  expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp
38
49
  1c1
39
- < Tu avec carté {count} itém has
50
+ < Tu a un carté avec {count} itéms
40
51
  ---
41
- > Tu avec carte {count} item has
52
+ > Tu a un carte avec {count} items
42
53
 
43
54
  EXPECTED
44
55
 
@@ -48,7 +59,7 @@ if String.method_defined?(:encoding)
48
59
  it 'produces a reverse ed diff from the two pieces' do
49
60
  expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp
50
61
  c1
51
- Tu avec carte {count} item has
62
+ Tu a un carte avec {count} items
52
63
  .
53
64
 
54
65
  EXPECTED
@@ -62,7 +73,7 @@ if String.method_defined?(:encoding)
62
73
  it 'produces a unified diff' do
63
74
  expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
64
75
  @@ -1 +1,2 @@
65
- +Tu avec carte {count} item has
76
+ +Tu a un carte avec {count} items
66
77
  EXPECTED
67
78
 
68
79
  expect(hunk.diff(:unified)).to eq(expected)
data/spec/issues_spec.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
+ require 'diff/lcs/hunk'
4
5
 
5
6
  describe 'Diff::LCS Issues' do
6
7
  include Diff::LCS::SpecHelper::Matchers
@@ -55,13 +56,99 @@ describe 'Diff::LCS Issues' do
55
56
  end
56
57
  end
57
58
 
58
- describe "issue #57" do
59
+ describe 'issue #57' do
59
60
  it 'should fail with a correct error' do
60
61
  expect {
61
- actual = {:category=>"app.rack.request"}
62
- expected = {:category=>"rack.middleware", :title=>"Anonymous Middleware"}
62
+ actual = { :category => 'app.rack.request' }
63
+ expected = { :category => 'rack.middleware', :title => 'Anonymous Middleware' }
63
64
  expect(actual).to eq(expected)
64
65
  }.to raise_error(RSpec::Expectations::ExpectationNotMetError)
65
66
  end
66
67
  end
68
+
69
+ describe 'issue #60' do
70
+ it 'should produce unified output with correct context' do
71
+ old_data = <<-DATA_OLD.strip.split("\n").map(&:chomp)
72
+ {
73
+ "name": "x",
74
+ "description": "hi"
75
+ }
76
+ DATA_OLD
77
+
78
+ new_data = <<-DATA_NEW.strip.split("\n").map(&:chomp)
79
+ {
80
+ "name": "x",
81
+ "description": "lo"
82
+ }
83
+ DATA_NEW
84
+
85
+ diff = ::Diff::LCS.diff(old_data, new_data)
86
+ hunk = ::Diff::LCS::Hunk.new(old_data, new_data, diff.first, 3, 0)
87
+
88
+ expect(hunk.diff(:unified)).to eq(<<-EXPECTED.chomp)
89
+ @@ -1,5 +1,5 @@
90
+ {
91
+ "name": "x",
92
+ - "description": "hi"
93
+ + "description": "lo"
94
+ }
95
+ EXPECTED
96
+ end
97
+ end
98
+
99
+ describe 'issue #65' do
100
+ def diff_lines(old_lines, new_lines)
101
+ file_length_difference = 0
102
+ previous_hunk = nil
103
+ output = []
104
+
105
+ Diff::LCS.diff(old_lines, new_lines).each do |piece|
106
+ hunk = Diff::LCS::Hunk.new(old_lines, new_lines, piece, 3, file_length_difference)
107
+ file_length_difference = hunk.file_length_difference
108
+ maybe_contiguous_hunks = (previous_hunk.nil? || hunk.merge(previous_hunk))
109
+
110
+ output << "#{previous_hunk.diff(:unified)}\n" unless maybe_contiguous_hunks
111
+
112
+ previous_hunk = hunk
113
+ end
114
+ output << "#{previous_hunk.diff(:unified, true)}\n" unless previous_hunk.nil?
115
+ output.join
116
+ end
117
+
118
+ it 'should not misplace the new chunk' do
119
+ old_data = [
120
+ 'recipe[a::default]', 'recipe[b::default]', 'recipe[c::default]',
121
+ 'recipe[d::default]', 'recipe[e::default]', 'recipe[f::default]',
122
+ 'recipe[g::default]', 'recipe[h::default]', 'recipe[i::default]',
123
+ 'recipe[j::default]', 'recipe[k::default]', 'recipe[l::default]',
124
+ 'recipe[m::default]', 'recipe[n::default]'
125
+ ]
126
+
127
+ new_data = [
128
+ 'recipe[a::default]', 'recipe[c::default]', 'recipe[d::default]',
129
+ 'recipe[e::default]', 'recipe[f::default]', 'recipe[g::default]',
130
+ 'recipe[h::default]', 'recipe[i::default]', 'recipe[j::default]',
131
+ 'recipe[k::default]', 'recipe[l::default]', 'recipe[m::default]',
132
+ 'recipe[n::default]', 'recipe[o::new]', 'recipe[p::new]',
133
+ 'recipe[q::new]', 'recipe[r::new]'
134
+ ]
135
+
136
+ expect(diff_lines(old_data, new_data)).to eq(<<-EODIFF)
137
+ @@ -1,5 +1,4 @@
138
+ recipe[a::default]
139
+ -recipe[b::default]
140
+ recipe[c::default]
141
+ recipe[d::default]
142
+ recipe[e::default]
143
+ @@ -12,3 +11,7 @@
144
+ recipe[l::default]
145
+ recipe[m::default]
146
+ recipe[n::default]
147
+ +recipe[o::new]
148
+ +recipe[p::new]
149
+ +recipe[q::new]
150
+ +recipe[r::new]
151
+ EODIFF
152
+ end
153
+ end
67
154
  end
data/spec/ldiff_spec.rb CHANGED
@@ -5,34 +5,41 @@ require 'spec_helper'
5
5
  RSpec.describe 'bin/ldiff' do
6
6
  include CaptureSubprocessIO
7
7
 
8
- let(:output_diff) { read_fixture }
9
- let(:output_diff_c) { read_fixture('-c') }
10
- let(:output_diff_e) { read_fixture('-e') }
11
- let(:output_diff_f) { read_fixture('-f') }
12
- let(:output_diff_u) { read_fixture('-u') }
8
+ fixtures = [
9
+ { :name => 'output.diff', :left => 'aX', :right => 'bXaX' },
10
+ { :name => 'output.diff.chef', :left => 'old-chef', :right => 'new-chef' },
11
+ { :name => 'output.diff.chef2', :left => 'old-chef2', :right => 'new-chef2' }
12
+ ].product([nil, '-e', '-f', '-c', '-u']).map { |(fixture, flag)|
13
+ fixture = fixture.dup
14
+ fixture[:flag] = flag
15
+ fixture
16
+ }
13
17
 
14
- specify do
15
- expect(run_ldiff).to eq(output_diff)
16
- end
17
-
18
- specify do
19
- expect(run_ldiff('-c')).to eq(output_diff_c)
20
- end
21
-
22
- specify do
23
- expect(run_ldiff('-e')).to eq(output_diff_e)
24
- end
18
+ def self.test_ldiff(fixture)
19
+ desc = [
20
+ fixture[:flag],
21
+ "spec/fixtures/#{fixture[:left]}",
22
+ "spec/fixtures/#{fixture[:right]}",
23
+ '#',
24
+ '=>',
25
+ "spec/fixtures/ldiff/#{fixture[:name]}#{fixture[:flag]}"
26
+ ].join(' ')
25
27
 
26
- specify do
27
- expect(run_ldiff('-f')).to eq(output_diff_f)
28
+ it desc do
29
+ expect(run_ldiff(fixture)).to eq(read_fixture(fixture))
30
+ end
28
31
  end
29
32
 
30
- specify do
31
- expect(run_ldiff('-u')).to eq(output_diff_u)
33
+ fixtures.each do |fixture|
34
+ test_ldiff(fixture)
32
35
  end
33
36
 
34
- def read_fixture(flag = nil)
35
- clean_data(IO.binread("spec/fixtures/ldiff/output.diff#{flag}"), flag)
37
+ def read_fixture(options)
38
+ fixture = options.fetch(:name)
39
+ flag = options.fetch(:flag)
40
+ name = "spec/fixtures/ldiff/#{fixture}#{flag}"
41
+ data = IO.__send__(IO.respond_to?(:binread) ? :binread : :read, name)
42
+ clean_data(data, flag)
36
43
  end
37
44
 
38
45
  def clean_data(data, flag)
@@ -49,25 +56,31 @@ RSpec.describe 'bin/ldiff' do
49
56
  def clean_output_timestamp(data)
50
57
  data.gsub(
51
58
  %r{
52
- [-*+]{3}
53
- \s
54
- spec/fixtures/(\w+)
55
- \s
59
+ ^
60
+ [-+*]{3}
61
+ \s*
62
+ spec/fixtures/(\S+)
63
+ \s*
56
64
  \d{4}-\d\d-\d\d
57
- \s
65
+ \s*
58
66
  \d\d:\d\d:\d\d(?:\.\d+)
59
- \s
67
+ \s*
60
68
  (?:[-+]\d{4}|Z)
61
69
  }x,
62
- '*** spec/fixtures/\1 0000-00-00 00:00:00.000000000 -0000'
70
+ '*** spec/fixtures/\1 0000-00-00 :00 =>:00 =>00.000000000 -0000'
63
71
  )
64
72
  end
65
73
 
66
- def run_ldiff(flag = nil, left: 'aX', right: 'bXaX')
74
+ def run_ldiff(options)
75
+ flag = options.fetch(:flag)
76
+ left = options.fetch(:left)
77
+ right = options.fetch(:right)
78
+
67
79
  stdout, stderr = capture_subprocess_io do
68
80
  system("ruby -Ilib bin/ldiff #{flag} spec/fixtures/#{left} spec/fixtures/#{right}")
69
81
  end
70
- expect(stderr).to be_empty
82
+
83
+ expect(stderr).to be_empty if RUBY_VERSION >= '1.9'
71
84
  expect(stdout).not_to be_empty
72
85
  clean_data(stdout, flag)
73
86
  end