/*
  JsUnit
  Copyright (C) 2001 Edward Hieatt, edward@jsunit.net

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

var JSUNIT_UNDEFINED_VALUE;
var isTestPageLoaded=false;
var tracer=null;
var thrower=null;
var assertNumber=0;
function GetAssertCount() {
	return assertNumber-1;
}
function CountAnAssert() {
	assertNumber++;
}
function DontCountLastAssert() {
	assertNumber--;
}
var DontCountNextAssert=DontCountLastAssert;
function _displayStringForValue(aVar) {
	if (aVar===null) return "null";
	if (aVar===JSUNIT_UNDEFINED_VALUE) return "undefined";
	return aVar;
}

function assert_throw(e) {
	if (thrower == null) {
		eval("throw e");
	}
	else {
		thrower(e);
	}
}

function fail(failureMessage) {
        assert_throw( new JsUnitException(null, failureMessage) );
}
function error(errorMessage) {
        var errorObject=new Object();
        errorObject.description=errorMessage;
        assert_throw( errorObject );
}
function argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) {
        return args.length==expectedNumberOfNonCommentArgs+1;
}
function commentArg(expectedNumberOfNonCommentArgs, args) {
        if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) {
                return args[0];
        }
        else
                return '(((assert #'+assertNumber.toString()+')))';
}
function nonCommentArg(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
        return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
               args[desiredNonCommentArgIndex] :
               args[desiredNonCommentArgIndex-1];
}
function _validateArguments(expectedNumberOfNonCommentArgs, args) {
        if (args.length!=expectedNumberOfNonCommentArgs &&
            args.length!=expectedNumberOfNonCommentArgs+1) {
                emsg="Incorrect number of arguments passed to assert function: "
					+args.length.toString()+" when "+expectedNumberOfNonCommentArgs.toString()
					+" or "+(expectedNumberOfNonCommentArgs+1).toString()+" expected";
                error(emsg);
        }
        else if (args.length==expectedNumberOfNonCommentArgs+1 && typeof(args[0])!="string") {
                error("Extra first argument to assert function must be a string, not a "
					+typeof(args[0]));
        }
}
function _assert(comment, booleanValue, failureMessage) {
		CountAnAssert();
        if (!booleanValue)
                assert_throw( new JsUnitException(comment, failureMessage) );
}
function assert() {
        _validateArguments(1, arguments);
        var booleanValue=nonCommentArg(1, 1, arguments);
        if (typeof(booleanValue)!="boolean" && booleanValue.constructor != Boolean)
                error("Bad argument to assert(boolean)");
        _assert(commentArg(1, arguments), booleanValue.valueOf()===true, "Call to assert(boolean) with false");
        return                            booleanValue.valueOf()===true;
}
function assertTrue() {
        _validateArguments(1, arguments);
        var booleanValue=nonCommentArg(1, 1, arguments);
        if (typeof(booleanValue)!="boolean")
                error("Bad argument to assertTrue(boolean)");
        _assert(commentArg(1, arguments), booleanValue===true, "Call to assertTrue(boolean) with false");
        return                            booleanValue===true;
}
function assertFalse() {
        _validateArguments(1, arguments);
        var booleanValue=nonCommentArg(1, 1, arguments);
        if (typeof(booleanValue)!="boolean")
                error("Bad argument to assertFalse(boolean)");
        _assert(commentArg(1, arguments), booleanValue===false, "Call to assertFalse(boolean) with true");
        return                            booleanValue===false;
}
function assertEquals() {
        _validateArguments(2, arguments);
        var var1=nonCommentArg(1, 2, arguments);
        var var2=nonCommentArg(2, 2, arguments);
        _assert(commentArg(2, arguments), var1===var2, "Expected " + var1 + " (" + typeof(var1) + ") but was "+_displayStringForValue(var2) +" ("+typeof(var2)+")");
		return                            var1===var2;        
}
function assertRange() {
        _validateArguments(3, arguments);
        var var1=nonCommentArg(1, 3, arguments);
        var var2=nonCommentArg(2, 3, arguments);
        var var3=nonCommentArg(3, 3, arguments);
        _assert(commentArg(3, arguments), var1<=var2 && var2<=var3, "Expected " + _displayStringForValue(var2) + " (" + typeof(var2) + ") to be between " + _displayStringForValue(var1) + " (" + typeof(var1) + ") and " + _displayStringForValue(var3) + " (" + typeof(var3) + ")  ");
		return                            var1<=var2 && var2<=var3;        
}
function assertNotEquals() {
        _validateArguments(2, arguments);
        var var1=nonCommentArg(1, 2, arguments);
        var var2=nonCommentArg(2, 2, arguments);
        _assert(commentArg(2, arguments), var1!==var2, "Expected not to be "+_displayStringForValue(var2));
		return                            var1!==var2;        
}
function assertNull() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), aVar===null, "Expected null but was "+_displayStringForValue(aVar));
		return                            aVar===null;        
}
function assertNotNull() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), aVar!==null, "Expected not to be null");
		return                            aVar!==null;        
}

function assertUndefined() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        var cmnt=commentArg(1, arguments);
        _assert(cmnt, aVar===JSUNIT_UNDEFINED_VALUE, "Expected undefined but was "+_displayStringForValue(aVar));
		return        aVar===JSUNIT_UNDEFINED_VALUE;
}

function assertNotUndefined() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), aVar!==JSUNIT_UNDEFINED_VALUE, "Expected to be defined");
		return                            aVar!==JSUNIT_UNDEFINED_VALUE;
}
var assertDefined=assertNotUndefined;
var assertNotDefined=assertUndefined;

function assertUndefinedOrNull() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        var cmnt=commentArg(1, arguments);
        _assert(cmnt, aVar===JSUNIT_UNDEFINED_VALUE || aVar===null, "Expected undefined or null but was "+_displayStringForValue(aVar));
		return        aVar===JSUNIT_UNDEFINED_VALUE || aVar===null;
}
function assertNotUndefinedAndNotNull() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), aVar!==JSUNIT_UNDEFINED_VALUE && aVar!==null, "Expected to be defined and nonnull but was "+_displayStringForValue(aVar));
		return                            aVar!==JSUNIT_UNDEFINED_VALUE && aVar!==null;
}
var assertDefinedAndNotNull=assertNotUndefinedAndNotNull;

function assertNaN() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), isNaN(aVar), "Expected NaN");
        return                            isNaN(aVar);
}
function assertNotNaN() {
        _validateArguments(1, arguments);
        var aVar=nonCommentArg(1, 1, arguments);
        _assert(commentArg(1, arguments), !isNaN(aVar), "Expected not NaN");
        return                            !isNaN(aVar);
}
function isLoaded() {
        return isTestPageLoaded;
}
function setUp() {
	assertNumber=1;
}
function tearDown() {
}
function getFunctionName(aFunction) {
        var name = aFunction.toString().match(/function (\w*)/)[1];
        if ((name == null) || (name.length==0))
                name = "anonymous";
        return name;
}
function getStackTrace() {
        var result = "";
        for (var a = arguments.caller; a !=null; a = a.caller) {
                result += "> "+getFunctionName(a.callee) + "\n";
                if (a.caller == a) {
                        result+="*";
                        break;
                }
        }
        return result;
}
function JsUnitException(comment, message) {
        this.isJsUnitException=true;
        this.comment=comment;
        this.jsUnitMessage=message;
        this.stackTrace=getStackTrace();
}
function JsUnitTestSuite() {
        this.isJsUnitTestSuite=true;
        this.testPages=Array();
        this.pageIndex=0;
}
function addTestPage(pageName) {
        with (this)
        testPages[testPages.length]=pageName;
}
function addTestSuite(suite) {
        with (this)
        for (var i=0; i<suite.testPages.length; i++)
                addTestPage(suite.testPages[i]);
}
function containsTestPages() {
        return this.testPages.length>0;
}
function nextPage() {
        return this.testPages[this.pageIndex++];
}
function hasMorePages() {
        return this.pageIndex<this.testPages.length;
}
JsUnitTestSuite.prototype.addTestPage=addTestPage;
JsUnitTestSuite.prototype.addTestSuite=addTestSuite;
JsUnitTestSuite.prototype.containsTestPages=containsTestPages;
JsUnitTestSuite.prototype.nextPage=nextPage;
JsUnitTestSuite.prototype.hasMorePages=hasMorePages;

function newOnLoadEvent() {
        isTestPageLoaded=true;
}

function warn() {
        if (tracer!=null) tracer.warn(arguments[0], arguments[1]);
}
function inform() {
        if (tracer!=null) tracer.inform(arguments[0], arguments[1]);
}
function debug() {
        if (tracer!=null) tracer.debug(arguments[0], arguments[1]);
}
function setTracer(aTracer) {
        tracer=aTracer;
}

window.onload=newOnLoadEvent;
