1147495Sgad#!/usr/local/bin/ruby
2147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
3147495Sgad# Copyright (c) 2005  - Garance Alistair Drosehn <gad@FreeBSD.org>.
4147495Sgad# All rights reserved.
5147495Sgad#
6147495Sgad#  Redistribution and use in source and binary forms, with or without
7147495Sgad#  modification, are permitted provided that the following conditions
8147495Sgad#  are met:
9147495Sgad#  1. Redistributions of source code must retain the above copyright
10147495Sgad#     notice, this list of conditions and the following disclaimer.
11147495Sgad#  2. Redistributions in binary form must reproduce the above copyright
12147495Sgad#     notice, this list of conditions and the following disclaimer in the
13147495Sgad#     documentation and/or other materials provided with the distribution.
14147495Sgad#
15147495Sgad#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16147495Sgad#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17147495Sgad#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18147495Sgad#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19147495Sgad#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20147495Sgad#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21147495Sgad#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22147495Sgad#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23147495Sgad#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24147495Sgad#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25147495Sgad#  SUCH DAMAGE.
26147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
27147495Sgad# $FreeBSD$
28147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
29147495Sgad#   This script was written to provide a battery of regression-tests for some
30147495Sgad# changes I am making to the `env' command.  I wrote a new script for this
31147495Sgad# for several reasons.  1) I needed to test all kinds of special-character
32147495Sgad# combinations, and I wanted to be able to type those in exactly as they would
33147495Sgad# would be in real-life situations.  2) I wanted to set environment variables
34147495Sgad# before executing a test, 3) I had many different details to test, so I wanted
35147495Sgad# to write up dozens of tests, without needing to create a hundred separate
36147495Sgad# little tiny files, 4) I wanted to test *failure* conditions, where I expected
37147495Sgad# the test would fail but I wanted to be sure that it failed the way I intended
38147495Sgad# it to fail.
39147495Sgad#   This script was written for the special "shebang-line" testing that I
40147495Sgad# wanted for my changes to `env', but I expect it could be turned into a
41147495Sgad# general-purpose test-suite with a little more work.
42147495Sgad#							Garance/June 12/2005
43147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
44147495Sgad
45147495Sgad
46147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
47147495Sgadclass ExpectedResult
48147495Sgad    attr_writer :cmdvalue, :shebang_args, :user_args
49147495Sgad    @@gbl_envs = Hash.new
50147495Sgad
51147495Sgad    def ExpectedResult.add_gblenv(avar, avalue)
52147495Sgad	@@gbl_envs[avar] = avalue
53147495Sgad    end
54147495Sgad
55147495Sgad    def initialize
56147495Sgad	@shebang_args = ""
57147495Sgad	@cmdvalue = 0
58147495Sgad	@clear_envs = Hash.new
59147495Sgad	@new_envs = Hash.new
60147495Sgad	@old_envs = Hash.new
61147495Sgad	@script_lines = ""
62147495Sgad	@expect_err = Array.new
63147495Sgad	@expect_out = Array.new
64147495Sgad	@symlinks = Array.new
65147495Sgad	@user_args = nil
66147495Sgad    end
67147495Sgad
68147495Sgad    def add_expecterr(aline)
69147495Sgad	@expect_err << aline
70147495Sgad    end
71147495Sgad
72147495Sgad    def add_expectout(aline)
73147495Sgad	@expect_out << aline
74147495Sgad    end
75147495Sgad
76147495Sgad    def add_script(aline)
77147495Sgad	@script_lines += aline
78147495Sgad	@script_lines += "\n"	if aline[-1] != "\n"
79147495Sgad    end
80147495Sgad
81147495Sgad    def add_clearenv(avar)
82147495Sgad	@clear_envs[avar] = true
83147495Sgad    end
84147495Sgad
85147495Sgad    def add_setenv(avar, avalue)
86147495Sgad	@new_envs[avar] = avalue
87147495Sgad    end
88147495Sgad
89147495Sgad    def add_symlink(srcf, newf)
90147495Sgad	@symlinks << Array.[](srcf, newf)
91147495Sgad    end
92147495Sgad
93147495Sgad    def check_out(name, fname, expect_arr)
94147495Sgad	idx = -1
95147495Sgad	all_matched = true
96147495Sgad	extra_lines = 0
97147495Sgad	rdata = File.open(fname)
98147495Sgad	rdata.each_line { |rline|
99147495Sgad	    rline.chomp!
100147495Sgad	    idx += 1
101147495Sgad	    if idx > expect_arr.length - 1
102147495Sgad		if extra_lines == 0 and $verbose >= 1
103147495Sgad		    printf "--   Extra line(s) on %s:\n", name
104147495Sgad		end
105147495Sgad		printf "--    [%d] > %s\n", idx, rline if $verbose >= 1
106147495Sgad		extra_lines += 1
107147495Sgad	    elsif rline != expect_arr[idx]
108147495Sgad		if all_matched and $verbose >= 1
109147495Sgad		    printf "--   Mismatched line(s) on %s:\n", name
110147495Sgad		end
111147495Sgad		printf "--    [%d] < %s\n", idx, expect_arr[idx] if $verbose >= 2
112147495Sgad		printf "--        > %s\n", rline if $verbose >= 1
113147495Sgad		all_matched = false
114147495Sgad	    else
115147495Sgad		printf "--    %s[%d] = %s\n", name, idx, rline if $verbose >= 5
116147495Sgad	    end
117147495Sgad	}
118147495Sgad	rdata.close
119147495Sgad	if extra_lines > 0
120147495Sgad	    printf "--   %d extra line(s) found on %s\n", extra_lines,
121147495Sgad	      name if $verbose == 0
122147495Sgad	    return false
123147495Sgad	end
124147495Sgad	if not all_matched
125147495Sgad	    printf "--   Mismatched line(s) found on %s\n",
126147495Sgad	      name if $verbose == 0
127147495Sgad	    return false
128147495Sgad	end
129147495Sgad	return true
130147495Sgad    end
131147495Sgad
132147495Sgad    def create_links
133147495Sgad	@symlinks.each { |fnames|
134147495Sgad	    if $verbose >= 2
135147495Sgad		printf "--  Creating: symlink %s %s\n", fnames[0], fnames[1]
136147495Sgad	    end
137147495Sgad	    symres = File.symlink(fnames[0], fnames[1])
138147495Sgad	    return false if symres == nil
139147495Sgad	    return false unless File.symlink?(fnames[1])
140147495Sgad	}
141147495Sgad	return true
142147495Sgad    end
143147495Sgad
144147495Sgad    def destroy_links
145147495Sgad	@symlinks.each { |fnames|
146147495Sgad	    if $verbose >= 2
147147495Sgad		printf "--  Removing: %s (symlink)\n", fnames[1]
148147495Sgad	    end
149147495Sgad	    if File.symlink?(fnames[1])
150147495Sgad		if File.delete(fnames[1]) != 1
151147495Sgad		    $stderr.printf "Warning: problem removing symlink '%s'\n",
152147495Sgad		      fnames[1]
153147495Sgad		end
154147495Sgad	    else
155147495Sgad		$stderr.printf "Warning: Symlink '%s' does not exist?!?\n",
156147495Sgad		  fnames[1]
157147495Sgad	    end
158147495Sgad	}
159147495Sgad	return true
160147495Sgad    end
161147495Sgad
162147495Sgad    def init_io_files
163147495Sgad	@stderr = $scriptfile + ".stderr"
164147495Sgad	@stdout = $scriptfile + ".stdout"
165147495Sgad	File.delete(@stderr)	if File.exists?(@stderr)
166147495Sgad	File.delete(@stdout)	if File.exists?(@stdout)
167147495Sgad	@stdin = "/dev/null"
168147495Sgad
169147495Sgad	@redirs = " <" + @stdin
170147495Sgad	@redirs += " >" + @stdout
171147495Sgad	@redirs += " 2>" + @stderr
172147495Sgad
173147495Sgad    end
174147495Sgad
175147495Sgad    def pop_envs
176147495Sgad	@new_envs.each_key { |evar|
177147495Sgad	    if @old_envs.has_key?(evar)
178147495Sgad		ENV[evar] = @old_envs[evar]
179147495Sgad	    else
180147495Sgad		ENV.delete(evar)
181147495Sgad	    end
182147495Sgad	}
183147495Sgad    end
184147495Sgad
185147495Sgad    def push_envs
186147495Sgad	@@gbl_envs.each_pair { |evar, eval|
187147495Sgad	    ENV[evar] = eval
188147495Sgad	}
189147495Sgad	@new_envs.each_pair { |evar, eval|
190147495Sgad	    if ENV.has_key?(evar)
191147495Sgad		@old_envs[evar] = ENV[evar]
192147495Sgad	    end
193147495Sgad	    ENV[evar] = eval
194147495Sgad	}
195147495Sgad    end
196147495Sgad
197147495Sgad    def run_test
198147495Sgad	tscript = File.open($scriptfile, "w")
199147495Sgad	tscript.printf "#!%s", $testpgm
200147495Sgad	tscript.printf " %s", @shebang_args if @shebang_args != ""
201147495Sgad	tscript.printf "\n"
202147495Sgad	tscript.printf "%s", @script_lines if @script_lines != ""
203147495Sgad	tscript.close
204147495Sgad	File.chmod(0755, $scriptfile)
205147495Sgad
206147495Sgad	usercmd = $scriptfile
207147495Sgad	usercmd += " " + @user_args	if @user_args != nil
208147495Sgad	init_io_files
209147495Sgad
210147495Sgad	push_envs
211147495Sgad	return 0 unless create_links
212147495Sgad	printf "-  Executing: %s\n", usercmd if $verbose >= 1
213147495Sgad	printf "-----   with: %s\n", @redirs if $verbose >= 6
214147495Sgad	sys_ok = system(usercmd + @redirs)
215147495Sgad	if sys_ok
216147495Sgad	    @sav_cmdvalue = 0
217147495Sgad	elsif $?.exited?
218147495Sgad	    @sav_cmdvalue = $?.exitstatus
219147495Sgad	else
220147495Sgad	    @sav_cmdvalue = 125
221147495Sgad	end
222147495Sgad	destroy_links
223147495Sgad	pop_envs
224147495Sgad	sys_ok = true
225147495Sgad	if @sav_cmdvalue != @cmdvalue
226147495Sgad	    printf "--   Expecting cmdvalue of %d, but $? == %d\n", @cmdvalue,
227147495Sgad	      @sav_cmdvalue
228147495Sgad	    sys_ok = false
229147495Sgad	end
230147495Sgad	sys_ok = false	unless check_out("stdout", @stdout, @expect_out)
231147495Sgad	sys_ok = false	unless check_out("stderr", @stderr, @expect_err)
232147495Sgad	return 1	if sys_ok
233147495Sgad	return 0
234147495Sgad    end
235147495Sgadend
236147495Sgad
237147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
238147495Sgad#   Processing of the command-line options given to the regress-sb.rb script.
239147495Sgad#
240147495Sgadclass CommandOptions
241147495Sgad    def CommandOptions.parse(command_args)
242147495Sgad	parse_ok = true
243147495Sgad	command_args.each { |userarg|
244147495Sgad	    case userarg
245147495Sgad	    when /^--rgdata=(\S+)$/
246147495Sgad		parse_ok = false	unless set_rgdatafile($1)
247147495Sgad	    when /^--testpgm=(\S+)$/
248147495Sgad		parse_ok = false	unless set_testpgm($1)
249147495Sgad		$cmdopt_testpgm = $testpgm
250147495Sgad	    when "--stop-on-error", "--stop_on_error"
251147495Sgad		$stop_on_error = true
252147495Sgad	    when /^--/
253147495Sgad		$stderr.printf "Error: Invalid long option: %s\n", userarg
254147495Sgad		parse_ok = false
255147495Sgad	    when /^-/
256147495Sgad		userarg = userarg[1...userarg.length]
257147495Sgad		userarg.each_byte { |byte|
258147495Sgad		    char = byte.chr
259147495Sgad		    case char
260147495Sgad		    when "v"
261147495Sgad			$verbose += 1
262147495Sgad		    else
263147495Sgad			$stderr.printf "Error: Invalid short option: -%s\n", char
264147495Sgad			parse_ok = false
265147495Sgad		    end
266147495Sgad		}
267147495Sgad	    else
268147495Sgad		$stderr.printf "Error: Invalid request: %s\n", userarg
269147495Sgad		parse_ok = false
270147495Sgad	    end
271147495Sgad	}
272147495Sgad	if $rgdatafile == nil
273147495Sgad	    rgmatch = Dir.glob("regress*.rgdata")
274147495Sgad	    if rgmatch.length == 1
275147495Sgad		$rgdatafile = rgmatch[0]
276147495Sgad		printf "Assuming --rgdata=%s\n", $rgdatafile
277147495Sgad	    else
278147495Sgad		$stderr.printf "Error: The --rgdata file was not specified\n"
279147495Sgad		parse_ok = false
280147495Sgad	    end
281147495Sgad	end
282147495Sgad	return parse_ok
283147495Sgad    end
284147495Sgad
285147495Sgad    def CommandOptions.set_rgdatafile(fname)
286147495Sgad	if not File.exists?(fname)
287147495Sgad	    $stderr.printf "Error: Rgdata file '%s' does not exist\n", fname
288147495Sgad	    return false
289147495Sgad	elsif not File.readable?(fname)
290147495Sgad	    $stderr.printf "Error: Rgdata file '%s' is not readable\n", fname
291147495Sgad	    return false
292147495Sgad	end
293147495Sgad	$rgdatafile = File.expand_path(fname)
294147495Sgad	return true
295147495Sgad    end
296147495Sgad
297147495Sgad    def CommandOptions.set_testpgm(fname)
298147495Sgad	if not File.exists?(fname)
299147495Sgad	    $stderr.printf "Error: Testpgm file '%s' does not exist\n", fname
300147495Sgad	    return false
301147495Sgad	elsif not File.executable?(fname)
302147495Sgad	    $stderr.printf "Error: Testpgm file '%s' is not executable\n", fname
303147495Sgad	    return false
304147495Sgad	end
305147495Sgad	$testpgm = File.expand_path(fname)
306147495Sgad	return true
307147495Sgad    end
308147495Sgadend
309147495Sgad
310147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
311147495Sgad#   Processing of the test-specific options specifed in each [test]/[run]
312147495Sgad#   section of the regression-data file.  This will set values in the
313147495Sgad#   global $testdata object.
314147495Sgad#
315147495Sgadclass RGTestOptions
316147495Sgad    @@rgtest_opts = nil;
317147495Sgad
318147495Sgad    def RGTestOptions.init_rgtopts
319147495Sgad	@@rgtest_opts = Hash.new
320147495Sgad	@@rgtest_opts["$?"] = true
321147495Sgad	@@rgtest_opts["clearenv"] = true
322147495Sgad	@@rgtest_opts["sb_args"] = true
323147495Sgad	@@rgtest_opts["script"] = true
324147495Sgad	@@rgtest_opts["setenv"] = true
325147495Sgad	@@rgtest_opts["stderr"] = true
326147495Sgad	@@rgtest_opts["stdout"] = true
327147495Sgad	@@rgtest_opts["symlink"] = true
328147495Sgad	@@rgtest_opts["user_args"] = true
329147495Sgad    end
330147495Sgad
331147495Sgad    def RGTestOptions.parse(optname, optval)
332147495Sgad	init_rgtopts	unless @@rgtest_opts
333147495Sgad
334147495Sgad	if not @@rgtest_opts.has_key?(optname)
335147495Sgad	    $stderr.printf "Error: Invalid test-option in rgdata file: %s\n",
336147495Sgad	      optname
337147495Sgad	    return false
338147495Sgad	end
339147495Sgad
340147495Sgad	#   Support a few very specific substitutions in values specified
341147495Sgad	#   for test data.  Format of all recognized values should be:
342147495Sgad	#		[%-object.value-%]
343147495Sgad	#   which is hopefully distinctive-enough that they will never
344228975Suqs	#   conflict with any naturally-occurring string.  Also note that
345147495Sgad	#   we only match the specific values that we recognize, and not
346147495Sgad	#   "just anything" that matches the general pattern.  There are
347147495Sgad	#   no blanks in the recognized values, but I use an x-tended
348147495Sgad	#   regexp and then add blanks to make it more readable.
349279779Sjilles	optval.gsub!(/\[%- testpgm\.pathname -%\]/x, $testpgm)
350147495Sgad	optval.gsub!(/\[%- testpgm\.basename -%\]/x, File.basename($testpgm))
351147495Sgad	optval.gsub!(/\[%- script\.pathname  -%\]/x, $scriptfile)
352147495Sgad
353147495Sgad	invalid_value = false
354147495Sgad	case optname
355147495Sgad	when "$?"
356147495Sgad	    if optval =~ /^\d+$/
357147495Sgad		$testdata.cmdvalue = optval.to_i
358147495Sgad	    else
359147495Sgad		invalid_value = true
360147495Sgad	    end
361147495Sgad	when "clearenv"
362147495Sgad	    if optval =~ /^\s*([A-Za-z]\w*)\s*$/
363147495Sgad		$testdata.add_clearenv($1)
364147495Sgad	    else
365147495Sgad		invalid_value = true
366147495Sgad	    end
367147495Sgad	when "sb_args"
368147495Sgad	    $testdata.shebang_args = optval
369147495Sgad	when "script"
370147495Sgad	    $testdata.add_script(optval)
371147495Sgad	when "setenv"
372147495Sgad	    if optval =~ /^\s*([A-Za-z]\w*)=(.*)$/
373147495Sgad		$testdata.add_setenv($1, $2)
374147495Sgad	    else
375147495Sgad		invalid_value = true
376147495Sgad	    end
377147495Sgad	when "stderr"
378147495Sgad	    $testdata.add_expecterr(optval)
379147495Sgad	when "stdout"
380147495Sgad	    $testdata.add_expectout(optval)
381147495Sgad	when "symlink"
382147495Sgad	    if optval =~ /^\s*(\S+)\s+(\S+)\s*$/
383147495Sgad		srcfile = $1
384147495Sgad		newfile = $2
385147495Sgad		if not File.exists?(srcfile)
386147495Sgad		    $stderr.printf "Error: source file '%s' does not exist.\n",
387147495Sgad			srcfile
388147495Sgad		    invalid_value = true
389147495Sgad		elsif File.exists?(newfile)
390147495Sgad		    $stderr.printf "Error: new file '%s' already exists.\n",
391147495Sgad			newfile
392147495Sgad		    invalid_value = true
393147495Sgad		else
394147495Sgad		    $testdata.add_symlink(srcfile, newfile)
395147495Sgad		end
396147495Sgad	    else
397147495Sgad		invalid_value = true
398147495Sgad	    end
399147495Sgad	when "user_args"
400147495Sgad	    $testdata.user_args = optval
401147495Sgad	else
402147495Sgad	    $stderr.printf "InternalError: Invalid test-option in rgdata file: %s\n",
403147495Sgad		optname
404147495Sgad	    return false
405147495Sgad	end
406147495Sgad
407147495Sgad	if invalid_value
408147495Sgad	    $stderr.printf "Error: Invalid value(s) for %s: %s\n",
409147495Sgad	      optname, optval
410147495Sgad	    return false
411147495Sgad	end
412147495Sgad	return true
413147495Sgad    end
414147495Sgadend
415147495Sgad
416147495Sgad# -------+---------+---------+-------- + --------+---------+---------+---------+
417147495Sgad#   Here's where the "main" routine begins...
418147495Sgad#
419147495Sgad
420147495Sgad$cmdopt_testpgm = nil
421147495Sgad$testpgm = nil
422147495Sgad$rgdatafile = nil
423147495Sgad$scriptfile = "/tmp/env-regress"
424147495Sgad$stop_on_error = false
425147495Sgad$verbose = 0
426147495Sgad
427147495Sgadexit 1 unless CommandOptions.parse(ARGV)
428147495Sgad
429147495Sgaderrline = nil
430147495Sgadtest_count = 0
431147495Sgadtestok_count = 0
432147495Sgadtest_lineno = -1
433147495Sgadmax_test = -1
434147495Sgadregress_data = File.open($rgdatafile)
435147495Sgadregress_data.each_line { |dline|
436147495Sgad    case dline
437147495Sgad    when /^\s*#/, /^\s*$/
438147495Sgad	#  Just a comment line, ignore it.
439147495Sgad    when /^\s*gblenv=\s*(.+)$/
440147495Sgad	if test_lineno > 0
441147495Sgad	    $stderr.printf "Error: Cannot define a global-value in the middle of a test (#5d)\n", test_lineno
442147495Sgad	    errline = regress_data.lineno
443147495Sgad	    break;
444147495Sgad	end
445147495Sgad        tempval = $1
446147495Sgad	if tempval !~ /^([A-Za-z]\w*)=(.*)$/
447147495Sgad	    $stderr.printf "Error: Invalid value for 'gblenv=' request: %s\n",
448147495Sgad	      tempval
449147495Sgad	    errline = regress_data.lineno
450147495Sgad	    break;
451147495Sgad	end
452147495Sgad	ExpectedResult.add_gblenv($1, $2)
453147495Sgad    when /^testpgm=\s*(\S+)\s*/
454147495Sgad	#   Set the location of the program to be tested, if it wasn't set
455147495Sgad	#   on the command-line processing.
456147495Sgad	if $cmdopt_testpgm == nil
457147495Sgad	    if not CommandOptions.set_testpgm($1)
458147495Sgad		errline = regress_data.lineno
459147495Sgad		break;
460147495Sgad	    end
461147495Sgad	end
462147495Sgad    when /^\[test\]$/
463147495Sgad	if test_lineno > 0
464147495Sgad	    $stderr.printf "Error: Request to define a [test], but we are still defining\n"
465147495Sgad	    $stderr.printf "       the [test] at line #%s\n", test_lineno
466147495Sgad	    errline = regress_data.lineno
467147495Sgad	    break;
468147495Sgad	end
469147495Sgad	test_lineno = regress_data.lineno
470147495Sgad	max_test = test_lineno
471147495Sgad	printf "- Defining test at line #%s\n", test_lineno if $verbose >= 6
472147495Sgad	$testdata = ExpectedResult.new
473147495Sgad    when /^\[end\]$/
474147495Sgad	#   User wants us to ignore the remainder of the rgdata file...
475147495Sgad	break;
476147495Sgad    when /^\[run\]$/
477147495Sgad	if test_lineno < 0
478147495Sgad	    $stderr.printf "Error: Request to [run] a test, but no test is presently defined\n"
479147495Sgad	    errline = regress_data.lineno
480147495Sgad	    break;
481147495Sgad	end
482147495Sgad	printf "-  Running test at line #%s\n", test_lineno if $verbose >= 1
483147495Sgad	run_result = $testdata.run_test
484147495Sgad	test_count += 1
485147495Sgad	printf "[Test #%3d: ", test_count
486147495Sgad	case run_result
487147495Sgad	when 0
488147495Sgad	    #   Test failed
489147495Sgad	    printf "Failed!  (line %4d)]\n", test_lineno
490147495Sgad	    break if $stop_on_error
491147495Sgad	when 1
492147495Sgad	    #   Test ran as expected
493147495Sgad	    testok_count += 1
494147495Sgad	    printf "OK]\n"
495147495Sgad	else
496147495Sgad	    #   Internal error of some sort
497147495Sgad	    printf "InternalError!  (line %4d)]\n", test_lineno
498147495Sgad            errline = regress_data.lineno
499147495Sgad            break;
500147495Sgad	end
501147495Sgad	test_lineno = -1
502147495Sgad
503147495Sgad    when /^(\s*)([^\s:]+)\s*:(.+)$/
504147495Sgad	blankpfx = $1
505147495Sgad	test_lhs = $2
506147495Sgad	test_rhs = $3
507147495Sgad	if test_lineno < 0
508147495Sgad	    $stderr.printf "Error: No test is presently being defined\n"
509147495Sgad	    errline = regress_data.lineno
510147495Sgad	    break;
511147495Sgad	end
512147495Sgad	#   All the real work happens in RGTestOptions.parse
513147495Sgad	if not RGTestOptions.parse(test_lhs, test_rhs)
514147495Sgad	    errline = regress_data.lineno
515147495Sgad	    break;
516147495Sgad	end
517147495Sgad	if blankpfx.length == 0
518147495Sgad	    $stderr.printf "Note: You should at least one blank before:%s\n",
519147495Sgad	      dline.chomp
520147495Sgad	    $stderr.printf "      at line %d of rgdata file %s\n",
521147495Sgad	      regress_data.lineno, $rgdatafile
522147495Sgad	end
523147495Sgad
524147495Sgad    else
525147495Sgad	$stderr.printf "Error: Invalid line: %s\n", dline.chomp
526147495Sgad	errline = regress_data.lineno
527147495Sgad	break;
528147495Sgad    end
529147495Sgad}
530147495Sgadregress_data.close
531147495Sgadif errline != nil
532147495Sgad    $stderr.printf "       at line %d of rgdata file %s\n", errline, $rgdatafile
533147495Sgad    exit 2
534147495Sgadend
535147495Sgadif testok_count != test_count
536147495Sgad    printf "%d of %d tests were successful.\n", testok_count, test_count
537147495Sgad    exit 1
538147495Sgadend
539147495Sgad
540147495Sgadprintf "All %d tests were successful!\n", testok_count
541147495Sgadexit 0
542