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