18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci===========
48c2ecf20Sopenharmony_ciUsing KUnit
58c2ecf20Sopenharmony_ci===========
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciThe purpose of this document is to describe what KUnit is, how it works, how it
88c2ecf20Sopenharmony_ciis intended to be used, and all the concepts and terminology that are needed to
98c2ecf20Sopenharmony_ciunderstand it. This guide assumes a working knowledge of the Linux kernel and
108c2ecf20Sopenharmony_cisome basic knowledge of testing.
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciFor a high level introduction to KUnit, including setting up KUnit for your
138c2ecf20Sopenharmony_ciproject, see :doc:`start`.
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciOrganization of this document
168c2ecf20Sopenharmony_ci=============================
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ciThis document is organized into two main sections: Testing and Isolating
198c2ecf20Sopenharmony_ciBehavior. The first covers what unit tests are and how to use KUnit to write
208c2ecf20Sopenharmony_cithem. The second covers how to use KUnit to isolate code and make it possible
218c2ecf20Sopenharmony_cito unit test code that was otherwise un-unit-testable.
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciTesting
248c2ecf20Sopenharmony_ci=======
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ciWhat is KUnit?
278c2ecf20Sopenharmony_ci--------------
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci"K" is short for "kernel" so "KUnit" is the "(Linux) Kernel Unit Testing
308c2ecf20Sopenharmony_ciFramework." KUnit is intended first and foremost for writing unit tests; it is
318c2ecf20Sopenharmony_cigeneral enough that it can be used to write integration tests; however, this is
328c2ecf20Sopenharmony_cia secondary goal. KUnit has no ambition of being the only testing framework for
338c2ecf20Sopenharmony_cithe kernel; for example, it does not intend to be an end-to-end testing
348c2ecf20Sopenharmony_ciframework.
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ciWhat is Unit Testing?
378c2ecf20Sopenharmony_ci---------------------
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ciA `unit test <https://martinfowler.com/bliki/UnitTest.html>`_ is a test that
408c2ecf20Sopenharmony_citests code at the smallest possible scope, a *unit* of code. In the C
418c2ecf20Sopenharmony_ciprogramming language that's a function.
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciUnit tests should be written for all the publicly exposed functions in a
448c2ecf20Sopenharmony_cicompilation unit; so that is all the functions that are exported in either a
458c2ecf20Sopenharmony_ci*class* (defined below) or all functions which are **not** static.
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ciWriting Tests
488c2ecf20Sopenharmony_ci-------------
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciTest Cases
518c2ecf20Sopenharmony_ci~~~~~~~~~~
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ciThe fundamental unit in KUnit is the test case. A test case is a function with
548c2ecf20Sopenharmony_cithe signature ``void (*)(struct kunit *test)``. It calls a function to be tested
558c2ecf20Sopenharmony_ciand then sets *expectations* for what should happen. For example:
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci.. code-block:: c
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	void example_test_success(struct kunit *test)
608c2ecf20Sopenharmony_ci	{
618c2ecf20Sopenharmony_ci	}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	void example_test_failure(struct kunit *test)
648c2ecf20Sopenharmony_ci	{
658c2ecf20Sopenharmony_ci		KUNIT_FAIL(test, "This test never passes.");
668c2ecf20Sopenharmony_ci	}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ciIn the above example ``example_test_success`` always passes because it does
698c2ecf20Sopenharmony_cinothing; no expectations are set, so all expectations pass. On the other hand
708c2ecf20Sopenharmony_ci``example_test_failure`` always fails because it calls ``KUNIT_FAIL``, which is
718c2ecf20Sopenharmony_cia special expectation that logs a message and causes the test case to fail.
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciExpectations
748c2ecf20Sopenharmony_ci~~~~~~~~~~~~
758c2ecf20Sopenharmony_ciAn *expectation* is a way to specify that you expect a piece of code to do
768c2ecf20Sopenharmony_cisomething in a test. An expectation is called like a function. A test is made
778c2ecf20Sopenharmony_ciby setting expectations about the behavior of a piece of code under test; when
788c2ecf20Sopenharmony_cione or more of the expectations fail, the test case fails and information about
798c2ecf20Sopenharmony_cithe failure is logged. For example:
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci.. code-block:: c
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	void add_test_basic(struct kunit *test)
848c2ecf20Sopenharmony_ci	{
858c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 1, add(1, 0));
868c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 2, add(1, 1));
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciIn the above example ``add_test_basic`` makes a number of assertions about the
908c2ecf20Sopenharmony_cibehavior of a function called ``add``; the first parameter is always of type
918c2ecf20Sopenharmony_ci``struct kunit *``, which contains information about the current test context;
928c2ecf20Sopenharmony_cithe second parameter, in this case, is what the value is expected to be; the
938c2ecf20Sopenharmony_cilast value is what the value actually is. If ``add`` passes all of these
948c2ecf20Sopenharmony_ciexpectations, the test case, ``add_test_basic`` will pass; if any one of these
958c2ecf20Sopenharmony_ciexpectations fails, the test case will fail.
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciIt is important to understand that a test case *fails* when any expectation is
988c2ecf20Sopenharmony_civiolated; however, the test will continue running, potentially trying other
998c2ecf20Sopenharmony_ciexpectations until the test case ends or is otherwise terminated. This is as
1008c2ecf20Sopenharmony_ciopposed to *assertions* which are discussed later.
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ciTo learn about more expectations supported by KUnit, see :doc:`api/test`.
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci.. note::
1058c2ecf20Sopenharmony_ci   A single test case should be pretty short, pretty easy to understand,
1068c2ecf20Sopenharmony_ci   focused on a single behavior.
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciFor example, if we wanted to properly test the add function above, we would
1098c2ecf20Sopenharmony_cicreate additional tests cases which would each test a different property that an
1108c2ecf20Sopenharmony_ciadd function should have like this:
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci.. code-block:: c
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	void add_test_basic(struct kunit *test)
1158c2ecf20Sopenharmony_ci	{
1168c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 1, add(1, 0));
1178c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 2, add(1, 1));
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	void add_test_negative(struct kunit *test)
1218c2ecf20Sopenharmony_ci	{
1228c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, 0, add(-1, 1));
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	void add_test_max(struct kunit *test)
1268c2ecf20Sopenharmony_ci	{
1278c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX));
1288c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN));
1298c2ecf20Sopenharmony_ci	}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	void add_test_overflow(struct kunit *test)
1328c2ecf20Sopenharmony_ci	{
1338c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, INT_MIN, add(INT_MAX, 1));
1348c2ecf20Sopenharmony_ci	}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ciNotice how it is immediately obvious what all the properties that we are testing
1378c2ecf20Sopenharmony_cifor are.
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ciAssertions
1408c2ecf20Sopenharmony_ci~~~~~~~~~~
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ciKUnit also has the concept of an *assertion*. An assertion is just like an
1438c2ecf20Sopenharmony_ciexpectation except the assertion immediately terminates the test case if it is
1448c2ecf20Sopenharmony_cinot satisfied.
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciFor example:
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci.. code-block:: c
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	static void mock_test_do_expect_default_return(struct kunit *test)
1518c2ecf20Sopenharmony_ci	{
1528c2ecf20Sopenharmony_ci		struct mock_test_context *ctx = test->priv;
1538c2ecf20Sopenharmony_ci		struct mock *mock = ctx->mock;
1548c2ecf20Sopenharmony_ci		int param0 = 5, param1 = -5;
1558c2ecf20Sopenharmony_ci		const char *two_param_types[] = {"int", "int"};
1568c2ecf20Sopenharmony_ci		const void *two_params[] = {&param0, &param1};
1578c2ecf20Sopenharmony_ci		const void *ret;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		ret = mock->do_expect(mock,
1608c2ecf20Sopenharmony_ci				      "test_printk", test_printk,
1618c2ecf20Sopenharmony_ci				      two_param_types, two_params,
1628c2ecf20Sopenharmony_ci				      ARRAY_SIZE(two_params));
1638c2ecf20Sopenharmony_ci		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
1648c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, -4, *((int *) ret));
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciIn this example, the method under test should return a pointer to a value, so
1688c2ecf20Sopenharmony_ciif the pointer returned by the method is null or an errno, we don't want to
1698c2ecf20Sopenharmony_cibother continuing the test since the following expectation could crash the test
1708c2ecf20Sopenharmony_cicase. `ASSERT_NOT_ERR_OR_NULL(...)` allows us to bail out of the test case if
1718c2ecf20Sopenharmony_cithe appropriate conditions have not been satisfied to complete the test.
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ciTest Suites
1748c2ecf20Sopenharmony_ci~~~~~~~~~~~
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciNow obviously one unit test isn't very helpful; the power comes from having
1778c2ecf20Sopenharmony_cimany test cases covering all of a unit's behaviors. Consequently it is common
1788c2ecf20Sopenharmony_cito have many *similar* tests; in order to reduce duplication in these closely
1798c2ecf20Sopenharmony_cirelated tests most unit testing frameworks - including KUnit - provide the
1808c2ecf20Sopenharmony_ciconcept of a *test suite*. A *test suite* is just a collection of test cases
1818c2ecf20Sopenharmony_cifor a unit of code with a set up function that gets invoked before every test
1828c2ecf20Sopenharmony_cicase and then a tear down function that gets invoked after every test case
1838c2ecf20Sopenharmony_cicompletes.
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ciExample:
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci.. code-block:: c
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	static struct kunit_case example_test_cases[] = {
1908c2ecf20Sopenharmony_ci		KUNIT_CASE(example_test_foo),
1918c2ecf20Sopenharmony_ci		KUNIT_CASE(example_test_bar),
1928c2ecf20Sopenharmony_ci		KUNIT_CASE(example_test_baz),
1938c2ecf20Sopenharmony_ci		{}
1948c2ecf20Sopenharmony_ci	};
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	static struct kunit_suite example_test_suite = {
1978c2ecf20Sopenharmony_ci		.name = "example",
1988c2ecf20Sopenharmony_ci		.init = example_test_init,
1998c2ecf20Sopenharmony_ci		.exit = example_test_exit,
2008c2ecf20Sopenharmony_ci		.test_cases = example_test_cases,
2018c2ecf20Sopenharmony_ci	};
2028c2ecf20Sopenharmony_ci	kunit_test_suite(example_test_suite);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ciIn the above example the test suite, ``example_test_suite``, would run the test
2058c2ecf20Sopenharmony_cicases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``;
2068c2ecf20Sopenharmony_cieach would have ``example_test_init`` called immediately before it and would
2078c2ecf20Sopenharmony_cihave ``example_test_exit`` called immediately after it.
2088c2ecf20Sopenharmony_ci``kunit_test_suite(example_test_suite)`` registers the test suite with the
2098c2ecf20Sopenharmony_ciKUnit test framework.
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci.. note::
2128c2ecf20Sopenharmony_ci   A test case will only be run if it is associated with a test suite.
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci``kunit_test_suite(...)`` is a macro which tells the linker to put the specified
2158c2ecf20Sopenharmony_citest suite in a special linker section so that it can be run by KUnit either
2168c2ecf20Sopenharmony_ciafter late_init, or when the test module is loaded (depending on whether the
2178c2ecf20Sopenharmony_citest was built in or not).
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ciFor more information on these types of things see the :doc:`api/test`.
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ciIsolating Behavior
2228c2ecf20Sopenharmony_ci==================
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ciThe most important aspect of unit testing that other forms of testing do not
2258c2ecf20Sopenharmony_ciprovide is the ability to limit the amount of code under test to a single unit.
2268c2ecf20Sopenharmony_ciIn practice, this is only possible by being able to control what code gets run
2278c2ecf20Sopenharmony_ciwhen the unit under test calls a function and this is usually accomplished
2288c2ecf20Sopenharmony_cithrough some sort of indirection where a function is exposed as part of an API
2298c2ecf20Sopenharmony_cisuch that the definition of that function can be changed without affecting the
2308c2ecf20Sopenharmony_cirest of the code base. In the kernel this primarily comes from two constructs,
2318c2ecf20Sopenharmony_ciclasses, structs that contain function pointers that are provided by the
2328c2ecf20Sopenharmony_ciimplementer, and architecture-specific functions which have definitions selected
2338c2ecf20Sopenharmony_ciat compile time.
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ciClasses
2368c2ecf20Sopenharmony_ci-------
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ciClasses are not a construct that is built into the C programming language;
2398c2ecf20Sopenharmony_cihowever, it is an easily derived concept. Accordingly, pretty much every project
2408c2ecf20Sopenharmony_cithat does not use a standardized object oriented library (like GNOME's GObject)
2418c2ecf20Sopenharmony_cihas their own slightly different way of doing object oriented programming; the
2428c2ecf20Sopenharmony_ciLinux kernel is no exception.
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ciThe central concept in kernel object oriented programming is the class. In the
2458c2ecf20Sopenharmony_cikernel, a *class* is a struct that contains function pointers. This creates a
2468c2ecf20Sopenharmony_cicontract between *implementers* and *users* since it forces them to use the
2478c2ecf20Sopenharmony_cisame function signature without having to call the function directly. In order
2488c2ecf20Sopenharmony_cifor it to truly be a class, the function pointers must specify that a pointer
2498c2ecf20Sopenharmony_cito the class, known as a *class handle*, be one of the parameters; this makes
2508c2ecf20Sopenharmony_ciit possible for the member functions (also known as *methods*) to have access
2518c2ecf20Sopenharmony_cito member variables (more commonly known as *fields*) allowing the same
2528c2ecf20Sopenharmony_ciimplementation to have multiple *instances*.
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ciTypically a class can be *overridden* by *child classes* by embedding the
2558c2ecf20Sopenharmony_ci*parent class* in the child class. Then when a method provided by the child
2568c2ecf20Sopenharmony_ciclass is called, the child implementation knows that the pointer passed to it is
2578c2ecf20Sopenharmony_ciof a parent contained within the child; because of this, the child can compute
2588c2ecf20Sopenharmony_cithe pointer to itself because the pointer to the parent is always a fixed offset
2598c2ecf20Sopenharmony_cifrom the pointer to the child; this offset is the offset of the parent contained
2608c2ecf20Sopenharmony_ciin the child struct. For example:
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci.. code-block:: c
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	struct shape {
2658c2ecf20Sopenharmony_ci		int (*area)(struct shape *this);
2668c2ecf20Sopenharmony_ci	};
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	struct rectangle {
2698c2ecf20Sopenharmony_ci		struct shape parent;
2708c2ecf20Sopenharmony_ci		int length;
2718c2ecf20Sopenharmony_ci		int width;
2728c2ecf20Sopenharmony_ci	};
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	int rectangle_area(struct shape *this)
2758c2ecf20Sopenharmony_ci	{
2768c2ecf20Sopenharmony_ci		struct rectangle *self = container_of(this, struct shape, parent);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		return self->length * self->width;
2798c2ecf20Sopenharmony_ci	};
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	void rectangle_new(struct rectangle *self, int length, int width)
2828c2ecf20Sopenharmony_ci	{
2838c2ecf20Sopenharmony_ci		self->parent.area = rectangle_area;
2848c2ecf20Sopenharmony_ci		self->length = length;
2858c2ecf20Sopenharmony_ci		self->width = width;
2868c2ecf20Sopenharmony_ci	}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ciIn this example (as in most kernel code) the operation of computing the pointer
2898c2ecf20Sopenharmony_cito the child from the pointer to the parent is done by ``container_of``.
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ciFaking Classes
2928c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ciIn order to unit test a piece of code that calls a method in a class, the
2958c2ecf20Sopenharmony_cibehavior of the method must be controllable, otherwise the test ceases to be a
2968c2ecf20Sopenharmony_ciunit test and becomes an integration test.
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ciA fake just provides an implementation of a piece of code that is different than
2998c2ecf20Sopenharmony_ciwhat runs in a production instance, but behaves identically from the standpoint
3008c2ecf20Sopenharmony_ciof the callers; this is usually done to replace a dependency that is hard to
3018c2ecf20Sopenharmony_cideal with, or is slow.
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ciA good example for this might be implementing a fake EEPROM that just stores the
3048c2ecf20Sopenharmony_ci"contents" in an internal buffer. For example, let's assume we have a class that
3058c2ecf20Sopenharmony_cirepresents an EEPROM:
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci.. code-block:: c
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	struct eeprom {
3108c2ecf20Sopenharmony_ci		ssize_t (*read)(struct eeprom *this, size_t offset, char *buffer, size_t count);
3118c2ecf20Sopenharmony_ci		ssize_t (*write)(struct eeprom *this, size_t offset, const char *buffer, size_t count);
3128c2ecf20Sopenharmony_ci	};
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ciAnd we want to test some code that buffers writes to the EEPROM:
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci.. code-block:: c
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	struct eeprom_buffer {
3198c2ecf20Sopenharmony_ci		ssize_t (*write)(struct eeprom_buffer *this, const char *buffer, size_t count);
3208c2ecf20Sopenharmony_ci		int flush(struct eeprom_buffer *this);
3218c2ecf20Sopenharmony_ci		size_t flush_count; /* Flushes when buffer exceeds flush_count. */
3228c2ecf20Sopenharmony_ci	};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	struct eeprom_buffer *new_eeprom_buffer(struct eeprom *eeprom);
3258c2ecf20Sopenharmony_ci	void destroy_eeprom_buffer(struct eeprom *eeprom);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ciWe can easily test this code by *faking out* the underlying EEPROM:
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci.. code-block:: c
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	struct fake_eeprom {
3328c2ecf20Sopenharmony_ci		struct eeprom parent;
3338c2ecf20Sopenharmony_ci		char contents[FAKE_EEPROM_CONTENTS_SIZE];
3348c2ecf20Sopenharmony_ci	};
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	ssize_t fake_eeprom_read(struct eeprom *parent, size_t offset, char *buffer, size_t count)
3378c2ecf20Sopenharmony_ci	{
3388c2ecf20Sopenharmony_ci		struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci		count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset);
3418c2ecf20Sopenharmony_ci		memcpy(buffer, this->contents + offset, count);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		return count;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	ssize_t fake_eeprom_write(struct eeprom *parent, size_t offset, const char *buffer, size_t count)
3478c2ecf20Sopenharmony_ci	{
3488c2ecf20Sopenharmony_ci		struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci		count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset);
3518c2ecf20Sopenharmony_ci		memcpy(this->contents + offset, buffer, count);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci		return count;
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	void fake_eeprom_init(struct fake_eeprom *this)
3578c2ecf20Sopenharmony_ci	{
3588c2ecf20Sopenharmony_ci		this->parent.read = fake_eeprom_read;
3598c2ecf20Sopenharmony_ci		this->parent.write = fake_eeprom_write;
3608c2ecf20Sopenharmony_ci		memset(this->contents, 0, FAKE_EEPROM_CONTENTS_SIZE);
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciWe can now use it to test ``struct eeprom_buffer``:
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci.. code-block:: c
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	struct eeprom_buffer_test {
3688c2ecf20Sopenharmony_ci		struct fake_eeprom *fake_eeprom;
3698c2ecf20Sopenharmony_ci		struct eeprom_buffer *eeprom_buffer;
3708c2ecf20Sopenharmony_ci	};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	static void eeprom_buffer_test_does_not_write_until_flush(struct kunit *test)
3738c2ecf20Sopenharmony_ci	{
3748c2ecf20Sopenharmony_ci		struct eeprom_buffer_test *ctx = test->priv;
3758c2ecf20Sopenharmony_ci		struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer;
3768c2ecf20Sopenharmony_ci		struct fake_eeprom *fake_eeprom = ctx->fake_eeprom;
3778c2ecf20Sopenharmony_ci		char buffer[] = {0xff};
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci		eeprom_buffer->flush_count = SIZE_MAX;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 1);
3828c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 1);
3858c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		eeprom_buffer->flush(eeprom_buffer);
3888c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff);
3898c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff);
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	static void eeprom_buffer_test_flushes_after_flush_count_met(struct kunit *test)
3938c2ecf20Sopenharmony_ci	{
3948c2ecf20Sopenharmony_ci		struct eeprom_buffer_test *ctx = test->priv;
3958c2ecf20Sopenharmony_ci		struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer;
3968c2ecf20Sopenharmony_ci		struct fake_eeprom *fake_eeprom = ctx->fake_eeprom;
3978c2ecf20Sopenharmony_ci		char buffer[] = {0xff};
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci		eeprom_buffer->flush_count = 2;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 1);
4028c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 1);
4058c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff);
4068c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff);
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	static void eeprom_buffer_test_flushes_increments_of_flush_count(struct kunit *test)
4108c2ecf20Sopenharmony_ci	{
4118c2ecf20Sopenharmony_ci		struct eeprom_buffer_test *ctx = test->priv;
4128c2ecf20Sopenharmony_ci		struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer;
4138c2ecf20Sopenharmony_ci		struct fake_eeprom *fake_eeprom = ctx->fake_eeprom;
4148c2ecf20Sopenharmony_ci		char buffer[] = {0xff, 0xff};
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		eeprom_buffer->flush_count = 2;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 1);
4198c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci		eeprom_buffer->write(eeprom_buffer, buffer, 2);
4228c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff);
4238c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff);
4248c2ecf20Sopenharmony_ci		/* Should have only flushed the first two bytes. */
4258c2ecf20Sopenharmony_ci		KUNIT_EXPECT_EQ(test, fake_eeprom->contents[2], 0);
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	static int eeprom_buffer_test_init(struct kunit *test)
4298c2ecf20Sopenharmony_ci	{
4308c2ecf20Sopenharmony_ci		struct eeprom_buffer_test *ctx;
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci		ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
4338c2ecf20Sopenharmony_ci		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci		ctx->fake_eeprom = kunit_kzalloc(test, sizeof(*ctx->fake_eeprom), GFP_KERNEL);
4368c2ecf20Sopenharmony_ci		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->fake_eeprom);
4378c2ecf20Sopenharmony_ci		fake_eeprom_init(ctx->fake_eeprom);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci		ctx->eeprom_buffer = new_eeprom_buffer(&ctx->fake_eeprom->parent);
4408c2ecf20Sopenharmony_ci		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->eeprom_buffer);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci		test->priv = ctx;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci		return 0;
4458c2ecf20Sopenharmony_ci	}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	static void eeprom_buffer_test_exit(struct kunit *test)
4488c2ecf20Sopenharmony_ci	{
4498c2ecf20Sopenharmony_ci		struct eeprom_buffer_test *ctx = test->priv;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		destroy_eeprom_buffer(ctx->eeprom_buffer);
4528c2ecf20Sopenharmony_ci	}
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci.. _kunit-on-non-uml:
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciKUnit on non-UML architectures
4578c2ecf20Sopenharmony_ci==============================
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ciBy default KUnit uses UML as a way to provide dependencies for code under test.
4608c2ecf20Sopenharmony_ciUnder most circumstances KUnit's usage of UML should be treated as an
4618c2ecf20Sopenharmony_ciimplementation detail of how KUnit works under the hood. Nevertheless, there
4628c2ecf20Sopenharmony_ciare instances where being able to run architecture-specific code or test
4638c2ecf20Sopenharmony_ciagainst real hardware is desirable. For these reasons KUnit supports running on
4648c2ecf20Sopenharmony_ciother architectures.
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ciRunning existing KUnit tests on non-UML architectures
4678c2ecf20Sopenharmony_ci-----------------------------------------------------
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ciThere are some special considerations when running existing KUnit tests on
4708c2ecf20Sopenharmony_cinon-UML architectures:
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci*   Hardware may not be deterministic, so a test that always passes or fails
4738c2ecf20Sopenharmony_ci    when run under UML may not always do so on real hardware.
4748c2ecf20Sopenharmony_ci*   Hardware and VM environments may not be hermetic. KUnit tries its best to
4758c2ecf20Sopenharmony_ci    provide a hermetic environment to run tests; however, it cannot manage state
4768c2ecf20Sopenharmony_ci    that it doesn't know about outside of the kernel. Consequently, tests that
4778c2ecf20Sopenharmony_ci    may be hermetic on UML may not be hermetic on other architectures.
4788c2ecf20Sopenharmony_ci*   Some features and tooling may not be supported outside of UML.
4798c2ecf20Sopenharmony_ci*   Hardware and VMs are slower than UML.
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ciNone of these are reasons not to run your KUnit tests on real hardware; they are
4828c2ecf20Sopenharmony_cionly things to be aware of when doing so.
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ciThe biggest impediment will likely be that certain KUnit features and
4858c2ecf20Sopenharmony_ciinfrastructure may not support your target environment. For example, at this
4868c2ecf20Sopenharmony_citime the KUnit Wrapper (``tools/testing/kunit/kunit.py``) does not work outside
4878c2ecf20Sopenharmony_ciof UML. Unfortunately, there is no way around this. Using UML (or even just a
4888c2ecf20Sopenharmony_ciparticular architecture) allows us to make a lot of assumptions that make it
4898c2ecf20Sopenharmony_cipossible to do things which might otherwise be impossible.
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ciNevertheless, all core KUnit framework features are fully supported on all
4928c2ecf20Sopenharmony_ciarchitectures, and using them is straightforward: all you need to do is to take
4938c2ecf20Sopenharmony_ciyour kunitconfig, your Kconfig options for the tests you would like to run, and
4948c2ecf20Sopenharmony_cimerge them into whatever config your are using for your platform. That's it!
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ciFor example, let's say you have the following kunitconfig:
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci.. code-block:: none
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	CONFIG_KUNIT=y
5018c2ecf20Sopenharmony_ci	CONFIG_KUNIT_EXAMPLE_TEST=y
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ciIf you wanted to run this test on an x86 VM, you might add the following config
5048c2ecf20Sopenharmony_cioptions to your ``.config``:
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci.. code-block:: none
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	CONFIG_KUNIT=y
5098c2ecf20Sopenharmony_ci	CONFIG_KUNIT_EXAMPLE_TEST=y
5108c2ecf20Sopenharmony_ci	CONFIG_SERIAL_8250=y
5118c2ecf20Sopenharmony_ci	CONFIG_SERIAL_8250_CONSOLE=y
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ciAll these new options do is enable support for a common serial console needed
5148c2ecf20Sopenharmony_cifor logging.
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ciNext, you could build a kernel with these tests as follows:
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci.. code-block:: bash
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	make ARCH=x86 olddefconfig
5228c2ecf20Sopenharmony_ci	make ARCH=x86
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ciOnce you have built a kernel, you could run it on QEMU as follows:
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci.. code-block:: bash
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	qemu-system-x86_64 -enable-kvm \
5298c2ecf20Sopenharmony_ci			   -m 1024 \
5308c2ecf20Sopenharmony_ci			   -kernel arch/x86_64/boot/bzImage \
5318c2ecf20Sopenharmony_ci			   -append 'console=ttyS0' \
5328c2ecf20Sopenharmony_ci			   --nographic
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ciInterspersed in the kernel logs you might see the following:
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci.. code-block:: none
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	TAP version 14
5398c2ecf20Sopenharmony_ci		# Subtest: example
5408c2ecf20Sopenharmony_ci		1..1
5418c2ecf20Sopenharmony_ci		# example_simple_test: initializing
5428c2ecf20Sopenharmony_ci		ok 1 - example_simple_test
5438c2ecf20Sopenharmony_ci	ok 1 - example
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ciCongratulations, you just ran a KUnit test on the x86 architecture!
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ciIn a similar manner, kunit and kunit tests can also be built as modules,
5488c2ecf20Sopenharmony_ciso if you wanted to run tests in this way you might add the following config
5498c2ecf20Sopenharmony_cioptions to your ``.config``:
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci.. code-block:: none
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	CONFIG_KUNIT=m
5548c2ecf20Sopenharmony_ci	CONFIG_KUNIT_EXAMPLE_TEST=m
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ciOnce the kernel is built and installed, a simple
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci.. code-block:: bash
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci	modprobe example-test
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci...will run the tests.
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci.. note::
5658c2ecf20Sopenharmony_ci   Note that you should make sure your test depends on ``KUNIT=y`` in Kconfig
5668c2ecf20Sopenharmony_ci   if the test does not support module build.  Otherwise, it will trigger
5678c2ecf20Sopenharmony_ci   compile errors if ``CONFIG_KUNIT`` is ``m``.
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ciWriting new tests for other architectures
5708c2ecf20Sopenharmony_ci-----------------------------------------
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ciThe first thing you must do is ask yourself whether it is necessary to write a
5738c2ecf20Sopenharmony_ciKUnit test for a specific architecture, and then whether it is necessary to
5748c2ecf20Sopenharmony_ciwrite that test for a particular piece of hardware. In general, writing a test
5758c2ecf20Sopenharmony_cithat depends on having access to a particular piece of hardware or software (not
5768c2ecf20Sopenharmony_ciincluded in the Linux source repo) should be avoided at all costs.
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ciEven if you only ever plan on running your KUnit test on your hardware
5798c2ecf20Sopenharmony_ciconfiguration, other people may want to run your tests and may not have access
5808c2ecf20Sopenharmony_cito your hardware. If you write your test to run on UML, then anyone can run your
5818c2ecf20Sopenharmony_citests without knowing anything about your particular setup, and you can still
5828c2ecf20Sopenharmony_cirun your tests on your hardware setup just by compiling for your architecture.
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci.. important::
5858c2ecf20Sopenharmony_ci   Always prefer tests that run on UML to tests that only run under a particular
5868c2ecf20Sopenharmony_ci   architecture, and always prefer tests that run under QEMU or another easy
5878c2ecf20Sopenharmony_ci   (and monetarily free) to obtain software environment to a specific piece of
5888c2ecf20Sopenharmony_ci   hardware.
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ciNevertheless, there are still valid reasons to write an architecture or hardware
5918c2ecf20Sopenharmony_cispecific test: for example, you might want to test some code that really belongs
5928c2ecf20Sopenharmony_ciin ``arch/some-arch/*``. Even so, try your best to write the test so that it
5938c2ecf20Sopenharmony_cidoes not depend on physical hardware: if some of your test cases don't need the
5948c2ecf20Sopenharmony_cihardware, only require the hardware for tests that actually need it.
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ciNow that you have narrowed down exactly what bits are hardware specific, the
5978c2ecf20Sopenharmony_ciactual procedure for writing and running the tests is pretty much the same as
5988c2ecf20Sopenharmony_ciwriting normal KUnit tests. One special caveat is that you have to reset
5998c2ecf20Sopenharmony_cihardware state in between test cases; if this is not possible, you may only be
6008c2ecf20Sopenharmony_ciable to run one test case per invocation.
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci.. TODO(brendanhiggins@google.com): Add an actual example of an architecture-
6038c2ecf20Sopenharmony_ci   dependent KUnit test.
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ciKUnit debugfs representation
6068c2ecf20Sopenharmony_ci============================
6078c2ecf20Sopenharmony_ciWhen kunit test suites are initialized, they create an associated directory
6088c2ecf20Sopenharmony_ciin ``/sys/kernel/debug/kunit/<test-suite>``.  The directory contains one file
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci- results: "cat results" displays results of each test case and the results
6118c2ecf20Sopenharmony_ci  of the entire suite for the last test run.
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ciThe debugfs representation is primarily of use when kunit test suites are
6148c2ecf20Sopenharmony_cirun in a native environment, either as modules or builtin.  Having a way
6158c2ecf20Sopenharmony_cito display results like this is valuable as otherwise results can be
6168c2ecf20Sopenharmony_ciintermixed with other events in dmesg output.  The maximum size of each
6178c2ecf20Sopenharmony_ciresults file is KUNIT_LOG_SIZE bytes (defined in ``include/kunit/test.h``).
618