xref: /freebsd/tools/regression/usr.bin/env/regress-sb.rb (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
16cc00fe2SGarance A Drosehn#!/usr/local/bin/ruby
26cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
36cc00fe2SGarance A Drosehn# Copyright (c) 2005  - Garance Alistair Drosehn <gad@FreeBSD.org>.
46cc00fe2SGarance A Drosehn# All rights reserved.
56cc00fe2SGarance A Drosehn#
66cc00fe2SGarance A Drosehn#  Redistribution and use in source and binary forms, with or without
76cc00fe2SGarance A Drosehn#  modification, are permitted provided that the following conditions
86cc00fe2SGarance A Drosehn#  are met:
96cc00fe2SGarance A Drosehn#  1. Redistributions of source code must retain the above copyright
106cc00fe2SGarance A Drosehn#     notice, this list of conditions and the following disclaimer.
116cc00fe2SGarance A Drosehn#  2. Redistributions in binary form must reproduce the above copyright
126cc00fe2SGarance A Drosehn#     notice, this list of conditions and the following disclaimer in the
136cc00fe2SGarance A Drosehn#     documentation and/or other materials provided with the distribution.
146cc00fe2SGarance A Drosehn#
156cc00fe2SGarance A Drosehn#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
166cc00fe2SGarance A Drosehn#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176cc00fe2SGarance A Drosehn#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186cc00fe2SGarance A Drosehn#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196cc00fe2SGarance A Drosehn#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
206cc00fe2SGarance A Drosehn#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
216cc00fe2SGarance A Drosehn#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226cc00fe2SGarance A Drosehn#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
236cc00fe2SGarance A Drosehn#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246cc00fe2SGarance A Drosehn#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
256cc00fe2SGarance A Drosehn#  SUCH DAMAGE.
266cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
276cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
286cc00fe2SGarance A Drosehn#   This script was written to provide a battery of regression-tests for some
296cc00fe2SGarance A Drosehn# changes I am making to the `env' command.  I wrote a new script for this
306cc00fe2SGarance A Drosehn# for several reasons.  1) I needed to test all kinds of special-character
316cc00fe2SGarance A Drosehn# combinations, and I wanted to be able to type those in exactly as they would
326cc00fe2SGarance A Drosehn# would be in real-life situations.  2) I wanted to set environment variables
336cc00fe2SGarance A Drosehn# before executing a test, 3) I had many different details to test, so I wanted
346cc00fe2SGarance A Drosehn# to write up dozens of tests, without needing to create a hundred separate
356cc00fe2SGarance A Drosehn# little tiny files, 4) I wanted to test *failure* conditions, where I expected
366cc00fe2SGarance A Drosehn# the test would fail but I wanted to be sure that it failed the way I intended
376cc00fe2SGarance A Drosehn# it to fail.
386cc00fe2SGarance A Drosehn#   This script was written for the special "shebang-line" testing that I
396cc00fe2SGarance A Drosehn# wanted for my changes to `env', but I expect it could be turned into a
406cc00fe2SGarance A Drosehn# general-purpose test-suite with a little more work.
416cc00fe2SGarance A Drosehn#							Garance/June 12/2005
426cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
436cc00fe2SGarance A Drosehn
446cc00fe2SGarance A Drosehn
456cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
466cc00fe2SGarance A Drosehnclass ExpectedResult
476cc00fe2SGarance A Drosehn    attr_writer :cmdvalue, :shebang_args, :user_args
486cc00fe2SGarance A Drosehn    @@gbl_envs = Hash.new
496cc00fe2SGarance A Drosehn
506cc00fe2SGarance A Drosehn    def ExpectedResult.add_gblenv(avar, avalue)
516cc00fe2SGarance A Drosehn	@@gbl_envs[avar] = avalue
526cc00fe2SGarance A Drosehn    end
536cc00fe2SGarance A Drosehn
546cc00fe2SGarance A Drosehn    def initialize
556cc00fe2SGarance A Drosehn	@shebang_args = ""
566cc00fe2SGarance A Drosehn	@cmdvalue = 0
576cc00fe2SGarance A Drosehn	@clear_envs = Hash.new
586cc00fe2SGarance A Drosehn	@new_envs = Hash.new
596cc00fe2SGarance A Drosehn	@old_envs = Hash.new
606cc00fe2SGarance A Drosehn	@script_lines = ""
616cc00fe2SGarance A Drosehn	@expect_err = Array.new
626cc00fe2SGarance A Drosehn	@expect_out = Array.new
636cc00fe2SGarance A Drosehn	@symlinks = Array.new
646cc00fe2SGarance A Drosehn	@user_args = nil
656cc00fe2SGarance A Drosehn    end
666cc00fe2SGarance A Drosehn
676cc00fe2SGarance A Drosehn    def add_expecterr(aline)
686cc00fe2SGarance A Drosehn	@expect_err << aline
696cc00fe2SGarance A Drosehn    end
706cc00fe2SGarance A Drosehn
716cc00fe2SGarance A Drosehn    def add_expectout(aline)
726cc00fe2SGarance A Drosehn	@expect_out << aline
736cc00fe2SGarance A Drosehn    end
746cc00fe2SGarance A Drosehn
756cc00fe2SGarance A Drosehn    def add_script(aline)
766cc00fe2SGarance A Drosehn	@script_lines += aline
776cc00fe2SGarance A Drosehn	@script_lines += "\n"	if aline[-1] != "\n"
786cc00fe2SGarance A Drosehn    end
796cc00fe2SGarance A Drosehn
806cc00fe2SGarance A Drosehn    def add_clearenv(avar)
816cc00fe2SGarance A Drosehn	@clear_envs[avar] = true
826cc00fe2SGarance A Drosehn    end
836cc00fe2SGarance A Drosehn
846cc00fe2SGarance A Drosehn    def add_setenv(avar, avalue)
856cc00fe2SGarance A Drosehn	@new_envs[avar] = avalue
866cc00fe2SGarance A Drosehn    end
876cc00fe2SGarance A Drosehn
886cc00fe2SGarance A Drosehn    def add_symlink(srcf, newf)
896cc00fe2SGarance A Drosehn	@symlinks << Array.[](srcf, newf)
906cc00fe2SGarance A Drosehn    end
916cc00fe2SGarance A Drosehn
926cc00fe2SGarance A Drosehn    def check_out(name, fname, expect_arr)
936cc00fe2SGarance A Drosehn	idx = -1
946cc00fe2SGarance A Drosehn	all_matched = true
956cc00fe2SGarance A Drosehn	extra_lines = 0
966cc00fe2SGarance A Drosehn	rdata = File.open(fname)
976cc00fe2SGarance A Drosehn	rdata.each_line { |rline|
986cc00fe2SGarance A Drosehn	    rline.chomp!
996cc00fe2SGarance A Drosehn	    idx += 1
1006cc00fe2SGarance A Drosehn	    if idx > expect_arr.length - 1
1016cc00fe2SGarance A Drosehn		if extra_lines == 0 and $verbose >= 1
1026cc00fe2SGarance A Drosehn		    printf "--   Extra line(s) on %s:\n", name
1036cc00fe2SGarance A Drosehn		end
1046cc00fe2SGarance A Drosehn		printf "--    [%d] > %s\n", idx, rline if $verbose >= 1
1056cc00fe2SGarance A Drosehn		extra_lines += 1
1066cc00fe2SGarance A Drosehn	    elsif rline != expect_arr[idx]
1076cc00fe2SGarance A Drosehn		if all_matched and $verbose >= 1
1086cc00fe2SGarance A Drosehn		    printf "--   Mismatched line(s) on %s:\n", name
1096cc00fe2SGarance A Drosehn		end
1106cc00fe2SGarance A Drosehn		printf "--    [%d] < %s\n", idx, expect_arr[idx] if $verbose >= 2
1116cc00fe2SGarance A Drosehn		printf "--        > %s\n", rline if $verbose >= 1
1126cc00fe2SGarance A Drosehn		all_matched = false
1136cc00fe2SGarance A Drosehn	    else
1146cc00fe2SGarance A Drosehn		printf "--    %s[%d] = %s\n", name, idx, rline if $verbose >= 5
1156cc00fe2SGarance A Drosehn	    end
1166cc00fe2SGarance A Drosehn	}
1176cc00fe2SGarance A Drosehn	rdata.close
1186cc00fe2SGarance A Drosehn	if extra_lines > 0
1196cc00fe2SGarance A Drosehn	    printf "--   %d extra line(s) found on %s\n", extra_lines,
1206cc00fe2SGarance A Drosehn	      name if $verbose == 0
1216cc00fe2SGarance A Drosehn	    return false
1226cc00fe2SGarance A Drosehn	end
1236cc00fe2SGarance A Drosehn	if not all_matched
1246cc00fe2SGarance A Drosehn	    printf "--   Mismatched line(s) found on %s\n",
1256cc00fe2SGarance A Drosehn	      name if $verbose == 0
1266cc00fe2SGarance A Drosehn	    return false
1276cc00fe2SGarance A Drosehn	end
1286cc00fe2SGarance A Drosehn	return true
1296cc00fe2SGarance A Drosehn    end
1306cc00fe2SGarance A Drosehn
1316cc00fe2SGarance A Drosehn    def create_links
1326cc00fe2SGarance A Drosehn	@symlinks.each { |fnames|
1336cc00fe2SGarance A Drosehn	    if $verbose >= 2
1346cc00fe2SGarance A Drosehn		printf "--  Creating: symlink %s %s\n", fnames[0], fnames[1]
1356cc00fe2SGarance A Drosehn	    end
1366cc00fe2SGarance A Drosehn	    symres = File.symlink(fnames[0], fnames[1])
1376cc00fe2SGarance A Drosehn	    return false if symres == nil
1386cc00fe2SGarance A Drosehn	    return false unless File.symlink?(fnames[1])
1396cc00fe2SGarance A Drosehn	}
1406cc00fe2SGarance A Drosehn	return true
1416cc00fe2SGarance A Drosehn    end
1426cc00fe2SGarance A Drosehn
1436cc00fe2SGarance A Drosehn    def destroy_links
1446cc00fe2SGarance A Drosehn	@symlinks.each { |fnames|
1456cc00fe2SGarance A Drosehn	    if $verbose >= 2
1466cc00fe2SGarance A Drosehn		printf "--  Removing: %s (symlink)\n", fnames[1]
1476cc00fe2SGarance A Drosehn	    end
1486cc00fe2SGarance A Drosehn	    if File.symlink?(fnames[1])
1496cc00fe2SGarance A Drosehn		if File.delete(fnames[1]) != 1
1506cc00fe2SGarance A Drosehn		    $stderr.printf "Warning: problem removing symlink '%s'\n",
1516cc00fe2SGarance A Drosehn		      fnames[1]
1526cc00fe2SGarance A Drosehn		end
1536cc00fe2SGarance A Drosehn	    else
1546cc00fe2SGarance A Drosehn		$stderr.printf "Warning: Symlink '%s' does not exist?!?\n",
1556cc00fe2SGarance A Drosehn		  fnames[1]
1566cc00fe2SGarance A Drosehn	    end
1576cc00fe2SGarance A Drosehn	}
1586cc00fe2SGarance A Drosehn	return true
1596cc00fe2SGarance A Drosehn    end
1606cc00fe2SGarance A Drosehn
1616cc00fe2SGarance A Drosehn    def init_io_files
1626cc00fe2SGarance A Drosehn	@stderr = $scriptfile + ".stderr"
1636cc00fe2SGarance A Drosehn	@stdout = $scriptfile + ".stdout"
1646cc00fe2SGarance A Drosehn	File.delete(@stderr)	if File.exists?(@stderr)
1656cc00fe2SGarance A Drosehn	File.delete(@stdout)	if File.exists?(@stdout)
1666cc00fe2SGarance A Drosehn	@stdin = "/dev/null"
1676cc00fe2SGarance A Drosehn
1686cc00fe2SGarance A Drosehn	@redirs = " <" + @stdin
1696cc00fe2SGarance A Drosehn	@redirs += " >" + @stdout
1706cc00fe2SGarance A Drosehn	@redirs += " 2>" + @stderr
1716cc00fe2SGarance A Drosehn
1726cc00fe2SGarance A Drosehn    end
1736cc00fe2SGarance A Drosehn
1746cc00fe2SGarance A Drosehn    def pop_envs
1756cc00fe2SGarance A Drosehn	@new_envs.each_key { |evar|
1766cc00fe2SGarance A Drosehn	    if @old_envs.has_key?(evar)
1776cc00fe2SGarance A Drosehn		ENV[evar] = @old_envs[evar]
1786cc00fe2SGarance A Drosehn	    else
1796cc00fe2SGarance A Drosehn		ENV.delete(evar)
1806cc00fe2SGarance A Drosehn	    end
1816cc00fe2SGarance A Drosehn	}
1826cc00fe2SGarance A Drosehn    end
1836cc00fe2SGarance A Drosehn
1846cc00fe2SGarance A Drosehn    def push_envs
1856cc00fe2SGarance A Drosehn	@@gbl_envs.each_pair { |evar, eval|
1866cc00fe2SGarance A Drosehn	    ENV[evar] = eval
1876cc00fe2SGarance A Drosehn	}
1886cc00fe2SGarance A Drosehn	@new_envs.each_pair { |evar, eval|
1896cc00fe2SGarance A Drosehn	    if ENV.has_key?(evar)
1906cc00fe2SGarance A Drosehn		@old_envs[evar] = ENV[evar]
1916cc00fe2SGarance A Drosehn	    end
1926cc00fe2SGarance A Drosehn	    ENV[evar] = eval
1936cc00fe2SGarance A Drosehn	}
1946cc00fe2SGarance A Drosehn    end
1956cc00fe2SGarance A Drosehn
1966cc00fe2SGarance A Drosehn    def run_test
1976cc00fe2SGarance A Drosehn	tscript = File.open($scriptfile, "w")
1986cc00fe2SGarance A Drosehn	tscript.printf "#!%s", $testpgm
1996cc00fe2SGarance A Drosehn	tscript.printf " %s", @shebang_args if @shebang_args != ""
2006cc00fe2SGarance A Drosehn	tscript.printf "\n"
2016cc00fe2SGarance A Drosehn	tscript.printf "%s", @script_lines if @script_lines != ""
2026cc00fe2SGarance A Drosehn	tscript.close
2036cc00fe2SGarance A Drosehn	File.chmod(0755, $scriptfile)
2046cc00fe2SGarance A Drosehn
2056cc00fe2SGarance A Drosehn	usercmd = $scriptfile
2066cc00fe2SGarance A Drosehn	usercmd += " " + @user_args	if @user_args != nil
2076cc00fe2SGarance A Drosehn	init_io_files
2086cc00fe2SGarance A Drosehn
2096cc00fe2SGarance A Drosehn	push_envs
2106cc00fe2SGarance A Drosehn	return 0 unless create_links
2116cc00fe2SGarance A Drosehn	printf "-  Executing: %s\n", usercmd if $verbose >= 1
2126cc00fe2SGarance A Drosehn	printf "-----   with: %s\n", @redirs if $verbose >= 6
2136cc00fe2SGarance A Drosehn	sys_ok = system(usercmd + @redirs)
2146cc00fe2SGarance A Drosehn	if sys_ok
2156cc00fe2SGarance A Drosehn	    @sav_cmdvalue = 0
2166cc00fe2SGarance A Drosehn	elsif $?.exited?
2176cc00fe2SGarance A Drosehn	    @sav_cmdvalue = $?.exitstatus
2186cc00fe2SGarance A Drosehn	else
2196cc00fe2SGarance A Drosehn	    @sav_cmdvalue = 125
2206cc00fe2SGarance A Drosehn	end
2216cc00fe2SGarance A Drosehn	destroy_links
2226cc00fe2SGarance A Drosehn	pop_envs
2236cc00fe2SGarance A Drosehn	sys_ok = true
2246cc00fe2SGarance A Drosehn	if @sav_cmdvalue != @cmdvalue
2256cc00fe2SGarance A Drosehn	    printf "--   Expecting cmdvalue of %d, but $? == %d\n", @cmdvalue,
2266cc00fe2SGarance A Drosehn	      @sav_cmdvalue
2276cc00fe2SGarance A Drosehn	    sys_ok = false
2286cc00fe2SGarance A Drosehn	end
2296cc00fe2SGarance A Drosehn	sys_ok = false	unless check_out("stdout", @stdout, @expect_out)
2306cc00fe2SGarance A Drosehn	sys_ok = false	unless check_out("stderr", @stderr, @expect_err)
2316cc00fe2SGarance A Drosehn	return 1	if sys_ok
2326cc00fe2SGarance A Drosehn	return 0
2336cc00fe2SGarance A Drosehn    end
2346cc00fe2SGarance A Drosehnend
2356cc00fe2SGarance A Drosehn
2366cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
2376cc00fe2SGarance A Drosehn#   Processing of the command-line options given to the regress-sb.rb script.
2386cc00fe2SGarance A Drosehn#
2396cc00fe2SGarance A Drosehnclass CommandOptions
2406cc00fe2SGarance A Drosehn    def CommandOptions.parse(command_args)
2416cc00fe2SGarance A Drosehn	parse_ok = true
2426cc00fe2SGarance A Drosehn	command_args.each { |userarg|
2436cc00fe2SGarance A Drosehn	    case userarg
2446cc00fe2SGarance A Drosehn	    when /^--rgdata=(\S+)$/
2456cc00fe2SGarance A Drosehn		parse_ok = false	unless set_rgdatafile($1)
2466cc00fe2SGarance A Drosehn	    when /^--testpgm=(\S+)$/
2476cc00fe2SGarance A Drosehn		parse_ok = false	unless set_testpgm($1)
2486cc00fe2SGarance A Drosehn		$cmdopt_testpgm = $testpgm
2496cc00fe2SGarance A Drosehn	    when "--stop-on-error", "--stop_on_error"
2506cc00fe2SGarance A Drosehn		$stop_on_error = true
2516cc00fe2SGarance A Drosehn	    when /^--/
2526cc00fe2SGarance A Drosehn		$stderr.printf "Error: Invalid long option: %s\n", userarg
2536cc00fe2SGarance A Drosehn		parse_ok = false
2546cc00fe2SGarance A Drosehn	    when /^-/
2556cc00fe2SGarance A Drosehn		userarg = userarg[1...userarg.length]
2566cc00fe2SGarance A Drosehn		userarg.each_byte { |byte|
2576cc00fe2SGarance A Drosehn		    char = byte.chr
2586cc00fe2SGarance A Drosehn		    case char
2596cc00fe2SGarance A Drosehn		    when "v"
2606cc00fe2SGarance A Drosehn			$verbose += 1
2616cc00fe2SGarance A Drosehn		    else
2626cc00fe2SGarance A Drosehn			$stderr.printf "Error: Invalid short option: -%s\n", char
2636cc00fe2SGarance A Drosehn			parse_ok = false
2646cc00fe2SGarance A Drosehn		    end
2656cc00fe2SGarance A Drosehn		}
2666cc00fe2SGarance A Drosehn	    else
2676cc00fe2SGarance A Drosehn		$stderr.printf "Error: Invalid request: %s\n", userarg
2686cc00fe2SGarance A Drosehn		parse_ok = false
2696cc00fe2SGarance A Drosehn	    end
2706cc00fe2SGarance A Drosehn	}
2716cc00fe2SGarance A Drosehn	if $rgdatafile == nil
2726cc00fe2SGarance A Drosehn	    rgmatch = Dir.glob("regress*.rgdata")
2736cc00fe2SGarance A Drosehn	    if rgmatch.length == 1
2746cc00fe2SGarance A Drosehn		$rgdatafile = rgmatch[0]
2756cc00fe2SGarance A Drosehn		printf "Assuming --rgdata=%s\n", $rgdatafile
2766cc00fe2SGarance A Drosehn	    else
2776cc00fe2SGarance A Drosehn		$stderr.printf "Error: The --rgdata file was not specified\n"
2786cc00fe2SGarance A Drosehn		parse_ok = false
2796cc00fe2SGarance A Drosehn	    end
2806cc00fe2SGarance A Drosehn	end
2816cc00fe2SGarance A Drosehn	return parse_ok
2826cc00fe2SGarance A Drosehn    end
2836cc00fe2SGarance A Drosehn
2846cc00fe2SGarance A Drosehn    def CommandOptions.set_rgdatafile(fname)
2856cc00fe2SGarance A Drosehn	if not File.exists?(fname)
2866cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Rgdata file '%s' does not exist\n", fname
2876cc00fe2SGarance A Drosehn	    return false
2886cc00fe2SGarance A Drosehn	elsif not File.readable?(fname)
2896cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Rgdata file '%s' is not readable\n", fname
2906cc00fe2SGarance A Drosehn	    return false
2916cc00fe2SGarance A Drosehn	end
2926cc00fe2SGarance A Drosehn	$rgdatafile = File.expand_path(fname)
2936cc00fe2SGarance A Drosehn	return true
2946cc00fe2SGarance A Drosehn    end
2956cc00fe2SGarance A Drosehn
2966cc00fe2SGarance A Drosehn    def CommandOptions.set_testpgm(fname)
2976cc00fe2SGarance A Drosehn	if not File.exists?(fname)
2986cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Testpgm file '%s' does not exist\n", fname
2996cc00fe2SGarance A Drosehn	    return false
3006cc00fe2SGarance A Drosehn	elsif not File.executable?(fname)
3016cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Testpgm file '%s' is not executable\n", fname
3026cc00fe2SGarance A Drosehn	    return false
3036cc00fe2SGarance A Drosehn	end
3046cc00fe2SGarance A Drosehn	$testpgm = File.expand_path(fname)
3056cc00fe2SGarance A Drosehn	return true
3066cc00fe2SGarance A Drosehn    end
3076cc00fe2SGarance A Drosehnend
3086cc00fe2SGarance A Drosehn
3096cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
3106cc00fe2SGarance A Drosehn#   Processing of the test-specific options specifed in each [test]/[run]
3116cc00fe2SGarance A Drosehn#   section of the regression-data file.  This will set values in the
3126cc00fe2SGarance A Drosehn#   global $testdata object.
3136cc00fe2SGarance A Drosehn#
3146cc00fe2SGarance A Drosehnclass RGTestOptions
3156cc00fe2SGarance A Drosehn    @@rgtest_opts = nil;
3166cc00fe2SGarance A Drosehn
3176cc00fe2SGarance A Drosehn    def RGTestOptions.init_rgtopts
3186cc00fe2SGarance A Drosehn	@@rgtest_opts = Hash.new
3196cc00fe2SGarance A Drosehn	@@rgtest_opts["$?"] = true
3206cc00fe2SGarance A Drosehn	@@rgtest_opts["clearenv"] = true
3216cc00fe2SGarance A Drosehn	@@rgtest_opts["sb_args"] = true
3226cc00fe2SGarance A Drosehn	@@rgtest_opts["script"] = true
3236cc00fe2SGarance A Drosehn	@@rgtest_opts["setenv"] = true
3246cc00fe2SGarance A Drosehn	@@rgtest_opts["stderr"] = true
3256cc00fe2SGarance A Drosehn	@@rgtest_opts["stdout"] = true
3266cc00fe2SGarance A Drosehn	@@rgtest_opts["symlink"] = true
3276cc00fe2SGarance A Drosehn	@@rgtest_opts["user_args"] = true
3286cc00fe2SGarance A Drosehn    end
3296cc00fe2SGarance A Drosehn
3306cc00fe2SGarance A Drosehn    def RGTestOptions.parse(optname, optval)
3316cc00fe2SGarance A Drosehn	init_rgtopts	unless @@rgtest_opts
3326cc00fe2SGarance A Drosehn
3336cc00fe2SGarance A Drosehn	if not @@rgtest_opts.has_key?(optname)
3346cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Invalid test-option in rgdata file: %s\n",
3356cc00fe2SGarance A Drosehn	      optname
3366cc00fe2SGarance A Drosehn	    return false
3376cc00fe2SGarance A Drosehn	end
3386cc00fe2SGarance A Drosehn
3396cc00fe2SGarance A Drosehn	#   Support a few very specific substitutions in values specified
3406cc00fe2SGarance A Drosehn	#   for test data.  Format of all recognized values should be:
3416cc00fe2SGarance A Drosehn	#		[%-object.value-%]
3426cc00fe2SGarance A Drosehn	#   which is hopefully distinctive-enough that they will never
3438ce070c1SUlrich Spörlein	#   conflict with any naturally-occurring string.  Also note that
3446cc00fe2SGarance A Drosehn	#   we only match the specific values that we recognize, and not
3456cc00fe2SGarance A Drosehn	#   "just anything" that matches the general pattern.  There are
3466cc00fe2SGarance A Drosehn	#   no blanks in the recognized values, but I use an x-tended
3476cc00fe2SGarance A Drosehn	#   regexp and then add blanks to make it more readable.
348*6ab1d4d9SJilles Tjoelker	optval.gsub!(/\[%- testpgm\.pathname -%\]/x, $testpgm)
3496cc00fe2SGarance A Drosehn	optval.gsub!(/\[%- testpgm\.basename -%\]/x, File.basename($testpgm))
3506cc00fe2SGarance A Drosehn	optval.gsub!(/\[%- script\.pathname  -%\]/x, $scriptfile)
3516cc00fe2SGarance A Drosehn
3526cc00fe2SGarance A Drosehn	invalid_value = false
3536cc00fe2SGarance A Drosehn	case optname
3546cc00fe2SGarance A Drosehn	when "$?"
3556cc00fe2SGarance A Drosehn	    if optval =~ /^\d+$/
3566cc00fe2SGarance A Drosehn		$testdata.cmdvalue = optval.to_i
3576cc00fe2SGarance A Drosehn	    else
3586cc00fe2SGarance A Drosehn		invalid_value = true
3596cc00fe2SGarance A Drosehn	    end
3606cc00fe2SGarance A Drosehn	when "clearenv"
3616cc00fe2SGarance A Drosehn	    if optval =~ /^\s*([A-Za-z]\w*)\s*$/
3626cc00fe2SGarance A Drosehn		$testdata.add_clearenv($1)
3636cc00fe2SGarance A Drosehn	    else
3646cc00fe2SGarance A Drosehn		invalid_value = true
3656cc00fe2SGarance A Drosehn	    end
3666cc00fe2SGarance A Drosehn	when "sb_args"
3676cc00fe2SGarance A Drosehn	    $testdata.shebang_args = optval
3686cc00fe2SGarance A Drosehn	when "script"
3696cc00fe2SGarance A Drosehn	    $testdata.add_script(optval)
3706cc00fe2SGarance A Drosehn	when "setenv"
3716cc00fe2SGarance A Drosehn	    if optval =~ /^\s*([A-Za-z]\w*)=(.*)$/
3726cc00fe2SGarance A Drosehn		$testdata.add_setenv($1, $2)
3736cc00fe2SGarance A Drosehn	    else
3746cc00fe2SGarance A Drosehn		invalid_value = true
3756cc00fe2SGarance A Drosehn	    end
3766cc00fe2SGarance A Drosehn	when "stderr"
3776cc00fe2SGarance A Drosehn	    $testdata.add_expecterr(optval)
3786cc00fe2SGarance A Drosehn	when "stdout"
3796cc00fe2SGarance A Drosehn	    $testdata.add_expectout(optval)
3806cc00fe2SGarance A Drosehn	when "symlink"
3816cc00fe2SGarance A Drosehn	    if optval =~ /^\s*(\S+)\s+(\S+)\s*$/
3826cc00fe2SGarance A Drosehn		srcfile = $1
3836cc00fe2SGarance A Drosehn		newfile = $2
3846cc00fe2SGarance A Drosehn		if not File.exists?(srcfile)
3856cc00fe2SGarance A Drosehn		    $stderr.printf "Error: source file '%s' does not exist.\n",
3866cc00fe2SGarance A Drosehn			srcfile
3876cc00fe2SGarance A Drosehn		    invalid_value = true
3886cc00fe2SGarance A Drosehn		elsif File.exists?(newfile)
3896cc00fe2SGarance A Drosehn		    $stderr.printf "Error: new file '%s' already exists.\n",
3906cc00fe2SGarance A Drosehn			newfile
3916cc00fe2SGarance A Drosehn		    invalid_value = true
3926cc00fe2SGarance A Drosehn		else
3936cc00fe2SGarance A Drosehn		    $testdata.add_symlink(srcfile, newfile)
3946cc00fe2SGarance A Drosehn		end
3956cc00fe2SGarance A Drosehn	    else
3966cc00fe2SGarance A Drosehn		invalid_value = true
3976cc00fe2SGarance A Drosehn	    end
3986cc00fe2SGarance A Drosehn	when "user_args"
3996cc00fe2SGarance A Drosehn	    $testdata.user_args = optval
4006cc00fe2SGarance A Drosehn	else
4016cc00fe2SGarance A Drosehn	    $stderr.printf "InternalError: Invalid test-option in rgdata file: %s\n",
4026cc00fe2SGarance A Drosehn		optname
4036cc00fe2SGarance A Drosehn	    return false
4046cc00fe2SGarance A Drosehn	end
4056cc00fe2SGarance A Drosehn
4066cc00fe2SGarance A Drosehn	if invalid_value
4076cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Invalid value(s) for %s: %s\n",
4086cc00fe2SGarance A Drosehn	      optname, optval
4096cc00fe2SGarance A Drosehn	    return false
4106cc00fe2SGarance A Drosehn	end
4116cc00fe2SGarance A Drosehn	return true
4126cc00fe2SGarance A Drosehn    end
4136cc00fe2SGarance A Drosehnend
4146cc00fe2SGarance A Drosehn
4156cc00fe2SGarance A Drosehn# -------+---------+---------+-------- + --------+---------+---------+---------+
4166cc00fe2SGarance A Drosehn#   Here's where the "main" routine begins...
4176cc00fe2SGarance A Drosehn#
4186cc00fe2SGarance A Drosehn
4196cc00fe2SGarance A Drosehn$cmdopt_testpgm = nil
4206cc00fe2SGarance A Drosehn$testpgm = nil
4216cc00fe2SGarance A Drosehn$rgdatafile = nil
4226cc00fe2SGarance A Drosehn$scriptfile = "/tmp/env-regress"
4236cc00fe2SGarance A Drosehn$stop_on_error = false
4246cc00fe2SGarance A Drosehn$verbose = 0
4256cc00fe2SGarance A Drosehn
4266cc00fe2SGarance A Drosehnexit 1 unless CommandOptions.parse(ARGV)
4276cc00fe2SGarance A Drosehn
4286cc00fe2SGarance A Drosehnerrline = nil
4296cc00fe2SGarance A Drosehntest_count = 0
4306cc00fe2SGarance A Drosehntestok_count = 0
4316cc00fe2SGarance A Drosehntest_lineno = -1
4326cc00fe2SGarance A Drosehnmax_test = -1
4336cc00fe2SGarance A Drosehnregress_data = File.open($rgdatafile)
4346cc00fe2SGarance A Drosehnregress_data.each_line { |dline|
4356cc00fe2SGarance A Drosehn    case dline
4366cc00fe2SGarance A Drosehn    when /^\s*#/, /^\s*$/
4376cc00fe2SGarance A Drosehn	#  Just a comment line, ignore it.
4386cc00fe2SGarance A Drosehn    when /^\s*gblenv=\s*(.+)$/
4396cc00fe2SGarance A Drosehn	if test_lineno > 0
4406cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Cannot define a global-value in the middle of a test (#5d)\n", test_lineno
4416cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
4426cc00fe2SGarance A Drosehn	    break;
4436cc00fe2SGarance A Drosehn	end
4446cc00fe2SGarance A Drosehn        tempval = $1
4456cc00fe2SGarance A Drosehn	if tempval !~ /^([A-Za-z]\w*)=(.*)$/
4466cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Invalid value for 'gblenv=' request: %s\n",
4476cc00fe2SGarance A Drosehn	      tempval
4486cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
4496cc00fe2SGarance A Drosehn	    break;
4506cc00fe2SGarance A Drosehn	end
4516cc00fe2SGarance A Drosehn	ExpectedResult.add_gblenv($1, $2)
4526cc00fe2SGarance A Drosehn    when /^testpgm=\s*(\S+)\s*/
4536cc00fe2SGarance A Drosehn	#   Set the location of the program to be tested, if it wasn't set
4546cc00fe2SGarance A Drosehn	#   on the command-line processing.
4556cc00fe2SGarance A Drosehn	if $cmdopt_testpgm == nil
4566cc00fe2SGarance A Drosehn	    if not CommandOptions.set_testpgm($1)
4576cc00fe2SGarance A Drosehn		errline = regress_data.lineno
4586cc00fe2SGarance A Drosehn		break;
4596cc00fe2SGarance A Drosehn	    end
4606cc00fe2SGarance A Drosehn	end
4616cc00fe2SGarance A Drosehn    when /^\[test\]$/
4626cc00fe2SGarance A Drosehn	if test_lineno > 0
4636cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Request to define a [test], but we are still defining\n"
4646cc00fe2SGarance A Drosehn	    $stderr.printf "       the [test] at line #%s\n", test_lineno
4656cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
4666cc00fe2SGarance A Drosehn	    break;
4676cc00fe2SGarance A Drosehn	end
4686cc00fe2SGarance A Drosehn	test_lineno = regress_data.lineno
4696cc00fe2SGarance A Drosehn	max_test = test_lineno
4706cc00fe2SGarance A Drosehn	printf "- Defining test at line #%s\n", test_lineno if $verbose >= 6
4716cc00fe2SGarance A Drosehn	$testdata = ExpectedResult.new
4726cc00fe2SGarance A Drosehn    when /^\[end\]$/
4736cc00fe2SGarance A Drosehn	#   User wants us to ignore the remainder of the rgdata file...
4746cc00fe2SGarance A Drosehn	break;
4756cc00fe2SGarance A Drosehn    when /^\[run\]$/
4766cc00fe2SGarance A Drosehn	if test_lineno < 0
4776cc00fe2SGarance A Drosehn	    $stderr.printf "Error: Request to [run] a test, but no test is presently defined\n"
4786cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
4796cc00fe2SGarance A Drosehn	    break;
4806cc00fe2SGarance A Drosehn	end
4816cc00fe2SGarance A Drosehn	printf "-  Running test at line #%s\n", test_lineno if $verbose >= 1
4826cc00fe2SGarance A Drosehn	run_result = $testdata.run_test
4836cc00fe2SGarance A Drosehn	test_count += 1
4846cc00fe2SGarance A Drosehn	printf "[Test #%3d: ", test_count
4856cc00fe2SGarance A Drosehn	case run_result
4866cc00fe2SGarance A Drosehn	when 0
4876cc00fe2SGarance A Drosehn	    #   Test failed
4886cc00fe2SGarance A Drosehn	    printf "Failed!  (line %4d)]\n", test_lineno
4896cc00fe2SGarance A Drosehn	    break if $stop_on_error
4906cc00fe2SGarance A Drosehn	when 1
4916cc00fe2SGarance A Drosehn	    #   Test ran as expected
4926cc00fe2SGarance A Drosehn	    testok_count += 1
4936cc00fe2SGarance A Drosehn	    printf "OK]\n"
4946cc00fe2SGarance A Drosehn	else
4956cc00fe2SGarance A Drosehn	    #   Internal error of some sort
4966cc00fe2SGarance A Drosehn	    printf "InternalError!  (line %4d)]\n", test_lineno
4976cc00fe2SGarance A Drosehn            errline = regress_data.lineno
4986cc00fe2SGarance A Drosehn            break;
4996cc00fe2SGarance A Drosehn	end
5006cc00fe2SGarance A Drosehn	test_lineno = -1
5016cc00fe2SGarance A Drosehn
5026cc00fe2SGarance A Drosehn    when /^(\s*)([^\s:]+)\s*:(.+)$/
5036cc00fe2SGarance A Drosehn	blankpfx = $1
5046cc00fe2SGarance A Drosehn	test_lhs = $2
5056cc00fe2SGarance A Drosehn	test_rhs = $3
5066cc00fe2SGarance A Drosehn	if test_lineno < 0
5076cc00fe2SGarance A Drosehn	    $stderr.printf "Error: No test is presently being defined\n"
5086cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
5096cc00fe2SGarance A Drosehn	    break;
5106cc00fe2SGarance A Drosehn	end
5116cc00fe2SGarance A Drosehn	#   All the real work happens in RGTestOptions.parse
5126cc00fe2SGarance A Drosehn	if not RGTestOptions.parse(test_lhs, test_rhs)
5136cc00fe2SGarance A Drosehn	    errline = regress_data.lineno
5146cc00fe2SGarance A Drosehn	    break;
5156cc00fe2SGarance A Drosehn	end
5166cc00fe2SGarance A Drosehn	if blankpfx.length == 0
5176cc00fe2SGarance A Drosehn	    $stderr.printf "Note: You should at least one blank before:%s\n",
5186cc00fe2SGarance A Drosehn	      dline.chomp
5196cc00fe2SGarance A Drosehn	    $stderr.printf "      at line %d of rgdata file %s\n",
5206cc00fe2SGarance A Drosehn	      regress_data.lineno, $rgdatafile
5216cc00fe2SGarance A Drosehn	end
5226cc00fe2SGarance A Drosehn
5236cc00fe2SGarance A Drosehn    else
5246cc00fe2SGarance A Drosehn	$stderr.printf "Error: Invalid line: %s\n", dline.chomp
5256cc00fe2SGarance A Drosehn	errline = regress_data.lineno
5266cc00fe2SGarance A Drosehn	break;
5276cc00fe2SGarance A Drosehn    end
5286cc00fe2SGarance A Drosehn}
5296cc00fe2SGarance A Drosehnregress_data.close
5306cc00fe2SGarance A Drosehnif errline != nil
5316cc00fe2SGarance A Drosehn    $stderr.printf "       at line %d of rgdata file %s\n", errline, $rgdatafile
5326cc00fe2SGarance A Drosehn    exit 2
5336cc00fe2SGarance A Drosehnend
5346cc00fe2SGarance A Drosehnif testok_count != test_count
5356cc00fe2SGarance A Drosehn    printf "%d of %d tests were successful.\n", testok_count, test_count
5366cc00fe2SGarance A Drosehn    exit 1
5376cc00fe2SGarance A Drosehnend
5386cc00fe2SGarance A Drosehn
5396cc00fe2SGarance A Drosehnprintf "All %d tests were successful!\n", testok_count
5406cc00fe2SGarance A Drosehnexit 0
541