//
// 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/String.h>
#include <cool/Queue.h>
#include <test.h>

DECLARE Queue<int>;
IMPLEMENT Queue<int>;
DECLARE Queue<double>;
IMPLEMENT Queue<double>;
DECLARE Queue<char*>;
IMPLEMENT Queue<char*>;
DECLARE Queue<String>;
IMPLEMENT Queue<String>;


Boolean my_compare_charP (const charP& s1, const charP& s2) {
  return (strcmp (s1, s2) ? FALSE : TRUE);
}

void test_int () {
  int foo;
  Queue<int> q0;
  TEST("Queue<int> q0", q0.capacity(), 0);
  Queue<int> q1(5);
  TEST("Queue<int> q1(5)", q1.capacity(), 5);
  Queue<int> q2(10);
  TEST("Queue<int> q2(10)", q2.capacity(), 10);
  TEST("q1.get(foo)", q1.get(foo), FALSE);   // false on an empty Queue
  TEST("q1.unget(4)", q1.unget(4), TRUE);
  TEST ("q1.length()", q1.length(), 1);
  TEST("q1.get()", q1.get(), 4);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q2.put(4)", q2.put(4), TRUE);
  TEST("q2.unput()", q2.unput(), 4);
  TEST("q1.put(5)", q1.put(5), TRUE);
  TEST("q1.get()", q1.get(), 5);
  TEST("q1.put(3)", q1.put(3), TRUE);
  TEST("q1.unget(2)", q1.unget(2), TRUE);
  TEST("q1.put(4)", q1.put(4), TRUE);
  TEST ("q1.length()", q1.length(), 3);
  TEST("q1.unget(1)", q1.unget(1), TRUE);
  TEST("q1.put(5)", q1.put(5), TRUE);
  TEST ("q1.length()", q1.length(), 5);
  TEST("q1.look()", q1.look(), 1);
  TEST("q2.put(1)", q2.put(1), TRUE);
  TEST("q2.put(2)", q2.put(2), TRUE);
  TEST("q2.put(3)", q2.put(3), TRUE);
  TEST("q2.put(4)", q2.put(4), TRUE);
  TEST("q2.put(5)", q2.put(5), TRUE);
  TEST("q1.operator==(q2)", q1.operator==(q2), TRUE);
  TEST("q1.find(5)", q1.find(5), TRUE);
  TEST("q2.find(6)", q2.find(6), FALSE);
  TEST("q1.remove()", q1.remove(), TRUE);
  TEST ("q1.length()", q1.length(), 4);
  TEST("q1.prev()", q1.prev(), TRUE);
  TEST("q2.find(5)", q2.find(5), TRUE);
  TEST("q2.next()", !q2.next(), TRUE);
  TEST("q2.next()", q2.next(), TRUE);
  TEST("q2.value()", q2.value(), 1);
  TEST("q2.remove(3)", q2.remove(3), TRUE);
  TEST("q2.value()", q2.value(), 4);
  TEST("q1.operator=(q2)", q1.operator=(q2), q2);
  TEST("q2.operator!=(q1)", q2.operator!=(q1), FALSE);
  q2.reset();
  TEST("q2.reset()", 1, 1);
  TEST("q2.length()", q2.length(), 4);
  q1.clear();
  TEST("q1.clear()", 1, 1);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q1.is_empty()", q1.is_empty(), TRUE);
  q1.resize(10);
  TEST("q1.resize(10)", 1, 1);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q1.capacity()", q1.capacity(), 10);
  Queue<int> q3 = q2;
  TEST("Queue<int> q3 = q2", q3.operator==(q2), TRUE);
}


