diff --git a/reactos/regtests/regtests/regtests.c b/reactos/regtests/regtests/regtests.c
index b904be16378..e321aaef745 100755
--- a/reactos/regtests/regtests/regtests.c
+++ b/reactos/regtests/regtests/regtests.c
@@ -98,3 +98,27 @@ _GetCurrentThread()
{
return GetCurrentThread();
}
+
+BOOL STDCALL
+_GetThreadContext(HANDLE hThread, LPCONTEXT lpContext)
+{
+ return GetThreadContext(hThread, lpContext);
+}
+
+DWORD STDCALL
+_SuspendThread(HANDLE hThread)
+{
+ return SuspendThread(hThread);
+}
+
+DWORD STDCALL
+_ResumeThread(HANDLE hThread)
+{
+ return ResumeThread(hThread);
+}
+
+VOID STDCALL
+_Sleep(DWORD dwMilliseconds)
+{
+ return Sleep(dwMilliseconds);
+}
diff --git a/reactos/regtests/regtests/regtests.def b/reactos/regtests/regtests/regtests.def
index 166d55050f9..3cd1eec7de4 100644
--- a/reactos/regtests/regtests/regtests.def
+++ b/reactos/regtests/regtests/regtests.def
@@ -14,3 +14,7 @@ _SetPriorityClass@8
_SetThreadPriority@8
_GetCurrentProcess@0
_GetCurrentThread@0
+_GetThreadContext@8
+_SuspendThread@4
+_ResumeThread@4
+_Sleep@4
diff --git a/reactos/regtests/shared/regtests.c b/reactos/regtests/shared/regtests.c
index 9c142a645a9..adc14c7da96 100755
--- a/reactos/regtests/shared/regtests.c
+++ b/reactos/regtests/shared/regtests.c
@@ -24,6 +24,9 @@ typedef struct _PERFORM_TEST_ARGS
TestOutputRoutine OutputRoutine;
_PTEST Test;
LPSTR TestName;
+ DWORD Result;
+ char Buffer[5000];
+ DWORD Time;
} PERFORM_TEST_ARGS;
int _Result;
@@ -38,13 +41,11 @@ InitializeTests()
}
char*
-FormatExecutionTime(char *buffer, LPFILETIME time)
+FormatExecutionTime(char *buffer, ULONG milliseconds)
{
- ULONG milliseconds = time->dwLowDateTime / 10000;
-
sprintf(buffer,
- "%ldms",
- milliseconds);
+ "%ldms",
+ milliseconds);
return buffer;
}
@@ -52,55 +53,147 @@ DWORD WINAPI
PerformTest(PVOID _arg)
{
PERFORM_TEST_ARGS *Args = (PERFORM_TEST_ARGS *)_arg;
- TestOutputRoutine OutputRoutine = Args->OutputRoutine;
_PTEST Test = Args->Test;
- LPSTR TestName = Args->TestName;
- HANDLE hThread;
+
+ _SetThreadPriority(_GetCurrentThread(), THREAD_PRIORITY_IDLE);
+
+ memset(Args->Buffer, 0, sizeof(Args->Buffer));
+
+ _SEH_TRY {
+ _Result = TS_OK;
+ _Buffer = Args->Buffer;
+ (Test->Routine)(TESTCMD_RUN);
+ Args->Result = _Result;
+ } _SEH_HANDLE {
+ Args->Result = TS_FAILED;
+ sprintf(Args->Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
+ } _SEH_END;
+ return 1;
+}
+
+BOOL
+IsContextChanged(LPCONTEXT context1, LPCONTEXT context2)
+{
+ return memcmp(context1, context2, sizeof(CONTEXT)) != 0;
+}
+
+VOID
+ControlNormalTest(HANDLE hThread,
+ PERFORM_TEST_ARGS *Args,
+ DWORD TimeOut)
+{
FILETIME time;
- FILETIME ExecutionTime;
- char OutputBuffer[5000];
+ FILETIME executionTime;
+ DWORD status;
+
+ status = _WaitForSingleObject(hThread, TimeOut);
+ if (status == WAIT_TIMEOUT)
+ {
+ _TerminateThread(hThread, 0);
+ Args->Result = TS_TIMEDOUT;
+ }
+ status = _GetThreadTimes(hThread,
+ &time,
+ &time,
+ &time,
+ &executionTime);
+ Args->Time = executionTime.dwLowDateTime / 10000;
+}
+
+VOID
+ControlPerformanceTest(HANDLE hThread,
+ PERFORM_TEST_ARGS *Args,
+ DWORD TimeOut)
+{
+ DWORD status;
+ CONTEXT lastContext;
+ CONTEXT currentContext;
+
+ ZeroMemory(&lastContext, sizeof(CONTEXT));
+ lastContext.ContextFlags = CONTEXT_FULL;
+ ZeroMemory(¤tContext, sizeof(CONTEXT));
+ currentContext.ContextFlags = CONTEXT_FULL;
+
+ do {
+ _Sleep(1);
+
+ if (_SuspendThread(hThread) == -1)
+ break;
+
+ if (_GetThreadContext(hThread, ¤tContext) == 0)
+ break;
+
+ if (IsContextChanged(¤tContext, &lastContext))
+ Args->Time++;
+
+ if (_ResumeThread(hThread) == -1)
+ break;
+
+ if (Args->Time >= TimeOut)
+ {
+ _TerminateThread(hThread, 0);
+ Args->Result = TS_TIMEDOUT;
+ break;
+ }
+
+ status = _WaitForSingleObject(hThread, 0);
+ if (status == WAIT_OBJECT_0 || status == WAIT_FAILED)
+ break;
+
+ lastContext = currentContext;
+ } while (TRUE);
+}
+
+VOID
+DisplayResult(PERFORM_TEST_ARGS* Args,
+ LPSTR OutputBuffer)
+{
char Buffer[5000];
char Format[100];
- hThread = _GetCurrentThread();
- _SetThreadPriority(hThread, THREAD_PRIORITY_IDLE);
-
- memset(Buffer, 0, sizeof(Buffer));
-
- _SEH_TRY {
- _Result = TS_OK;
- _Buffer = Buffer;
- (Test->Routine)(TESTCMD_RUN);
- } _SEH_HANDLE {
- _Result = TS_FAILED;
- sprintf(Buffer, "due to exception 0x%lx", _SEH_GetExceptionCode());
- } _SEH_END;
-
- if (_Result == TS_OK)
+ if (Args->Result == TS_OK)
{
- if (!_GetThreadTimes(hThread,
- &time,
- &time,
- &time,
- &ExecutionTime))
- {
- ExecutionTime.dwLowDateTime = 0;
- ExecutionTime.dwHighDateTime = 0;
- }
sprintf(OutputBuffer,
"[%s] Success [%s]\n",
- TestName,
+ Args->TestName,
FormatExecutionTime(Format,
- &ExecutionTime));
+ Args->Time));
+ }
+ else if (Args->Result == TS_TIMEDOUT)
+ {
+ sprintf(OutputBuffer,
+ "[%s] Timed out [%s]\n",
+ Args->TestName,
+ FormatExecutionTime(Format,
+ Args->Time));
}
else
- sprintf(OutputBuffer, "[%s] Failed (%s)\n", TestName, Buffer);
+ sprintf(OutputBuffer, "[%s] Failed (%s)\n", Args->TestName, Buffer);
- if (OutputRoutine != NULL)
- (*OutputRoutine)(OutputBuffer);
+ if (Args->OutputRoutine != NULL)
+ (*Args->OutputRoutine)(OutputBuffer);
else
- DbgPrint(OutputBuffer);
- return 1;
+ DbgPrint(OutputBuffer);
+}
+
+VOID
+ControlTest(HANDLE hThread,
+ PERFORM_TEST_ARGS *Args,
+ DWORD TestType,
+ DWORD TimeOut)
+{
+ switch (TestType)
+ {
+ case TT_NORMAL:
+ ControlNormalTest(hThread, Args, TimeOut);
+ break;
+ case TT_PERFORMANCE:
+ ControlPerformanceTest(hThread, Args, TimeOut);
+ break;
+ default:
+ printf("Unknown test type %ld\n", TestType);
+ break;
+ }
}
VOID
@@ -113,11 +206,13 @@ PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
HANDLE hThread;
char OutputBuffer[1024];
char Name[200];
+ DWORD TestType;
DWORD TimeOut;
Args.OutputRoutine = OutputRoutine;
Args.TestName = Name;
-
+ Args.Time = 0;
+
CurrentEntry = AllTests.Flink;
for (; CurrentEntry != &AllTests; CurrentEntry = NextEntry)
{
@@ -141,40 +236,34 @@ PerformTests(TestOutputRoutine OutputRoutine, LPSTR TestName)
if ((TestName != NULL) && (_stricmp(Name, TestName) != 0))
continue;
+ TestType = TT_NORMAL;
+ _Result = TS_OK;
+ _Buffer = (char *)&TestType;
+ (Current->Routine)(TESTCMD_TESTTYPE);
+ if (_Result != TS_OK)
+ TestType = TT_NORMAL;
+
/* Get timeout for test */
TimeOut = 0;
_Result = TS_OK;
_Buffer = (char *)&TimeOut;
(Current->Routine)(TESTCMD_TIMEOUT);
if (_Result != TS_OK || TimeOut == INFINITE)
- TimeOut = 5000;
+ TimeOut = 5000;
- /* Run test in thread */
+ /* Run test in a separate thread */
hThread = _CreateThread(NULL, 0, PerformTest, (PVOID)&Args, 0, NULL);
if (hThread == NULL)
- sprintf(OutputBuffer,
- "[%s] Failed (CreateThread() failed: %d)\n",
- Name, (unsigned int)_GetLastError());
- else if (_WaitForSingleObject(hThread, TimeOut) == WAIT_TIMEOUT)
{
- if (!_TerminateThread(hThread, 0))
- sprintf(OutputBuffer,
- "[%s] Failed (timed out after %dms; TerminateThread() failed: %d)\n",
- Name, (int)TimeOut, (unsigned int)_GetLastError());
- else
- sprintf(OutputBuffer, "[%s] Failed (timed out after %dms)\n", Name, (int)TimeOut);
- _CloseHandle(hThread);
+ printf("[%s] Failed (CreateThread() failed: %ld)\n",
+ Name,
+ _GetLastError());
+ Args.Result = TS_FAILED;
}
else
- {
- _CloseHandle(hThread);
- continue;
- }
+ ControlTest(hThread, &Args, TestType, TimeOut);
- if (OutputRoutine != NULL)
- (*OutputRoutine)(OutputBuffer);
- else
- DbgPrint(OutputBuffer);
+ DisplayResult(&Args, OutputBuffer);
}
}
diff --git a/reactos/regtests/shared/regtests.h b/reactos/regtests/shared/regtests.h
index 93ce5fe7fa6..65df8c2028c 100755
--- a/reactos/regtests/shared/regtests.h
+++ b/reactos/regtests/shared/regtests.h
@@ -16,10 +16,16 @@ void SetupOnce()
/* Valid values for Command parameter of TestRoutine */
#define TESTCMD_RUN 0 /* Buffer contains information about what failed */
-#define TESTCMD_TESTNAME 1 /* Buffer contains description of test */
-#define TESTCMD_TIMEOUT 2 /* Buffer contains timeout for test (DWORD, default is 5000 ms) */
+#define TESTCMD_TESTTYPE 1 /* Buffer contains type of test */
+#define TESTCMD_TESTNAME 2 /* Buffer contains description of test */
+#define TESTCMD_TIMEOUT 3 /* Buffer contains timeout for test (DWORD, default is 5000 ms) */
+
+/* Test types */
+#define TT_NORMAL 0
+#define TT_PERFORMANCE 1
/* Valid values for return values of TestRoutine */
+#define TS_TIMEDOUT -2
#define TS_EXCEPTION -1
#define TS_OK 0
#define TS_FAILED 1
@@ -28,7 +34,7 @@ extern int _Result;
extern char *_Buffer;
/* Macros to simplify tests */
-#define _DispatcherTimeout(FunctionName, TestName, TimeOut) \
+#define _DispatcherTypeTimeout(FunctionName, TestName, TestType, TimeOut) \
void \
FunctionName(int Command) \
{ \
@@ -37,6 +43,9 @@ FunctionName(int Command) \
case TESTCMD_RUN: \
RunTest(); \
break; \
+ case TESTCMD_TESTTYPE: \
+ *(PDWORD)_Buffer = (DWORD)TestType; \
+ break; \
case TESTCMD_TESTNAME: \
strcpy(_Buffer, TestName); \
break; \
@@ -49,7 +58,14 @@ FunctionName(int Command) \
} \
}
-#define _Dispatcher(FunctionName, TestName) _DispatcherTimeout(FunctionName, TestName, 5000)
+#define _DispatcherTimeout(FunctionName, TestName, TimeOut) \
+ _DispatcherTypeTimeout(FunctionName, TestName, TT_NORMAL, TimeOut)
+
+#define _DispatcherType(FunctionName, TestName, TestType) \
+ _DispatcherTypeTimeout(FunctionName, TestName, TestType, 5000)
+
+#define _Dispatcher(FunctionName, TestName) \
+ _DispatcherTimeout(FunctionName, TestName, 5000)
static inline void
AppendAssertion(char *message)
@@ -211,6 +227,18 @@ _GetCurrentProcess();
HANDLE STDCALL
_GetCurrentThread();
+BOOL STDCALL
+_GetThreadContext(HANDLE hThread, LPCONTEXT lpContext);
+
+DWORD STDCALL
+_SuspendThread(HANDLE hThread);
+
+DWORD STDCALL
+_ResumeThread(HANDLE hThread);
+
+VOID STDCALL
+_Sleep(DWORD dwMilliseconds);
+
static inline PCHAR
FrameworkGetExportedFunctionNameInternal(_PAPI_DESCRIPTION ApiDescription)
diff --git a/reactos/subsys/win32k/tests/stubs.xml b/reactos/subsys/win32k/tests/stubs.xml
index 06dd4a94257..b5abcec6b5d 100644
--- a/reactos/subsys/win32k/tests/stubs.xml
+++ b/reactos/subsys/win32k/tests/stubs.xml
@@ -136,6 +136,8 @@
ObReferenceObjectByName@32
HalQueryDisplayOwnership@0
IoDeviceObjectType
+ @KfReleaseSpinLock@8
+ @KfAcquireSpinLock@4
FT_Init_FreeType
diff --git a/reactos/subsys/win32k/tests/tests/DIB_24BPP_ColorFill-performance.c b/reactos/subsys/win32k/tests/tests/DIB_24BPP_ColorFill-performance.c
index 3d1b8237101..60e4cb8ee32 100644
--- a/reactos/subsys/win32k/tests/tests/DIB_24BPP_ColorFill-performance.c
+++ b/reactos/subsys/win32k/tests/tests/DIB_24BPP_ColorFill-performance.c
@@ -31,7 +31,7 @@ static void RunTest()
UINT i;
SetupSurface(&surface, &rect);
- for (i = 0; i < 1000; i++)
+ for (i = 0; i < 10000; i++)
{
BOOLEAN success = DIB_24BPP_ColorFill(&surface, &rect, color);
_AssertTrue(success);
@@ -41,4 +41,4 @@ static void RunTest()
CleanupSurface(&surface);
}
-_Dispatcher(Dib_24bpp_colorfill_performanceTest, "DIB_24BPP_ColorFill performance")
+_DispatcherType(Dib_24bpp_colorfill_performanceTest, "DIB_24BPP_ColorFill performance", TT_PERFORMANCE)
diff --git a/reactos/tools/rbuild/testsupportcode.cpp b/reactos/tools/rbuild/testsupportcode.cpp
index f35b9af7465..e238e0eaab0 100644
--- a/reactos/tools/rbuild/testsupportcode.cpp
+++ b/reactos/tools/rbuild/testsupportcode.cpp
@@ -364,8 +364,9 @@ TestSupportCode::WriteStartupFile ( Module& module )
s = s + sprintf ( s, " LPSTR lpszCmdParam,\n" );
s = s + sprintf ( s, " int nCmdShow)\n" );
s = s + sprintf ( s, "{\n" );
- s = s + sprintf ( s, " _SetPriorityClass(_GetCurrentProcess(), IDLE_PRIORITY_CLASS);\n" );
- s = s + sprintf ( s, " InitializeTests();\n" );
+ s = s + sprintf ( s, " _SetPriorityClass(_GetCurrentProcess(), HIGH_PRIORITY_CLASS);\n" );
+ s = s + sprintf ( s, " _SetThreadPriority(_GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);\n" );
+ s = s + sprintf ( s, " InitializeTests();\n" );
s = s + sprintf ( s, " RegisterTests();\n" );
s = s + sprintf ( s, " SetupOnce();\n" );
s = s + sprintf ( s, " PerformTests(ConsoleWrite, NULL);\n" );