|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
unittest.h
Abstract:
This is the source file for the unit test support lib
Author(s):
Vincent Geglia Environment:
User Mode
Notes:
USER32.LIB, and KERNEL32.LIB must be linked with this WINDOWS.H must be #included prior to this header file
Revision History:
Initial version, 011119, vincentg
--*/
//
// General includes
//
//
// NTLOG definitions
//
#define TLS_LOGALL 0x0000FFFFL // Log output. Logs all the time.
#define TLS_INFO 0x00002000L // Log information.
#define TLS_SEV1 0x00000002L // Log at Severity 1 level
#define TLS_PASS 0x00000020L // Log at Pass level
#define TLS_REFRESH 0x00010000L // Create new file || trunc to zero.
#define TLS_MONITOR 0x00080000L // Output to 2nd screen.
#define TLS_VARIATION 0x00000200L // Log testcase level.
#define TL_VARIATION TLS_VARIATION,TEXT(__FILE__),(int)__LINE__
//
// Define progress bits
// These bits are used to track the progress through
// a given function, for the purposes of providing
// proper cleanup. They are also useful for debugging.
//
//
// Progress macros
//
#if 0
#define FORCEERRORPATH
#define FORCEERRORPATHBIT 0x2
#endif
#if 0
#ifdef DBG
#define ECHOPROGRESSDATA
#endif
#endif
#ifdef ECHOPROGRESSDATA
#define PROGRESS_INIT(x) DWORD progressbits = 0; \
UCHAR functionname [100]; \ strcpy (functionname, x); \ printf("****\nFunction: %s\n(module %s, line %d)\nPROGRESS TRACKING INITIALIZED\n****\n\n", functionname, __FILE__, __LINE__); #ifdef FORCEERRORPATH
#define PROGRESS_UPDATE(x) printf("****\nFunction: %s\n(module %s, line %d)\nPROGRESS UPDATE (WAS %08lx", functionname, __FILE__, __LINE__, progressbits); \
printf(", NOW %08lx).\nForcing error path %08lx\n****\n\n", progressbits |= x, FORCEERRORPATHBIT);\ if (progressbits & FORCEERRORPATHBIT) {\ goto exitcleanup;\ } #else
#define PROGRESS_UPDATE(x) printf("****\nFunction: %s\n(module %s, line %d)\nPROGRESS UPDATE (WAS %08lx", functionname, __FILE__, __LINE__, progressbits); \
printf(", NOW %08lx).\n****\n\n", progressbits |= x); #endif
#define PROGRESS_GET progressbits
#define PROGRESS_END progressbits = 0
#else
#define PROGRESS_INIT(x) DWORD progressbits = 0
#define PROGRESS_UPDATE(x) progressbits |= x
#define PROGRESS_GET progressbits
#define PROGRESS_END progressbits = 0
#endif
//
// Globals
//
HANDLE g_log = INVALID_HANDLE_VALUE; BOOL g_usentlog = FALSE; BOOL g_genericresult = TRUE;
typedef HANDLE (*Dll_tlCreateLog) (LPSTR, DWORD); typedef BOOL (*Dll_tlAddParticipant) (HANDLE, DWORD, int); typedef BOOL (*Dll_tlStartVariation) (HANDLE); typedef BOOL (*Dll_tlLog) (HANDLE, DWORD, LPCSTR, int,...); typedef DWORD (*Dll_tlEndVariation) (HANDLE); typedef BOOL (*Dll_tlRemoveParticipant) (HANDLE); typedef BOOL (*Dll_tlDestroyLog) (HANDLE); typedef VOID (*Dll_tlReportStats) (HANDLE);
Dll_tlCreateLog _tlCreateLog; Dll_tlAddParticipant _tlAddParticipant; Dll_tlDestroyLog _tlDestroyLog; Dll_tlEndVariation _tlEndVariation; Dll_tlLog _tlLog; Dll_tlRemoveParticipant _tlRemoveParticipant; Dll_tlStartVariation _tlStartVariation; Dll_tlReportStats _tlReportStats;
//
// Definitions
//
#define LOGINFO(x) LogNTLOG (g_log, LOG_INFO, x)
#define LOGENTRYTEXTLENGTH 12
#define LOGENTRYTEXTPASS "\n**PASS**: \0"
#define LOGENTRYTEXTFAIL "\n**FAIL**: \0"
#define LOGENTRYTEXTINFO "\n**INFO**: \0"
//
// Structures
//
typedef enum { UNIT_TEST_STATUS_SUCCESS = 0, UNIT_TEST_STATUS_NOT_RUN, UNIT_TEST_STATUS_FAILURE } UNIT_TEST_STATUS;
typedef enum { LOG_PASS = 0, LOG_FAIL, LOG_INFO } LOG_ENTRY_TYPE;
//
// Function prototypes
//
BOOL UtInitLog ( PUCHAR Logfilename );
VOID UtCloseLog ( VOID );
VOID UtLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText, ... );
VOID UtLogINFO ( PUCHAR LogText, ... );
VOID UtLogPASS ( PUCHAR LogText, ... );
VOID UtLogFAIL ( PUCHAR LogText, ... );
PUCHAR UtParseCmdLine ( PUCHAR Search, int Argc, char *Argv[] );
//
// Private function prototypes
//
BOOL UtpInitGenericLog ( PUCHAR Logfilename );
BOOL UtpInitNtLog ( PUCHAR Logfilename );
VOID UtpCloseGenericLog ( VOID );
VOID UtpCloseNtLog ( VOID );
VOID UtpLogGenericLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText );
VOID UtpLogNtLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText );
//
// Code
//
BOOL UtInitLog ( PUCHAR Logfilename )
/*++
Routine Description:
This routine sets up the unit test log mechanism
Arguments:
None Return Value:
TRUE if successful FALSE if unsuccessful N.B. - FALSE is returned if a log session already exists.
--*/
//
// InitNTLOG progress bits
//
#define UtInitLog_ENTRY 0x00000001
#define UtInitLog_LOADNTLOG 0x00000002
#define UtInitLog_COMPLETION 0x00000004
{ UCHAR logfilepath [MAX_PATH]; DWORD logstyle; BOOL bstatus = FALSE; HMODULE ntlogmodule = NULL; PROGRESS_INIT ("UtInitLog"); PROGRESS_UPDATE (UtInitLog_ENTRY);
if (g_log != INVALID_HANDLE_VALUE) {
bstatus = FALSE; goto exitcleanup; }
//
// Try to initialize NTLOG first
//
PROGRESS_UPDATE (UtInitLog_LOADNTLOG); ntlogmodule = LoadLibrary ("NTLOG.DLL");
if (ntlogmodule != NULL) {
if (!(_tlCreateLog = (Dll_tlCreateLog) GetProcAddress (ntlogmodule, "tlCreateLog_A")) || !(_tlAddParticipant = (Dll_tlAddParticipant) GetProcAddress (ntlogmodule, "tlAddParticipant")) || !(_tlDestroyLog = (Dll_tlDestroyLog) GetProcAddress (ntlogmodule, "tlDestroyLog")) || !(_tlEndVariation = (Dll_tlEndVariation) GetProcAddress (ntlogmodule, "tlEndVariation")) || !(_tlLog = (Dll_tlLog) GetProcAddress (ntlogmodule, "tlLog_A")) || !(_tlRemoveParticipant = (Dll_tlRemoveParticipant)GetProcAddress (ntlogmodule, "tlRemoveParticipant"))|| !(_tlStartVariation = (Dll_tlStartVariation) GetProcAddress (ntlogmodule, "tlStartVariation")) || !(_tlReportStats = (Dll_tlReportStats) GetProcAddress (ntlogmodule, "tlReportStats")) )
{ bstatus = FALSE; goto exitcleanup; }
bstatus = UtpInitNtLog (Logfilename); if (bstatus == TRUE) {
g_usentlog = TRUE; }
} else {
bstatus = UtpInitGenericLog (Logfilename);
if (bstatus == TRUE) {
g_usentlog = FALSE; g_genericresult = TRUE; } } PROGRESS_UPDATE (UtInitLog_COMPLETION);
exitcleanup:
//
// Cleanup
//
PROGRESS_END; return bstatus; }
VOID UtCloseLog ( VOID )
/*++
Routine Description:
This routine closes the logging session and summarizes results
Arguments:
None Return Value:
None
--*/
{ if (g_usentlog == TRUE) {
UtpCloseNtLog ();
} else {
UtpCloseGenericLog (); }
g_log = INVALID_HANDLE_VALUE; }
VOID UtLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText, ... )
/*++
Routine Description:
This routine logs an entry to a unit test logging session.
Arguments:
A log entry type Text to log Return Value:
None
--*/
//
// UtLog progress bits
//
#define UtLog_ENTRY 0x00000001
#define UtLog_LOG 0x00000002
#define UtLog_COMPLETION 0x00000004
{ va_list va; UCHAR logtext[1000]; PROGRESS_INIT ("UtLog"); PROGRESS_UPDATE (UtLog_ENTRY);
if (g_log == INVALID_HANDLE_VALUE) {
goto exitcleanup; }
va_start (va, LogText); _vsnprintf (logtext, sizeof (logtext), LogText, va); va_end (va); if (g_usentlog == TRUE) {
UtpLogNtLog (LogEntryType, logtext);
} else { UtpLogGenericLog (LogEntryType, logtext); }
PROGRESS_UPDATE (UtLog_LOG); PROGRESS_UPDATE (UtLog_COMPLETION);
exitcleanup:
PROGRESS_END; return; }
VOID UtLogINFO ( PUCHAR LogText, ... )
/*++
Routine Description:
This routine logs an INFO entry
Arguments:
Text describing the entry Return Value:
None
--*/
{ va_list va; va_start (va, LogText); UtLog (LOG_INFO, LogText, va); va_end (va); }
VOID UtLogPASS ( PUCHAR LogText, ... )
/*++
Routine Description:
This routine logs a PASS entry
Arguments:
Text describing the entry Return Value:
None
--*/
{ va_list va; va_start (va, LogText); UtLog (LOG_INFO, LogText, va); va_end (va); }
VOID UtLogFAIL ( PUCHAR LogText, ... )
/*++
Routine Description:
This routine logs an FAIL entry
Arguments:
Text describing the entry Return Value:
None
--*/
{ va_list va; va_start (va, LogText); UtLog (LOG_FAIL, LogText, va); va_end (va); }
PUCHAR UtParseCmdLine ( PUCHAR Search, int Argc, char *Argv[] )
/*++
Routine Description:
This routine parses the command line
Arguments:
Search - string to search for Argc - argc passed into main Argv - argv passed into main Return Value:
A pointer to the first instance of the string in the parameter list or NULL if the string does not exist
--*/
{ int count = 0; PUCHAR instance;
for (count = 0; count < Argc; count ++) {
instance = strstr (Argv[count], Search); if (instance) {
return instance; } }
return 0;
}
BOOL UtpInitGenericLog ( PUCHAR Logfilename )
/*++
Routine Description:
This routine initializes a generic log (no NTLOG available)
Arguments:
Name of log file to create Return Value:
TRUE if successful FALSE if unsuccessful
--*/
#define UtpInitGenericLog_ENTRY 0x00000001
#define UtpInitGenericLog_CREATEFILE 0x00000002
#define UtpInitGenericLog_COMPLETION 0x00000004
{ UCHAR logfilepath [MAX_PATH]; BOOL bstatus = FALSE; PROGRESS_INIT ("UtpInitGenericLog"); PROGRESS_UPDATE (UtpInitGenericLog_ENTRY); if (strlen (Logfilename) > MAX_PATH) {
goto exitcleanup; }
strcpy (logfilepath, Logfilename); strcat (logfilepath, ".log");
g_log = CreateFile (logfilepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (g_log == INVALID_HANDLE_VALUE) {
goto exitcleanup; }
PROGRESS_UPDATE (UtpInitGenericLog_CREATEFILE);
UtLog (LOG_INFO, "GENERICLOG: %s initialized.", logfilepath); bstatus = TRUE; PROGRESS_UPDATE (UtpInitGenericLog_COMPLETION); exitcleanup: PROGRESS_END; return bstatus; }
BOOL UtpInitNtLog ( PUCHAR Logfilename )
/*++
Routine Description:
This routine initializes an NTLOG log file
Arguments:
Name of log file to create Return Value:
TRUE if successful FALSE if unsuccessful
--*/
//
// InitNTLOG progress bits
//
#define UtpInitNtLog_ENTRY 0x00000001
#define UtpInitNtLog_CREATELOG 0x00000002
#define UtpInitNtLog_ADDPARTICIPANT 0x00000004
#define UtpInitNtLog_COMPLETION 0x00000008
{ UCHAR logfilepath [MAX_PATH]; DWORD logstyle; BOOL bstatus = FALSE; PROGRESS_INIT ("UtpInitNtLog"); PROGRESS_UPDATE (UtpInitNtLog_ENTRY);
if (strlen (Logfilename) > MAX_PATH) {
goto exitcleanup; }
strcpy (logfilepath, Logfilename); strcat (logfilepath, ".log");
logstyle = TLS_LOGALL | TLS_MONITOR | TLS_REFRESH; g_log = _tlCreateLog(logfilepath, logstyle);
if (g_log == INVALID_HANDLE_VALUE) {
goto exitcleanup; }
PROGRESS_UPDATE (UtpInitNtLog_CREATELOG);
bstatus = _tlAddParticipant (g_log, 0, 0);
if (bstatus == FALSE) {
goto exitcleanup; }
PROGRESS_UPDATE (UtpInitNtLog_ADDPARTICIPANT);
UtLog (LOG_INFO, "NTLOG: %s initialized.", logfilepath); PROGRESS_UPDATE (UtpInitNtLog_COMPLETION);
bstatus = TRUE; exitcleanup:
//
// Cleanup
//
if (!(PROGRESS_GET & UtpInitNtLog_COMPLETION)) { if (PROGRESS_GET & UtpInitNtLog_ADDPARTICIPANT) { _tlRemoveParticipant (g_log); } if (PROGRESS_GET & UtpInitNtLog_CREATELOG) { _tlDestroyLog (g_log); }
g_log = INVALID_HANDLE_VALUE; }
if (PROGRESS_GET & UtpInitNtLog_COMPLETION) {
g_usentlog = TRUE; } PROGRESS_END; return bstatus; }
VOID UtpCloseGenericLog ( VOID )
/*++
Routine Description:
This routine closes a generic logging session.
Arguments:
None Return Value:
None
--*/
{ if (g_genericresult == TRUE) {
UtLog (LOG_INFO, "** TEST PASSED **");
} else { UtLog (LOG_INFO, "** TEST FAILED **");
}
FlushFileBuffers (g_log); CloseHandle (g_log); }
VOID UtpCloseNtLog ( VOID )
/*++
Routine Description:
This routine closes an NTLOG logging session.
Arguments:
None Return Value:
None
--*/
//
// CloseNTLOG progress bits
//
#define UtpCloseNtLog_ENTRY 0x00000001
#define UtpCloseNtLog_SUMMARIZE 0x00000002
#define UtpCloseNtLog_REMOVEPARTICIPANT 0x00000004
#define UtpCloseNtLog_DESTROYLOG 0x00000008
#define UtpCloseNtLog_COMPLETION 0x00000010
{ BOOL bstatus = FALSE;
PROGRESS_INIT ("UtpCloseNtLog"); PROGRESS_UPDATE (UtpCloseNtLog_ENTRY); if (g_log == INVALID_HANDLE_VALUE) {
goto exitcleanup; } _tlReportStats (g_log); PROGRESS_UPDATE (UtpCloseNtLog_SUMMARIZE); bstatus = _tlRemoveParticipant (g_log);
if (bstatus == FALSE) {
goto exitcleanup; }
PROGRESS_UPDATE (UtpCloseNtLog_REMOVEPARTICIPANT); bstatus = _tlDestroyLog (g_log);
if (bstatus == FALSE) {
goto exitcleanup; }
PROGRESS_UPDATE (UtpCloseNtLog_DESTROYLOG);
PROGRESS_UPDATE (UtpCloseNtLog_COMPLETION);
exitcleanup:
PROGRESS_END; return; }
VOID UtpLogGenericLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText )
/*++
Routine Description:
This routine enters a log event for a generic log file
Arguments:
LogEntryType - The type of entry to log LogText - Text describing the logging event Return Value:
None
--*/
#define UtpLogGenericLog_ENTRY 0x00000001
#define UtpLogGenericLog_LOG 0x00000002
#define UtpLogGenericLog_COMPLETION 0x00000004
{ UCHAR logentrytypetext [LOGENTRYTEXTLENGTH]; DWORD byteswritten = 0; BOOL bstatus = FALSE;
PROGRESS_INIT ("UtpLogGenericLog"); PROGRESS_UPDATE (UtpLogGenericLog_ENTRY); ZeroMemory (logentrytypetext, sizeof (logentrytypetext)); //
// Update our generic result - if we see a variation fail, the
// whole test is considered a failure.
//
if (g_genericresult == TRUE) {
g_genericresult = LogEntryType == LOG_FAIL ? FALSE : TRUE; }
switch (LogEntryType) { case LOG_PASS: strcpy (logentrytypetext, LOGENTRYTEXTPASS); break;
case LOG_FAIL: strcpy (logentrytypetext, LOGENTRYTEXTFAIL); break; case LOG_INFO: strcpy (logentrytypetext, LOGENTRYTEXTINFO); break;
default: break; }
bstatus = WriteFile (g_log, logentrytypetext, sizeof (logentrytypetext), &byteswritten, NULL);
bstatus = WriteFile (g_log, LogText, strlen (LogText), &byteswritten, NULL);
printf("%s%s", logentrytypetext, LogText); PROGRESS_UPDATE (UtpLogGenericLog_LOG); PROGRESS_UPDATE (UtpLogGenericLog_COMPLETION); }
VOID UtpLogNtLog ( LOG_ENTRY_TYPE LogEntryType, PUCHAR LogText )
/*++
Routine Description:
This routine enters a log event for NTLOG log files
Arguments:
LogEntryType - The type of entry to log LogText - Text describing the logging event Return Value:
None
--*/
#define UtpLogNtLog_ENTRY 0x00000001
#define UtpLogNtLog_LOG 0x00000002
#define UtpLogNtLog_COMPLETION 0x00000004
{ DWORD loglevel = 0; BOOL bstatus = FALSE; PROGRESS_INIT ("UtpLogNtLog"); PROGRESS_UPDATE (UtpLogNtLog_ENTRY);
loglevel = (LogEntryType == LOG_PASS ? TLS_PASS : 0) | (LogEntryType == LOG_FAIL ? TLS_SEV1 : 0) | (LogEntryType == LOG_INFO ? TLS_INFO : 0); bstatus = _tlLog (g_log, loglevel | TL_VARIATION, LogText); PROGRESS_UPDATE (UtpLogNtLog_LOG); PROGRESS_UPDATE (UtpLogNtLog_COMPLETION); }
|