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

//-------------------------------------------------------------
// Test package

void test_Package () {
  Package* p = SYM_package_g;
  TEST ("cout << SYM_package_g;", TRUE, TRUE);
  cout << SYM_package_g << "\n";
  TEST ("Find with new symbol", p->find("test symbol"), FALSE);
  Symbol* new_sym = p->intern("test symbol");
  TEST ("Find with old symbol", p->find("test symbol"), TRUE);
  TEST ("Find with const symbol", p->find("test_symbol2"), TRUE);
  TEST ("Value after find", p->value(), SYM(test_symbol2));
  TEST ("Intern with old symbol", p->intern("test symbol"), new_sym);
  TEST ("get_key", strcmp(p->get_key(new_sym), "test symbol"), 0);
  TEST ("Remove symbol", p->remove(new_sym), TRUE);
  TEST ("Remove absent symbol", p->remove(new_sym), FALSE);
  TEST ("Put with old symbol", p->put("test symbol", *new_sym), TRUE);
  TEST ("Remove symbol name", p->remove("test symbol"), TRUE);
  TEST ("Remove absent symbol name", (p->remove("test symbol")), FALSE);
  Package package2 = (*SYM_package_g);
  TEST ("Copy and == check", (package2==(*SYM_package_g)), TRUE);
  TEST ("Copy and != check", package2!=(*SYM_package_g), FALSE);
  }

// completion tester.
//    calling complete on the "word" argument, completes to "result",
//    and returns the symbol named "symb".  There should be "c"
//    completions.  If "c" is not one, "symb" may differ, depending
//    on the ordering of symbols in the package.
static void
test_completion_helper (char* word, char* result, char* symb,
			int c, Boolean sensitive) {
  String cword = word;
  int n = complete(*SYM_package_g, cword, sensitive);
  const char* symname = (n>0) ? SYM_package_g->value()->name() : "";
  char message[100];
  sprintf(message, "Complete %d, %s -> %s  SYM %s",
	  n, word, (char*) cword, symname);
  TEST(message, (n==c &&
		 cword==result &&
		 (n!=1 || !strcmp(symname, symb))), TRUE);
}

void test_completion () {
  test_completion_helper("a", "abc", "abc", 1, TRUE);
  test_completion_helper("ab", "abc", "abc", 1, TRUE);
  test_completion_helper("abc", "abc", "abc", 1, TRUE);
  test_completion_helper("abcd", "abcd", "abcdq", 2, TRUE);
  test_completion_helper("abcde", "abcde", "abcde", 1, TRUE);
  test_completion_helper("abcdef", "abcdefg", "abcdefg", 1, TRUE);
  test_completion_helper("abcdefg", "abcdefg", "abcdefg", 1, TRUE);
  test_completion_helper("abcdefx", "abcdefx", "", 0, TRUE);

  test_completion_helper("A", "abc", "abc", 1, FALSE);
  test_completion_helper("aB", "abc", "abc", 1, FALSE);
  test_completion_helper("aBC", "abc", "abc", 1, FALSE);
  test_completion_helper("abCd", "abcd", "abcdq", 2, FALSE);
  test_completion_helper("aBCDE", "abcde", "abcde", 1, FALSE);
  test_completion_helper("abcDEF", "abcdefg", "abcdefg", 1, FALSE);
  test_completion_helper("abcdeFg", "abcdefg", "abcdefg", 1, FALSE);
  test_completion_helper("aBCDEFX", "aBCDEFX", "", 0, FALSE);
}

// Spelling tester.
//   calling correct on the "word" argument results in "num" 
//   matches, and "err" spelling errors.
static void test_spell_helper (char* word, int num,
			       int err, Boolean sensitive) {
  int errors;
  int n = correct(*SYM_package_g, word, sensitive, &errors);
  char message[100];
  sprintf(message, "Spell %s -> %s   (%d errors)",
	  word, (n>0) ? SYM_package_g->value()->name() : "", errors);
  TEST(message, (num==n && err==errors), TRUE);
}

void test_spell() {
  test_spell_helper("a", 0, 1, TRUE);
  test_spell_helper("ab", 1, 1, TRUE);
  test_spell_helper("ba", 0, 1, TRUE);
  test_spell_helper("abx", 1, 1, TRUE);
  test_spell_helper("xbc", 1, 1, TRUE);
  test_spell_helper("abcd", 3, 1, TRUE);
  test_spell_helper("bacde", 1, 1, TRUE);
  test_spell_helper("abced", 1, 1, TRUE);
  test_spell_helper("abde", 1, 1, TRUE);
  test_spell_helper("bcde", 1, 1, TRUE);
  test_spell_helper("abdc", 1, 1, TRUE);
  test_spell_helper("abcde", 1, 0, TRUE);
  test_spell_helper("xbcde", 1, 1, TRUE);
  test_spell_helper("abcdx", 2, 1, TRUE);

  test_spell_helper("A", 0, 1, FALSE);
  test_spell_helper("aB", 1, 1, FALSE);
  test_spell_helper("Ba", 0, 1, FALSE);
  test_spell_helper("aBx", 1, 1, FALSE);
  test_spell_helper("Xbc", 1, 1, FALSE);
  test_spell_helper("abCd", 3, 1, FALSE);
  test_spell_helper("bAcde", 1, 1, FALSE);
  test_spell_helper("abcEd", 1, 1, FALSE);
  test_spell_helper("ABDE", 1, 1, FALSE);
  test_spell_helper("bcdE", 1, 1, FALSE);
  test_spell_helper("Abdc", 1, 1, FALSE);
  test_spell_helper("abCDE", 1, 0, FALSE);
  test_spell_helper("XBCDE", 1, 1, FALSE);
  test_spell_helper("aBCDX", 2, 1, FALSE);
}

int main (void) {
  START("Package");
  test_Package();
  Package* p = SYM_package_g;
  p->clear();
  p->intern("abc");
  p->intern("abcde");
  p->intern("abcdq");
  p->intern("abcdefg");
  p->intern("abcdefghijk");
  test_completion();
  test_spell();
  TEST ("Describe", TRUE, TRUE);
  p->describe(cout);
  SUMMARY();
  return 0;
}


