Kernel mode Unit tests

Given that it is 2021, are there any good unit test frameworks for kernel mode? So far we have been just trying to compile everything in user mode as much a possible, but it doesn’t always work, and faking the NTOS kernel apis is a huge job in itself.

Wanted to check what you folks are using these days, or any other bright ideas in this regard also helps.

Making a shared library that compiles in user- and kernel- mode is the best I have seen for proper unit tests.

I have also seen writing an entry point such as IOCTL or Flt communication port for your driver that executes test code. This has the benefit of running in kernel mode, and not requiring goofy translation to make things work in usermode.

On top of that I have done things like build a driver to attach above my real driver, and then user mode tests that call down to that to exercise specific code paths and test their returns, and user mode tests that call filesys operations at the usermode level. Both of those are technically integration tests, but still useful.

@Jeremy_Hurren said:
Making a shared library that compiles in user- and kernel- mode is the best I have seen for proper unit tests.

I have also seen writing an entry point such as IOCTL or Flt communication port for your driver that executes test code. This has the benefit of running in kernel mode, and not requiring goofy translation to make things work in usermode.

On top of that I have done things like build a driver to attach above my real driver, and then user mode tests that call down to that to exercise specific code paths and test their returns, and user mode tests that call filesys operations at the usermode level. Both of those are technically integration tests, but still useful.

Yes, these are pretty much what we have, for the sandwich mode those only work for devices which have filtering though.

There tend to be at least three different “parts” of driver functionality… and they each lend themselves to distinct testing disciplines:

One part is the device-interface logic, which deals with register manipulation and device service. This is really the hardest to test, if you ask me. And testing it is entirely hardware dependent.

The second part is the OS interface logic, where you get, queue, and process Requests and the data gotten from and returned to them. Reasonable testing here can be done using a combination of Static Analysis and the Driver Verifiers (with the device/driver “put through its paces” via custom code).

The third and final part is any significant data structure manipulation and algorithmic code your driver may contain. This best lends its self to compontentization and testing in user mode. We wrote an article about this a while back in The NT Insider.

Of course, there’s also more special-purpose types of testing as well, like security tests with fuzzing and such.

As you see, none of the above really lend themselves to an off-the-shelf testing framework.

Peter

@“Peter_Viscarola_(OSR)” said:
There tend to be at least three different “parts” of driver functionality… and they each lend themselves to distinct testing disciplines:

One part is the device-interface logic, which deals with register manipulation and device service. This is really the hardest to test, if you ask me. And testing it is entirely hardware dependent.

The second part is the OS interface logic, where you get, queue, and process Requests and the data gotten from and returned to them. Reasonable testing here can be done using a combination of Static Analysis and the Driver Verifiers (with the device/driver “put through its paces” via custom code).

The third and final part is any significant data structure manipulation and algorithmic code your driver may contain. This best lends its self to compontentization and testing in user mode. We wrote an article about this a while back in The NT Insider.

Of course, there’s also more special-purpose types of testing as well, like security tests with fuzzing and such.

As you see, none of the above really lend themselves to an off-the-shelf testing framework.

Peter

Since we are on the topic of user mode testing, has OSR ever tried write C++ drivers. I ask from the perspective of testing ease.
void foo()
{
do stuff…
ExAllocatePoolWithTag();
do other stuff…
}
This pattern of static binding will make us fake the ExAllocatePoolWithTag()

however making it a bit more C++y
void foo()
{
do stuff…
IOSInterface->MyWrapperForExAllocatePoolWithTag();
do other stuff…
}
makes replacing the IOSInterface object with a mocked one using google mocks easier.

Just wanted to know if you guys have tried both, and what your experience has been?

has OSR ever tried write C++ drivers

There have been sooooo many posts on this topic over the years, I’d really rather not review it all here.

tl;dr C++ as a better C, yes… good idea. Drivers using fully a OO C++ design? Very bad idea. Creates a big mess. The native API is a C API after all. I really don’t think myThing->AlloccateMemory is any different from calling MyThingAllocateMemory that “does the right thing” user-mode vs kernel-mode.

Did you read the article I linked?

PEter

@“Peter_Viscarola_(OSR)” said:
Did you read the article I linked?

Yes, I had read it before.

Essentially all of my drivers are in C++, using C++ features. Almost all streaming drivers are in C++ because the samples have been in C++ since the days of Win98. In some cases (audio in particular), the port/miniport models require C++ and the use of derived classes.