//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//

#include <cool/List.h>
#include <test.h>

DECLARE List<int>;

// *****************
// List of int tests
// *****************

int my_compare_int(const int& t1, const int& t2) {
  return ((t1 < t2) ? -1 : 1);
}

void list_int_op_test1() {
  
  List<int> ltemp1;
  List<int> ltemp2;

  // List l0 is ().
  List<int> l0;
  TEST("List<int> l0", 1, 1);

  // List l1(3) is (3).
  List<int> l1(3);
  TEST("List<int> l1(3)", 1, 1);

  // List l2(2,l1) is (2 3).
  List<int> l2(2,l1);
  TEST("List<int> l2(2,l1)", 1, 1);

  // List l3(1,l2) is (1 2 3).
  List<int> l3(1,l2);
  TEST("List<int> l3(1,l2)", 1, 1);

  // List l4(3,1,2,3) is (1 2 3).
  List<int> l4(3,1,2,3);
  TEST("List<int> l4(3,1,2,3)", 1, 1);

  // List l5(l4) is (1 2 3).
  List<int> l5(l4);

  TEST("List<int> l5(l4)", 1, 1);

  TEST("l3 == l4", l3==l4, TRUE);

  TEST("l5[2]", l5[2]==3 && l5.value()==3, TRUE);
//  TEST("l5[-1]", l5[-1], ERROR);
//  TEST("l5[3]", l5[3], ERROR);
  TEST("l5.get(1)", l5.get(1)==2, TRUE);
  TEST_RUN("l5[1]=43", l5[1]=43, l5[1]==43, TRUE);
  TEST_RUN("l5.put(55,1)", l5.put(55,1), l5.get(1)==55, TRUE);
  // l5 is (1 55 3);
  TEST_RUN("l5.tail(ltemp1)", l5.tail(ltemp1),
	   (ltemp1.length()==2 && ltemp1[0]==55 && ltemp1[1]==3), TRUE);
  TEST_RUN("l5.tail(ltemp1,0)", l5.tail(ltemp1,0),
	   (ltemp1.length()==3 && ltemp1[0]==1 && ltemp1[1]==55 
	    && ltemp1[2]==3),
	   TRUE);
  TEST_RUN("l5.tail(ltemp1,3)", l5.tail(ltemp1,3), ltemp1.is_empty(), TRUE);
  TEST_RUN("l5.tail(ltemp1,5)", l5.tail(ltemp1,5), ltemp1.is_empty(), TRUE);

  // l5 is (1 55 3);
  TEST_RUN("l5.last(ltemp1, 0)", l5.last(ltemp1, 0), ltemp1.is_empty(), TRUE);
  TEST_RUN("l5.last(ltemp1)", l5.last(ltemp1),
	   (ltemp1.length()==1 && ltemp1[0]==3), TRUE);
  TEST_RUN("l5.last(ltemp1,2)", l5.last(ltemp1,2),
	   (ltemp1.length()==2 && ltemp1[0]==55 && ltemp1[1]==3),
	   TRUE);
  TEST_RUN("l5.last(ltemp1,3)", l5.last(ltemp1,3),
	   (ltemp1.length()==3 && ltemp1[0]==1 && ltemp1[1]==55 
	    && ltemp1[2]==3),
	   TRUE);
  TEST_RUN("l5.last(ltemp1,5)", l5.last(ltemp1,5), ltemp1.is_empty(), TRUE);
  // l2 is (2 3)
  TEST("l2.is_empty()", l2.is_empty(), FALSE);
  // l3 is (1 2 3)
  TEST("l3.length()", l3.length()== 3, TRUE);
}

