mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'linux-kselftest-5.5-rc1-kunit' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest KUnit support gtom Shuah Khan: "This adds KUnit, a lightweight unit testing and mocking framework for the Linux kernel from Brendan Higgins. KUnit is not an end-to-end testing framework. It is currently supported on UML and sub-systems can write unit tests and run them in UML env. KUnit documentation is included in this update. In addition, this Kunit update adds 3 new kunit tests: - proc sysctl test from Iurii Zaikin - the 'list' doubly linked list test from David Gow - ext4 tests for decoding extended timestamps from Iurii Zaikin In the future KUnit will be linked to Kselftest framework to provide a way to trigger KUnit tests from user-space" * tag 'linux-kselftest-5.5-rc1-kunit' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (23 commits) lib/list-test: add a test for the 'list' doubly linked list ext4: add kunit test for decoding extended timestamps Documentation: kunit: Fix verification command kunit: Fix '--build_dir' option kunit: fix failure to build without printk MAINTAINERS: add proc sysctl KUnit test to PROC SYSCTL section kernel/sysctl-test: Add null pointer test for sysctl.c:proc_dointvec() MAINTAINERS: add entry for KUnit the unit testing framework Documentation: kunit: add documentation for KUnit kunit: defconfig: add defconfigs for building KUnit tests kunit: tool: add Python wrappers for running KUnit tests kunit: test: add tests for KUnit managed resources kunit: test: add the concept of assertions kunit: test: add tests for kunit test abort kunit: test: add support for test abort objtool: add kunit_try_catch_throw to the noreturn list kunit: test: add initial tests lib: enable building KUnit in lib/ kunit: test: add the concept of expectations kunit: test: add assertion printing library ...
This commit is contained in:
commit
e25645b181
44 files changed
+7067
No files matched your search
@@ -24,6 +24,7 @@ whole; patches welcome!
|
||||
gdb-kernel-debugging
|
||||
kgdb
|
||||
kselftest
|
||||
kunit/index
|
||||
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=============
|
||||
API Reference
|
||||
=============
|
||||
.. toctree::
|
||||
|
||||
test
|
||||
|
||||
This section documents the KUnit kernel testing API. It is divided into the
|
||||
following sections:
|
||||
|
||||
================================= ==============================================
|
||||
:doc:`test` documents all of the standard testing API
|
||||
excluding mocking or mocking related features.
|
||||
================================= ==============================================
|
||||
@@ -0,0 +1,11 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========
|
||||
Test API
|
||||
========
|
||||
|
||||
This file documents all of the standard testing API excluding mocking or mocking
|
||||
related features.
|
||||
|
||||
.. kernel-doc:: include/kunit/test.h
|
||||
:internal:
|
||||
@@ -0,0 +1,62 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
==========================
|
||||
Frequently Asked Questions
|
||||
==========================
|
||||
|
||||
How is this different from Autotest, kselftest, etc?
|
||||
====================================================
|
||||
KUnit is a unit testing framework. Autotest, kselftest (and some others) are
|
||||
not.
|
||||
|
||||
A `unit test <https://martinfowler.com/bliki/UnitTest.html>`_ is supposed to
|
||||
test a single unit of code in isolation, hence the name. A unit test should be
|
||||
the finest granularity of testing and as such should allow all possible code
|
||||
paths to be tested in the code under test; this is only possible if the code
|
||||
under test is very small and does not have any external dependencies outside of
|
||||
the test's control like hardware.
|
||||
|
||||
There are no testing frameworks currently available for the kernel that do not
|
||||
require installing the kernel on a test machine or in a VM and all require
|
||||
tests to be written in userspace and run on the kernel under test; this is true
|
||||
for Autotest, kselftest, and some others, disqualifying any of them from being
|
||||
considered unit testing frameworks.
|
||||
|
||||
Does KUnit support running on architectures other than UML?
|
||||
===========================================================
|
||||
|
||||
Yes, well, mostly.
|
||||
|
||||
For the most part, the KUnit core framework (what you use to write the tests)
|
||||
can compile to any architecture; it compiles like just another part of the
|
||||
kernel and runs when the kernel boots. However, there is some infrastructure,
|
||||
like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support
|
||||
other architectures.
|
||||
|
||||
In short, this means that, yes, you can run KUnit on other architectures, but
|
||||
it might require more work than using KUnit on UML.
|
||||
|
||||
For more information, see :ref:`kunit-on-non-uml`.
|
||||
|
||||
What is the difference between a unit test and these other kinds of tests?
|
||||
==========================================================================
|
||||
Most existing tests for the Linux kernel would be categorized as an integration
|
||||
test, or an end-to-end test.
|
||||
|
||||
- A unit test is supposed to test a single unit of code in isolation, hence the
|
||||
name. A unit test should be the finest granularity of testing and as such
|
||||
should allow all possible code paths to be tested in the code under test; this
|
||||
is only possible if the code under test is very small and does not have any
|
||||
external dependencies outside of the test's control like hardware.
|
||||
- An integration test tests the interaction between a minimal set of components,
|
||||
usually just two or three. For example, someone might write an integration
|
||||
test to test the interaction between a driver and a piece of hardware, or to
|
||||
test the interaction between the userspace libraries the kernel provides and
|
||||
the kernel itself; however, one of these tests would probably not test the
|
||||
entire kernel along with hardware interactions and interactions with the
|
||||
userspace.
|
||||
- An end-to-end test usually tests the entire system from the perspective of the
|
||||
code under test. For example, someone might write an end-to-end test for the
|
||||
kernel by installing a production configuration of the kernel on production
|
||||
hardware with a production userspace and then trying to exercise some behavior
|
||||
that depends on interactions between the hardware, the kernel, and userspace.
|
||||
@@ -0,0 +1,79 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=========================================
|
||||
KUnit - Unit Testing for the Linux Kernel
|
||||
=========================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
start
|
||||
usage
|
||||
api/index
|
||||
faq
|
||||
|
||||
What is KUnit?
|
||||
==============
|
||||
|
||||
KUnit is a lightweight unit testing and mocking framework for the Linux kernel.
|
||||
These tests are able to be run locally on a developer's workstation without a VM
|
||||
or special hardware.
|
||||
|
||||
KUnit is heavily inspired by JUnit, Python's unittest.mock, and
|
||||
Googletest/Googlemock for C++. KUnit provides facilities for defining unit test
|
||||
cases, grouping related test cases into test suites, providing common
|
||||
infrastructure for running tests, and much more.
|
||||
|
||||
Get started now: :doc:`start`
|
||||
|
||||
Why KUnit?
|
||||
==========
|
||||
|
||||
A unit test is supposed to test a single unit of code in isolation, hence the
|
||||
name. A unit test should be the finest granularity of testing and as such should
|
||||
allow all possible code paths to be tested in the code under test; this is only
|
||||
possible if the code under test is very small and does not have any external
|
||||
dependencies outside of the test's control like hardware.
|
||||
|
||||
Outside of KUnit, there are no testing frameworks currently
|
||||
available for the kernel that do not require installing the kernel on a test
|
||||
machine or in a VM and all require tests to be written in userspace running on
|
||||
the kernel; this is true for Autotest, and kselftest, disqualifying
|
||||
any of them from being considered unit testing frameworks.
|
||||
|
||||
KUnit addresses the problem of being able to run tests without needing a virtual
|
||||
machine or actual hardware with User Mode Linux. User Mode Linux is a Linux
|
||||
architecture, like ARM or x86; however, unlike other architectures it compiles
|
||||
to a standalone program that can be run like any other program directly inside
|
||||
of a host operating system; to be clear, it does not require any virtualization
|
||||
support; it is just a regular program.
|
||||
|
||||
KUnit is fast. Excluding build time, from invocation to completion KUnit can run
|
||||
several dozen tests in only 10 to 20 seconds; this might not sound like a big
|
||||
deal to some people, but having such fast and easy to run tests fundamentally
|
||||
changes the way you go about testing and even writing code in the first place.
|
||||
Linus himself said in his `git talk at Google
|
||||
<https://gist.github.com/lorn/1272686/revisions#diff-53c65572127855f1b003db4064a94573R874>`_:
|
||||
|
||||
"... a lot of people seem to think that performance is about doing the
|
||||
same thing, just doing it faster, and that is not true. That is not what
|
||||
performance is all about. If you can do something really fast, really
|
||||
well, people will start using it differently."
|
||||
|
||||
In this context Linus was talking about branching and merging,
|
||||
but this point also applies to testing. If your tests are slow, unreliable, are
|
||||
difficult to write, and require a special setup or special hardware to run,
|
||||
then you wait a lot longer to write tests, and you wait a lot longer to run
|
||||
tests; this means that tests are likely to break, unlikely to test a lot of
|
||||
things, and are unlikely to be rerun once they pass. If your tests are really
|
||||
fast, you run them all the time, every time you make a change, and every time
|
||||
someone sends you some code. Why trust that someone ran all their tests
|
||||
correctly on every change when you can just run them yourself in less time than
|
||||
it takes to read their test log?
|
||||
|
||||
How do I use it?
|
||||
================
|
||||
|
||||
* :doc:`start` - for new users of KUnit
|
||||
* :doc:`usage` - for a more detailed explanation of KUnit features
|
||||
* :doc:`api/index` - for the list of KUnit APIs used for testing
|
||||
@@ -0,0 +1,180 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===============
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
Installing dependencies
|
||||
=======================
|
||||
KUnit has the same dependencies as the Linux kernel. As long as you can build
|
||||
the kernel, you can run KUnit.
|
||||
|
||||
KUnit Wrapper
|
||||
=============
|
||||
Included with KUnit is a simple Python wrapper that helps format the output to
|
||||
easily use and read KUnit output. It handles building and running the kernel, as
|
||||
well as formatting the output.
|
||||
|
||||
The wrapper can be run with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./tools/testing/kunit/kunit.py run
|
||||
|
||||
Creating a kunitconfig
|
||||
======================
|
||||
The Python script is a thin wrapper around Kbuild as such, it needs to be
|
||||
configured with a ``kunitconfig`` file. This file essentially contains the
|
||||
regular Kernel config, with the specific test targets as well.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO
|
||||
cd $PATH_TO_LINUX_REPO
|
||||
ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig
|
||||
|
||||
You may want to add kunitconfig to your local gitignore.
|
||||
|
||||
Verifying KUnit Works
|
||||
---------------------
|
||||
|
||||
To make sure that everything is set up correctly, simply invoke the Python
|
||||
wrapper from your kernel repo:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./tools/testing/kunit/kunit.py run
|
||||
|
||||
.. note::
|
||||
You may want to run ``make mrproper`` first.
|
||||
|
||||
If everything worked correctly, you should see the following:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
Generating .config ...
|
||||
Building KUnit Kernel ...
|
||||
Starting KUnit Kernel ...
|
||||
|
||||
followed by a list of tests that are run. All of them should be passing.
|
||||
|
||||
.. note::
|
||||
Because it is building a lot of sources for the first time, the ``Building
|
||||
kunit kernel`` step may take a while.
|
||||
|
||||
Writing your first test
|
||||
=======================
|
||||
|
||||
In your kernel repo let's add some code that we can test. Create a file
|
||||
``drivers/misc/example.h`` with the contents:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int misc_example_add(int left, int right);
|
||||
|
||||
create a file ``drivers/misc/example.c``:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "example.h"
|
||||
|
||||
int misc_example_add(int left, int right)
|
||||
{
|
||||
return left + right;
|
||||
}
|
||||
|
||||
Now add the following lines to ``drivers/misc/Kconfig``:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
config MISC_EXAMPLE
|
||||
bool "My example"
|
||||
|
||||
and the following lines to ``drivers/misc/Makefile``:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
obj-$(CONFIG_MISC_EXAMPLE) += example.o
|
||||
|
||||
Now we are ready to write the test. The test will be in
|
||||
``drivers/misc/example-test.c``:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include "example.h"
|
||||
|
||||
/* Define the test cases. */
|
||||
|
||||
static void misc_example_add_test_basic(struct kunit *test)
|
||||
{
|
||||
KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0));
|
||||
KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1));
|
||||
KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1));
|
||||
KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX));
|
||||
KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN));
|
||||
}
|
||||
|
||||
static void misc_example_test_failure(struct kunit *test)
|
||||
{
|
||||
KUNIT_FAIL(test, "This test never passes.");
|
||||
}
|
||||
|
||||
static struct kunit_case misc_example_test_cases[] = {
|
||||
KUNIT_CASE(misc_example_add_test_basic),
|
||||
KUNIT_CASE(misc_example_test_failure),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite misc_example_test_suite = {
|
||||
.name = "misc-example",
|
||||
.test_cases = misc_example_test_cases,
|
||||
};
|
||||
kunit_test_suite(misc_example_test_suite);
|
||||
|
||||
Now add the following to ``drivers/misc/Kconfig``:
|
||||
|
||||
.. code-block:: kconfig
|
||||
|
||||
config MISC_EXAMPLE_TEST
|
||||
bool "Test for my example"
|
||||
depends on MISC_EXAMPLE && KUNIT
|
||||
|
||||
and the following to ``drivers/misc/Makefile``:
|
||||
|
||||
.. code-block:: make
|
||||
|
||||
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
|
||||
|
||||
Now add it to your ``kunitconfig``:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
CONFIG_MISC_EXAMPLE=y
|
||||
CONFIG_MISC_EXAMPLE_TEST=y
|
||||
|
||||
Now you can run the test:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./tools/testing/kunit/kunit.py
|
||||
|
||||
You should see the following failure:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
...
|
||||
[16:08:57] [PASSED] misc-example:misc_example_add_test_basic
|
||||
[16:08:57] [FAILED] misc-example:misc_example_test_failure
|
||||
[16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17
|
||||
[16:08:57] This test never passes.
|
||||
...
|
||||
|
||||
Congrats! You just wrote your first KUnit test!
|
||||
|
||||
Next Steps
|
||||
==========
|
||||
* Check out the :doc:`usage` page for a more
|
||||
in-depth explanation of KUnit.
|
||||
File diff suppressed because it is too large.
Load diff
+20
@@ -8928,6 +8928,17 @@ S: Maintained
|
||||
F: tools/testing/selftests/
|
||||
F: Documentation/dev-tools/kselftest*
|
||||
|
||||
KERNEL UNIT TESTING FRAMEWORK (KUnit)
|
||||
M: Brendan Higgins <brendanhiggins@google.com>
|
||||
L: linux-kselftest@vger.kernel.org
|
||||
L: kunit-dev@googlegroups.com
|
||||
W: https://google.github.io/kunit-docs/third_party/kernel/docs/
|
||||
S: Maintained
|
||||
F: Documentation/dev-tools/kunit/
|
||||
F: include/kunit/
|
||||
F: lib/kunit/
|
||||
F: tools/testing/kunit/
|
||||
|
||||
KERNEL USERMODE HELPER
|
||||
M: Luis Chamberlain <mcgrof@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
@@ -9505,6 +9516,13 @@ F: Documentation/misc-devices/lis3lv02d.rst
|
||||
F: drivers/misc/lis3lv02d/
|
||||
F: drivers/platform/x86/hp_accel.c
|
||||
|
||||
LIST KUNIT TEST
|
||||
M: David Gow <davidgow@google.com>
|
||||
L: linux-kselftest@vger.kernel.org
|
||||
L: kunit-dev@googlegroups.com
|
||||
S: Maintained
|
||||
F: lib/list-test.c
|
||||
|
||||
LIVE PATCHING
|
||||
M: Josh Poimboeuf <jpoimboe@redhat.com>
|
||||
M: Jiri Kosina <jikos@kernel.org>
|
||||
@@ -13139,12 +13157,14 @@ F: Documentation/filesystems/proc.txt
|
||||
PROC SYSCTL
|
||||
M: Luis Chamberlain <mcgrof@kernel.org>
|
||||
M: Kees Cook <keescook@chromium.org>
|
||||
M: Iurii Zaikin <yzaikin@google.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: fs/proc/proc_sysctl.c
|
||||
F: include/linux/sysctl.h
|
||||
F: kernel/sysctl.c
|
||||
F: kernel/sysctl-test.c
|
||||
F: tools/testing/selftests/sysctl/
|
||||
|
||||
PS3 NETWORK SUPPORT
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
CONFIG_KUNIT=y
|
||||
CONFIG_KUNIT_TEST=y
|
||||
CONFIG_KUNIT_EXAMPLE_TEST=y
|
||||
@@ -106,3 +106,20 @@ config EXT4_DEBUG
|
||||
If you select Y here, then you will be able to turn on debugging
|
||||
with a command such as:
|
||||
echo 1 > /sys/module/ext4/parameters/mballoc_debug
|
||||
|
||||
config EXT4_KUNIT_TESTS
|
||||
bool "KUnit tests for ext4"
|
||||
select EXT4_FS
|
||||
depends on KUNIT
|
||||
help
|
||||
This builds the ext4 KUnit tests.
|
||||
|
||||
KUnit tests run during boot and output the results to the debug log
|
||||
in TAP format (http://testanything.org/). Only useful for kernel devs
|
||||
running KUnit test harness and are not for inclusion into a production
|
||||
build.
|
||||
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
@@ -13,4 +13,5 @@ ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
|
||||
|
||||
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
|
||||
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
|
||||
ext4-$(CONFIG_EXT4_KUNIT_TESTS) += inode-test.o
|
||||
ext4-$(CONFIG_FS_VERITY) += verity.o
|
||||
@@ -0,0 +1,272 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* KUnit test of ext4 inode that verify the seconds part of [a/c/m]
|
||||
* timestamps in ext4 inode structs are decoded correctly.
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/time64.h>
|
||||
|
||||
#include "ext4.h"
|
||||
|
||||
/*
|
||||
* For constructing the nonnegative timestamp lower bound value.
|
||||
* binary: 00000000 00000000 00000000 00000000
|
||||
*/
|
||||
#define LOWER_MSB_0 0L
|
||||
/*
|
||||
* For constructing the nonnegative timestamp upper bound value.
|
||||
* binary: 01111111 11111111 11111111 11111111
|
||||
*
|
||||
*/
|
||||
#define UPPER_MSB_0 0x7fffffffL
|
||||
/*
|
||||
* For constructing the negative timestamp lower bound value.
|
||||
* binary: 10000000 00000000 00000000 00000000
|
||||
*/
|
||||
#define LOWER_MSB_1 (-0x80000000L)
|
||||
/*
|
||||
* For constructing the negative timestamp upper bound value.
|
||||
* binary: 11111111 11111111 11111111 11111111
|
||||
*/
|
||||
#define UPPER_MSB_1 (-1L)
|
||||
/*
|
||||
* Upper bound for nanoseconds value supported by the encoding.
|
||||
* binary: 00111111 11111111 11111111 11111111
|
||||
*/
|
||||
#define MAX_NANOSECONDS ((1L << 30) - 1)
|
||||
|
||||
#define CASE_NAME_FORMAT "%s: msb:%x lower_bound:%x extra_bits: %x"
|
||||
|
||||
#define LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE\
|
||||
"1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits"
|
||||
#define UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE\
|
||||
"1969-12-31 Upper bound of 32bit < 0 timestamp, no extra bits"
|
||||
#define LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE\
|
||||
"1970-01-01 Lower bound of 32bit >=0 timestamp, no extra bits"
|
||||
#define UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE\
|
||||
"2038-01-19 Upper bound of 32bit >=0 timestamp, no extra bits"
|
||||
#define LOWER_BOUND_NEG_LO_1_CASE\
|
||||
"2038-01-19 Lower bound of 32bit <0 timestamp, lo extra sec bit on"
|
||||
#define UPPER_BOUND_NEG_LO_1_CASE\
|
||||
"2106-02-07 Upper bound of 32bit <0 timestamp, lo extra sec bit on"
|
||||
#define LOWER_BOUND_NONNEG_LO_1_CASE\
|
||||
"2106-02-07 Lower bound of 32bit >=0 timestamp, lo extra sec bit on"
|
||||
#define UPPER_BOUND_NONNEG_LO_1_CASE\
|
||||
"2174-02-25 Upper bound of 32bit >=0 timestamp, lo extra sec bit on"
|
||||
#define LOWER_BOUND_NEG_HI_1_CASE\
|
||||
"2174-02-25 Lower bound of 32bit <0 timestamp, hi extra sec bit on"
|
||||
#define UPPER_BOUND_NEG_HI_1_CASE\
|
||||
"2242-03-16 Upper bound of 32bit <0 timestamp, hi extra sec bit on"
|
||||
#define LOWER_BOUND_NONNEG_HI_1_CASE\
|
||||
"2242-03-16 Lower bound of 32bit >=0 timestamp, hi extra sec bit on"
|
||||
#define UPPER_BOUND_NONNEG_HI_1_CASE\
|
||||
"2310-04-04 Upper bound of 32bit >=0 timestamp, hi extra sec bit on"
|
||||
#define UPPER_BOUND_NONNEG_HI_1_NS_1_CASE\
|
||||
"2310-04-04 Upper bound of 32bit>=0 timestamp, hi extra sec bit 1. 1 ns"
|
||||
#define LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE\
|
||||
"2378-04-22 Lower bound of 32bit>= timestamp. Extra sec bits 1. Max ns"
|
||||
#define LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE\
|
||||
"2378-04-22 Lower bound of 32bit >=0 timestamp. All extra sec bits on"
|
||||
#define UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE\
|
||||
"2446-05-10 Upper bound of 32bit >=0 timestamp. All extra sec bits on"
|
||||
|
||||
struct timestamp_expectation {
|
||||
const char *test_case_name;
|
||||
struct timespec64 expected;
|
||||
u32 extra_bits;
|
||||
bool msb_set;
|
||||
bool lower_bound;
|
||||
};
|
||||
|
||||
static time64_t get_32bit_time(const struct timestamp_expectation * const test)
|
||||
{
|
||||
if (test->msb_set) {
|
||||
if (test->lower_bound)
|
||||
return LOWER_MSB_1;
|
||||
|
||||
return UPPER_MSB_1;
|
||||
}
|
||||
|
||||
if (test->lower_bound)
|
||||
return LOWER_MSB_0;
|
||||
return UPPER_MSB_0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test data is derived from the table in the Inode Timestamps section of
|
||||
* Documentation/filesystems/ext4/inodes.rst.
|
||||
*/
|
||||
static void inode_test_xtimestamp_decoding(struct kunit *test)
|
||||
{
|
||||
const struct timestamp_expectation test_data[] = {
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 0,
|
||||
.expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 0,
|
||||
.expected = {.tv_sec = -1LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 0,
|
||||
.expected = {0LL, 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 0,
|
||||
.expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NEG_LO_1_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 1,
|
||||
.expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NEG_LO_1_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 1,
|
||||
.expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NONNEG_LO_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 1,
|
||||
.expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NONNEG_LO_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 1,
|
||||
.expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NEG_HI_1_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 2,
|
||||
.expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NEG_HI_1_CASE,
|
||||
.msb_set = true,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 2,
|
||||
.expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NONNEG_HI_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 2,
|
||||
.expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NONNEG_HI_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 2,
|
||||
.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NONNEG_HI_1_NS_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 6,
|
||||
.expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 0xFFFFFFFF,
|
||||
.expected = {.tv_sec = 0x300000000LL,
|
||||
.tv_nsec = MAX_NANOSECONDS},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = true,
|
||||
.extra_bits = 3,
|
||||
.expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L},
|
||||
},
|
||||
|
||||
{
|
||||
.test_case_name = UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE,
|
||||
.msb_set = false,
|
||||
.lower_bound = false,
|
||||
.extra_bits = 3,
|
||||
.expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L},
|
||||
}
|
||||
};
|
||||
|
||||
struct timespec64 timestamp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_data); ++i) {
|
||||
timestamp.tv_sec = get_32bit_time(&test_data[i]);
|
||||
ext4_decode_extra_time(×tamp,
|
||||
cpu_to_le32(test_data[i].extra_bits));
|
||||
|
||||
KUNIT_EXPECT_EQ_MSG(test,
|
||||
test_data[i].expected.tv_sec,
|
||||
timestamp.tv_sec,
|
||||
CASE_NAME_FORMAT,
|
||||
test_data[i].test_case_name,
|
||||
test_data[i].msb_set,
|
||||
test_data[i].lower_bound,
|
||||
test_data[i].extra_bits);
|
||||
KUNIT_EXPECT_EQ_MSG(test,
|
||||
test_data[i].expected.tv_nsec,
|
||||
timestamp.tv_nsec,
|
||||
CASE_NAME_FORMAT,
|
||||
test_data[i].test_case_name,
|
||||
test_data[i].msb_set,
|
||||
test_data[i].lower_bound,
|
||||
test_data[i].extra_bits);
|
||||
}
|
||||
}
|
||||
|
||||
static struct kunit_case ext4_inode_test_cases[] = {
|
||||
KUNIT_CASE(inode_test_xtimestamp_decoding),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite ext4_inode_test_suite = {
|
||||
.name = "ext4_inode_test",
|
||||
.test_cases = ext4_inode_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(ext4_inode_test_suite);
|
||||
@@ -0,0 +1,356 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Assertion and expectation serialization API.
|
||||
*
|
||||
* Copyright (C) 2019, Google LLC.
|
||||
* Author: Brendan Higgins <brendanhiggins@google.com>
|
||||
*/
|
||||
|
||||
#ifndef _KUNIT_ASSERT_H
|
||||
#define _KUNIT_ASSERT_H
|
||||
|
||||
#include <kunit/string-stream.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
struct kunit;
|
||||
|
||||
/**
|
||||
* enum kunit_assert_type - Type of expectation/assertion.
|
||||
* @KUNIT_ASSERTION: Used to denote that a kunit_assert represents an assertion.
|
||||
* @KUNIT_EXPECTATION: Denotes that a kunit_assert represents an expectation.
|
||||
*
|
||||
* Used in conjunction with a &struct kunit_assert to denote whether it
|
||||
* represents an expectation or an assertion.
|
||||
*/
|
||||
enum kunit_assert_type {
|
||||
KUNIT_ASSERTION,
|
||||
KUNIT_EXPECTATION,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct kunit_assert - Data for printing a failed assertion or expectation.
|
||||
* @test: the test case this expectation/assertion is associated with.
|
||||
* @type: the type (either an expectation or an assertion) of this kunit_assert.
|
||||
* @line: the source code line number that the expectation/assertion is at.
|
||||
* @file: the file path of the source file that the expectation/assertion is in.
|
||||
* @message: an optional message to provide additional context.
|
||||
* @format: a function which formats the data in this kunit_assert to a string.
|
||||
*
|
||||
* Represents a failed expectation/assertion. Contains all the data necessary to
|
||||
* format a string to a user reporting the failure.
|
||||
*/
|
||||
struct kunit_assert {
|
||||
struct kunit *test;
|
||||
enum kunit_assert_type type;
|
||||
int line;
|
||||
const char *file;
|
||||
struct va_format message;
|
||||
void (*format)(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
};
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_VA_FMT_NULL - Default initializer for struct va_format.
|
||||
*
|
||||
* Used inside a struct initialization block to initialize struct va_format to
|
||||
* default values where fmt and va are null.
|
||||
*/
|
||||
#define KUNIT_INIT_VA_FMT_NULL { .fmt = NULL, .va = NULL }
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_ASSERT_STRUCT() - Initializer for a &struct kunit_assert.
|
||||
* @kunit: The test case that this expectation/assertion is associated with.
|
||||
* @assert_type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @fmt: The formatting function which builds a string out of this kunit_assert.
|
||||
*
|
||||
* The base initializer for a &struct kunit_assert.
|
||||
*/
|
||||
#define KUNIT_INIT_ASSERT_STRUCT(kunit, assert_type, fmt) { \
|
||||
.test = kunit, \
|
||||
.type = assert_type, \
|
||||
.file = __FILE__, \
|
||||
.line = __LINE__, \
|
||||
.message = KUNIT_INIT_VA_FMT_NULL, \
|
||||
.format = fmt \
|
||||
}
|
||||
|
||||
void kunit_base_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
void kunit_assert_print_msg(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* struct kunit_fail_assert - Represents a plain fail expectation/assertion.
|
||||
* @assert: The parent of this type.
|
||||
*
|
||||
* Represents a simple KUNIT_FAIL/KUNIT_ASSERT_FAILURE that always fails.
|
||||
*/
|
||||
struct kunit_fail_assert {
|
||||
struct kunit_assert assert;
|
||||
};
|
||||
|
||||
void kunit_fail_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_FAIL_ASSERT_STRUCT() - Initializer for &struct kunit_fail_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
*
|
||||
* Initializes a &struct kunit_fail_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_FAIL_ASSERT_STRUCT(test, type) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_fail_assert_format) \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kunit_unary_assert - Represents a KUNIT_{EXPECT|ASSERT}_{TRUE|FALSE}
|
||||
* @assert: The parent of this type.
|
||||
* @condition: A string representation of a conditional expression.
|
||||
* @expected_true: True if of type KUNIT_{EXPECT|ASSERT}_TRUE, false otherwise.
|
||||
*
|
||||
* Represents a simple expectation or assertion that simply asserts something is
|
||||
* true or false. In other words, represents the expectations:
|
||||
* KUNIT_{EXPECT|ASSERT}_{TRUE|FALSE}
|
||||
*/
|
||||
struct kunit_unary_assert {
|
||||
struct kunit_assert assert;
|
||||
const char *condition;
|
||||
bool expected_true;
|
||||
};
|
||||
|
||||
void kunit_unary_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_UNARY_ASSERT_STRUCT() - Initializes &struct kunit_unary_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @cond: A string representation of the expression asserted true or false.
|
||||
* @expect_true: True if of type KUNIT_{EXPECT|ASSERT}_TRUE, false otherwise.
|
||||
*
|
||||
* Initializes a &struct kunit_unary_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_UNARY_ASSERT_STRUCT(test, type, cond, expect_true) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_unary_assert_format), \
|
||||
.condition = cond, \
|
||||
.expected_true = expect_true \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kunit_ptr_not_err_assert - An expectation/assertion that a pointer is
|
||||
* not NULL and not a -errno.
|
||||
* @assert: The parent of this type.
|
||||
* @text: A string representation of the expression passed to the expectation.
|
||||
* @value: The actual evaluated pointer value of the expression.
|
||||
*
|
||||
* Represents an expectation/assertion that a pointer is not null and is does
|
||||
* not contain a -errno. (See IS_ERR_OR_NULL().)
|
||||
*/
|
||||
struct kunit_ptr_not_err_assert {
|
||||
struct kunit_assert assert;
|
||||
const char *text;
|
||||
const void *value;
|
||||
};
|
||||
|
||||
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_PTR_NOT_ERR_ASSERT_STRUCT() - Initializes a
|
||||
* &struct kunit_ptr_not_err_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @txt: A string representation of the expression passed to the expectation.
|
||||
* @val: The actual evaluated pointer value of the expression.
|
||||
*
|
||||
* Initializes a &struct kunit_ptr_not_err_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_PTR_NOT_ERR_STRUCT(test, type, txt, val) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_ptr_not_err_assert_format), \
|
||||
.text = txt, \
|
||||
.value = val \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kunit_binary_assert - An expectation/assertion that compares two
|
||||
* non-pointer values (for example, KUNIT_EXPECT_EQ(test, 1 + 1, 2)).
|
||||
* @assert: The parent of this type.
|
||||
* @operation: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_text: A string representation of the expression in the left slot.
|
||||
* @left_value: The actual evaluated value of the expression in the left slot.
|
||||
* @right_text: A string representation of the expression in the right slot.
|
||||
* @right_value: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Represents an expectation/assertion that compares two non-pointer values. For
|
||||
* example, to expect that 1 + 1 == 2, you can use the expectation
|
||||
* KUNIT_EXPECT_EQ(test, 1 + 1, 2);
|
||||
*/
|
||||
struct kunit_binary_assert {
|
||||
struct kunit_assert assert;
|
||||
const char *operation;
|
||||
const char *left_text;
|
||||
long long left_value;
|
||||
const char *right_text;
|
||||
long long right_value;
|
||||
};
|
||||
|
||||
void kunit_binary_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_BINARY_ASSERT_STRUCT() - Initializes a
|
||||
* &struct kunit_binary_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @op_str: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_str: A string representation of the expression in the left slot.
|
||||
* @left_val: The actual evaluated value of the expression in the left slot.
|
||||
* @right_str: A string representation of the expression in the right slot.
|
||||
* @right_val: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Initializes a &struct kunit_binary_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_BINARY_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
op_str, \
|
||||
left_str, \
|
||||
left_val, \
|
||||
right_str, \
|
||||
right_val) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_binary_assert_format), \
|
||||
.operation = op_str, \
|
||||
.left_text = left_str, \
|
||||
.left_value = left_val, \
|
||||
.right_text = right_str, \
|
||||
.right_value = right_val \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kunit_binary_ptr_assert - An expectation/assertion that compares two
|
||||
* pointer values (for example, KUNIT_EXPECT_PTR_EQ(test, foo, bar)).
|
||||
* @assert: The parent of this type.
|
||||
* @operation: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_text: A string representation of the expression in the left slot.
|
||||
* @left_value: The actual evaluated value of the expression in the left slot.
|
||||
* @right_text: A string representation of the expression in the right slot.
|
||||
* @right_value: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Represents an expectation/assertion that compares two pointer values. For
|
||||
* example, to expect that foo and bar point to the same thing, you can use the
|
||||
* expectation KUNIT_EXPECT_PTR_EQ(test, foo, bar);
|
||||
*/
|
||||
struct kunit_binary_ptr_assert {
|
||||
struct kunit_assert assert;
|
||||
const char *operation;
|
||||
const char *left_text;
|
||||
const void *left_value;
|
||||
const char *right_text;
|
||||
const void *right_value;
|
||||
};
|
||||
|
||||
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT() - Initializes a
|
||||
* &struct kunit_binary_ptr_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @op_str: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_str: A string representation of the expression in the left slot.
|
||||
* @left_val: The actual evaluated value of the expression in the left slot.
|
||||
* @right_str: A string representation of the expression in the right slot.
|
||||
* @right_val: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Initializes a &struct kunit_binary_ptr_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_BINARY_PTR_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
op_str, \
|
||||
left_str, \
|
||||
left_val, \
|
||||
right_str, \
|
||||
right_val) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_binary_ptr_assert_format), \
|
||||
.operation = op_str, \
|
||||
.left_text = left_str, \
|
||||
.left_value = left_val, \
|
||||
.right_text = right_str, \
|
||||
.right_value = right_val \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct kunit_binary_str_assert - An expectation/assertion that compares two
|
||||
* string values (for example, KUNIT_EXPECT_STREQ(test, foo, "bar")).
|
||||
* @assert: The parent of this type.
|
||||
* @operation: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_text: A string representation of the expression in the left slot.
|
||||
* @left_value: The actual evaluated value of the expression in the left slot.
|
||||
* @right_text: A string representation of the expression in the right slot.
|
||||
* @right_value: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Represents an expectation/assertion that compares two string values. For
|
||||
* example, to expect that the string in foo is equal to "bar", you can use the
|
||||
* expectation KUNIT_EXPECT_STREQ(test, foo, "bar");
|
||||
*/
|
||||
struct kunit_binary_str_assert {
|
||||
struct kunit_assert assert;
|
||||
const char *operation;
|
||||
const char *left_text;
|
||||
const char *left_value;
|
||||
const char *right_text;
|
||||
const char *right_value;
|
||||
};
|
||||
|
||||
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
|
||||
struct string_stream *stream);
|
||||
|
||||
/**
|
||||
* KUNIT_INIT_BINARY_STR_ASSERT_STRUCT() - Initializes a
|
||||
* &struct kunit_binary_str_assert.
|
||||
* @test: The test case that this expectation/assertion is associated with.
|
||||
* @type: The type (assertion or expectation) of this kunit_assert.
|
||||
* @op_str: A string representation of the comparison operator (e.g. "==").
|
||||
* @left_str: A string representation of the expression in the left slot.
|
||||
* @left_val: The actual evaluated value of the expression in the left slot.
|
||||
* @right_str: A string representation of the expression in the right slot.
|
||||
* @right_val: The actual evaluated value of the expression in the right slot.
|
||||
*
|
||||
* Initializes a &struct kunit_binary_str_assert. Intended to be used in
|
||||
* KUNIT_EXPECT_* and KUNIT_ASSERT_* macros.
|
||||
*/
|
||||
#define KUNIT_INIT_BINARY_STR_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
op_str, \
|
||||
left_str, \
|
||||
left_val, \
|
||||
right_str, \
|
||||
right_val) { \
|
||||
.assert = KUNIT_INIT_ASSERT_STRUCT(test, \
|
||||
type, \
|
||||
kunit_binary_str_assert_format), \
|
||||
.operation = op_str, \
|
||||
.left_text = left_str, \
|
||||
.left_value = left_val, \
|
||||
.right_text = right_str, \
|
||||
.right_value = right_val \
|
||||
}
|
||||
|
||||
#endif /* _KUNIT_ASSERT_H */
|
||||
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* C++ stream style string builder used in KUnit for building messages.
|
||||
*
|
||||
* Copyright (C) 2019, Google LLC.
|
||||
* Author: Brendan Higgins <brendanhiggins@google.com>
|
||||
*/
|
||||
|
||||
#ifndef _KUNIT_STRING_STREAM_H
|
||||
#define _KUNIT_STRING_STREAM_H
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
struct string_stream_fragment {
|
||||
struct kunit *test;
|
||||
struct list_head node;
|
||||
char *fragment;
|
||||
};
|
||||
|
||||
struct string_stream {
|
||||
size_t length;
|
||||
struct list_head fragments;
|
||||
/* length and fragments are protected by this lock */
|
||||
spinlock_t lock;
|
||||
struct kunit *test;
|
||||
gfp_t gfp;
|
||||
};
|
||||
|
||||
struct kunit;
|
||||
|
||||
struct string_stream *alloc_string_stream(struct kunit *test, gfp_t gfp);
|
||||
|
||||
int __printf(2, 3) string_stream_add(struct string_stream *stream,
|
||||
const char *fmt, ...);
|
||||
|
||||
int string_stream_vadd(struct string_stream *stream,
|
||||
const char *fmt,
|
||||
va_list args);
|
||||
|
||||
char *string_stream_get_string(struct string_stream *stream);
|
||||
|
||||
int string_stream_append(struct string_stream *stream,
|
||||
struct string_stream *other);
|
||||
|
||||
bool string_stream_is_empty(struct string_stream *stream);
|
||||
|
||||
int string_stream_destroy(struct string_stream *stream);
|
||||
|
||||
#endif /* _KUNIT_STRING_STREAM_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,75 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* An API to allow a function, that may fail, to be executed, and recover in a
|
||||
* controlled manner.
|
||||
*
|
||||
* Copyright (C) 2019, Google LLC.
|
||||
* Author: Brendan Higgins <brendanhiggins@google.com>
|
||||
*/
|
||||
|
||||
#ifndef _KUNIT_TRY_CATCH_H
|
||||
#define _KUNIT_TRY_CATCH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
typedef void (*kunit_try_catch_func_t)(void *);
|
||||
|
||||
struct completion;
|
||||
struct kunit;
|
||||
|
||||
/**
|
||||
* struct kunit_try_catch - provides a generic way to run code which might fail.
|
||||
* @test: The test case that is currently being executed.
|
||||
* @try_completion: Completion that the control thread waits on while test runs.
|
||||
* @try_result: Contains any errno obtained while running test case.
|
||||
* @try: The function, the test case, to attempt to run.
|
||||
* @catch: The function called if @try bails out.
|
||||
* @context: used to pass user data to the try and catch functions.
|
||||
*
|
||||
* kunit_try_catch provides a generic, architecture independent way to execute
|
||||
* an arbitrary function of type kunit_try_catch_func_t which may bail out by
|
||||
* calling kunit_try_catch_throw(). If kunit_try_catch_throw() is called, @try
|
||||
* is stopped at the site of invocation and @catch is called.
|
||||
*
|
||||
* struct kunit_try_catch provides a generic interface for the functionality
|
||||
* needed to implement kunit->abort() which in turn is needed for implementing
|
||||
* assertions. Assertions allow stating a precondition for a test simplifying
|
||||
* how test cases are written and presented.
|
||||
*
|
||||
* Assertions are like expectations, except they abort (call
|
||||
* kunit_try_catch_throw()) when the specified condition is not met. This is
|
||||
* useful when you look at a test case as a logical statement about some piece
|
||||
* of code, where assertions are the premises for the test case, and the
|
||||
* conclusion is a set of predicates, rather expectations, that must all be
|
||||
* true. If your premises are violated, it does not makes sense to continue.
|
||||
*/
|
||||
struct kunit_try_catch {
|
||||
/* private: internal use only. */
|
||||
struct kunit *test;
|
||||
struct completion *try_completion;
|
||||
int try_result;
|
||||
kunit_try_catch_func_t try;
|
||||
kunit_try_catch_func_t catch;
|
||||
void *context;
|
||||
};
|
||||
|
||||
void kunit_try_catch_init(struct kunit_try_catch *try_catch,
|
||||
struct kunit *test,
|
||||
kunit_try_catch_func_t try,
|
||||
kunit_try_catch_func_t catch);
|
||||
|
||||
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
|
||||
|
||||
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
|
||||
|
||||
static inline int kunit_try_catch_get_result(struct kunit_try_catch *try_catch)
|
||||
{
|
||||
return try_catch->try_result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exposed for testing only.
|
||||
*/
|
||||
void kunit_generic_try_catch_init(struct kunit_try_catch *try_catch);
|
||||
|
||||
#endif /* _KUNIT_TRY_CATCH_H */
|
||||
@@ -115,6 +115,8 @@ obj-$(CONFIG_TORTURE_TEST) += torture.o
|
||||
obj-$(CONFIG_HAS_IOMEM) += iomem.o
|
||||
obj-$(CONFIG_RSEQ) += rseq.o
|
||||
|
||||
obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
|
||||
|
||||
obj-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak.o
|
||||
KASAN_SANITIZE_stackleak.o := n
|
||||
KCOV_INSTRUMENT_stackleak.o := n
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* KUnit test of proc sysctl.
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
#define KUNIT_PROC_READ 0
|
||||
#define KUNIT_PROC_WRITE 1
|
||||
|
||||
static int i_zero;
|
||||
static int i_one_hundred = 100;
|
||||
|
||||
/*
|
||||
* Test that proc_dointvec will not try to use a NULL .data field even when the
|
||||
* length is non-zero.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_null_tbl_data(struct kunit *test)
|
||||
{
|
||||
struct ctl_table null_data_table = {
|
||||
.procname = "foo",
|
||||
/*
|
||||
* Here we are testing that proc_dointvec behaves correctly when
|
||||
* we give it a NULL .data field. Normally this would point to a
|
||||
* piece of memory where the value would be stored.
|
||||
*/
|
||||
.data = NULL,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
/*
|
||||
* proc_dointvec expects a buffer in user space, so we allocate one. We
|
||||
* also need to cast it to __user so sparse doesn't get mad.
|
||||
*/
|
||||
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
|
||||
GFP_USER);
|
||||
size_t len;
|
||||
loff_t pos;
|
||||
|
||||
/*
|
||||
* We don't care what the starting length is since proc_dointvec should
|
||||
* not try to read because .data is NULL.
|
||||
*/
|
||||
len = 1234;
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&null_data_table,
|
||||
KUNIT_PROC_READ, buffer, &len,
|
||||
&pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
|
||||
/*
|
||||
* See above.
|
||||
*/
|
||||
len = 1234;
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&null_data_table,
|
||||
KUNIT_PROC_WRITE, buffer, &len,
|
||||
&pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to the previous test, we create a struct ctrl_table that has a .data
|
||||
* field that proc_dointvec cannot do anything with; however, this time it is
|
||||
* because we tell proc_dointvec that the size is 0.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_table_maxlen_unset(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
struct ctl_table data_maxlen_unset_table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
/*
|
||||
* So .data is no longer NULL, but we tell proc_dointvec its
|
||||
* length is 0, so it still shouldn't try to use it.
|
||||
*/
|
||||
.maxlen = 0,
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
|
||||
GFP_USER);
|
||||
size_t len;
|
||||
loff_t pos;
|
||||
|
||||
/*
|
||||
* As before, we don't care what buffer length is because proc_dointvec
|
||||
* cannot do anything because its internal .data buffer has zero length.
|
||||
*/
|
||||
len = 1234;
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&data_maxlen_unset_table,
|
||||
KUNIT_PROC_READ, buffer, &len,
|
||||
&pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
|
||||
/*
|
||||
* See previous comment.
|
||||
*/
|
||||
len = 1234;
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&data_maxlen_unset_table,
|
||||
KUNIT_PROC_WRITE, buffer, &len,
|
||||
&pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we provide a valid struct ctl_table, but we try to read and write from
|
||||
* it using a buffer of zero length, so it should still fail in a similar way as
|
||||
* before.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_table_len_is_zero(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
/* Good table. */
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
|
||||
GFP_USER);
|
||||
/*
|
||||
* However, now our read/write buffer has zero length.
|
||||
*/
|
||||
size_t len = 0;
|
||||
loff_t pos;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_READ, buffer,
|
||||
&len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_WRITE, buffer,
|
||||
&len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that proc_dointvec refuses to read when the file position is non-zero.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_table_read_but_position_set(
|
||||
struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
/* Good table. */
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
void __user *buffer = (void __user *)kunit_kzalloc(test, sizeof(int),
|
||||
GFP_USER);
|
||||
/*
|
||||
* We don't care about our buffer length because we start off with a
|
||||
* non-zero file position.
|
||||
*/
|
||||
size_t len = 1234;
|
||||
/*
|
||||
* proc_dointvec should refuse to read into the buffer since the file
|
||||
* pos is non-zero.
|
||||
*/
|
||||
loff_t pos = 1;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_READ, buffer,
|
||||
&len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, (size_t)0, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that we can read a two digit number in a sufficiently size buffer.
|
||||
* Nothing fancy.
|
||||
*/
|
||||
static void sysctl_test_dointvec_read_happy_single_positive(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
/* Good table. */
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
size_t len = 4;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
/* Store 13 in the data field. */
|
||||
*((int *)table.data) = 13;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_READ,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_ASSERT_EQ(test, (size_t)3, len);
|
||||
buffer[len] = '\0';
|
||||
/* And we read 13 back out. */
|
||||
KUNIT_EXPECT_STREQ(test, "13\n", buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as previous test, just now with negative numbers.
|
||||
*/
|
||||
static void sysctl_test_dointvec_read_happy_single_negative(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
/* Good table. */
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
size_t len = 5;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
*((int *)table.data) = -16;
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_READ,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_ASSERT_EQ(test, (size_t)4, len);
|
||||
buffer[len] = '\0';
|
||||
KUNIT_EXPECT_STREQ(test, "-16\n", (char *)buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that a simple positive write works.
|
||||
*/
|
||||
static void sysctl_test_dointvec_write_happy_single_positive(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
/* Good table. */
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
char input[] = "9";
|
||||
size_t len = sizeof(input) - 1;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
|
||||
memcpy(buffer, input, len);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_WRITE,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, sizeof(input) - 1, len);
|
||||
KUNIT_EXPECT_EQ(test, sizeof(input) - 1, (size_t)pos);
|
||||
KUNIT_EXPECT_EQ(test, 9, *((int *)table.data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as previous test, but now with negative numbers.
|
||||
*/
|
||||
static void sysctl_test_dointvec_write_happy_single_negative(struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
char input[] = "-9";
|
||||
size_t len = sizeof(input) - 1;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
|
||||
memcpy(buffer, input, len);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, 0, proc_dointvec(&table, KUNIT_PROC_WRITE,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, sizeof(input) - 1, len);
|
||||
KUNIT_EXPECT_EQ(test, sizeof(input) - 1, (size_t)pos);
|
||||
KUNIT_EXPECT_EQ(test, -9, *((int *)table.data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that writing a value smaller than the minimum possible value is not
|
||||
* allowed.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_write_single_less_int_min(
|
||||
struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
size_t max_len = 32, len = max_len;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
unsigned long abs_of_less_than_min = (unsigned long)INT_MAX
|
||||
- (INT_MAX + INT_MIN) + 1;
|
||||
|
||||
/*
|
||||
* We use this rigmarole to create a string that contains a value one
|
||||
* less than the minimum accepted value.
|
||||
*/
|
||||
KUNIT_ASSERT_LT(test,
|
||||
(size_t)snprintf(buffer, max_len, "-%lu",
|
||||
abs_of_less_than_min),
|
||||
max_len);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec(&table, KUNIT_PROC_WRITE,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_EXPECT_EQ(test, max_len, len);
|
||||
KUNIT_EXPECT_EQ(test, 0, *((int *)table.data));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that writing the maximum possible value works.
|
||||
*/
|
||||
static void sysctl_test_api_dointvec_write_single_greater_int_max(
|
||||
struct kunit *test)
|
||||
{
|
||||
int data = 0;
|
||||
struct ctl_table table = {
|
||||
.procname = "foo",
|
||||
.data = &data,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &i_zero,
|
||||
.extra2 = &i_one_hundred,
|
||||
};
|
||||
size_t max_len = 32, len = max_len;
|
||||
loff_t pos = 0;
|
||||
char *buffer = kunit_kzalloc(test, max_len, GFP_USER);
|
||||
char __user *user_buffer = (char __user *)buffer;
|
||||
unsigned long greater_than_max = (unsigned long)INT_MAX + 1;
|
||||
|
||||
KUNIT_ASSERT_GT(test, greater_than_max, (unsigned long)INT_MAX);
|
||||
KUNIT_ASSERT_LT(test, (size_t)snprintf(buffer, max_len, "%lu",
|
||||
greater_than_max),
|
||||
max_len);
|
||||
KUNIT_EXPECT_EQ(test, -EINVAL, proc_dointvec(&table, KUNIT_PROC_WRITE,
|
||||
user_buffer, &len, &pos));
|
||||
KUNIT_ASSERT_EQ(test, max_len, len);
|
||||
KUNIT_EXPECT_EQ(test, 0, *((int *)table.data));
|
||||
}
|
||||
|
||||
static struct kunit_case sysctl_test_cases[] = {
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_null_tbl_data),
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_table_maxlen_unset),
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_table_len_is_zero),
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_table_read_but_position_set),
|
||||
KUNIT_CASE(sysctl_test_dointvec_read_happy_single_positive),
|
||||
KUNIT_CASE(sysctl_test_dointvec_read_happy_single_negative),
|
||||
KUNIT_CASE(sysctl_test_dointvec_write_happy_single_positive),
|
||||
KUNIT_CASE(sysctl_test_dointvec_write_happy_single_negative),
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_write_single_less_int_min),
|
||||
KUNIT_CASE(sysctl_test_api_dointvec_write_single_greater_int_max),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite sysctl_test_suite = {
|
||||
.name = "sysctl_test",
|
||||
.test_cases = sysctl_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suite(sysctl_test_suite);
|
||||
@@ -1664,6 +1664,8 @@ config PROVIDE_OHCI1394_DMA_INIT
|
||||
|
||||
See Documentation/debugging-via-ohci1394.txt for more information.
|
||||
|
||||
source "lib/kunit/Kconfig"
|
||||
|
||||
menuconfig RUNTIME_TESTING_MENU
|
||||
bool "Runtime Testing"
|
||||
def_bool y
|
||||
@@ -1948,6 +1950,35 @@ config TEST_SYSCTL
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SYSCTL_KUNIT_TEST
|
||||
bool "KUnit test for sysctl"
|
||||
depends on KUNIT
|
||||
help
|
||||
This builds the proc sysctl unit test, which runs on boot.
|
||||
Tests the API contract and implementation correctness of sysctl.
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config LIST_KUNIT_TEST
|
||||
bool "KUnit Test for Kernel Linked-list structures"
|
||||
depends on KUNIT
|
||||
help
|
||||
This builds the linked list KUnit test suite.
|
||||
It tests that the API and basic functionality of the list_head type
|
||||
and associated macros.
|
||||
|
||||
KUnit tests run during boot and output the results to the debug log
|
||||
in TAP format (http://testanything.org/). Only useful for kernel devs
|
||||
running the KUnit test harness, and not intended for inclusion into a
|
||||
production build.
|
||||
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TEST_UDELAY
|
||||
tristate "udelay test driver"
|
||||
help
|
||||
|
||||
@@ -92,6 +92,8 @@ obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o
|
||||
|
||||
obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/
|
||||
|
||||
obj-$(CONFIG_KUNIT) += kunit/
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
|
||||
CFLAGS_kobject.o += -DDEBUG
|
||||
CFLAGS_kobject_uevent.o += -DDEBUG
|
||||
@@ -290,3 +292,6 @@ obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
|
||||
obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
|
||||
obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
|
||||
obj-$(CONFIG_OBJAGG) += objagg.o
|
||||
|
||||
# KUnit tests
|
||||
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
|
||||
Loaded 20 of 44 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user