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