void list_int_op_test2() {
  
  List<int> ltemp1;
  List<int> ltemp2;

  ltemp1 = List<int>(4,11,22,33,44);
  List<int> l6;

  TEST_RUN("l6.but_last(ltemp2, 0)", ltemp1.copy(l6);  l6.but_last(ltemp2, 0),
	   (ltemp2.length()==4 && ltemp2[0]==11 && ltemp2[1]==22 
	    && ltemp2[2]==33 && ltemp2[3]==44),
	   TRUE);

  // l6 is now (11 22 33 44)
  TEST_RUN("l6.but_last(ltemp2)", l6.but_last(ltemp2),
	   (ltemp2.length()==3 && ltemp2[0]==11 && ltemp2[1]==22 
	    && ltemp2[2]==33),
	   TRUE);
  TEST_RUN("l6.but_last(ltemp2, 2)", l6.but_last(ltemp2, 2),
	   (ltemp2.length()==2 && ltemp2[0]==11 && ltemp2[1]==22),
	   TRUE);
  TEST_RUN("l6.but_last(ltemp2, 4)", l6.but_last(ltemp2, 4), 
	   (ltemp2.length()==0), TRUE);
  TEST_RUN("l6.but_last(ltemp2, 5)", l6.but_last(ltemp2, 5),
	   (ltemp2.length()==0), TRUE);

  TEST_RUN("l6.clear()", l6.clear(), (l6.length()==0), TRUE); 
  // l6 is now ()
  TEST("l6.is_empty()", l6.is_empty(), TRUE);
  TEST("l6.length()", l6.length()==0, TRUE);

  // l6 is (11 22 33 44)
  TEST_RUN("l6.position(33)", ltemp1.copy(l6), 
	   (l6.position(33)==2 && l6.value()==33), TRUE);
  TEST("l6.position(2)", l6.position(2)==-1, TRUE);
}

void list_int_op_test3() {
  int temp;
  List<int> ltemp1;
  List<int> ltemp2;
  List<int> l0;
  List<int> l1(3);				// List l1 is (3).
  List<int> l2(2,l1);				// List l2 is (2 3).
  List<int> l3(1,l2);				// List l3 is (1 2 3).
  List<int> l4(3,1,55,3);			// List l4 is (1 55 3).
  List<int> l5(l4);				// List l5 is (1 2 3).
  List<int> l6(4, 11, 22, 33, 44);		// List l6 is (11 22 33 44)

  List<int> l9;
  TEST_RUN("l4.copy(l9)", l4.copy(l9), (l4==l9), TRUE);
  TEST_RUN("l9 = l4", l9 = l4, (l4==l9), TRUE);

  // l6 is (11 22 33 44)
  ltemp1 = List<int>(4,44,33,22,11);
  TEST_RUN("l6.reverse()", l6.reverse(), (l6==ltemp1), TRUE);

  // l6 is (44 33 22 11)
  TEST_RUN("l6.push_end(66)", l6.push_end(66), 
	   (l6.length()==5 && l6[4]==66 && l6.value()==66),
	   TRUE);
  TEST_RUN("l6.push(77)", l6.push(77), 
	   (l6.length()==6 && l6[0]==77 && l6.value()==77), TRUE);
  TEST_RUN("l6.push_new(88)", l6.push_new(88), 
	   (l6.length()==7 && l6[0]==88 && l6.value()==88),
	   TRUE);
  TEST_RUN("l6.push_new(22)", l6.push_new(22), 
	   (l6.length()==7 && l6[0]==88), TRUE);
  TEST("l6.pop()", (l6.pop(temp), temp), 88);

  // l6 is (77 44 33 22 11 66)
  // l2 is (2 3)
  // l4 is (1 55 3)

  // l6 is now (77 44 33 22 11 66 2 3)
  TEST_RUN("l6.append(l2)", l6.append(l2),
	   (l6.value()==2 && l6.length()==8 && l6[6]==2 && l6[7]==3), TRUE);

  // l6 is now (1 55 3 77 44 33 22 11 66 2 3)
  TEST_RUN("l6.prepend(l4)", l6.prepend(l4),
	   (l6.value()==1 && l6.length()==11 && l6[0]==1 && l6[1]==55 
	    && l6[2]==3),
	   TRUE);

  TEST_RUN("l6.set_tail(l2, 14)", l6.copy(ltemp1), l6.set_tail(l2,14), FALSE);
  TEST("l6.set_tail(l2, 14) ==", l6==ltemp1, TRUE);
  ltemp2 = List<int>(6,1,55,3,77,2,3);
  TEST("l6.set_tail(l2,4)", l6.set_tail(l2,4), TRUE);
  TEST("l6.set_tail(l2,4) ==", (l6==ltemp2), TRUE);
  TEST("l6.set_tail(l2,4) value", l6.value(), 2);
  TEST_RUN("l6.set_tail(l2)", l6.set_tail(l2),
	   (l6.value()==2 && l6.length()==3 && l6[0]==1 && l6[1]==2 
	    && l6[2]==3),
	   TRUE);
  TEST_RUN("l6.set_tail(l2,0)", l6.set_tail(l2,0),
	   (l6.value()==2 && l6.length()==2 && l6[0]==2 && l6[1]==3), TRUE);

}