void test_double () {
  double foo;
  Queue<double> q0;
  TEST("Queue<double> q0", q0.capacity(), 0);
  Queue<double> q1(5);
  TEST("Queue<double> q1(5)", q1.capacity(), 5);
  Queue<double> q2(10);
  TEST("Queue<double> q2(10)", q2.capacity(), 10);
  TEST("q1.get(foo)", q1.get(foo), FALSE);   // false on an empty Queue
  TEST("q1.unget(4.0)", q1.unget(4.0), TRUE);
  TEST ("q1.length()", q1.length(), 1);
  TEST("q1.get()", q1.get(), 4.0);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q2.put(4.0)", q2.put(4.0), TRUE);
  TEST("q2.unput()", q2.unput(), 4.0);
  TEST("q1.put(5.0)", q1.put(5.0), TRUE);
  TEST("q1.get()", q1.get(), 5.0);
  TEST("q1.put(3.0)", q1.put(3.0), TRUE);
  TEST("q1.unget(2.0)", q1.unget(2.0), TRUE);
  TEST("q1.put(4.0)", q1.put(4.0), TRUE);
  TEST ("q1.length()", q1.length(), 3);
  TEST("q1.unget(1.0)", q1.unget(1.0), TRUE);
  TEST("q1.put(5.0)", q1.put(5.0), TRUE);
  TEST ("q1.length()", q1.length(), 5);
  TEST("q1.look()", q1.look(), 1.0);
  TEST("q2.put(1)", q2.put(1.0), TRUE);
  TEST("q2.put(2)", q2.put(2.0), TRUE);
  TEST("q2.put(3)", q2.put(3.0), TRUE);
  TEST("q2.put(4)", q2.put(4.0), TRUE);
  TEST("q2.put(5)", q2.put(5.0), TRUE);
  TEST("q1.operator==(q2)", q1.operator==(q2), TRUE);
  TEST("q1.find(5.0)", q1.find(5.0), TRUE);
  TEST("q2.find(6.0)", q2.find(6.0), FALSE);
  TEST("q1.remove()", q1.remove(), TRUE);
  TEST ("q1.length()", q1.length(), 4);
  TEST("q1.prev()", q1.prev(), TRUE);
  TEST("q2.find(5.0)", q2.find(5.0), TRUE);
  TEST("q2.next()", !q2.next(), TRUE);
  TEST("q2.next()", q2.next(), TRUE);
  TEST("q2.value()", q2.value(), 1.0);
  TEST("q2.remove(3.0)", q2.remove(3.0), TRUE);
  TEST("q2.value()", q2.value(), 4.0);
  TEST("q1.operator=(q2)", q1.operator=(q2), q2);
  TEST("q2.operator!=(q1)", q2.operator!=(q1), FALSE);
  q2.reset();
  TEST("q2.reset()", 1, 1);
  TEST("q2.length()", q2.length(), 4);
  q1.clear();
  TEST("q1.clear()", 1, 1);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q1.is_empty()", q1.is_empty(), TRUE);
  q1.resize(10);
  TEST("q1.resize(10)", 1, 1);
  TEST ("q1.length()", q1.length(), 0);
  TEST("q1.capacity()", q1.capacity(), 10);
  Queue<double> q3 = q2;
  TEST("Queue<double> q3 = q2", q3.operator==(q2), TRUE);
}


void test_charP () {
  char* foo;
  Queue<char*> q0;
  TEST("Queue<char*> q0", q0.capacity(), 0);
  Queue<char*> q1(5);
  TEST("Queue<char*> q1(5)", q1.capacity(), 5);
  Queue<char*> q2(10);
  TEST("Queue<char*> q2(10)", q2.capacity(), 10);
  TEST("q1.get(foo)", q1.get(foo), FALSE);   // false on empty Queue
  q1.set_compare(&my_compare_charP);
  TEST("q1.unget(\"AAA\")", q1.unget("AAA"), TRUE);
  TEST("q1.get()", strcmp (q1.get(), "AAA"), 0);
  TEST("q2.put(\"AAA\")", q2.put("AAA"), TRUE);
  TEST("q2.unput()", strcmp (q2.unput(), "AAA"), 0);
  TEST("q1.put(\"BBB\")", q1.put("BBB"), TRUE);
  TEST("q1.get()", strcmp (q1.get(), "BBB"), 0);
  TEST("q1.put(\"CCC\")", q1.put("CCC"), TRUE);
  TEST("q1.unget(\"DDD\")", q1.unget("DDD"), TRUE);
  TEST("q1.put(\"BBB\")", q1.put("BBB"), TRUE);
  TEST("q1.unget(\"EEE\")", q1.unget("EEE"), TRUE);
  TEST("q1.put(\"AAA\")", q1.put("AAA"), TRUE);
  TEST("q1.look()", strcmp (q1.look(), "EEE"), 0);
  TEST("q2.put(\"EEE\")", q2.put("EEE"), TRUE);
  TEST("q2.put(\"DDD\")", q2.put("DDD"), TRUE);
  TEST("q2.put(\"CCC\")", q2.put("CCC"), TRUE);
  TEST("q2.put(\"BBB\")", q2.put("BBB"), TRUE);
  TEST("q2.put(\"AAA\")", q2.put("AAA"), TRUE);
  TEST("q1.operator==(q2)", q1.operator==(q2), TRUE);
  TEST("q1.find(\"AAA\")", q1.find("AAA"), TRUE);
  TEST("q2.find(\"FFF\")", q2.find("FFF"), FALSE);
  TEST("q1.remove()", q1.remove(), TRUE);
  TEST("q1.prev()", q1.prev(), TRUE);
  TEST("q2.find(\"AAA\")", q2.find("AAA"), TRUE);
  TEST("q2.next()", !q2.next(), TRUE);
  TEST("q2.next()", q2.next(), TRUE);
  TEST("q2.value()", strcmp (q2.value(), "EEE"), 0);
// The following removed because a cfront 2.0 bug prevents it's compilation
#ifdef BUGGYCFRONT
  TEST("q2.remove(\"DDD\")", q2.remove("DDD"), TRUE);
  TEST("q2.value()", strcmp (q2.value(), "CCC"), 0);
  TEST("q2.length()", q2.length(), 4);
#endif
  TEST("q1.operator=(q2)", (q1.operator=(q2), q1==q2), TRUE);
  TEST("q2.operator!=(q1)", q2.operator!=(q1), FALSE);
  q2.reset();
  TEST("q2.reset()", 1, 1);
  q1.clear();
  TEST("q1.clear()", 1, 1);
  TEST("q1.is_empty()", q1.is_empty(), TRUE);
  q1.resize(10);
  TEST("q1.resize(10)", q1.capacity(), 10);
  TEST("q1.capacity()", q1.capacity(), 10);
  Queue<char*> q3 = q2;
  TEST("Queue<char*> q3 = q2", q3.operator==(q2), TRUE);
}


