363 lines
8.1 KiB
Ruby
Executable File
363 lines
8.1 KiB
Ruby
Executable File
#!/usr/local/bin/ruby
|
|
#----------------------------------------------------------------------
|
|
# run-regression.rb
|
|
#----------------------------------------------------------------------
|
|
# Copyright (c) 2007-2012 by Johan Holmberg. All rights reserved.
|
|
#----------------------------------------------------------------------
|
|
# @(#) $Id$
|
|
#----------------------------------------------------------------------
|
|
|
|
require "rbconfig"
|
|
require "dbm"
|
|
require "digest/md5"
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
TMPFILES = [
|
|
"tmp-cmdtest-2",
|
|
"tmp-cmdtest-2/tmp-command.sh",
|
|
"tmp-cmdtest-2/tmp-stderr.log",
|
|
"tmp-cmdtest-2/tmp-stdout.log",
|
|
"tmp-cmdtest-2/workdir",
|
|
"tmp-cmdtest-2/workdir/TIMESTAMP"
|
|
]
|
|
|
|
class ActualTcRegression
|
|
|
|
def initialize
|
|
@count = 0
|
|
@f = File.open("TC_actual-regression.rb", "w")
|
|
|
|
@f.puts [
|
|
"class TC_cmdtest < Cmdtest::Testcase",
|
|
"",
|
|
" def setup",
|
|
TMPFILES.map {|file| " ignore_file #{file.inspect}" },
|
|
" end",
|
|
"",
|
|
]
|
|
|
|
end
|
|
|
|
def _list_elements(level, lines)
|
|
lines.map do |line|
|
|
" " * level + line.inspect + ","
|
|
end
|
|
end
|
|
|
|
def _indent(level, lines)
|
|
lines.map do |line|
|
|
" " * level + line
|
|
end
|
|
end
|
|
|
|
def _gen_count
|
|
@count += 1
|
|
end
|
|
|
|
def _comment_str(lines)
|
|
lines.each do |line|
|
|
if line =~ /^#/ # ..
|
|
res = line.sub(/^#\s*/, "")
|
|
return res
|
|
end
|
|
end
|
|
return "no comment given"
|
|
end
|
|
|
|
def add(prefix, code, stdout)
|
|
@f.puts [
|
|
" def test_#{_gen_count}",
|
|
" create_file \"TC_tmp.rb\", [",
|
|
" 'class TC_cmdtest < Cmdtest::Testcase',",
|
|
" ' def test_foo',",
|
|
_list_elements(3, _indent(2, prefix)),
|
|
_list_elements(3, _indent(2, code)),
|
|
" ' end',",
|
|
" 'end',",
|
|
" ]",
|
|
"",
|
|
" cmd 'cmdtest.rb --quiet' do",
|
|
" comment #{_comment_str(code).inspect}",
|
|
" stdout_equal [",
|
|
_list_elements(4, stdout),
|
|
" ]",
|
|
" end",
|
|
" end",
|
|
"",
|
|
].flatten
|
|
end
|
|
|
|
def write
|
|
@f.puts [
|
|
"",
|
|
"end",
|
|
"",
|
|
]
|
|
|
|
@f.close
|
|
end
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
class ActualRegression
|
|
|
|
def initialize
|
|
@o2 = ActualTcRegression.new
|
|
|
|
@f = File.open("actual-regression.rb", "w")
|
|
end
|
|
|
|
def add(prefix, code, stdout)
|
|
prefix = prefix.map {|line| line.chomp }
|
|
code = code .map {|line| line.chomp }
|
|
stdout = stdout.map {|line| line.to_s.chomp }
|
|
|
|
@o2.add(prefix,code,stdout)
|
|
|
|
@f.puts prefix
|
|
@f.puts "#" + "-" * 35
|
|
@f.puts code
|
|
@f.puts "# stdout begin"
|
|
@f.puts stdout.map {|line| "# %s" % [line] }
|
|
@f.puts "# stdout end"
|
|
end
|
|
|
|
def write
|
|
@o2.write
|
|
|
|
@f.close
|
|
end
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
class RegressionData
|
|
|
|
def initialize(files)
|
|
@lines = files.map {|file| File.readlines(file) }.flatten
|
|
@i = 0
|
|
end
|
|
|
|
def eof?
|
|
j = @i
|
|
while j < @lines.size && @lines[j].strip.empty?
|
|
j += 1
|
|
end
|
|
return j >= @lines.size
|
|
end
|
|
|
|
def skip_to(pattern)
|
|
# ignore return value
|
|
get_to(pattern)
|
|
end
|
|
|
|
def _show_line(i)
|
|
puts "%d: %s" % [
|
|
i,
|
|
@lines[i],
|
|
]
|
|
end
|
|
|
|
def get_to(pattern)
|
|
res = []
|
|
i1 = @i
|
|
while ! eof? && @lines[@i] !~ pattern
|
|
_show_line(@i) if $opt_verbose
|
|
res << @lines[@i]
|
|
@i += 1
|
|
end
|
|
if eof?
|
|
puts "Error: looking at:"
|
|
_show_line(i1)
|
|
raise "eof looking for #{pattern}"
|
|
end
|
|
# get past matching line
|
|
@i += 1
|
|
return res
|
|
end
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
SystemResult = Struct.new(:status, :stdout, :stderr)
|
|
|
|
def my_system(cmd)
|
|
full_cmd = "#{cmd} > tmp-stdout 2> tmp-stderr"
|
|
#puts "+ #{full_cmd}"
|
|
ok = system full_cmd
|
|
status = $?.exitstatus
|
|
stdout = File.readlines("tmp-stdout")
|
|
stderr = File.readlines("tmp-stderr")
|
|
if status != 0
|
|
puts "INTERNAL ERROR:"
|
|
puts "STDOUT:"
|
|
puts stdout
|
|
puts "STDERR:"
|
|
puts stderr
|
|
exit 1
|
|
end
|
|
#p [:my_system, cmd, status, stdout, stderr]
|
|
return SystemResult.new(status, stdout, stderr)
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
def indented(lines)
|
|
lines.map {|line| " " + line.to_s }
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
def indent_lines(level, lines)
|
|
lines.map do |line|
|
|
" " * level + line
|
|
end
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
def matching_arrays(a,b)
|
|
return false if a.size != b.size
|
|
a.each_index do |i|
|
|
return false unless a[i] === b[i]
|
|
end
|
|
return true
|
|
end
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
$opt_verbose = false
|
|
$opt_only = nil
|
|
$opt_remember = false
|
|
|
|
while /^-/ =~ ARGV[0]
|
|
arg = ARGV.shift
|
|
case arg
|
|
when "-v"
|
|
$opt_verbose = true
|
|
when "-r"
|
|
$opt_remember = true
|
|
when /^--only=(\d+)$/
|
|
$opt_only = $1.to_i
|
|
else
|
|
puts "Error: unknown option: #{arg}"
|
|
exit 1
|
|
end
|
|
end
|
|
|
|
path_dirs = [ File.expand_path("t/bin") ]
|
|
if RUBY_PLATFORM =~ /mswin/
|
|
path_dirs.unshift File.expand_path("t/bin/windows")
|
|
else
|
|
path_dirs.unshift File.expand_path("t/bin/unix")
|
|
end
|
|
|
|
ENV["PATH"] = [
|
|
path_dirs,
|
|
ENV["PATH"]
|
|
].join(Config::CONFIG["PATH_SEPARATOR"])
|
|
|
|
files = ARGV.empty? ? Dir.glob("t/*.rb") : ARGV
|
|
rd = RegressionData.new(files)
|
|
|
|
tests = []
|
|
|
|
while ! rd.eof?
|
|
prefix = rd.get_to( /^#----------/ )
|
|
code = rd.get_to( /^# stdout begin/ )
|
|
stdout = rd.get_to( /^# stdout end/ ).map do |line|
|
|
if line =~ /^# (.*\n)/ #..
|
|
$1
|
|
elsif line =~ /^#\/(.*)/ #..
|
|
Regexp.new($1)
|
|
else
|
|
line # should not occur
|
|
end
|
|
end
|
|
tests << [prefix, code, stdout]
|
|
end
|
|
|
|
puts "###"
|
|
puts "### found %d tests in file." % [tests.size]
|
|
puts "###"
|
|
|
|
act = ActualRegression.new
|
|
|
|
already_ok = DBM.open("already_ok")
|
|
if ! $opt_remember
|
|
already_ok.clear
|
|
end
|
|
|
|
errors = 0
|
|
iii = -1
|
|
for prefix, code, stdout in tests
|
|
iii += 1
|
|
next if $opt_only && iii != $opt_only
|
|
|
|
digest = Digest::MD5.hexdigest([prefix,code,stdout].flatten.join)
|
|
if already_ok.has_key?(digest)
|
|
#puts "### #{iii}: %s ... [[cahced]]" % [code[0].chomp]
|
|
next
|
|
end
|
|
|
|
code_str = code.join("\n")
|
|
if code_str =~ /REQUIRE: \s+ (.*)/x
|
|
expr = $1
|
|
if ! eval(expr)
|
|
puts "### #{iii}: SKIP: %s: %s ..." % [expr, code[0].chomp]
|
|
act.add(prefix, code, stdout)
|
|
next
|
|
end
|
|
end
|
|
|
|
puts "### #{iii}: %s ..." % [code[0].chomp]
|
|
|
|
lines = []
|
|
#lines << "require 'Test/Cmd'"
|
|
lines << ""
|
|
lines << "class TC_foo < Cmdtest::Testcase"
|
|
lines << ""
|
|
lines << " def test_foo"
|
|
lines << indent_lines(2, code)
|
|
lines << " end"
|
|
lines << ""
|
|
lines << "end"
|
|
lines << ""
|
|
lines.flatten!
|
|
|
|
File.open("CMDTEST_tmp_regression.rb", "w") do |f|
|
|
f.puts lines
|
|
end
|
|
|
|
res = my_system "ruby -w bin/cmdtest.rb --no-exit-code --quiet --ruby_s CMDTEST_tmp_regression.rb"
|
|
if res.status != 0
|
|
puts "ERROR: non-zero exit from:"
|
|
puts lines
|
|
exit 1
|
|
end
|
|
if matching_arrays(stdout, res.stdout)
|
|
already_ok[digest] = true
|
|
else
|
|
puts "ERROR: unexpected STDOUT:"
|
|
puts "ACTUAL:"
|
|
puts indented(res.stdout)
|
|
puts "EXPECTED:"
|
|
puts indented(stdout)
|
|
errors += 1
|
|
end
|
|
|
|
act.add(prefix, code, res.stdout)
|
|
end
|
|
|
|
act.write
|
|
|
|
puts
|
|
if errors == 0
|
|
puts "### all tests OK"
|
|
else
|
|
puts "--- error in #{errors} tests"
|
|
end
|
|
puts
|