mirror of
https://github.com/reactos/reactos.git
synced 2025-08-08 16:03:27 +00:00
[KMTEST]
- Add support for recovering from crashed tests - Add check to prevent us from running the test every boot - Delete some useless code - Record test result information in the registry - Under the Kmtest\Parameters key, you will find CurrentStage which is the stage that testing is on (almost always 8 if it boots). You will also find <Test Name>SuccessCount which is the number of successful tests, <Test Name>FailureCount which is the number of failed tests, <Test Name>TotalCount which is the total number of tests, and <Test Name>SkippedCount which is the number of tests that have been skipped - Enjoy your reg testing! :) svn path=/trunk/; revision=47309
This commit is contained in:
parent
d7bbeaed19
commit
afcd401a32
10 changed files with 330 additions and 676 deletions
|
@ -25,8 +25,12 @@
|
|||
#include <ddk/ntddk.h>
|
||||
#include "kmtest.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
LONG successes;
|
||||
LONG failures;
|
||||
LONG skipped;
|
||||
tls_data glob_data;
|
||||
|
||||
/* PRIVATE FUNCTIONS ***********************************************************/
|
||||
|
@ -35,12 +39,61 @@ StartTest()
|
|||
{
|
||||
successes = 0;
|
||||
failures = 0;
|
||||
skipped = 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
FinishTest(LPSTR TestName)
|
||||
FinishTest(HANDLE KeyHandle, LPWSTR TestName)
|
||||
{
|
||||
DbgPrint("%s: %d test executed (0 marked as todo, %d failures), 0 skipped.\n", TestName, successes + failures, failures);
|
||||
WCHAR KeyName[100];
|
||||
LONG total = successes + failures;
|
||||
UNICODE_STRING KeyNameU;
|
||||
|
||||
wcscpy(KeyName, TestName);
|
||||
wcscat(KeyName, L"SuccessCount");
|
||||
RtlInitUnicodeString(&KeyNameU, KeyName);
|
||||
|
||||
ZwSetValueKey(KeyHandle,
|
||||
&KeyNameU,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&successes,
|
||||
sizeof(ULONG));
|
||||
|
||||
wcscpy(KeyName, TestName);
|
||||
wcscat(KeyName, L"FailureCount");
|
||||
RtlInitUnicodeString(&KeyNameU, KeyName);
|
||||
|
||||
ZwSetValueKey(KeyHandle,
|
||||
&KeyNameU,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&failures,
|
||||
sizeof(ULONG));
|
||||
|
||||
wcscpy(KeyName, TestName);
|
||||
wcscat(KeyName, L"TotalCount");
|
||||
RtlInitUnicodeString(&KeyNameU, KeyName);
|
||||
|
||||
ZwSetValueKey(KeyHandle,
|
||||
&KeyNameU,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&total,
|
||||
sizeof(ULONG));
|
||||
|
||||
wcscpy(KeyName, TestName);
|
||||
wcscat(KeyName, L"SkipCount");
|
||||
RtlInitUnicodeString(&KeyNameU, KeyName);
|
||||
|
||||
ZwSetValueKey(KeyHandle,
|
||||
&KeyNameU,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&skipped,
|
||||
sizeof(ULONG));
|
||||
|
||||
DbgPrint("%S: %d test executed (0 marked as todo, %d failures), %d skipped.\n", TestName, total, failures, skipped);
|
||||
}
|
||||
|
||||
void kmtest_set_location(const char* file, int line)
|
||||
|
@ -105,11 +158,14 @@ PWCHAR CreateLowerDeviceRegistryKey(PUNICODE_STRING RegistryPath, PWCHAR NewDriv
|
|||
/*
|
||||
* Test Declarations
|
||||
*/
|
||||
VOID NtoskrnlIoTests();
|
||||
VOID NtoskrnlKeTests();
|
||||
VOID NtoskrnlObTest();
|
||||
VOID NtoskrnlExecutiveTests();
|
||||
VOID NtoskrnlPoolsTest();
|
||||
VOID RegisterDI_Test(HANDLE KeyHandle);
|
||||
VOID NtoskrnlIoMdlTest(HANDLE KeyHandle);
|
||||
VOID NtoskrnlIoIrpTest(HANDLE KeyHandle);
|
||||
VOID NtoskrnlObTest(HANDLE KeyHandle);
|
||||
VOID ExTimerTest(HANDLE KeyHandle);
|
||||
VOID PoolsTest(HANDLE KeyHandle);
|
||||
VOID PoolsCorruption(HANDLE KeyHandle);
|
||||
VOID KeStallTest(HANDLE KeyHandle);
|
||||
VOID DriverObjectTest(PDRIVER_OBJECT, int);
|
||||
VOID DeviceCreateDeleteTest(PDRIVER_OBJECT);
|
||||
VOID DeviceObjectTest(PDEVICE_OBJECT);
|
||||
|
@ -119,6 +175,19 @@ BOOLEAN DetachDeviceTest(PDEVICE_OBJECT);
|
|||
BOOLEAN AttachDeviceTest(PDEVICE_OBJECT, PWCHAR);
|
||||
VOID LowerDeviceKernelAPITest(PDEVICE_OBJECT, BOOLEAN);
|
||||
|
||||
typedef enum {
|
||||
TestStageExTimer = 0,
|
||||
TestStageIoMdl,
|
||||
TestStageIoDi,
|
||||
TestStageIoIrp,
|
||||
TestStageMmPoolTest,
|
||||
TestStageMmPoolCorruption,
|
||||
TestStageOb,
|
||||
TestStageKeStall,
|
||||
TestStageDrv,
|
||||
TestStageMax
|
||||
} TEST_STAGE;
|
||||
|
||||
/*
|
||||
* KmtestDispatch
|
||||
*/
|
||||
|
@ -192,7 +261,148 @@ KmtestUnload(IN PDRIVER_OBJECT DriverObject)
|
|||
|
||||
IoDeleteDevice(MainDeviceObject);
|
||||
}
|
||||
FinishTest("Driver Tests");
|
||||
}
|
||||
|
||||
static
|
||||
PKEY_VALUE_PARTIAL_INFORMATION
|
||||
NTAPI
|
||||
ReadRegistryValue(HANDLE KeyHandle, PWCHAR ValueName)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION InformationBuffer = NULL;
|
||||
ULONG AllocatedLength = 0, RequiredLength = 0;
|
||||
UNICODE_STRING ValueNameU;
|
||||
|
||||
RtlInitUnicodeString(&ValueNameU, ValueName);
|
||||
|
||||
Status = ZwQueryValueKey(KeyHandle,
|
||||
&ValueNameU,
|
||||
KeyValuePartialInformation,
|
||||
NULL,
|
||||
0,
|
||||
&RequiredLength);
|
||||
if (Status == STATUS_BUFFER_TOO_SMALL || Status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
InformationBuffer = ExAllocatePool(PagedPool, RequiredLength);
|
||||
AllocatedLength = RequiredLength;
|
||||
if (!InformationBuffer) return NULL;
|
||||
|
||||
Status = ZwQueryValueKey(KeyHandle,
|
||||
&ValueNameU,
|
||||
KeyValuePartialInformation,
|
||||
InformationBuffer,
|
||||
AllocatedLength,
|
||||
&RequiredLength);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to read %S (0x%x)\n", ValueName, Status);
|
||||
if (InformationBuffer != NULL)
|
||||
ExFreePool(InformationBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return InformationBuffer;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
RunKernelModeTest(PDRIVER_OBJECT DriverObject,
|
||||
PUNICODE_STRING RegistryPath,
|
||||
HANDLE KeyHandle,
|
||||
TEST_STAGE Stage)
|
||||
{
|
||||
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"CurrentStage");
|
||||
PWCHAR LowerDriverRegPath;
|
||||
|
||||
DPRINT1("Running stage %d test...\n", Stage);
|
||||
|
||||
ZwSetValueKey(KeyHandle,
|
||||
&KeyName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&Stage,
|
||||
sizeof(ULONG));
|
||||
|
||||
switch (Stage)
|
||||
{
|
||||
case TestStageExTimer:
|
||||
ExTimerTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageIoMdl:
|
||||
NtoskrnlIoMdlTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageIoDi:
|
||||
RegisterDI_Test(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageIoIrp:
|
||||
NtoskrnlIoIrpTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageMmPoolTest:
|
||||
PoolsTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageMmPoolCorruption:
|
||||
PoolsCorruption(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageOb:
|
||||
NtoskrnlObTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageKeStall:
|
||||
KeStallTest(KeyHandle);
|
||||
break;
|
||||
|
||||
case TestStageDrv:
|
||||
/* Start the tests for the driver routines */
|
||||
StartTest();
|
||||
|
||||
/* Do DriverObject Test for Driver Entry */
|
||||
DriverObjectTest(DriverObject, 0);
|
||||
|
||||
/* Create and delete device, on return MainDeviceObject has been created */
|
||||
DeviceCreateDeleteTest(DriverObject);
|
||||
|
||||
/* Make sure a device object was created */
|
||||
if (MainDeviceObject)
|
||||
{
|
||||
LowerDriverRegPath = CreateLowerDeviceRegistryKey(RegistryPath, L"kmtestassist");
|
||||
|
||||
if (LowerDriverRegPath)
|
||||
{
|
||||
/* Load driver test and load the lower driver */
|
||||
if (ZwLoadTest(DriverObject, RegistryPath, LowerDriverRegPath))
|
||||
{
|
||||
AttachDeviceTest(MainDeviceObject, L"kmtestassists");
|
||||
if (AttachDeviceObject)
|
||||
{
|
||||
LowerDeviceKernelAPITest(MainDeviceObject, FALSE);
|
||||
}
|
||||
|
||||
/* Unload lower driver without detaching from its device */
|
||||
ZwUnloadTest(DriverObject, RegistryPath, LowerDriverRegPath);
|
||||
LowerDeviceKernelAPITest(MainDeviceObject, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("Failed to load kmtestassist driver\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FinishTest(KeyHandle, L"DriverTest");
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -204,61 +414,98 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
|
|||
PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
int i;
|
||||
PWCHAR LowerDriverRegPath;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING ParameterKeyName = RTL_CONSTANT_STRING(L"Parameters");
|
||||
PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
|
||||
PULONG KeyValue;
|
||||
TEST_STAGE CurrentStage;
|
||||
HANDLE DriverKeyHandle, ParameterKeyHandle;
|
||||
|
||||
DbgPrint("\n===============================================\n");
|
||||
DbgPrint("Kernel Mode Regression Driver Test starting...\n");
|
||||
DbgPrint("===============================================\n");
|
||||
|
||||
MainDeviceObject = NULL;
|
||||
AttachDeviceObject = NULL;
|
||||
ThisDriverObject = DriverObject;
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
RegistryPath,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
NtoskrnlExecutiveTests();
|
||||
NtoskrnlKeTests();
|
||||
NtoskrnlIoTests();
|
||||
NtoskrnlObTest();
|
||||
NtoskrnlPoolsTest();
|
||||
|
||||
/* Start the tests for the driver routines */
|
||||
StartTest();
|
||||
|
||||
/* Do DriverObject Test for Driver Entry */
|
||||
DriverObjectTest(DriverObject, 0);
|
||||
/* Create and delete device, on return MainDeviceObject has been created */
|
||||
DeviceCreateDeleteTest(DriverObject);
|
||||
|
||||
/* Make sure a device object was created */
|
||||
if (MainDeviceObject)
|
||||
Status = ZwOpenKey(&DriverKeyHandle,
|
||||
KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
LowerDriverRegPath = CreateLowerDeviceRegistryKey(RegistryPath, L"kmtestassist");
|
||||
DPRINT1("Failed to open %wZ\n", RegistryPath);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (LowerDriverRegPath)
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&ParameterKeyName,
|
||||
OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
||||
DriverKeyHandle,
|
||||
NULL);
|
||||
Status = ZwCreateKey(&ParameterKeyHandle,
|
||||
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
NULL);
|
||||
ZwClose(DriverKeyHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to create %wZ\\%wZ\n", RegistryPath, &ParameterKeyName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
KeyInfo = ReadRegistryValue(ParameterKeyHandle, L"CurrentStage");
|
||||
if (KeyInfo)
|
||||
{
|
||||
if (KeyInfo->DataLength != sizeof(ULONG))
|
||||
{
|
||||
/* Load driver test and load the lower driver */
|
||||
if (ZwLoadTest(DriverObject, RegistryPath, LowerDriverRegPath))
|
||||
{
|
||||
AttachDeviceTest(MainDeviceObject, L"kmtestassists");
|
||||
if (AttachDeviceObject)
|
||||
{
|
||||
LowerDeviceKernelAPITest(MainDeviceObject, FALSE);
|
||||
}
|
||||
|
||||
/* Unload lower driver without detaching from its device */
|
||||
ZwUnloadTest(DriverObject, RegistryPath, LowerDriverRegPath);
|
||||
LowerDeviceKernelAPITest(MainDeviceObject, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgPrint("Failed to load kmtestassist driver\n");
|
||||
}
|
||||
DPRINT1("Invalid data length for CurrentStage: %d\n", KeyInfo->DataLength);
|
||||
ExFreePool(KeyInfo);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
KeyValue = (PULONG)KeyInfo->Data;
|
||||
|
||||
if ((*KeyValue) + 1 < TestStageMax)
|
||||
{
|
||||
DPRINT1("Resuming testing after a crash at stage %d\n", (*KeyValue));
|
||||
|
||||
CurrentStage = (TEST_STAGE)((*KeyValue) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Testing was completed on a previous boot\n");
|
||||
ExFreePool(KeyInfo);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ExFreePool(KeyInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
DPRINT1("Starting a fresh test\n");
|
||||
CurrentStage = (TEST_STAGE)0;
|
||||
}
|
||||
|
||||
/* Run the tests */
|
||||
while (CurrentStage < TestStageMax)
|
||||
{
|
||||
RunKernelModeTest(DriverObject,
|
||||
RegistryPath,
|
||||
ParameterKeyHandle,
|
||||
CurrentStage);
|
||||
CurrentStage++;
|
||||
}
|
||||
|
||||
DPRINT1("Testing is complete!\n");
|
||||
ZwClose(ParameterKeyHandle);
|
||||
|
||||
/* Set all MajorFunctions to NULL to verify that kernel fixes them */
|
||||
for (i = 1; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
||||
DriverObject->MajorFunction[i] = NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue