/*
	ZUnitTest.hpp
	Author: Patrick Baggett

	Purpose :	Header for ZUnitTest type and associated functions
				Ignore the ugly C preprocessor hacks. They only make repetitive things
				less repetitive.

	Changelog :
	12/18/2011 - Removed dependency on ZString (crertel)
	12/15/2010 - Created (ptbaggett)
*/

#pragma once

#ifndef _ZUNITTEST_H
#define _ZUNITTEST_H

#include <stdio.h>			//for printf (among other things)

#include <SST/SST_Assert.h>	//for SST_OS_SetRuntimeAssertHandler

//Global flags used during the unit tests
namespace ZUnitTestGlobals
{
	extern int ARGC;			//The argument count provided to main()
	extern char **ARGV;			//The argument values provided to main()
	extern int NonInteractive;	//Flag indicating this is a non-interactive run
	extern int TestNumber;		//Test number to run
};

//Our unit test structure, which details a single unit test
typedef struct ZUnitTest
{
	const char* testName;		//Name of the test
	const char* (*testFunc)();	//Function that should be called 
} ZUnitTest;

//Unit test block structure, which details a set of ZUnitTests
typedef struct ZUnitTestBlock
{
	ZUnitTest* tests;			//Array of tests
	const char* blockName;		//The name of this test block
	int nrTests;				//Number of tests
} ZUnitTestBlock;

//Declares a ZUnitTestBlock given a data type name. Ensures ZUnitTestBlocks have consistent names for use in TestMain.cpp
#define DECLARE_ZTESTBLOCK(Type) ZUnitTestBlock Type##Tests = { Type##UnitTests, #Type, sizeof(Type##UnitTests) / sizeof(ZUnitTest) };

//This value is returned by a single ZUnitTest function to indicate success (anything else indicates failure)
#define ZTEST_SUCCESS ""

//Tests a condition, and returns a string if the test condition is false
#define TASSERT(condition, msg)	if (!(condition)) { return msg; }

//Test assertion failure
#define TASSERT_FAIL(msg) { return msg; }

//Runs a unit test block, returns true if and only if all tests are successful
bool RunUnitTests(ZUnitTestBlock* block);

/*************************************************************************/

extern const char* g_assert_message;
extern bool g_assert_triggered;

extern int ZTEST_HandleAssert(const char* _msg, void* _arg);

//The following methods can be used by test methods to cause an assert to trip the g_assert_triggered flag, check the flag, and then reset
extern void ZTEST_BeginHandleAssert();
extern bool ZTEST_CheckAssert();
extern void ZTEST_EndHandleAssert();

/*************************************************************************/

#endif
