/*
 * $Id: Tester.java,v 1.1.1.1 1998/05/11 18:43:03 metlov Exp $
 *
 * Galaxy PBW server 2.0 abstract core package.
 *
 * Implementation of the Galaxy game server for playing over WWW. For more
 * information about Galaxy PBW development visit :
 *    http://galaxy.fzu.cz/GalaxyServer/
 *
 * (c) 1996,1997,1998 by Konstantin Metlov(metlov@fzu.cz);
 *
 * Galaxy PBW server package is Distributed under GNU General Public License
 *
 *    This code comes with ABSOLUTELY NO WARRANTY.
 *  For license details see COPYING file in this directory.
 *
 */

package gnu.jel.debug;

import java.io.PrintWriter;
import java.io.OutputStream;

public class Tester {
  private int succ_tst;
  private int fail_tst;
  private long initTime;
  private long totalTestTime;
  private String doing=null;
  private long initTestTime;
  private OutputStream log_stream;
  private PrintWriter log;
  
  public Tester(OutputStream stream) {
    log_stream=stream;
    log=new PrintWriter(log_stream,true);
    initTime=System.currentTimeMillis();
  };
  
  public void startTest(String descr) {
    if (Debug.enabled) {
      Debug.assert(doing==null,"Concurrent testing is not supported.");
      StringBuffer stb=new StringBuffer(descr);
      stb.append(" ______________________________________________________________________");
      stb.setLength(60);
      doing=stb.toString();
      log.print(doing); log.flush();
      initTestTime=System.currentTimeMillis();
    };
  };
  
  public void testOK() {
    if (Debug.enabled) {
      long elapsed=System.currentTimeMillis()-initTestTime;
      Debug.assert(doing!=null,"No test to succeed.");
      succ_tst++;
      log.print(": OK   (in ");
      log.print(elapsed); totalTestTime+=elapsed;
      log.println(" ms)");
      doing=null;
    };
  };

  public void testFail() {
    if (Debug.enabled) {
      long elapsed=System.currentTimeMillis()-initTestTime;
      Debug.assert(doing!=null,"No test to fail.");
      fail_tst++;
      log.print(": FAIL (in ");
      log.print(elapsed); totalTestTime+=elapsed;
      log.println(" ms)");
      doing=null;
    };
  };

  public void testFailProgressing() {
    if (Debug.enabled && (doing!=null)) testFail();
  };
  
  public void summarize() {
    if (Debug.enabled) {
      Debug.assert(doing==null,"Can't summarize, while test is in progress.");
      long elapsed=System.currentTimeMillis()-initTime;
      log.println();
      log.println("------");
      log.print("Total tests : "); log.print(succ_tst+fail_tst);
      log.print("  Passed : "); log.print(succ_tst);
      log.print("  Failed : "); log.print(fail_tst);
      log.print("  Test run time :"); log.print(totalTestTime);
      log.print("  Elapsed time :"); log.print(elapsed);
      log.println();
      log.print("Date of run :");
      log.println(new java.util.Date());
    };
  };
  
