Skip to content

Commit

Permalink
Merge tag 'linux-kselftest-kunit-5.11-rc1' of git://git.kernel.org/pu…
Browse files Browse the repository at this point in the history
…b/scm/linux/kernel/git/shuah/linux-kselftest

Pull Kunit updates from Shuah Khan:

 - documentation update and fix to kunit_tool to parse diagnostic
   messages correctly from David Gow

 - Support for Parameterized Testing and fs/ext4 test updates to use
   KUnit parameterized testing feature from Arpitha Raghunandan

 - Helper to derive file names depending on --build_dir argument from
   Andy Shevchenko

* tag 'linux-kselftest-kunit-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  fs: ext4: Modify inode-test.c to use KUnit parameterized testing feature
  kunit: Support for Parameterized Testing
  kunit: kunit_tool: Correctly parse diagnostic messages
  Documentation: kunit: provide guidance for testing many inputs
  kunit: Introduce get_file_path() helper
  • Loading branch information
Linus Torvalds committed Dec 16, 2020
2 parents 7194850 + 5f6b99d commit 706451d
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 193 deletions.
83 changes: 77 additions & 6 deletions Documentation/dev-tools/kunit/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ project, see :doc:`start`.
Organization of this document
=============================

This document is organized into two main sections: Testing and Isolating
Behavior. The first covers what unit tests are and how to use KUnit to write
them. The second covers how to use KUnit to isolate code and make it possible
to unit test code that was otherwise un-unit-testable.
This document is organized into two main sections: Testing and Common Patterns.
The first covers what unit tests are and how to use KUnit to write them. The
second covers common testing patterns, e.g. how to isolate code and make it
possible to unit test code that was otherwise un-unit-testable.

Testing
=======
Expand Down Expand Up @@ -218,8 +218,11 @@ test was built in or not).

For more information on these types of things see the :doc:`api/test`.

Common Patterns
===============

Isolating Behavior
==================
------------------

The most important aspect of unit testing that other forms of testing do not
provide is the ability to limit the amount of code under test to a single unit.
Expand All @@ -233,7 +236,7 @@ implementer, and architecture-specific functions which have definitions selected
at compile time.

Classes
-------
~~~~~~~

Classes are not a construct that is built into the C programming language;
however, it is an easily derived concept. Accordingly, pretty much every project
Expand Down Expand Up @@ -451,6 +454,74 @@ We can now use it to test ``struct eeprom_buffer``:
destroy_eeprom_buffer(ctx->eeprom_buffer);
}
Testing against multiple inputs
-------------------------------

Testing just a few inputs might not be enough to have confidence that the code
works correctly, e.g. for a hash function.

In such cases, it can be helpful to have a helper macro or function, e.g. this
fictitious example for ``sha1sum(1)``

.. code-block:: c
/* Note: the cast is to satisfy overly strict type-checking. */
#define TEST_SHA1(in, want) \
sha1sum(in, out); \
KUNIT_EXPECT_STREQ_MSG(test, (char *)out, want, "sha1sum(%s)", in);
char out[40];
TEST_SHA1("hello world", "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed");
TEST_SHA1("hello world!", "430ce34d020724ed75a196dfc2ad67c77772d169");
Note the use of ``KUNIT_EXPECT_STREQ_MSG`` to give more context when it fails
and make it easier to track down. (Yes, in this example, ``want`` is likely
going to be unique enough on its own).

The ``_MSG`` variants are even more useful when the same expectation is called
multiple times (in a loop or helper function) and thus the line number isn't
enough to identify what failed, like below.

In some cases, it can be helpful to write a *table-driven test* instead, e.g.

.. code-block:: c
int i;
char out[40];
struct sha1_test_case {
const char *str;
const char *sha1;
};
struct sha1_test_case cases[] = {
{
.str = "hello world",
.sha1 = "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
},
{
.str = "hello world!",
.sha1 = "430ce34d020724ed75a196dfc2ad67c77772d169",
},
};
for (i = 0; i < ARRAY_SIZE(cases); ++i) {
sha1sum(cases[i].str, out);
KUNIT_EXPECT_STREQ_MSG(test, (char *)out, cases[i].sha1,
"sha1sum(%s)", cases[i].str);
}
There's more boilerplate involved, but it can:

* be more readable when there are multiple inputs/outputs thanks to field names,

* E.g. see ``fs/ext4/inode-test.c`` for an example of both.
* reduce duplication if test cases can be shared across multiple tests.

* E.g. if we wanted to also test ``sha256sum``, we could add a ``sha256``
field and reuse ``cases``.

.. _kunit-on-non-uml:

KUnit on non-UML architectures
Expand Down
Loading

0 comments on commit 706451d

Please sign in to comment.