void list_int_op_test4() {
  List<int> ltemp1;
  List<int> ltemp2;

  ltemp1 = List<int>(4,44,33,22,11);

  List<int> l8(5,11,22,33,44,55);
  l8.copy(ltemp1);
  ltemp2 = List<int>(4,11,22,33,55);
  TEST_RUN("l8.remove(77)", l8.remove(77), (l8==ltemp1), TRUE);
  TEST_RUN("l8.remove(44)", l8.remove(44), (l8==ltemp2 && l8.value()==55),
	   TRUE);

  List<int> l11(7,11,22,33,11,22,33,44,11,11);
  ltemp1 = List<int>(4,11,22,33,44);
  l11.remove_duplicates();
  TEST_RUN("l11.remove_duplicates()", l11.remove_duplicates(), (l11==ltemp1),
	   TRUE);

  // l8 is now (11 22 33 55)
  l8.copy(ltemp1);
  ltemp2 = List<int>(4,11,55,33,55);
  TEST_RUN("l8.replace(66,22)", l8.replace(66,22), (l8==ltemp1), TRUE);
  TEST_RUN("l8.replace(22,55)", l8.replace(22,55), 
	   (l8==ltemp2 && l8.value()==55), TRUE);

  l8.copy(ltemp1);
  ltemp2 = List<int>(4,11,22,33,22);
  TEST_RUN("l8.replace_all(66,22)", l8.replace_all(66,22), (l8==ltemp1), TRUE);
  TEST_RUN("l8.replace_all(55,22)", l8.replace_all(55,22), (l8==ltemp2), TRUE);


  // l8 is now (11 22 33 22)
  l8.copy(ltemp1);
  ltemp2 = List<int>(5,11,22,111,33,22);
  TEST_RUN("l8.insert_after(111,44)", l8.insert_after(111,44), (l8==ltemp1),
	   TRUE);
  TEST_RUN("l8.insert_after(111,22)", l8.insert_after(111,22), 
	   (l8==ltemp2 && l8.value()==111), TRUE);

  TEST_RUN("l8.insert_before(222,44)", 
	   l8.copy(ltemp1); l8.insert_before(222,44), 
	   (l8==ltemp1), TRUE);
  ltemp2 = List<int>(6,11,222,22,111,33,22);
  TEST_RUN("l8.insert_before(222,22)", l8.insert_before(222,22),
	   (l8==ltemp2 && l8.value()==222), TRUE);
  ltemp2 = List<int>(7,333,11,222,22,111,33,22);
  TEST_RUN("l8.insert_before(333,11)", l8.insert_before(333,11),
	   (l8==ltemp2 && l8.value()==333), TRUE);
}

void list_int_sort_test() {

  List<int> l1(4,6,66,22,222);
  List<int> l2(4,61,12,222,666);
  List<int> l3(4,7,51,77,24);
  List<int> l4(2,22,33);
  List<int> ltemp1;

  ltemp1 = List<int>(8,6,61,12,66,22,222,222,666);
  TEST_RUN("l1.merge(l2,my_compare_int)", l1.merge(l2,my_compare_int), 
	   (l1==ltemp1), TRUE);

  ltemp1 = List<int>(6,22,33,61,12,222,666);
  TEST_RUN("l4.merge(l2,my_compare_int)", l4.merge(l2,my_compare_int), 
	   (l4==ltemp1), TRUE);

  ltemp1 = List<int>(4,12,61,222,666);
  TEST_RUN("l2.sort(my_compare_int)", l2.sort(my_compare_int), (l2==ltemp1),
	   TRUE);

  ltemp1 = List<int>(4,7,24,51,77);
  TEST_RUN("l3.sort(my_compare_int)", l3.sort(my_compare_int), (l3==ltemp1),
	   TRUE);
}

void list_int_io_test() {

  // ** an automated test would get input from file, rather than cin **
  List<int> input_list;
//  cout << "\nTesting operator>> for List<int>.";
//  cout << "\nExample of List<int> is (1 2 3).";
//  cout << "\nPlease enter a List<int> structure: ";
//  cin >> input_list;
//  cout << "\nInput_list is now set to: " << input_list << ".\n";

}

extern void list_int_currentpos_test();
extern void list_int_set_test();

void test_list_int() {

  cout << "\n*** Testing List of Int ***\n\n";
  list_int_op_test1();
  list_int_op_test2();
  list_int_op_test3();
  list_int_op_test4();
  list_int_set_test();
  list_int_sort_test();
  list_int_currentpos_test();
  list_int_io_test();
}
