diff-lcs 1.4.1 → 1.5.0

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