Windows-Server-2003/public/internal/base/inc/unittest.h

1014 lines
18 KiB
C

/*++
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);
}