/*
 * dotest - test truth statements found in line tests of dotest_testline file
 *
 * This file was created by Ernest Bowen <ebowen at une dot edu dot au>
 * and modified by Landon Curt Noll.
 *
 * This dotest_code has been placed in the public domain.  Please do not
 * copyright this dotest_code.
 *
 * ERNEST BOWEN AND LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS         SOFTWARE,  INCLUDING  ALL IMPLIED WARRANTIES OF MER-
 * CHANTABILITY AND FITNESS.  IN NO EVENT SHALL         LANDON  CURT
 * NOLL	 BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM  LOSS  OF
 * USE,	 DATA  OR  PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR  IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * This file is not covered under version 2.1 of the GNU LGPL.
 *
 * Under source dotest_code control:	2006/03/08 05:54:09
 * File existed as early as:	2006
 */


/*
 * dotest - perform tests from dotest_testline file
 *
 * given:
 *	dotest_file	filename containing single test lines
 *	dotest_code	regress.cal test number to use (def: 0)
 *	dotest_maxcond	max error conditions allowed (def: <0 ==> 2^31-1)
 *
 * returns:
 *	number of line test failures
 *
 * NOTE: All variables used by the dotest() function start with "dotest_".
 *	 The dotest_file and dotest_read should not use any variable
 *	 that starts with "dotest_".
 */
define dotest(dotest_file, dotest_code = 0, dotest_maxcond = -1)
{
    local dotest_f_file;	/* open file containing test lines */
    local dotest_testline;	/* test line */
    local dotest_testeval;	/* eval value from dotest_testline test line */
    local dotest_tmperrcnt;	/* temp error count after line test */
    local dotest_errcnt;	/* total number of errors */
    local dotest_failcnt;	/* number of line tests failed */
    local dotest_testnum;	/* number of test lines evaluated */
    local dotest_linenum;	/* test line number */
    local dotest_old_errmax;	/* value of errmax() prior to calling */
    local dotest_old_errcount;	/* value of errcount() prior to calling */

    /*
     * preserve calling stats
     */
    dotest_old_errmax = errmax();
    dotest_old_errcount = errcount(0);

    /*
     * initialize test accounting
     */
    dotest_errcnt = errcount();
    dotest_failcnt = 0;
    dotest_testnum = 0;
    dotest_linenum = 0;

    /*
     * setup error accounting for dotest
     */
    if (dotest_maxcond >= 0 && dotest_maxcond < 2147483647) {
	    errmax(dotest_maxcond + dotest_old_errcount + 1),;
    } else {
	    errmax(2147483647),;
    }

    /*
     * open the test line file
     */
    printf("%d-: opening line file: %d", dotest_code, dotest_file);
    dotest_f_file = fpathopen(dotest_file, "r");
    if (!isfile(dotest_f_file)) {
	printf("**** Unable to file or open file \"%s\"\n",
		dotest_file);
	quit;
    }
    printf('%d: testing "%s"\n', dotest_code, dotest_file);

    /*
     * perform dotest_testline test on each line of the file
     */
    for (;;) {

	/* get the next test line */
	dotest_testline = fgets(dotest_f_file);
	++dotest_linenum;
	if (iserror(dotest_testline)) {
	    quit "**** Error while reading file";
	} else if (isnull(dotest_testline)) {
	    /* EOF - end of test file */
	    break;
	}

	/* skip empty lines */
	if (dotest_testline == "\n") {
	    continue;
	}

	/* evaluate the test line */
	dotest_testeval = eval(dotest_testline);

	/* ignore white space or comment lines */
	if (isnull(dotest_testeval)) {
	    continue;
	}

	/* look for test line parse errors */
	if (iserror(dotest_testeval)) {
	    printf("**** evaluation error: ");
	    ++dotest_failcnt;

	/* look for test line dotest_failcnt */
	} else if (dotest_testeval != 1) {
	    printf("**** did not return 1: ");
	    ++dotest_failcnt;
	}

	/* show the test line we just performed */
	printf("%d-%d: %s", dotest_code, dotest_linenum, dotest_testline);

	/* error accounting */
	dotest_tmperrcnt = errcount() - dotest_errcnt;
	if (dotest_tmperrcnt > 0) {

	    /* report any other errors */
	    if (dotest_tmperrcnt > 1) {
		printf("%d-%d: NOTE: %d error conditions(s): %s\n",
		    dotest_code, dotest_linenum, dotest_tmperrcnt);
	    }

	    /* report the calc error string */
	    printf("%d-%d: NOTE: last error string: %s\n",
	        dotest_code, dotest_linenum, strerror());

	    /* new error count level */
	    dotest_errcnt = errcount();
	    if (dotest_maxcond >= 0 &&
	        dotest_old_errcount-dotest_errcnt > dotest_maxcond) {
		printf("%d-%d: total error conditions: %d > %d\n",
		       dotest_code, dotest_linenum,
		       dotest_maxcond, dotest_old_errcount-dotest_errcnt);
	    }
	}
    }

    /*
     * test the close of the line file
     */
    printf("%d-: detected %d error condition(s), many of which may be OK\n",
	   dotest_code, dotest_old_errcount-dotest_errcnt);
    printf("%d-: closing line file: %d\n", dotest_code, dotest_file);
    fclose(dotest_f_file);

    /*
     * test line file accounting
     */
    if (dotest_failcnt > 0) {
	printf("**** %d-: %d test failure(s) in %d line(s)\n",
	    dotest_code, dotest_failcnt, dotest_linenum);
    } else {
	printf("%d-: no failure(s) in %d line(s)\n",
	    dotest_code, dotest_linenum);
    }

    /*
     * prepare to return to the caller environment
     *
     * We increase the caller's error count by the number
     * of line tests that failed, not the number of internal
     * errors that were noted.
     */
    errmax(dotest_old_errmax),;
    errcount(dotest_old_errcount + dotest_failcnt),;

    /*
     * All Done!!! -- Jessica Noll, Age 2
     */
    return dotest_failcnt;
}
