/*
 * test4600 - 4600 series of the regress.cal test suite
 *
 * Copyright (C) 1999  Ernest Bowen and Landon Curt Noll
 *
 * Primary author:  Ernest Bowen
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Under source code control:	1996/07/02 20:04:40
 * File existed as early as:	1996
 *
 * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
 */


defaultverbose = 1;	/* default verbose value */

/*
 * test globals
 */
global A, f, pos;

define stest(str, verbose)
{
	local x;

	/* setup */
	if (isnull(verbose))
		verbose = defaultverbose;
	if (verbose > 0) {
		print str:":",:;
	}
	x = rm("-f", "junk4600");

	/*
	 * do file operations
	 */
	f = fopen("junk4600", "wb");
	if (iserror(f)) {
		print 'failed';
		print '**** fopen("junk4600", "wb") failed';
		return 1;
	}
	if (iserror(fputs(f,
	 "Fourscore and seven years ago our fathers brought forth\n",
	 "on this continent a new nation, conceived in liberty and dedicated\n",
	 "to the proposition that all men are created equal.\n"))) {
		print 'failed';
		print '**** fputs(f, "Fourscore ... failed';
		return 1;
	}
	if (iserror(freopen(f, "rb"))) {
		print 'failed';
		print '**** iserror(freopen(f, "rb")) failed';
		return 1;
	}
	if (iserror(rewind(f))) {
		print 'failed';
		print '**** iserror(rewind(f)) failed';
		return 1;
	}
	if (search(f, "and") != 10) {
		print 'failed';
		print '**** search(f, "and") != 10 failed';
		return 1;
	}
	if (ftell(f) != 13) {
		print 'failed';
		print '**** ftell(f) != 13 failed';
		return 1;
	}
	if (search(f, "and") != 109) {
		print 'failed';
		print '**** search(f, "and") != 109 failed';
		return 1;
	}
	if (ftell(f) != 112) {
		print 'failed';
		print '**** ftell(f) != 112 failed';
		return 1;
	}
	if (!isnull(search(f, "and"))) {
		print 'failed';
		print '**** !isnull(search(f, "and")) failed';
		return 1;
	}
	if (ftell(f) != 172) {
		print 'failed';
		print '**** ftell(f) != 172 failed';
		return 1;
	}
	if (rsearch(f, "and") != 109) {
		print 'failed';
		print '**** rsearch(f, "and") != 109 failed';
		return 1;
	}
	if (ftell(f) != 111) {
		print 'failed';
		print '**** ftell(f) != 111 failed';
		return 1;
	}
	if (iserror(fseek(f, -4, 1))) {
		print 'failed';
		print '**** iserror(fseek(f, -4, 1)) failed';
		return 1;
	}
	if (rsearch(f, "and") != 10) {
		print 'failed';
		print '**** rsearch(f, "and") != 10 failed';
		return 1;
	}
	if (ftell(f) != 12) {
		print 'failed';
		print '**** ftell(f) != 12 failed';
		return 1;
	}
	if (iserror(fseek(f, -4, 1))) {
		print 'failed';
		print '**** iserror(fseek(f, -4, 1)) failed';
		return 1;
	}
	if (!isnull(rsearch(f, "and"))) {
		print 'failed';
		print '**** !isnull(rsearch(f, "and")) failed';
		return 1;
	}
	if (ftell(f) != 0) {
		print 'failed';
		print '**** ftell(f) != 0 failed';
		return 1;
	}
	if (iserror(fclose(f))) {
		print 'failed';
		print '**** iserror(fclose(f)) failed';
		return 1;
	}

	/*
	 * cleanup
	 */
	x = rm("junk4600");
	if (verbose > 0) {
		printf("passed\n");
	}
	return 0;
}

define ttest(str, m, n, verbose)
{
	local a, s, i, j;

	if (isnull(verbose))
		verbose = defaultverbose;
	if (verbose > 0) {
		print str:":",:;
	}
	i = rm("-f", "junk4600");
	f = fopen("junk4600", "wb");

	if (isnull(n))
		n = 4;
	if (isnull(m))
		m = 4;

	mat A[m];
	mat pos[m + 1];

	pos[0] = 0;
	for (i = 0; i < m; i++) {
		j = 1 + randbit(n);
		a = "";
		while (j-- > 0)
			a = strcat(a, char(rand(32, 127)));
		A[i] = a;
		fputs(f, a);
		pos[i+1] = ftell(f);
		if (verbose > 1)
			printf("A[%d] has length %d\n", i, strlen(a));
	}
	fflush(f);
	if (verbose > 1)
		printf("File has size %d\n", pos[i]);
	freopen(f, "rb");
	if (size(f) != pos[i]) {
		print 'failed';
		printf("**** Failure 1 for file size\n");
		return 1;
	}
	for (i = 0; i < m; i++) {
		rewind(f);
		for (;;) {
			j = search(f, A[i]);
			if (isnull(j) || j > pos[i]) {
				print 'failed';
				printf("**** Failure 2 for i = %d\n", i);
				return 1;
			}
			if (j == pos[i])
				break;
			fseek(f, j + 1, 0);

		}
		if (ftell(f) != pos[i + 1]) {
			print 'failed';
			printf("**** Failure 3 for i = %d\n", i);
			return 1;
		}
	}
	for (i = m - 1; i >= 0; i--) {
		fseek(f, 0, 2);
		for (;;) {
			j = rsearch(f, A[i]);
			if (isnull(j) || j < pos[i]) {
				print 'failed';
				printf("**** Failure 4 for i = %d\n", i);
				return 1;
			}
			if (j == pos[i])
				break;
			fseek(f, -1, 1);
		}
		if (ftell(f) != pos[i + 1] - 1) {
			print 'failed';
			printf("**** Failure 5 for i = %d\n", i);
			return 1;
		}
	}
	if (iserror(fclose(f))) {
		print 'failed';
		printf("**** Failure 6 for i = %d\n", i);
		return 1;
	}
	i = rm("junk4600");
	if (verbose > 0) {
		printf("passed\n");
	}
	return 0;
}

define sprint(x)
{
	local i, n;

	n = strlen(x);
	for (i = 1; i <= n; i++) print ord(substr(x, i, 1)),;
	print;
}

define findline(f,s)
{

	if (!isfile(f))
		quit "First argument to be a file";
	if (!isstr(s))
		quit "Second argument to be a string";
	if (!isnull(search(f,s))) {
		rsearch(f, "\n");
		print fgetline(f);
	}
}

define findlineold(f,s)
{
	local str;

	if (!isfile(f))
		quit "First argument to be a file";
	if (!isstr(s))
		quit "Second argument to be a string";

	while (!isnull(str = fgetline(f)) && strpos(str, s) == 0);
		print str;
}

/*
 * test4600 - perform all of the above tests a bunch of times
 */
define test4600(v, tnum)
{
	local n;	/* test parameter */
	local i;

	/*
	 * set test parameters
	 */
	srand(4600e4600);

	/*
	 * test a lot of stuff
	 */
	for (i=0; i < 10; ++i) {
		err += ttest(strcat(str(tnum++),
			     ": ttest(",str(i),",",str(i),")"), i, i, v);
		err += stest(strcat(str(tnum++), ": stest()"), v);
	}

	/*
	 * report results
	 */
	if (v > 1) {
		if (err) {
			print "****", err, "error(s) found in testall";
		} else {
			print "no errors in testall";
		}
	}
	return tnum;
}