void test_String () {
  Queue<String> q0;
  TEST("Queue<String> q0", q0.capacity(), 0);
  Queue<String> q1(5);
  TEST("Queue<String> q1(5)", q1.capacity(), 5);
  Queue<String> q2(10);
  TEST("Queue<String> q2(10)", q2.capacity(), 10);
  //TEST("q1.get()", q1.get(), ERROR);   // should error on an empty Queue
  TEST("q1.unget(String(\"AAA\"))", q1.unget(String("AAA")), TRUE);
  TEST("q1.get()", strcmp (q1.get(), String("AAA")), 0);
  TEST("q2.put(String(\"AAA\"))", q2.put(String("AAA")), TRUE);
  TEST("q2.unput()", strcmp (q2.unput(), String("AAA")), 0);
  TEST("q1.put(String(\"BBB\"))", q1.put(String("BBB")), TRUE);
  TEST("q1.get()", strcmp (q1.get(), String("BBB")), 0);
  TEST("q1.put(String(\"CCC\"))", q1.put(String("CCC")), TRUE);
  TEST("q1.unget(String(\"DDD\"))", q1.unget(String("DDD")), TRUE);
  TEST("q1.put(String(\"BBB\"))", q1.put(String("BBB")), TRUE);
  TEST("q1.unget(String(\"EEE\"))", q1.unget(String("EEE")), TRUE);
  TEST("q1.put(String(\"AAA\"))", q1.put(String("AAA")), TRUE);
  TEST("q1.look()", strcmp (q1.look(), String("EEE")), 0);
  TEST("q2.put(String(\"EEE\"))", q2.put(String("EEE")), TRUE);
  TEST("q2.put(String(\"DDD\"))", q2.put(String("DDD")), TRUE);
  TEST("q2.put(String(\"CCC\"))", q2.put(String("CCC")), TRUE);
  TEST("q2.put(String(\"BBB\"))", q2.put(String("BBB")), TRUE);
  TEST("q2.put(String(\"AAA\"))", q2.put(String("AAA")), TRUE);
  TEST("q1.operator==(q2)", q1.operator==(q2), TRUE);
  TEST("q1.find(String(\"AAA\"))", q1.find(String("AAA")), TRUE);
  TEST("q2.find(\"FFF\")", q2.find("FFF"), FALSE);
  TEST("q1.remove()", q1.remove(), TRUE);
  TEST("q1.prev()", q1.prev(), TRUE);
  TEST("q2.find(String(\"AAA\"))", q2.find(String("AAA")), TRUE);
  TEST("q2.next()", !q2.next(), TRUE);
  TEST("q2.next()", q2.next(), TRUE);
  TEST("q2.value()", strcmp (q2.value(), String("EEE")), 0);
  TEST("q2.remove(String(\"DDD\"))", q2.remove(String("DDD")), TRUE);
  TEST("q2.value()", strcmp (q2.value(), String("CCC")), 0);
  TEST("q1.operator=(q2)", (q1.operator=(q2), q1==q2), TRUE);
  TEST("q2.operator!=(q1)", q2.operator!=(q1), FALSE);
  q2.reset();
  TEST("q2.reset()", 1, 1);
  TEST("q2.length()", q2.length(), 4);
  q1.clear();
  TEST("q1.clear()", 1, 1);
  TEST("q1.is_empty()", q1.is_empty(), TRUE);
  q1.resize(10);
  TEST("q1.resize(10)", q1.capacity(), 10);
  TEST("q1.capacity()", q1.capacity(), 10);
  Queue<String> q3 = q2;
  TEST("Queue<String> q3 = q2", q3.operator==(q2), TRUE);
}

int main (void) {
  START("Queue");
  test_int();
  test_double();
  test_charP();
  test_String();
  SUMMARY();
  return 0;
}

