/**********************************************************************/
/*                                                                    */
/*	CRISP - Programmable editor                                   */
/*	===========================                                   */
/*                                                                    */
/*  File:          regress.m                                          */
/*  Author:        P. D. Fox                                          */
/*  Created:       20 Feb 1991                     		      */
/*                                                                    */
/*  Copyright (c) 1990, 1991 Paul Fox                                 */
/*                All Rights Reserved.                                */
/*                                                                    */
/*                                                                    */
/*--------------------------------------------------------------------*/
/*   Description:						      */
/*   								      */
/*   This  file  is  used  when debugging and fixing CRISP to aid in  */
/*   regression testing - catching bugs introduced inadvertently.     */
/*   								      */
/*   This  script  does  not attempt to exhaustively test CRISP, but  */
/*   tests  are  added  whenever  a  bug is found, to ensure the bug  */
/*   does not get missed in the future.				      */
/*   								      */
/*   The  tests  in  this  file  are  mainly  to do with testing the  */
/*   interpreter  and  simple aspects of the language. No attempt is  */
/*   made   to   test   the   correctnesss   of   the   display,  or  */
/*   reading/writing files.					      */
/*   								      */
/*   This  file  can also be run after porting CRISP, to ensure that  */
/*   these  tests  work  as  expected. If anything doesn't work that  */
/*   should, the porter will hae to check for portability problems.   */
/*   								      */
/*   These tests attempt to do things in order of complexity.	      */
/**********************************************************************/

/*static char sccs_id[] = "%Z% %M% %R%.%L%";*/

# include	"crisp.h"

# define	TEST(x, cond)	if (!(cond)) failed(x); else passed();

string	gs1, gs2, gs3, gi, gj, gk;
list	gl1 = {
		"One", "Two", "Three", {"x", "y"},
		"fred", {"Off", "On"}
		};
