/usr/lib/ruby/vendor_ruby/unit_diff.rb is in ruby-zentest 4.11.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | require 'tempfile'
require 'rbconfig'
##
# UnitDiff makes reading Test::Unit output easy and fun. Instead of a
# confusing jumble of text with nearly unnoticable changes like this:
#
# 1) Failure:
# test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
# <"new GPolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
# 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
# -123.00000)])"> expected but was
# <"new Gpolyline([\n new GPoint( 47.00000, -122.00000),\n new GPoint( 46.5000
# 0, -122.50000),\n new GPoint( 46.75000, -122.75000),\n new GPoint( 46.00000,
# -123.00000)])">.
#
#
# You get an easy-to-read diff output like this:
#
# 1) Failure:
# test_to_gpoints(RouteTest) [test/unit/route_test.rb:29]:
# 1c1
# < new GPolyline([
# ---
# > new Gpolyline([
#
# == Usage
#
# test.rb | unit_diff [options]
# options:
# -b ignore whitespace differences
# -c contextual diff
# -h show usage
# -k keep temp diff files around
# -l prefix line numbers on the diffs
# -u unified diff [default]
# -p plain diff
# -v display version
class UnitDiff
WINDOZE = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
DIFF = if WINDOZE
'diff.exe'
else
if system("gdiff", __FILE__, __FILE__)
'gdiff' # solaris and kin suck
else
'diff'
end
end unless defined? DIFF
##
# Handy wrapper for UnitDiff#unit_diff.
def self.unit_diff
trap 'INT' do exit 1 end
puts UnitDiff.new.unit_diff
end
def parse_input(input, output)
current = []
data = []
data << current
print_lines = true
term = "\nFinished".split(//).map { |c| c[0] }
term_length = term.size
old_sync = output.sync
output.sync = true
while line = input.gets
case line
when /^(Loaded suite|Started|# Running tests:)/ then
print_lines = true
output.puts line
chars = []
while c = input.getc do
output.putc c
chars << c
tail = chars[-term_length..-1]
break if chars.size >= term_length and tail == term
end
output.puts input.gets # the rest of "Finished in..."
output.puts
next
when /^\s*$/, /^\(?\s*\d+\) (Failure|Error):/, /^\d+\)/ then
print_lines = false
current = []
data << current
when /^Finished in \d/ then
print_lines = false
end
output.puts line if print_lines
current << line
end
output.sync = old_sync
data = data.reject { |o| o == ["\n"] or o.empty? }
footer = data.pop
data.map do |result|
break if result.any? { |l| l =~ / expected( but was|, not)/ }
header = result.find do |l|
l =~ /^\(?\s*\d+\) (Failure|Error):/
end
break unless header
message_index = result.index(header) + 2
result[message_index..-1] = result[message_index..-1].join
end
return data, footer
end
# Parses a single diff recording the header and what
# was expected, and what was actually obtained.
def parse_diff(result)
header = []
expect = []
butwas = []
footer = []
state = :header
until result.empty? do
case state
when :header then
header << result.shift
state = :expect if result.first =~ /^<|^Expected/
when :expect then
case result.first
when /^Expected (.*?) to equal (.*?):$/ then
expect << $1
butwas << $2
state = :footer
result.shift
when /^Expected (.*?), not (.*)$/m then
expect << $1
butwas << $2
state = :footer
result.shift
when /^Expected (.*?)$/ then
expect << "#{$1}\n"
result.shift
when /^to equal / then
state = :spec_butwas
bw = result.shift.sub(/^to equal (.*):?$/, '\1')
butwas << bw
else
state = :butwas if result.first.sub!(/ expected( but was|, not)/, '')
expect << result.shift
end
when :butwas then
butwas = result[0..-1]
result.clear
when :spec_butwas then
if result.first =~ /^\s+\S+ at |^:\s*$/
state = :footer
else
butwas << result.shift
end
when :footer then
butwas.last.sub!(/:$/, '')
footer = result.map {|l| l.chomp }
result.clear
else
raise "unknown state #{state}"
end
end
return header, expect, nil, footer if butwas.empty?
expect.last.chomp!
expect.first.sub!(/^<\"/, '')
expect.last.sub!(/\">$/, '')
butwas.last.chomp!
butwas.last.chop! if butwas.last =~ /\.$/
butwas.first.sub!( /^<\"/, '')
butwas.last.sub!(/\">$/, '')
return header, expect, butwas, footer
end
##
# Scans Test::Unit output +input+ looking for comparison failures and makes
# them easily readable by passing them through diff.
def unit_diff(input=ARGF, output=$stdout)
$b = false unless defined? $b
$c = false unless defined? $c
$k = false unless defined? $k
$u = true unless defined? $u
$p = false unless defined? $p
data, footer = self.parse_input(input, output)
output = []
# Output
data.each do |result|
if result.first =~ /Error/ then
output.push result.join('')
next
end
prefix, expect, butwas, result_footer = parse_diff(result)
output.push prefix.compact.map {|line| line.strip}.join("\n")
if butwas then
output.push self.diff(expect, butwas)
output.push result_footer
output.push ''
else
output.push expect.join('')
end
end
if footer then
footer.shift if footer.first.strip.empty?
output.push footer.compact.map {|line| line.strip}.join("\n")
end
return output.flatten.join("\n")
end
def diff expect, butwas
output = nil
Tempfile.open("expect") do |a|
a.write(massage(expect))
a.rewind
Tempfile.open("butwas") do |b|
b.write(massage(butwas))
b.rewind
diff_flags = $p ? "" : $c ? "-c" : "-u"
diff_flags += " -b" if $b
result = `#{DIFF} #{diff_flags} #{a.path} #{b.path}`
result.sub!(/^\-\-\- .+/, "--- expected")
result.sub!(/^\+\+\+ .+/, "+++ actual")
output = if result.empty? then
"[no difference--suspect ==]"
else
result.split(/\n/)
end
if $k then
warn "moving #{a.path} to #{a.path}.keep"
File.rename a.path, a.path + ".keep"
warn "moving #{b.path} to #{b.path}.keep"
File.rename b.path, b.path + ".keep"
end
end
end
output
end
def massage(data)
# unescape newlines, strip <> from entire string
data = data.join
data = data.gsub(/\\n/, "\n").gsub(/0x[a-f0-9]+/m, '0xXXXXXX') + "\n"
data += "\n" unless data[-1] == ?\n
data
end
end
|