#include "StdAfx.h"
#include "UnitTestFrameWork.h"
#include <excpt.h>
#include <Shellapi.h>
void UnitTestSuite::RegisterTest(UnitTest * test, char * testName)
{
	TestList * newTest = new TestList();
	newTest->TestName = testName;
	newTest->Test = test;
	newTest->pNext = 0;
	if (pLastTest)
	{
		pLastTest->pNext = newTest;
		pLastTest = newTest;
	}
	else
	{
		pFirstTest = newTest;
		pLastTest = newTest;
	}
}
UnitTestSuite::UnitTestSuite()
{
	pFirstTest = 0;
	pLastTest = 0;
	pNextTestSuite = 0;
}
UnitTestSuite::~UnitTestSuite()
{
	TestList * pCurTest = pFirstTest;
	while(pCurTest)
	{
		pFirstTest = pFirstTest->pNext;
		delete pCurTest;
		pCurTest = pFirstTest;
	}
	pFirstTest = 0;
	pLastTest = 0;
	pNextTestSuite = 0;
}
int UnitTestSuite::HandleException(unsigned int c, struct _EXCEPTION_POINTERS *e)
{
	unsigned int code = 0;
	struct _EXCEPTION_POINTERS *ep = NULL;
	
	code = c;
	ep = e;
	printf("\tException Detected: ");
	switch (code)
	{
	case EXCEPTION_ACCESS_VIOLATION:
		printf("EXCEPTION_ACCESS_VIOLATION\r\n");
		break;
	case EXCEPTION_DATATYPE_MISALIGNMENT:
		printf("EXCEPTION_DATATYPE_MISALIGNMENT\r\n");
		break;
	case EXCEPTION_BREAKPOINT:
		printf("EXCEPTION_BREAKPOINT\r\n");
		break;
	case EXCEPTION_SINGLE_STEP:
		printf("EXCEPTION_SINGLE_STEP\r\n");
		break;
	case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
		printf("EXCEPTION_ARRAY_BOUNDS_EXCEEDED\r\n");
		break;
	case EXCEPTION_FLT_DENORMAL_OPERAND:
		printf("EXCEPTION_FLT_DENORMAL_OPERAND\r\n");
		break;
	case EXCEPTION_FLT_DIVIDE_BY_ZERO:
		printf("EXCEPTION_FLT_DIVIDE_BY_ZERO\r\n");
		break;
	case EXCEPTION_FLT_INEXACT_RESULT:
		printf("EXCEPTION_FLT_INEXACT_RESULT\r\n");
		break;
	case EXCEPTION_FLT_INVALID_OPERATION:
		printf("EXCEPTION_FLT_INVALID_OPERATION\r\n");
		break;
	case EXCEPTION_FLT_OVERFLOW:
		printf("EXCEPTION_FLT_OVERFLOW\r\n");
		break;
	case EXCEPTION_FLT_STACK_CHECK:
		printf("EXCEPTION_FLT_STACK_CHECK\r\n");
		break;
	case EXCEPTION_FLT_UNDERFLOW:
		printf("EXCEPTION_FLT_UNDERFLOW\r\n");
		break;
	case EXCEPTION_INT_DIVIDE_BY_ZERO:
		printf("EXCEPTION_INT_DIVIDE_BY_ZERO\r\n");
		break;
	case EXCEPTION_INT_OVERFLOW:
		printf("EXCEPTION_INT_OVERFLOW\r\n");
		break;
	case EXCEPTION_PRIV_INSTRUCTION:
		printf("EXCEPTION_PRIV_INSTRUCTION\r\n");
		break;
	case EXCEPTION_IN_PAGE_ERROR:
		printf("EXCEPTION_IN_PAGE_ERROR\r\n");
		break;
	case EXCEPTION_ILLEGAL_INSTRUCTION:
		printf("EXCEPTION_ILLEGAL_INSTRUCTION\r\n");
		break;
	case EXCEPTION_NONCONTINUABLE_EXCEPTION:
		printf("EXCEPTION_NONCONTINUABLE_EXCEPTION\r\n");
		break;
	case EXCEPTION_STACK_OVERFLOW:
		printf("EXCEPTION_STACK_OVERFLOW\r\n");
		break;
	case EXCEPTION_INVALID_DISPOSITION:
		printf("EXCEPTION_INVALID_DISPOSITION\r\n");
		break;
	case EXCEPTION_GUARD_PAGE:
		printf("EXCEPTION_GUARD_PAGE\r\n");
		break;
	case EXCEPTION_INVALID_HANDLE:
		printf("EXCEPTION_INVALID_HANDLE\r\n");
		break;
	//case EXCEPTION_POSSIBLE_DEADLOCK:
	//    printf("EXCEPTION_POSSIBLE_DEADLOCK\r\n");
	//    break;
	default:
		printf("UNKOWN EXCEPTION\r\n");
		break;
	}
	return EXCEPTION_EXECUTE_HANDLER;
}
LPPROCESS_INFORMATION UnitTestSuite::RunProgram(char * cmdLine, char * cwd, bool newConsole, bool waitForExit)
{
	LPSTARTUPINFOA si = new STARTUPINFOA;
	LPPROCESS_INFORMATION pi = new PROCESS_INFORMATION;
	ZeroMemory( si, sizeof(STARTUPINFOA) );
	si->cb = sizeof(si);
	ZeroMemory( pi, sizeof(PROCESS_INFORMATION) );
	// Start the child process. 
	if( !CreateProcessA( 
		NULL,           // No module name (use command line)
		cmdLine,        // Command line
		NULL,           // Process handle not inheritable
		NULL,           // Thread handle not inheritable
		FALSE,          // Set handle inheritance to FALSE
		newConsole?CREATE_NEW_CONSOLE:0,              // No creation flags
		NULL,           // Use parent's environment block
		cwd,            // Starting directory 
		si,             // Pointer to STARTUPINFO structure
		pi )            // Pointer to PROCESS_INFORMATION structure
	) 
	{
		printf( "CreateProcess failed (%d).\n", GetLastError() );
		return NULL;
	}
	if (waitForExit)
	{
		// Wait until child process exits.
		WaitForSingleObject( pi->hProcess, INFINITE );
		// Close process and thread handles. 
		CloseHandle( pi->hProcess );
		CloseHandle( pi->hThread );
	}
	delete si;
	return pi;
}
bool UnitTestSuite::EndProcess(LPPROCESS_INFORMATION pi)
{
	TerminateProcess( pi->hProcess, 0);
	
	// Wait until child process exits.
	WaitForSingleObject( pi->hProcess, INFINITE );
	// Close process and thread handles. 
	CloseHandle( pi->hProcess );
	CloseHandle( pi->hThread );
	delete pi;
	return true;
}
bool UnitTestSuite::rmDir(char * path)
{
	char szDir[MAX_PATH+1];  // +1 for the double null terminate
	SHFILEOPSTRUCTA fos = {0};
	strcpy(szDir, path);
	int len = strlen(szDir);
	szDir[len+1] = 0; // double null terminate for SHFileOperation
	// delete the folder and everything inside
	fos.wFunc = FO_DELETE;
	fos.pFrom = szDir;
	fos.fFlags = FOF_NO_UI;
	return SHFileOperation( &fos );
}
void UnitTestSuite::RunTests()
{
	TestList * pCurrentTest = pFirstTest;
	while (pCurrentTest)
	{
		unsigned int code = 0;
		struct _EXCEPTION_POINTERS *ep = NULL;
		__try 
		{
			printf("Test %s:\r\n", pCurrentTest->TestName);
			if (!Setup())
			{
				printf("\tSetup  Failed!!\r\n");
				UnitTestFrameWork::IncrementTestsFailed();
				if (endOnFailure)
					return;
			}
			else
			{
				bool passed = (*pCurrentTest->Test)();
				bool tearDownPassed = TearDown(pCurrentTest->TestName);
				if (passed)
					printf("\tPassed\r\n");
				else 
					printf("\t<<<<***Failed!!***>>>>\r\n");
				if (!tearDownPassed)
					printf("\tTearDown Failed!!\r\n");
				if (!passed || !tearDownPassed)
				{
					UnitTestFrameWork::IncrementTestsFailed();
					if (endOnFailure)
						return;
				}
				UnitTestFrameWork::IncrementTestsPassed();
			}
		} 
		__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
		{
			UnitTestFrameWork::IncrementTestsFailed();
			if (endOnFailure)
				return;
		}
		pCurrentTest = pCurrentTest->pNext;
	}
	if (pNextTestSuite)
		pNextTestSuite->RunTests();
}
bool UnitTestSuite::Assert(bool condition, char* FailStr, int Line, char * FileName)
{
	if (condition) // It's as expected
		return true;
	if (breakOnFailure)
		__debugbreak();
	printf("\t%s: Line: %d, %s:\r\n", FailStr, Line, FileName);
	return false;
}
bool UnitTestSuite::breakOnFailure = false;
bool UnitTestSuite::endOnFailure = false;
UnitTestFrameWork::UnitTestFrameWork(void)
{
}
UnitTestSuite * UnitTestFrameWork::pFirstTestSuite = 0;
UnitTestSuite * UnitTestFrameWork::pLastTestSuite = 0;
void UnitTestFrameWork::RegisterTestSuite(UnitTestSuite * pSuite)
{
	if (pLastTestSuite)
	{
		pLastTestSuite->NextTestSuite(pSuite);
		pLastTestSuite = pSuite;
	}
	else
	{
		pFirstTestSuite = pSuite;
		pLastTestSuite = pSuite;
	}
}
int UnitTestFrameWork::testsPassed = 0;
int UnitTestFrameWork::testsFailed = 0;
void UnitTestFrameWork::RunTests()
{
	testsPassed = 0;
	testsFailed = 0;
	if (pFirstTestSuite)
		pFirstTestSuite->RunTests();
	printf("Tests Passed %d, TestFailed: %d\r\n", testsPassed, testsFailed);
	// delete all the test suites
	while (pFirstTestSuite)
	{
		UnitTestSuite * pCurrentTestSuite = pFirstTestSuite;
		pFirstTestSuite = pCurrentTestSuite->NextTestSuite();
		delete pCurrentTestSuite;
	}
	p4base::Cleanup();
}
                     
                                
                    
                
            
                | # | 
                Change | 
                User | 
                Description | 
                Committed | 
                 | 
            
        
        
        
        
            
                | 
                    
                        #3                    
                 | 
                
                    28480                 | 
                
                    eskopljak                 | 
                
                    submit                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
        
            
                | 
                    
                        #2                    
                 | 
                
                    28479                 | 
                
                    eskopljak                 | 
                
                    submit                 | 
                
                    
                 | 
                
                                                                                                        
                                     | 
            
        
            
                | 
                    
                        #1                    
                 | 
                
                    28441                 | 
                
                    eskopljak                 | 
                
                    Merging using p4api.net_branch                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
                
    
                
            
                | 
                    
                    //guest/perforce_software/p4api-net/main/p4bridge-unit-test/UnitTestFrameWork.cpp                 | 
            
        
        
        
        
            
                | 
                    
                        #1                    
                 | 
                
                    19043                 | 
                
                    Liz Lam                 | 
                
                    Rename p4api.net to p4api-net                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
                
    
                
            
                | 
                    
                    //guest/perforce_software/p4api.net/main/p4bridge-unit-test/UnitTestFrameWork.cpp                 | 
            
        
        
        
        
            
                | 
                    
                        #1                    
                 | 
                
                    19042                 | 
                
                    Liz Lam                 | 
                
                    Rename/move file(s) to proper main branch.                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
                
    
                
            
                | 
                    
                    //guest/perforce_software/p4api.net/p4bridge-unit-test/UnitTestFrameWork.cpp                 | 
            
        
        
        
        
            
                | 
                    
                        #3                    
                 | 
                
                    11220                 | 
                
                    Matt Attaway                 | 
                
                    Update Workshop version with most recent 14.2 patch of p4api.net                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
        
            
                | 
                    
                        #2                    
                 | 
                
                    8964                 | 
                
                    Bill                 | 
                
                    fix line endings                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         | 
            
        
            
                | 
                    
                        #1                    
                 | 
                
                    8873                 | 
                
                    Matt Attaway                 | 
                
                    Initial add of the P4API.NET source code                 | 
                
                    
                 | 
                
                                            
                                                                
                                                                
                                                         |