void
regress()
{
	int	i, j, k;
	int	num_passed, num_failed;
	list	l1, l2, l3;
	float	f1;
	declare	d1;
	string s1, s2, s3;
	declare a57, b57;
	list	failed_list;
	
	refresh();
	
	num_passed = 0;
	num_failed = 0;

	i = j = k = 0;
	s1 = "String one";
	s2 = "String two";
	s3 = "String three";
	
	TEST(1, i == 0);

	s1 = s2;
	TEST(2, s1 == "String two");
	TEST(3, s1 == "String two" + "");
	
	s1 = s2 + s3;
	TEST(4, s1 == "String twoString three");

	s1 = substr("ABC", -10000, 20);
	TEST(5, s1 == "ABC");

	s1 = substr("ABC", 10000, 20);
	TEST(6, s1 == "");

	s2 = "HELLO";
	s2 = s2;
	TEST(7, s2 == "HELLO");

	s2 = "S2";
	s1 = s2 + "-second-" + s2;
	TEST(8, s1 == "S2-second-S2");

	s1 = "variable";
	k = 99;
	TEST(9, test1_macro("literal-string", 23, s1, k));

	test2_macro(i, j, k, s1, s2, s3);
	TEST(10, k == 27);
	TEST(11, s1 == "literal");
	TEST(12, s2 == "variable");

	k = 1 ? 2 : 3;
	TEST(13, k == 2);
	
	s1 = 1 ? "abc" : "def";
	TEST(14, s1 == "abc");

	s1 = 0 ? "abc" : "def";
	TEST(15, s1 == "def");

	s2 = "variable";
	k = 99;
	sprintf(s1, "%s,%d,%s,%d", "literal", 1, s2, k);
	TEST(16, s1 == "literal,1,variable,99");

	TEST(17, test3_macro() == "XYZZY");

	switch (3) {
	  case 1: k = 101; break;
	  case 2: k = 102; break;
	  case 3: k = 103; break;
	  }
	TEST(18, k == 103);
	
	sprintf(s1, "--%s--", 1 ? "abc" : "def");
	TEST(19, s1 == "--abc--");
	
	TEST(20, test4_macro() == 0);

	switch ("hello") {
	  case "hello, everybod":
	  	s1 = "first";
		break;
	  case "hello":
	  	s1 = "second";
		break;
	  default:
	  	s1 = "default";
	  }
	TEST(21, s1 == "second");

	s1 = "hello, everybod";
	s2 = "hello";
	switch ("hello") {
	  case s1:
	   	s1 = "first";
		break;
	  case s2:
	  	s1 = "second";
		break;
	  default:
	  	s1 = "default";
	  }
	TEST(22, s1 == "second");
	
	s1 = "";
	s1 = substr(s1, index(s1, ";") + 1);
	TEST(23, s1 == "");

	gs1 = "";
	get_parm(2, gs1);
	gs1 = substr(gs1, index(gs1, ";") + 1);
	TEST(24, gs1 == "");

	s1 = "xyz";
	s1 += "abc";
	TEST(25, s1 == "xyzabc");

	s1 = "xyz";
	s2 = "abc";
	s1 += s2;
	TEST(26, s1 == "xyzabc");

	s1 = "xyz";
	s2 = s1;
	s1 += s2;
	TEST(27, s1 == "xyzxyz");

	TEST(28, test5_macro() == "XYZ");

	s1 = "xyz";
	TEST(29, (s1 += "abc") == "xyzabc");

	s1 = "xyz";
	TEST(30, (s1 += s1) == "xyzxyz");

	s1 = "xyz";
	TEST(31, (s1 = s1) == "xyz");

	l1 = quote_list(123, "xyz", hello());
	TEST(32, length_of_list(l1) == 3);

	l2 = l1;
	TEST(33, l1[0] == l2[0]);

	d1 = l1[0];
	TEST(34, is_integer(d1));

	d1 = l1[1];
	TEST(35, is_string(d1));

	d1 = l1[2];
	TEST(36, is_list(d1));

	d1 = l1[3];
	TEST(37, is_null(d1));

	l1 = quote_list(1);
	l1[0] = 2;
	TEST(38, l1[0] == 2);

	l1 = quote_list(1, "abc");
	l1[0] = 2;
	TEST(39, l1[0] == 2);

	l1 = quote_list("abc");
	l1[0] = 2;
	TEST(40, l1[0] == 2);
	
	l1 = quote_list("abc", 1);
	l1[1] = 2;
	TEST(41, l1[1] == 2);

	l1 = quote_list(1, "abc", 3);
	l1[1] = 2;
	TEST(42, l1[1] == 2);

	l1 = quote_list(1, 2, 3);
	l1[1] = "abc";
	TEST(43, l1[1] == "abc");

	l1 = quote_list(1, 2, 3);
	l2 = l1;
	l1[1] = l2;
	TEST(44, length_of_list(l1) == 5);

	l1 = quote_list(1, 2, 3);
	l1[1] = quote_list(1, 2, 3);
	TEST(45, length_of_list(l1) == 5);
	
	TEST(46, 1. == 1);

	l1 = quote_list(1, 2, 3);
	l1[1] = make_list(quote_list(1, 2, 3));
	l1[3] = "end";
	TEST(47, l1[3] == "end");
	TEST(48, length_of_list(l1) == 4);

	l3[0] = 0;
	l3[1] = 1;
	l3[2] = 2;
	TEST(49, l3[0] == 0);
	TEST(50, l3[1] == 1);
	TEST(51, l3[2] == 2);
	
	l1 = NULL;
	TEST(52, length_of_list(l1) == 0);

	l1[0] = "hello";
	TEST(53, l1[0] == "hello");
	
	s1 = "abc";
	l1[0] = s1;
	TEST(54, l1[0] == "abc");
	
	s1 = "abc";
	l1[0] = s1;
	s1 = "123456789";
	TEST(55, l1[0] == "abc");
	
	b57 = "hello";
	a57 = b57;
	TEST(56, a57 == "hello");

	TEST(57, test57_macro() == 99);
	
	l1 = quote_list("one", "", "three");
	s1 = "TWO";
	l1[1] = s1;
	l1[1] = s1;
	TEST(58, l1[1] == "TWO");

	s1 = "TWO";
	gl1[1] = s1;
	gl1[1] = s1;
	TEST(58, gl1[1] == "TWO");
	
	unregister_macro(3, "hello_mum");
	unregister_macro(3, "hello_mum");
	unregister_macro(3, "hello_mum");
	TEST(59, 1 == 1);
	
	l1 = quote_list(1, 2, 3);
	l2 = make_list(l1);
	l1[1] = l2;
	TEST(60, length_of_list(l1) == 3);
	
	l1 = quote_list("hello", "list", 1, NULL, 2.3);
	l2 = make_list(l1);
	l1[1] = l2;
	TEST(61, length_of_list(l1) == 5);
	
	l1 = quote_list(1, 2, 3);
	l1[1] = make_list(quote_list(1, 2, 3));
	TEST(62, length_of_list(l1) == 3);
	
	l1 = quote_list(1, 2, 3);
	l1[2] = make_list(quote_list(1, 2, 3));
	TEST(63, length_of_list(l1) == 3);
	
	l1 = quote_list(1, 2, 3);
	l1[0] = make_list(quote_list(1, 2, 3));
	TEST(64, length_of_list(l1) == 3);
	
	l1 = make_list(quote_list(1, 2, 3));
	l1 += "abc";
	l1 += "def";
	l1[1] = 1;
	TEST(65, length_of_list(l1) == 3);
	
	l1 = make_list(quote_list(1, 2, 3), quote_list(1, 2, 3));
	TEST(66, car(car(l1)) == 1);
	TEST(67, length_of_list(l1) == 2);
	
	l1 = NULL;
	nth(99, l1);
	TEST(68, 3 == 1 + 2);
	
	TEST(69, trim("harry  ") == "harry");
	TEST(70, ltrim("  harry") == "harry");
	
	s1 = "  harry  ";
	TEST(71, trim(s1) == "  harry");
	TEST(72, ltrim(s1) == "harry  ");
	TEST(73, atoi("98") == 98);
	TEST(74, strlen("abcd") == 4);
	s1 = "abcd" + " ";
	TEST(75, strlen(s1) == 5);
	
	TEST(76, strlen("nothing") == 7);
	
	/***********************************************/
	/*   Test for segmentation violations.	       */
	/***********************************************/
	l1 = command_list();
	TEST(77, is_list(l1));
	l1 = macro_list();
	TEST(78, is_list(l1));
	
	d1 = "hello";
	d1 = NULL;
	TEST(79, typeof(d1) == "NULL");
	
	l1 = macro_list();
	TEST(80, strlen(l1) != 0);
	
	TEST(81, length_of_list(cdr(macro_list())) > 0);
	
	f1 = 2.34;
	i = f1;
	TEST(82, i == 2);
	TEST(83, is_integer(i));
	
	testa_macro();
	
	TEST(86, int_to_key(key_to_int("<Up>")) == "<Up>");
	
	TEST(87, search_list(NULL, "def", quote_list("abc", "def", "ghi")) == 1);
	l1 = quote_list("abc");
	l1 += "def";
	l1 += "ghi";
	TEST(88, search_list(NULL, "def", l1) == 1);
	
	l1 = quote_list(1, 2, 3);
	l1 = l1 + l1;
	TEST(89, length_of_list(l1) == 6);
	l1[1] = quote_list("a", "b", "c");
	TEST(90, length_of_list(l1) == 8);
	
	l2 = l1;
	l1[0] = 99;
	TEST(91, l1[0] != l2[0]);
	
	i = 99;
	s1 = "abc";
	s1 = s1 + i;
	TEST(92, s1 == "abc99");
	
	i = 99;
	s1 = "abc";
	s1 = i + s1;
	TEST(93, s1 == "99abc");
	
	s1 = "abc";
	s1 += 0;
	TEST(94, s1 == "abc0");
	
	TEST(95, "abc" + "def" == "abcdef");
	TEST(96, 1 + "def" == "1def");
	TEST(97, "abc" + 1 == "abc1");
	TEST(98, 1.2 + "def" == "1.2def");
	TEST(99, "abc" + 1.2 == "abc1.2");
	l1 = quote_list("abc");
	l1 += "def";
	l1 += "ghi";
	TEST(100, re_search(NULL, "def", l1) == 1);
	
	/***********************************************/
	/*   Following  tests  check out re_translate  */
	/*   with  a  string  parameter.  We  use the  */
	/*   sub and gsub macros defined in crisp.cr.  */
	/***********************************************/
	TEST(101, gsub("ana", "anda", "banana") == "bandana");
	TEST(102, gsub("a", "-&-", "banana") == "b-a-n-a-n-a-");
	TEST(103, gsub("a+", "-&-", "banana") == "b-a-n-a-n-a-");
	TEST(104, gsub("a+", "-a-", "baaaanaaaaanaaaa") == "b-a-n-a-n-a-");
	TEST(105, sub("ana", "anda", "banana") == "bandana");
	TEST(106, sub("a", "-&-", "banana") == "b-a-nana");
	TEST(107, sub("a+", "-&-", "banana") == "b-a-nana");
	TEST(108, sub("a+", "-a-", "baaaanaaaaanaaaa") == "b-a-naaaaanaaaa");
	TEST(109, sub("na$", "na.", "banana") == "banana.");
	TEST(110, gsub("^a", "A", "anana") == "Anana");
	TEST(111, gsub("n.n", "[&]", "banana") == "ba[nan]a");
	
	TEST(112, if_test() == 1);
	
	TEST(113, sub("f\\(.*\\)t", "F\\1T", "first:second") == "FirsT:second");
	
	TEST(114, gsub("a|n", "z", "anana") == "zzzzz");
	/***********************************************/
	/*   Turn  off  buffer  changed flag, because  */
	/*   it's  not  worth  saving the output from  */
	/*   this macro.			       */
	/***********************************************/
	set_buffer_flags(~ BF_CHANGED);
	message("Tests passed: %d, failed: %d", num_passed, num_failed);
	if (num_failed == 0)
		return;
		
	edit_file("Regression-Test");
	clear_buffer();
	for (i = 0; i < length_of_list(failed_list); )
		insert(failed_list[i++]);
}
void
passed()
{	extern int num_passed;

	++num_passed;
}
void
failed(int num)
{	extern list failed_list;
	extern int num_failed;

	failed_list += "Test " + num + ": Failed.\n";
	++num_failed;
}
int
test1_macro()
{	string	s1, s2;
	int	i1, i2;

	get_parm(0, s1);
	get_parm(1, i1);
	get_parm(2, s2);
	get_parm(3, i2);
	return s1 == "literal-string" && i1 == 23 && s2 == "variable" && i2 == 99;
}
void
test2_macro()
{	string	s1 = "variable";

	put_parm(0, 25);
	put_parm(1, 26);
	put_parm(2, 27);
	put_parm(3, "literal");
	put_parm(4, s1);
}
string
test3_macro()
{
	returns("XYZZY");
}
int
test4_macro()
{	int	dir, re;
	string	prompt;
	
	dir = 0;
	re = 1;
	sprintf(prompt, "%c Pattern%s: ", 
		dir ? 25 : 24, re ? "" : "(RE off)");
	return prompt != "\030 Pattern: ";
}
string
test5_macro()
{	string	s1 = "XYZ";

	returns(1 ? s1 : "def");
}
int
test57_macro()
{	int	i;

	while (i < 10) {
		i = 20;
		switch (113) {
		  case 1:
		  case 2:
		  case 113:
			return 99;
		  default:
	  		i = 30;
			break;
		  }
		}
	return i;
}
void
testa_macro()
{	float	f1;
	int	i;
	declare	d1;
	
	d1 = execute_macro(" + 123 0.0");
       	f1 = cvt_to_object("1.23");
	i = f1;
	TEST(84, i == 1);
	TEST(85, is_integer(i));
}
/**********************************************************************/
/*   Tests to make sure we are not losing memory.		      */
/**********************************************************************/
void
leak_tests()
{	int	i;
	list	l1;

	/***********************************************/
	/*   Some memory leakage tests.		       */
	/***********************************************/
	l1 = NULL;
	for (i = 0; i < 1000; i++) {
		l1 += 0;
		}
	TEST(76, length_of_list(l1) == 1000);
}
/**********************************************************************/
/*   Test an obscure bug caused by the if-stmt code.		      */
/**********************************************************************/
int
if_test()
{	string	line;
	line = xcompletion("Edit file:");
	return 1;
}
string
xcompletion()
{
	if (1)
		return xcompl_file("");
}
string
xcompl_file(string file)
{
	return file;
}

