DEV Community

carmeli-tamir
carmeli-tamir

Posted on • Updated on

How to write python unit tests for kernel code

Intro

Testing is a crucial part of every software project, and the Linux Kernel is no exception. Not to repeat many great articles about the subject such as this one,

the article will try to cover some of the testing efforts in the Linux Kernel community, based on an LWN article covering the topic.

The solutions for end to end testing category include syzbot which fuzzes the kernel to find crashes; kselftests and LTP that test kernel features such as cgroups, inotify, bpf, chmod and more; and kernelCI that tests the kernel boots on a variety of boards.

As for unit tests we have the recently merged to mainline KUnit and Oracle's KTF. In both frameworks tests are written in C and execute within the Kernel.

So, what's missing? Aside from having a couple of solutions that pretty much solve the same problem, it seems that the testing efforts are going in the right direction. However, if you want to unit test your code, you're going to have to write kernel code. Writing kernel code usually takes more time than writing python code, and certainly require a different skill and experience.

Skunk

Skunk aims to bridge the mentioned gap of time and skill, and enables Python programmers to unit test kernel code. It basically "wraps" kernel function calls in userspace and sends them to the Skunk Kernel Module, which performs the actual call and returns the response to user space.

Skunk uses a version of Google Protobuf that is ported to the Linux Kernel to pack and unpack function calls and return values. Generally speaking, parsing stuff in the kernel is considered a bad practice in terms of security since it might lead to all sorts of bugs and vulnerabilities. However, Skunk is only meant to run on a testing environment and definitely not on production.

The Skunk architecture is roughly:
Skunk Architecture

Let's consider this simple example of testing the kernel implementation of strstr:

sk = Skunk()
ret = sk.call_function_two_arg(
                                "strstr",                                               # Function name
                                2,                                                      # Number of arguments
                                skunk_pb2.FunctionCall.string,                          # Type of return value
                                "whatisthemeaningoflife", skunk_pb2.Argument.string,    # First argument value and type
                                "ning", skunk_pb2.Argument.string)                      # Second argument value and type

assert ret.string=="ningoflife", "error"

As you might have guessed, Skunk is just starting, and with the help of the open source community we aim to make it much more comfortable to use. In the longer term we also aim to enable mocking.

Summary

We reviewed some of the Linux Kernel testing solutions. We then introduced Skunk and explained that it might mitigate difficulties that currently exist when writing kernel UT.
Skunk needs your help to move forward. There are already open issues suitable for new comers. Any help is appreciated!

Top comments (0)