  /*--SPECIALIZED TEST METHODS--------------------------------------*/
  public boolean compare(byte[] got, byte[] exp) {
    if (Debug.enabled) {
      boolean OK=exp.length==got.length;
      
      if (!OK) {
	testFail();
	log.print("ByteArray length mismatch. Expected : ");
	log.print(exp.length);
	log.print("    Got : ");
	log.println(got.length);
	// Print dump
	for(int j=0; j<got.length; j+=16) {
	  log.print("GOT: ");
	  printHexLine16(log,got,j);
	  log.println();
	};

	
	log.println();
	return false;
      };
      
      int i;
      for(i=0;(OK && (i<exp.length));i++) OK=(exp[i]==got[i]); 
      
      if (!OK) {
	testFail();
	log.print("ByteArray contents mismatch at position ");
	log.print(i); log.print(" ("); log.print(Integer.toHexString(i));
	log.println(" hex ).");
	
	// Print dump
	for(int j=0; j<exp.length; j+=16) {
	  log.print("EXP: ");
	  printHexLine16(log,exp,j);
	  log.println();
	  log.print("GOT: ");
	  printHexLine16(log,got,j);
	  log.println();
	  if ((i>=j) && (i<j+16)) {
	    log.println(fillLeft("^^",5+8+(i-j)/4+2*(i-j)+1,' '));
	  } else log.println();
	};
	
	log.println();
      };
      if (OK) testOK();
    };
    return true;
  };
  /*
EXP: XXXXXXXX DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD  |AAAAAAAAAAAAAAAA | 
GOT: XXXXXXXX DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD  |AAAAAAAAAAAAAAAA |
   */
  public void printHexLine16(PrintWriter o,byte[] data, int offset) {
    if (Debug.enabled) {
      // Print Offset
      o.print(fillLeft(Integer.toHexString(offset),8,'0'));
      
      // Print HEX
      for(int i=0;i<16;i++) {
	if (i%4==0) o.print(' ');
	if (offset+i<data.length) { // print byte
	  String bstr=Integer.toHexString(data[offset+i]);
	  Debug.assert(bstr.length()<3,"Crazy !!! Bytes are bigger than 256.");
	  if (bstr.length()<2) o.print('0');
	  o.print(bstr);
	} else { // print spaces
	  o.print(' '); o.print(' ');
	};
      };
      
      o.print(' '); o.print(' '); o.print('|');
      // Print ASCII
      for(int i=0;i<16;i++) {
	if (offset+i<data.length) {
	  if (data[offset+i]<32) o.write('.'); else o.write(data[offset+i]);
	} else {
	  o.print(' ');
	};
      };
      o.print('|');
    };
  };
  
  private String fillLeft(String str,int len, char chr) {
    if (Debug.enabled) {
      Debug.assert(len>str.length(),"Offset too large.");
      StringBuffer result=new StringBuffer();
      for(int i=0;i<len-str.length();i++) result.append(chr);
      result.append(str);
      return result.toString();
    };
    return "";
  };

  public boolean compare(String got,String exp) {
    if (exp.equals(got)) {
      testOK();
      return true;
    };
    testFail();
    log.print("EXP: \""); log.print(exp); log.println("\"");
    log.print("GOT: \""); log.print(got); log.println("\"");
    log.println();
    return false;
  };

  public boolean compare(int got,int exp) {
    if (exp==got) {
      testOK();
      return true;
    };
    testFail();
    log.print("EXP: "); log.print(exp); log.println();
    log.print("GOT: "); log.print(got); log.println();
    log.println();
    return false;
  };

/*= UNIT TEST START ==================================================== */
  public static void main(String[] args) {
    if (Debug.enabled) {
      Tester tester=new Tester(System.out);
      tester.startTest("Simple non standard test (should pass)");
      tester.testOK();
      
      tester.startTest("Simple non standard test (should fail)");
      tester.testFail();
    
      byte b1[]={01, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,
		 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
		 41,42,43,44,45};
      byte b2[]={01, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,
		 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
		 41,42,43,44,45,46};
      byte b3[]={01, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,
		 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
		 41,42,43,44,45,66};
      
      tester.startTest("Byte array test (should pass)");
      tester.compare(b1,b1);
    
      tester.startTest("Byte array test (should fail length)");
      tester.compare(b1,b2);

      tester.startTest("Byte array test (should fail contents)");
      tester.compare(b3,b2);

      String s1="a string";
      String s2="another string";
      String s3="a string";

      tester.startTest("String cmp test (should pass)");
      tester.compare(s3,s1);

      tester.startTest("String cmp test (should fail)");
      tester.compare(s2,s1);


      tester.startTest("Integer cmp test (should pass)");
      tester.compare(1,1);

      tester.startTest("Integer cmp test (should fail)");
      tester.compare(2,1);

      
      tester.summarize();
      
    };
  };
/*= UNIT TEST END =======================================================*/
};






