forked from Minki/linux
linux-kselftest-kunit-5.7-rc1
This kunit update for Linux-5.7-rc1 consists of: - debugfs support for displaying kunit test suite results; this is especially useful for module-loaded tests to allow disentangling of test result display from other dmesg events. CONFIG_KUNIT_DEBUGFS enables/disables the debugfs support. - Several fixes and improvements to kunit framework and tool. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAl6Ez+4ACgkQCwJExA0N QxzMBA//fxXD9tUtmc8ePFmbvcdTbb9QxhXP+HYNvAP5xzEGr4UzxGj4yLPv6PfG V/dlpFmPRxN4FjAreYWLz8j+2MRq+Yn7gti9Lv8IOmIc7LXIqOijzrAqax+kd3zt pcXoQY92gJOewhEMaAFmGaXwJ7Dd2clBNwmgTjOs0RMOMh3nCctwkbEK+0vowlfG PcB2sCkdLMGptJBi6IxHHAAddcGCo29LzufzfYbub1gOK2K9lH0xC+2E31lmFR87 loAGtKebtQFkMj2Y9Ynrq+hdK0uZ4lhdDgYBSH7IZUXc4tOEMhFGPxVDiEJN3xf0 NZFeajqFHov9GueixGOxm4fkHe+AneW5OQvKsKM0kQiNaGv9oi995FUfA0qDc4Bt Gd+Cv1bJ44+Cg0K7PE/TjIrCmBMy/xbSvnB/uhDkSDBZOElOHzyO4nz6XxfBmQpM SwGTBKweNkHubYw/pzU3WrEoby0dmOEXg3twjCzLAL790AcpJNT3VPq8HfWvAs/a NgBcdnKQw1Ex3Ph08mWNrSG3/kmioplNK8dXz893uC/uK/Oj2WMsp8AnunDqT1Rz 20Ypx6g/vMGHqG2zenvNTs3IVOb0NlSSHj4rInreCRR4HDAu/Gl0ka+ZC3wqmcui uxL4/8qfIFftGWxaxbk0bW1+mamUcyvOThd9aULUlayEp3CQP70= =5w9O -----END PGP SIGNATURE----- Merge tag 'linux-kselftest-kunit-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest Pull kunit updates from Shuah Khan: "This kunit update consists of: - debugfs support for displaying kunit test suite results. This is especially useful for module-loaded tests to allow disentangling of test result display from other dmesg events. CONFIG_KUNIT_DEBUGFS enables/disables the debugfs support. - Several fixes and improvements to kunit framework and tool" * tag 'linux-kselftest-kunit-5.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: kunit: tool: add missing test data file content kunit: update documentation to describe debugfs representation kunit: subtests should be indented 4 spaces according to TAP kunit: add log test kunit: add debugfs /sys/kernel/debug/kunit/<suite>/results display Documentation: kunit: Make the KUnit documentation less UML-specific Fix linked-list KUnit test when run multiple times kunit: kunit_tool: Allow .kunitconfig to disable config items kunit: Always print actual pointer values in asserts kunit: add --make_options kunit: Run all KUnit tests through allyesconfig kunit: kunit_parser: make parser more robust
This commit is contained in:
commit
668f1e9267
@ -17,14 +17,23 @@ 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.
|
||||
|
||||
KUnit consists of a kernel component, which provides a set of macros for easily
|
||||
writing unit tests. Tests written against KUnit will run on kernel boot if
|
||||
built-in, or when loaded if built as a module. These tests write out results to
|
||||
the kernel log in `TAP <https://testanything.org/>`_ format.
|
||||
|
||||
To make running these tests (and reading the results) easier, KUnit offers
|
||||
:doc:`kunit_tool <kunit-tool>`, which builds a `User Mode Linux
|
||||
<http://user-mode-linux.sourceforge.net>`_ kernel, runs it, and parses the test
|
||||
results. This provides a quick way of running KUnit tests during development,
|
||||
without requiring a virtual machine or separate hardware.
|
||||
|
||||
Get started now: :doc:`start`
|
||||
|
||||
Why KUnit?
|
||||
@ -36,21 +45,20 @@ 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 provides a common framework for unit tests within the kernel.
|
||||
|
||||
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 tests can be run on most architectures, and most tests are architecture
|
||||
independent. All built-in KUnit tests run on kernel startup. Alternatively,
|
||||
KUnit and KUnit tests can be built as modules and tests will run when the test
|
||||
module is loaded.
|
||||
|
||||
Alternatively, kunit and kunit tests can be built as modules and tests will
|
||||
run when the test module is loaded.
|
||||
.. note::
|
||||
|
||||
KUnit can also run tests without needing a virtual machine or actual
|
||||
hardware under User Mode Linux. User Mode Linux is a Linux architecture,
|
||||
like ARM or x86, which compiles the kernel as a Linux executable. KUnit
|
||||
can be used with UML either by building with ``ARCH=um`` (like any other
|
||||
architecture), or by using :doc:`kunit_tool <kunit-tool>`.
|
||||
|
||||
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
|
||||
@ -81,3 +89,5 @@ 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
|
||||
* :doc:`kunit-tool` - for more information on the kunit_tool helper script
|
||||
* :doc:`faq` - for answers to some common questions about KUnit
|
||||
|
@ -12,6 +12,13 @@ the Linux kernel as UML (`User Mode Linux
|
||||
<http://user-mode-linux.sourceforge.net/>`_), running KUnit tests, parsing
|
||||
the test results and displaying them in a user friendly manner.
|
||||
|
||||
kunit_tool 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 the kernel as a standalone Linux executable 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.
|
||||
|
||||
What is a kunitconfig?
|
||||
======================
|
||||
|
||||
|
@ -9,11 +9,10 @@ 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.
|
||||
Running tests with the KUnit Wrapper
|
||||
====================================
|
||||
Included with KUnit is a simple Python wrapper which runs tests under User Mode
|
||||
Linux, and formats the test results.
|
||||
|
||||
The wrapper can be run with:
|
||||
|
||||
@ -21,22 +20,42 @@ The wrapper can be run with:
|
||||
|
||||
./tools/testing/kunit/kunit.py run --defconfig
|
||||
|
||||
For more information on this wrapper (also called kunit_tool) checkout the
|
||||
For more information on this wrapper (also called kunit_tool) check out the
|
||||
:doc:`kunit-tool` page.
|
||||
|
||||
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.
|
||||
-----------------------
|
||||
If you want to run a specific set of tests (rather than those listed in the
|
||||
KUnit defconfig), you can provide Kconfig options in the ``.kunitconfig`` file.
|
||||
This file essentially contains the regular Kernel config, with the specific
|
||||
test targets as well. The ``.kunitconfig`` should also contain any other config
|
||||
options required by the tests.
|
||||
|
||||
A good starting point for a ``.kunitconfig`` is the KUnit defconfig:
|
||||
.. code-block:: bash
|
||||
|
||||
cd $PATH_TO_LINUX_REPO
|
||||
cp arch/um/configs/kunit_defconfig .kunitconfig
|
||||
|
||||
Verifying KUnit Works
|
||||
---------------------
|
||||
You can then add any other Kconfig options you wish, e.g.:
|
||||
.. code-block:: none
|
||||
|
||||
CONFIG_LIST_KUNIT_TEST=y
|
||||
|
||||
:doc:`kunit_tool <kunit-tool>` will ensure that all config options set in
|
||||
``.kunitconfig`` are set in the kernel ``.config`` before running the tests.
|
||||
It'll warn you if you haven't included the dependencies of the options you're
|
||||
using.
|
||||
|
||||
.. note::
|
||||
Note that removing something from the ``.kunitconfig`` will not trigger a
|
||||
rebuild of the ``.config`` file: the configuration is only updated if the
|
||||
``.kunitconfig`` is not a subset of ``.config``. This means that you can use
|
||||
other tools (such as make menuconfig) to adjust other config options.
|
||||
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
|
||||
To make sure that everything is set up correctly, simply invoke the Python
|
||||
wrapper from your kernel repo:
|
||||
@ -62,6 +81,41 @@ followed by a list of tests that are run. All of them should be passing.
|
||||
Because it is building a lot of sources for the first time, the
|
||||
``Building KUnit kernel`` step may take a while.
|
||||
|
||||
Running tests without the KUnit Wrapper
|
||||
=======================================
|
||||
|
||||
If you'd rather not use the KUnit Wrapper (if, for example, you need to
|
||||
integrate with other systems, or use an architecture other than UML), KUnit can
|
||||
be included in any kernel, and the results read out and parsed manually.
|
||||
|
||||
.. note::
|
||||
KUnit is not designed for use in a production system, and it's possible that
|
||||
tests may reduce the stability or security of the system.
|
||||
|
||||
|
||||
|
||||
Configuring the kernel
|
||||
----------------------
|
||||
|
||||
In order to enable KUnit itself, you simply need to enable the ``CONFIG_KUNIT``
|
||||
Kconfig option (it's under Kernel Hacking/Kernel Testing and Coverage in
|
||||
menuconfig). From there, you can enable any KUnit tests you want: they usually
|
||||
have config options ending in ``_KUNIT_TEST``.
|
||||
|
||||
KUnit and KUnit tests can be compiled as modules: in this case the tests in a
|
||||
module will be run when the module is loaded.
|
||||
|
||||
Running the tests
|
||||
-----------------
|
||||
|
||||
Build and run your kernel as usual. Test output will be written to the kernel
|
||||
log in `TAP <https://testanything.org/>`_ format.
|
||||
|
||||
.. note::
|
||||
It's possible that there will be other lines and/or data interspersed in the
|
||||
TAP output.
|
||||
|
||||
|
||||
Writing your first test
|
||||
=======================
|
||||
|
||||
|
@ -591,3 +591,17 @@ able to run one test case per invocation.
|
||||
|
||||
.. TODO(brendanhiggins@google.com): Add an actual example of an architecture
|
||||
dependent KUnit test.
|
||||
|
||||
KUnit debugfs representation
|
||||
============================
|
||||
When kunit test suites are initialized, they create an associated directory
|
||||
in /sys/kernel/debug/kunit/<test-suite>. The directory contains one file
|
||||
|
||||
- results: "cat results" displays results of each test case and the results
|
||||
of the entire suite for the last test run.
|
||||
|
||||
The debugfs representation is primarily of use when kunit test suites are
|
||||
run in a native environment, either as modules or builtin. Having a way
|
||||
to display results like this is valuable as otherwise results can be
|
||||
intermixed with other events in dmesg output. The maximum size of each
|
||||
results file is KUNIT_LOG_SIZE bytes (defined in include/kunit/test.h).
|
||||
|
@ -81,6 +81,17 @@ struct kunit_resource {
|
||||
|
||||
struct kunit;
|
||||
|
||||
/* Size of log associated with test. */
|
||||
#define KUNIT_LOG_SIZE 512
|
||||
|
||||
/*
|
||||
* TAP specifies subtest stream indentation of 4 spaces, 8 spaces for a
|
||||
* sub-subtest. See the "Subtests" section in
|
||||
* https://node-tap.org/tap-protocol/
|
||||
*/
|
||||
#define KUNIT_SUBTEST_INDENT " "
|
||||
#define KUNIT_SUBSUBTEST_INDENT " "
|
||||
|
||||
/**
|
||||
* struct kunit_case - represents an individual test case.
|
||||
*
|
||||
@ -123,8 +134,14 @@ struct kunit_case {
|
||||
|
||||
/* private: internal use only. */
|
||||
bool success;
|
||||
char *log;
|
||||
};
|
||||
|
||||
static inline char *kunit_status_to_string(bool status)
|
||||
{
|
||||
return status ? "ok" : "not ok";
|
||||
}
|
||||
|
||||
/**
|
||||
* KUNIT_CASE - A helper for creating a &struct kunit_case
|
||||
*
|
||||
@ -157,6 +174,10 @@ struct kunit_suite {
|
||||
int (*init)(struct kunit *test);
|
||||
void (*exit)(struct kunit *test);
|
||||
struct kunit_case *test_cases;
|
||||
|
||||
/* private - internal use only */
|
||||
struct dentry *debugfs;
|
||||
char *log;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -175,6 +196,7 @@ struct kunit {
|
||||
|
||||
/* private: internal use only. */
|
||||
const char *name; /* Read only after initialization! */
|
||||
char *log; /* Points at case log after initialization */
|
||||
struct kunit_try_catch try_catch;
|
||||
/*
|
||||
* success starts as true, and may only be set to false during a
|
||||
@ -193,10 +215,19 @@ struct kunit {
|
||||
struct list_head resources; /* Protected by lock. */
|
||||
};
|
||||
|
||||
void kunit_init_test(struct kunit *test, const char *name);
|
||||
void kunit_init_test(struct kunit *test, const char *name, char *log);
|
||||
|
||||
int kunit_run_tests(struct kunit_suite *suite);
|
||||
|
||||
size_t kunit_suite_num_test_cases(struct kunit_suite *suite);
|
||||
|
||||
unsigned int kunit_test_case_num(struct kunit_suite *suite,
|
||||
struct kunit_case *test_case);
|
||||
|
||||
int __kunit_test_suites_init(struct kunit_suite **suites);
|
||||
|
||||
void __kunit_test_suites_exit(struct kunit_suite **suites);
|
||||
|
||||
/**
|
||||
* kunit_test_suites() - used to register one or more &struct kunit_suite
|
||||
* with KUnit.
|
||||
@ -226,20 +257,22 @@ int kunit_run_tests(struct kunit_suite *suite);
|
||||
static struct kunit_suite *suites[] = { __VA_ARGS__, NULL}; \
|
||||
static int kunit_test_suites_init(void) \
|
||||
{ \
|
||||
unsigned int i; \
|
||||
for (i = 0; suites[i] != NULL; i++) \
|
||||
kunit_run_tests(suites[i]); \
|
||||
return 0; \
|
||||
return __kunit_test_suites_init(suites); \
|
||||
} \
|
||||
late_initcall(kunit_test_suites_init); \
|
||||
static void __exit kunit_test_suites_exit(void) \
|
||||
{ \
|
||||
return; \
|
||||
return __kunit_test_suites_exit(suites); \
|
||||
} \
|
||||
module_exit(kunit_test_suites_exit)
|
||||
|
||||
#define kunit_test_suite(suite) kunit_test_suites(&suite)
|
||||
|
||||
#define kunit_suite_for_each_test_case(suite, test_case) \
|
||||
for (test_case = suite->test_cases; test_case->run_case; test_case++)
|
||||
|
||||
bool kunit_suite_has_succeeded(struct kunit_suite *suite);
|
||||
|
||||
/*
|
||||
* Like kunit_alloc_resource() below, but returns the struct kunit_resource
|
||||
* object that contains the allocation. This is mostly for testing purposes.
|
||||
@ -356,8 +389,22 @@ static inline void *kunit_kzalloc(struct kunit *test, size_t size, gfp_t gfp)
|
||||
|
||||
void kunit_cleanup(struct kunit *test);
|
||||
|
||||
#define kunit_printk(lvl, test, fmt, ...) \
|
||||
printk(lvl "\t# %s: " fmt, (test)->name, ##__VA_ARGS__)
|
||||
void kunit_log_append(char *log, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* printk and log to per-test or per-suite log buffer. Logging only done
|
||||
* if CONFIG_KUNIT_DEBUGFS is 'y'; if it is 'n', no log is allocated/used.
|
||||
*/
|
||||
#define kunit_log(lvl, test_or_suite, fmt, ...) \
|
||||
do { \
|
||||
printk(lvl fmt, ##__VA_ARGS__); \
|
||||
kunit_log_append((test_or_suite)->log, fmt "\n", \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define kunit_printk(lvl, test, fmt, ...) \
|
||||
kunit_log(lvl, test, KUNIT_SUBTEST_INDENT "# %s: " fmt, \
|
||||
(test)->name, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* kunit_info() - Prints an INFO level message associated with @test.
|
||||
|
@ -14,6 +14,14 @@ menuconfig KUNIT
|
||||
|
||||
if KUNIT
|
||||
|
||||
config KUNIT_DEBUGFS
|
||||
bool "KUnit - Enable /sys/kernel/debug/kunit debugfs representation"
|
||||
help
|
||||
Enable debugfs representation for kunit. Currently this consists
|
||||
of /sys/kernel/debug/kunit/<test_suite>/results files for each
|
||||
test suite, which allow users to see results of the last test suite
|
||||
run that occurred.
|
||||
|
||||
config KUNIT_TEST
|
||||
tristate "KUnit test for KUnit"
|
||||
help
|
||||
|
@ -5,6 +5,10 @@ kunit-objs += test.o \
|
||||
assert.o \
|
||||
try-catch.o
|
||||
|
||||
ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
|
||||
kunit-objs += debugfs.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
|
||||
|
||||
# string-stream-test compiles built-in only.
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Author: Brendan Higgins <brendanhiggins@google.com>
|
||||
*/
|
||||
#include <kunit/assert.h>
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "string-stream.h"
|
||||
|
||||
@ -53,12 +54,12 @@ void kunit_unary_assert_format(const struct kunit_assert *assert,
|
||||
kunit_base_assert_format(assert, stream);
|
||||
if (unary_assert->expected_true)
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s to be true, but is false\n",
|
||||
unary_assert->condition);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
|
||||
unary_assert->condition);
|
||||
else
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s to be false, but is true\n",
|
||||
unary_assert->condition);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
|
||||
unary_assert->condition);
|
||||
kunit_assert_print_msg(assert, stream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
|
||||
@ -72,13 +73,13 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
|
||||
kunit_base_assert_format(assert, stream);
|
||||
if (!ptr_assert->value) {
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s is not null, but is\n",
|
||||
ptr_assert->text);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
|
||||
ptr_assert->text);
|
||||
} else if (IS_ERR(ptr_assert->value)) {
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s is not error, but is: %ld\n",
|
||||
ptr_assert->text,
|
||||
PTR_ERR(ptr_assert->value));
|
||||
KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",
|
||||
ptr_assert->text,
|
||||
PTR_ERR(ptr_assert->value));
|
||||
}
|
||||
kunit_assert_print_msg(assert, stream);
|
||||
}
|
||||
@ -92,16 +93,16 @@ void kunit_binary_assert_format(const struct kunit_assert *assert,
|
||||
|
||||
kunit_base_assert_format(assert, stream);
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, "\t\t%s == %lld\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, "\t\t%s == %lld",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
kunit_assert_print_msg(assert, stream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
|
||||
@ -114,16 +115,16 @@ void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
|
||||
|
||||
kunit_base_assert_format(assert, stream);
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, "\t\t%s == %pK\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, "\t\t%s == %pK",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
kunit_assert_print_msg(assert, stream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
|
||||
@ -136,16 +137,16 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
|
||||
|
||||
kunit_base_assert_format(assert, stream);
|
||||
string_stream_add(stream,
|
||||
"\tExpected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, "\t\t%s == %s\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, "\t\t%s == %s",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->operation,
|
||||
binary_assert->right_text);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %s\n",
|
||||
binary_assert->left_text,
|
||||
binary_assert->left_value);
|
||||
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %s",
|
||||
binary_assert->right_text,
|
||||
binary_assert->right_value);
|
||||
kunit_assert_print_msg(assert, stream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
|
||||
|
116
lib/kunit/debugfs.c
Normal file
116
lib/kunit/debugfs.c
Normal file
@ -0,0 +1,116 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates.
|
||||
* Author: Alan Maguire <alan.maguire@oracle.com>
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#include "string-stream.h"
|
||||
|
||||
#define KUNIT_DEBUGFS_ROOT "kunit"
|
||||
#define KUNIT_DEBUGFS_RESULTS "results"
|
||||
|
||||
/*
|
||||
* Create a debugfs representation of test suites:
|
||||
*
|
||||
* Path Semantics
|
||||
* /sys/kernel/debug/kunit/<testsuite>/results Show results of last run for
|
||||
* testsuite
|
||||
*
|
||||
*/
|
||||
|
||||
static struct dentry *debugfs_rootdir;
|
||||
|
||||
void kunit_debugfs_cleanup(void)
|
||||
{
|
||||
debugfs_remove_recursive(debugfs_rootdir);
|
||||
}
|
||||
|
||||
void kunit_debugfs_init(void)
|
||||
{
|
||||
if (!debugfs_rootdir)
|
||||
debugfs_rootdir = debugfs_create_dir(KUNIT_DEBUGFS_ROOT, NULL);
|
||||
}
|
||||
|
||||
static void debugfs_print_result(struct seq_file *seq,
|
||||
struct kunit_suite *suite,
|
||||
struct kunit_case *test_case)
|
||||
{
|
||||
if (!test_case || !test_case->log)
|
||||
return;
|
||||
|
||||
seq_printf(seq, "%s", test_case->log);
|
||||
}
|
||||
|
||||
/*
|
||||
* /sys/kernel/debug/kunit/<testsuite>/results shows all results for testsuite.
|
||||
*/
|
||||
static int debugfs_print_results(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct kunit_suite *suite = (struct kunit_suite *)seq->private;
|
||||
bool success = kunit_suite_has_succeeded(suite);
|
||||
struct kunit_case *test_case;
|
||||
|
||||
if (!suite || !suite->log)
|
||||
return 0;
|
||||
|
||||
seq_printf(seq, "%s", suite->log);
|
||||
|
||||
kunit_suite_for_each_test_case(suite, test_case)
|
||||
debugfs_print_result(seq, suite, test_case);
|
||||
|
||||
seq_printf(seq, "%s %d - %s\n",
|
||||
kunit_status_to_string(success), 1, suite->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debugfs_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_release(inode, file);
|
||||
}
|
||||
|
||||
static int debugfs_results_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct kunit_suite *suite;
|
||||
|
||||
suite = (struct kunit_suite *)inode->i_private;
|
||||
|
||||
return single_open(file, debugfs_print_results, suite);
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_results_fops = {
|
||||
.open = debugfs_results_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = debugfs_release,
|
||||
};
|
||||
|
||||
void kunit_debugfs_create_suite(struct kunit_suite *suite)
|
||||
{
|
||||
struct kunit_case *test_case;
|
||||
|
||||
/* Allocate logs before creating debugfs representation. */
|
||||
suite->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
|
||||
kunit_suite_for_each_test_case(suite, test_case)
|
||||
test_case->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
|
||||
|
||||
suite->debugfs = debugfs_create_dir(suite->name, debugfs_rootdir);
|
||||
|
||||
debugfs_create_file(KUNIT_DEBUGFS_RESULTS, S_IFREG | 0444,
|
||||
suite->debugfs,
|
||||
suite, &debugfs_results_fops);
|
||||
}
|
||||
|
||||
void kunit_debugfs_destroy_suite(struct kunit_suite *suite)
|
||||
{
|
||||
struct kunit_case *test_case;
|
||||
|
||||
debugfs_remove_recursive(suite->debugfs);
|
||||
kfree(suite->log);
|
||||
kunit_suite_for_each_test_case(suite, test_case)
|
||||
kfree(test_case->log);
|
||||
}
|
30
lib/kunit/debugfs.h
Normal file
30
lib/kunit/debugfs.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020, Oracle and/or its affiliates.
|
||||
*/
|
||||
|
||||
#ifndef _KUNIT_DEBUGFS_H
|
||||
#define _KUNIT_DEBUGFS_H
|
||||
|
||||
#include <kunit/test.h>
|
||||
|
||||
#ifdef CONFIG_KUNIT_DEBUGFS
|
||||
|
||||
void kunit_debugfs_create_suite(struct kunit_suite *suite);
|
||||
void kunit_debugfs_destroy_suite(struct kunit_suite *suite);
|
||||
void kunit_debugfs_init(void);
|
||||
void kunit_debugfs_cleanup(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void kunit_debugfs_create_suite(struct kunit_suite *suite) { }
|
||||
|
||||
static inline void kunit_debugfs_destroy_suite(struct kunit_suite *suite) { }
|
||||
|
||||
static inline void kunit_debugfs_init(void) { }
|
||||
|
||||
static inline void kunit_debugfs_cleanup(void) { }
|
||||
|
||||
#endif /* CONFIG_KUNIT_DEBUGFS */
|
||||
|
||||
#endif /* _KUNIT_DEBUGFS_H */
|
@ -134,7 +134,7 @@ static void kunit_resource_test_init_resources(struct kunit *test)
|
||||
{
|
||||
struct kunit_test_resource_context *ctx = test->priv;
|
||||
|
||||
kunit_init_test(&ctx->test, "testing_test_init_test");
|
||||
kunit_init_test(&ctx->test, "testing_test_init_test", NULL);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources));
|
||||
}
|
||||
@ -301,7 +301,7 @@ static int kunit_resource_test_init(struct kunit *test)
|
||||
|
||||
test->priv = ctx;
|
||||
|
||||
kunit_init_test(&ctx->test, "test_test_context");
|
||||
kunit_init_test(&ctx->test, "test_test_context", NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -329,6 +329,44 @@ static struct kunit_suite kunit_resource_test_suite = {
|
||||
.exit = kunit_resource_test_exit,
|
||||
.test_cases = kunit_resource_test_cases,
|
||||
};
|
||||
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite);
|
||||
|
||||
static void kunit_log_test(struct kunit *test);
|
||||
|
||||
static struct kunit_case kunit_log_test_cases[] = {
|
||||
KUNIT_CASE(kunit_log_test),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite kunit_log_test_suite = {
|
||||
.name = "kunit-log-test",
|
||||
.test_cases = kunit_log_test_cases,
|
||||
};
|
||||
|
||||
static void kunit_log_test(struct kunit *test)
|
||||
{
|
||||
struct kunit_suite *suite = &kunit_log_test_suite;
|
||||
|
||||
kunit_log(KERN_INFO, test, "put this in log.");
|
||||
kunit_log(KERN_INFO, test, "this too.");
|
||||
kunit_log(KERN_INFO, suite, "add to suite log.");
|
||||
kunit_log(KERN_INFO, suite, "along with this.");
|
||||
|
||||
#ifdef CONFIG_KUNIT_DEBUGFS
|
||||
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
|
||||
strstr(test->log, "put this in log."));
|
||||
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
|
||||
strstr(test->log, "this too."));
|
||||
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
|
||||
strstr(suite->log, "add to suite log."));
|
||||
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
|
||||
strstr(suite->log, "along with this."));
|
||||
#else
|
||||
KUNIT_EXPECT_PTR_EQ(test, test->log, (char *)NULL);
|
||||
KUNIT_EXPECT_PTR_EQ(test, suite->log, (char *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
|
||||
&kunit_log_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
148
lib/kunit/test.c
148
lib/kunit/test.c
@ -10,6 +10,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched/debug.h>
|
||||
|
||||
#include "debugfs.h"
|
||||
#include "string-stream.h"
|
||||
#include "try-catch-impl.h"
|
||||
|
||||
@ -28,73 +29,117 @@ static void kunit_print_tap_version(void)
|
||||
}
|
||||
}
|
||||
|
||||
static size_t kunit_test_cases_len(struct kunit_case *test_cases)
|
||||
/*
|
||||
* Append formatted message to log, size of which is limited to
|
||||
* KUNIT_LOG_SIZE bytes (including null terminating byte).
|
||||
*/
|
||||
void kunit_log_append(char *log, const char *fmt, ...)
|
||||
{
|
||||
char line[KUNIT_LOG_SIZE];
|
||||
va_list args;
|
||||
int len_left;
|
||||
|
||||
if (!log)
|
||||
return;
|
||||
|
||||
len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
|
||||
if (len_left <= 0)
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(line, sizeof(line), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
strncat(log, line, len_left);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_log_append);
|
||||
|
||||
size_t kunit_suite_num_test_cases(struct kunit_suite *suite)
|
||||
{
|
||||
struct kunit_case *test_case;
|
||||
size_t len = 0;
|
||||
|
||||
for (test_case = test_cases; test_case->run_case; test_case++)
|
||||
kunit_suite_for_each_test_case(suite, test_case)
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
|
||||
|
||||
static void kunit_print_subtest_start(struct kunit_suite *suite)
|
||||
{
|
||||
kunit_print_tap_version();
|
||||
pr_info("\t# Subtest: %s\n", suite->name);
|
||||
pr_info("\t1..%zd\n", kunit_test_cases_len(suite->test_cases));
|
||||
kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
|
||||
suite->name);
|
||||
kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
|
||||
kunit_suite_num_test_cases(suite));
|
||||
}
|
||||
|
||||
static void kunit_print_ok_not_ok(bool should_indent,
|
||||
static void kunit_print_ok_not_ok(void *test_or_suite,
|
||||
bool is_test,
|
||||
bool is_ok,
|
||||
size_t test_number,
|
||||
const char *description)
|
||||
{
|
||||
const char *indent, *ok_not_ok;
|
||||
struct kunit_suite *suite = is_test ? NULL : test_or_suite;
|
||||
struct kunit *test = is_test ? test_or_suite : NULL;
|
||||
|
||||
if (should_indent)
|
||||
indent = "\t";
|
||||
/*
|
||||
* We do not log the test suite results as doing so would
|
||||
* mean debugfs display would consist of the test suite
|
||||
* description and status prior to individual test results.
|
||||
* Hence directly printk the suite status, and we will
|
||||
* separately seq_printf() the suite status for the debugfs
|
||||
* representation.
|
||||
*/
|
||||
if (suite)
|
||||
pr_info("%s %zd - %s",
|
||||
kunit_status_to_string(is_ok),
|
||||
test_number, description);
|
||||
else
|
||||
indent = "";
|
||||
|
||||
if (is_ok)
|
||||
ok_not_ok = "ok";
|
||||
else
|
||||
ok_not_ok = "not ok";
|
||||
|
||||
pr_info("%s%s %zd - %s\n", indent, ok_not_ok, test_number, description);
|
||||
kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT "%s %zd - %s",
|
||||
kunit_status_to_string(is_ok),
|
||||
test_number, description);
|
||||
}
|
||||
|
||||
static bool kunit_suite_has_succeeded(struct kunit_suite *suite)
|
||||
bool kunit_suite_has_succeeded(struct kunit_suite *suite)
|
||||
{
|
||||
const struct kunit_case *test_case;
|
||||
|
||||
for (test_case = suite->test_cases; test_case->run_case; test_case++)
|
||||
kunit_suite_for_each_test_case(suite, test_case) {
|
||||
if (!test_case->success)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_suite_has_succeeded);
|
||||
|
||||
static void kunit_print_subtest_end(struct kunit_suite *suite)
|
||||
{
|
||||
static size_t kunit_suite_counter = 1;
|
||||
|
||||
kunit_print_ok_not_ok(false,
|
||||
kunit_print_ok_not_ok((void *)suite, false,
|
||||
kunit_suite_has_succeeded(suite),
|
||||
kunit_suite_counter++,
|
||||
suite->name);
|
||||
}
|
||||
|
||||
static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case,
|
||||
size_t test_number)
|
||||
unsigned int kunit_test_case_num(struct kunit_suite *suite,
|
||||
struct kunit_case *test_case)
|
||||
{
|
||||
kunit_print_ok_not_ok(true,
|
||||
test_case->success,
|
||||
test_number,
|
||||
test_case->name);
|
||||
struct kunit_case *tc;
|
||||
unsigned int i = 1;
|
||||
|
||||
kunit_suite_for_each_test_case(suite, tc) {
|
||||
if (tc == test_case)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_test_case_num);
|
||||
|
||||
static void kunit_print_string_stream(struct kunit *test,
|
||||
struct string_stream *stream)
|
||||
@ -102,6 +147,9 @@ static void kunit_print_string_stream(struct kunit *test,
|
||||
struct string_stream_fragment *fragment;
|
||||
char *buf;
|
||||
|
||||
if (string_stream_is_empty(stream))
|
||||
return;
|
||||
|
||||
buf = string_stream_get_string(stream);
|
||||
if (!buf) {
|
||||
kunit_err(test,
|
||||
@ -175,11 +223,14 @@ void kunit_do_assertion(struct kunit *test,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_do_assertion);
|
||||
|
||||
void kunit_init_test(struct kunit *test, const char *name)
|
||||
void kunit_init_test(struct kunit *test, const char *name, char *log)
|
||||
{
|
||||
spin_lock_init(&test->lock);
|
||||
INIT_LIST_HEAD(&test->resources);
|
||||
test->name = name;
|
||||
test->log = log;
|
||||
if (test->log)
|
||||
test->log[0] = '\0';
|
||||
test->success = true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_init_test);
|
||||
@ -290,7 +341,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
|
||||
struct kunit_try_catch *try_catch;
|
||||
struct kunit test;
|
||||
|
||||
kunit_init_test(&test, test_case->name);
|
||||
kunit_init_test(&test, test_case->name, test_case->log);
|
||||
try_catch = &test.try_catch;
|
||||
|
||||
kunit_try_catch_init(try_catch,
|
||||
@ -303,19 +354,20 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
|
||||
kunit_try_catch_run(try_catch, &context);
|
||||
|
||||
test_case->success = test.success;
|
||||
|
||||
kunit_print_ok_not_ok(&test, true, test_case->success,
|
||||
kunit_test_case_num(suite, test_case),
|
||||
test_case->name);
|
||||
}
|
||||
|
||||
int kunit_run_tests(struct kunit_suite *suite)
|
||||
{
|
||||
struct kunit_case *test_case;
|
||||
size_t test_case_count = 1;
|
||||
|
||||
kunit_print_subtest_start(suite);
|
||||
|
||||
for (test_case = suite->test_cases; test_case->run_case; test_case++) {
|
||||
kunit_suite_for_each_test_case(suite, test_case)
|
||||
kunit_run_case_catch_errors(suite, test_case);
|
||||
kunit_print_test_case_ok_not_ok(test_case, test_case_count++);
|
||||
}
|
||||
|
||||
kunit_print_subtest_end(suite);
|
||||
|
||||
@ -323,6 +375,37 @@ int kunit_run_tests(struct kunit_suite *suite)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kunit_run_tests);
|
||||
|
||||
static void kunit_init_suite(struct kunit_suite *suite)
|
||||
{
|
||||
kunit_debugfs_create_suite(suite);
|
||||
}
|
||||
|
||||
int __kunit_test_suites_init(struct kunit_suite **suites)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; suites[i] != NULL; i++) {
|
||||
kunit_init_suite(suites[i]);
|
||||
kunit_run_tests(suites[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__kunit_test_suites_init);
|
||||
|
||||
static void kunit_exit_suite(struct kunit_suite *suite)
|
||||
{
|
||||
kunit_debugfs_destroy_suite(suite);
|
||||
}
|
||||
|
||||
void __kunit_test_suites_exit(struct kunit_suite **suites)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; suites[i] != NULL; i++)
|
||||
kunit_exit_suite(suites[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__kunit_test_suites_exit);
|
||||
|
||||
struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
|
||||
kunit_resource_init_t init,
|
||||
kunit_resource_free_t free,
|
||||
@ -489,12 +572,15 @@ EXPORT_SYMBOL_GPL(kunit_cleanup);
|
||||
|
||||
static int __init kunit_init(void)
|
||||
{
|
||||
kunit_debugfs_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(kunit_init);
|
||||
|
||||
static void __exit kunit_exit(void)
|
||||
{
|
||||
kunit_debugfs_cleanup();
|
||||
}
|
||||
module_exit(kunit_exit);
|
||||
|
||||
|
@ -659,7 +659,7 @@ static void list_test_list_for_each_prev_safe(struct kunit *test)
|
||||
static void list_test_list_for_each_entry(struct kunit *test)
|
||||
{
|
||||
struct list_test_struct entries[5], *cur;
|
||||
static LIST_HEAD(list);
|
||||
LIST_HEAD(list);
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
@ -680,7 +680,7 @@ static void list_test_list_for_each_entry(struct kunit *test)
|
||||
static void list_test_list_for_each_entry_reverse(struct kunit *test)
|
||||
{
|
||||
struct list_test_struct entries[5], *cur;
|
||||
static LIST_HEAD(list);
|
||||
LIST_HEAD(list);
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
|
1
tools/testing/kunit/.gitattributes
vendored
Normal file
1
tools/testing/kunit/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
test_data/* binary
|
41
tools/testing/kunit/configs/broken_on_uml.config
Normal file
41
tools/testing/kunit/configs/broken_on_uml.config
Normal file
@ -0,0 +1,41 @@
|
||||
# These are currently broken on UML and prevent allyesconfig from building
|
||||
# CONFIG_STATIC_LINK is not set
|
||||
# CONFIG_UML_NET_VECTOR is not set
|
||||
# CONFIG_UML_NET_VDE is not set
|
||||
# CONFIG_UML_NET_PCAP is not set
|
||||
# CONFIG_NET_PTP_CLASSIFY is not set
|
||||
# CONFIG_IP_VS is not set
|
||||
# CONFIG_BRIDGE_EBT_BROUTE is not set
|
||||
# CONFIG_BRIDGE_EBT_T_FILTER is not set
|
||||
# CONFIG_BRIDGE_EBT_T_NAT is not set
|
||||
# CONFIG_MTD_NAND_CADENCE is not set
|
||||
# CONFIG_MTD_NAND_NANDSIM is not set
|
||||
# CONFIG_BLK_DEV_NULL_BLK is not set
|
||||
# CONFIG_BLK_DEV_RAM is not set
|
||||
# CONFIG_SCSI_DEBUG is not set
|
||||
# CONFIG_NET_VENDOR_XILINX is not set
|
||||
# CONFIG_NULL_TTY is not set
|
||||
# CONFIG_PTP_1588_CLOCK is not set
|
||||
# CONFIG_PINCTRL_EQUILIBRIUM is not set
|
||||
# CONFIG_DMABUF_SELFTESTS is not set
|
||||
# CONFIG_COMEDI is not set
|
||||
# CONFIG_XIL_AXIS_FIFO is not set
|
||||
# CONFIG_EXFAT_FS is not set
|
||||
# CONFIG_STM_DUMMY is not set
|
||||
# CONFIG_FSI_MASTER_ASPEED is not set
|
||||
# CONFIG_JFS_FS is not set
|
||||
# CONFIG_UBIFS_FS is not set
|
||||
# CONFIG_CRAMFS is not set
|
||||
# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
|
||||
# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
|
||||
# CONFIG_KCOV is not set
|
||||
# CONFIG_LKDTM is not set
|
||||
# CONFIG_REED_SOLOMON_TEST is not set
|
||||
# CONFIG_TEST_RHASHTABLE is not set
|
||||
# CONFIG_TEST_MEMINIT is not set
|
||||
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
|
||||
# CONFIG_DEBUG_INFO_BTF is not set
|
||||
# CONFIG_PTP_1588_CLOCK_INES is not set
|
||||
# CONFIG_QCOM_CPR is not set
|
||||
# CONFIG_RESET_BRCMSTB_RESCAL is not set
|
||||
# CONFIG_RESET_INTEL_GW is not set
|
@ -22,7 +22,9 @@ import kunit_parser
|
||||
|
||||
KunitResult = namedtuple('KunitResult', ['status','result'])
|
||||
|
||||
KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs', 'build_dir', 'defconfig'])
|
||||
KunitRequest = namedtuple('KunitRequest', ['raw_output','timeout', 'jobs',
|
||||
'build_dir', 'defconfig',
|
||||
'alltests', 'make_options'])
|
||||
|
||||
KernelDirectoryPath = sys.argv[0].split('tools/testing/kunit/')[0]
|
||||
|
||||
@ -47,7 +49,7 @@ def get_kernel_root_path():
|
||||
def run_tests(linux: kunit_kernel.LinuxSourceTree,
|
||||
request: KunitRequest) -> KunitResult:
|
||||
config_start = time.time()
|
||||
success = linux.build_reconfig(request.build_dir)
|
||||
success = linux.build_reconfig(request.build_dir, request.make_options)
|
||||
config_end = time.time()
|
||||
if not success:
|
||||
return KunitResult(KunitStatus.CONFIG_FAILURE, 'could not configure kernel')
|
||||
@ -55,24 +57,24 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree,
|
||||
kunit_parser.print_with_timestamp('Building KUnit Kernel ...')
|
||||
|
||||
build_start = time.time()
|
||||
success = linux.build_um_kernel(request.jobs, request.build_dir)
|
||||
success = linux.build_um_kernel(request.alltests,
|
||||
request.jobs,
|
||||
request.build_dir,
|
||||
request.make_options)
|
||||
build_end = time.time()
|
||||
if not success:
|
||||
return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel')
|
||||
|
||||
kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
|
||||
test_start = time.time()
|
||||
|
||||
test_result = kunit_parser.TestResult(kunit_parser.TestStatus.SUCCESS,
|
||||
[],
|
||||
'Tests not Parsed.')
|
||||
kunit_output = linux.run_kernel(
|
||||
timeout=None if request.alltests else request.timeout,
|
||||
build_dir=request.build_dir)
|
||||
if request.raw_output:
|
||||
kunit_parser.raw_output(
|
||||
linux.run_kernel(timeout=request.timeout,
|
||||
build_dir=request.build_dir))
|
||||
raw_output = kunit_parser.raw_output(kunit_output)
|
||||
isolated = list(kunit_parser.isolate_kunit_output(raw_output))
|
||||
test_result = kunit_parser.parse_test_result(isolated)
|
||||
else:
|
||||
kunit_output = linux.run_kernel(timeout=request.timeout,
|
||||
build_dir=request.build_dir)
|
||||
test_result = kunit_parser.parse_run_tests(kunit_output)
|
||||
test_end = time.time()
|
||||
|
||||
@ -120,6 +122,14 @@ def main(argv, linux=None):
|
||||
help='Uses a default .kunitconfig.',
|
||||
action='store_true')
|
||||
|
||||
run_parser.add_argument('--alltests',
|
||||
help='Run all KUnit tests through allyesconfig',
|
||||
action='store_true')
|
||||
|
||||
run_parser.add_argument('--make_options',
|
||||
help='X=Y make option, can be repeated.',
|
||||
action='append')
|
||||
|
||||
cli_args = parser.parse_args(argv)
|
||||
|
||||
if cli_args.subcommand == 'run':
|
||||
@ -143,7 +153,9 @@ def main(argv, linux=None):
|
||||
cli_args.timeout,
|
||||
cli_args.jobs,
|
||||
cli_args.build_dir,
|
||||
cli_args.defconfig)
|
||||
cli_args.defconfig,
|
||||
cli_args.alltests,
|
||||
cli_args.make_options)
|
||||
result = run_tests(linux, request)
|
||||
if result.status != KunitStatus.SUCCESS:
|
||||
sys.exit(1)
|
||||
|
@ -9,16 +9,18 @@
|
||||
import collections
|
||||
import re
|
||||
|
||||
CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$'
|
||||
CONFIG_PATTERN = r'^CONFIG_\w+=\S+$'
|
||||
|
||||
KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry'])
|
||||
CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
|
||||
CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+)$'
|
||||
|
||||
KconfigEntryBase = collections.namedtuple('KconfigEntry', ['name', 'value'])
|
||||
|
||||
class KconfigEntry(KconfigEntryBase):
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.raw_entry
|
||||
if self.value == 'n':
|
||||
return r'# CONFIG_%s is not set' % (self.name)
|
||||
else:
|
||||
return r'CONFIG_%s=%s' % (self.name, self.value)
|
||||
|
||||
|
||||
class KconfigParseError(Exception):
|
||||
@ -38,7 +40,17 @@ class Kconfig(object):
|
||||
self._entries.append(entry)
|
||||
|
||||
def is_subset_of(self, other: 'Kconfig') -> bool:
|
||||
return self.entries().issubset(other.entries())
|
||||
for a in self.entries():
|
||||
found = False
|
||||
for b in other.entries():
|
||||
if a.name != b.name:
|
||||
continue
|
||||
if a.value != b.value:
|
||||
return False
|
||||
found = True
|
||||
if a.value != 'n' and found == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def write_to_file(self, path: str) -> None:
|
||||
with open(path, 'w') as f:
|
||||
@ -54,9 +66,20 @@ class Kconfig(object):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
elif config_matcher.match(line) or is_not_set_matcher.match(line):
|
||||
self._entries.append(KconfigEntry(line))
|
||||
elif line[0] == '#':
|
||||
|
||||
match = config_matcher.match(line)
|
||||
if match:
|
||||
entry = KconfigEntry(match.group(1), match.group(2))
|
||||
self.add_entry(entry)
|
||||
continue
|
||||
|
||||
empty_match = is_not_set_matcher.match(line)
|
||||
if empty_match:
|
||||
entry = KconfigEntry(empty_match.group(1), 'n')
|
||||
self.add_entry(entry)
|
||||
continue
|
||||
|
||||
if line[0] == '#':
|
||||
continue
|
||||
else:
|
||||
raise KconfigParseError('Failed to parse: ' + line)
|
||||
|
@ -10,11 +10,16 @@
|
||||
import logging
|
||||
import subprocess
|
||||
import os
|
||||
import signal
|
||||
|
||||
from contextlib import ExitStack
|
||||
|
||||
import kunit_config
|
||||
import kunit_parser
|
||||
|
||||
KCONFIG_PATH = '.config'
|
||||
kunitconfig_path = '.kunitconfig'
|
||||
BROKEN_ALLCONFIG_PATH = 'tools/testing/kunit/configs/broken_on_uml.config'
|
||||
|
||||
class ConfigError(Exception):
|
||||
"""Represents an error trying to configure the Linux kernel."""
|
||||
@ -35,19 +40,40 @@ class LinuxSourceTreeOperations(object):
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise ConfigError(e.output)
|
||||
|
||||
def make_olddefconfig(self, build_dir):
|
||||
def make_olddefconfig(self, build_dir, make_options):
|
||||
command = ['make', 'ARCH=um', 'olddefconfig']
|
||||
if make_options:
|
||||
command.extend(make_options)
|
||||
if build_dir:
|
||||
command += ['O=' + build_dir]
|
||||
try:
|
||||
subprocess.check_output(command)
|
||||
subprocess.check_output(command, stderr=subprocess.PIPE)
|
||||
except OSError as e:
|
||||
raise ConfigError('Could not call make command: ' + e)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise ConfigError(e.output)
|
||||
|
||||
def make(self, jobs, build_dir):
|
||||
def make_allyesconfig(self):
|
||||
kunit_parser.print_with_timestamp(
|
||||
'Enabling all CONFIGs for UML...')
|
||||
process = subprocess.Popen(
|
||||
['make', 'ARCH=um', 'allyesconfig'],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.STDOUT)
|
||||
process.wait()
|
||||
kunit_parser.print_with_timestamp(
|
||||
'Disabling broken configs to run KUnit tests...')
|
||||
with ExitStack() as es:
|
||||
config = open(KCONFIG_PATH, 'a')
|
||||
disable = open(BROKEN_ALLCONFIG_PATH, 'r').read()
|
||||
config.write(disable)
|
||||
kunit_parser.print_with_timestamp(
|
||||
'Starting Kernel with all configs takes a few minutes...')
|
||||
|
||||
def make(self, jobs, build_dir, make_options):
|
||||
command = ['make', 'ARCH=um', '--jobs=' + str(jobs)]
|
||||
if make_options:
|
||||
command.extend(make_options)
|
||||
if build_dir:
|
||||
command += ['O=' + build_dir]
|
||||
try:
|
||||
@ -57,18 +83,16 @@ class LinuxSourceTreeOperations(object):
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise BuildError(e.output)
|
||||
|
||||
def linux_bin(self, params, timeout, build_dir):
|
||||
def linux_bin(self, params, timeout, build_dir, outfile):
|
||||
"""Runs the Linux UML binary. Must be named 'linux'."""
|
||||
linux_bin = './linux'
|
||||
if build_dir:
|
||||
linux_bin = os.path.join(build_dir, 'linux')
|
||||
process = subprocess.Popen(
|
||||
[linux_bin] + params,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
process.wait(timeout=timeout)
|
||||
return process
|
||||
with open(outfile, 'w') as output:
|
||||
process = subprocess.Popen([linux_bin] + params,
|
||||
stdout=output,
|
||||
stderr=subprocess.STDOUT)
|
||||
process.wait(timeout)
|
||||
|
||||
|
||||
def get_kconfig_path(build_dir):
|
||||
@ -84,6 +108,7 @@ class LinuxSourceTree(object):
|
||||
self._kconfig = kunit_config.Kconfig()
|
||||
self._kconfig.read_from_file(kunitconfig_path)
|
||||
self._ops = LinuxSourceTreeOperations()
|
||||
signal.signal(signal.SIGINT, self.signal_handler)
|
||||
|
||||
def clean(self):
|
||||
try:
|
||||
@ -107,19 +132,19 @@ class LinuxSourceTree(object):
|
||||
return False
|
||||
return True
|
||||
|
||||
def build_config(self, build_dir):
|
||||
def build_config(self, build_dir, make_options):
|
||||
kconfig_path = get_kconfig_path(build_dir)
|
||||
if build_dir and not os.path.exists(build_dir):
|
||||
os.mkdir(build_dir)
|
||||
self._kconfig.write_to_file(kconfig_path)
|
||||
try:
|
||||
self._ops.make_olddefconfig(build_dir)
|
||||
self._ops.make_olddefconfig(build_dir, make_options)
|
||||
except ConfigError as e:
|
||||
logging.error(e)
|
||||
return False
|
||||
return self.validate_config(build_dir)
|
||||
|
||||
def build_reconfig(self, build_dir):
|
||||
def build_reconfig(self, build_dir, make_options):
|
||||
"""Creates a new .config if it is not a subset of the .kunitconfig."""
|
||||
kconfig_path = get_kconfig_path(build_dir)
|
||||
if os.path.exists(kconfig_path):
|
||||
@ -128,26 +153,33 @@ class LinuxSourceTree(object):
|
||||
if not self._kconfig.is_subset_of(existing_kconfig):
|
||||
print('Regenerating .config ...')
|
||||
os.remove(kconfig_path)
|
||||
return self.build_config(build_dir)
|
||||
return self.build_config(build_dir, make_options)
|
||||
else:
|
||||
return True
|
||||
else:
|
||||
print('Generating .config ...')
|
||||
return self.build_config(build_dir)
|
||||
return self.build_config(build_dir, make_options)
|
||||
|
||||
def build_um_kernel(self, jobs, build_dir):
|
||||
def build_um_kernel(self, alltests, jobs, build_dir, make_options):
|
||||
if alltests:
|
||||
self._ops.make_allyesconfig()
|
||||
try:
|
||||
self._ops.make_olddefconfig(build_dir)
|
||||
self._ops.make(jobs, build_dir)
|
||||
self._ops.make_olddefconfig(build_dir, make_options)
|
||||
self._ops.make(jobs, build_dir, make_options)
|
||||
except (ConfigError, BuildError) as e:
|
||||
logging.error(e)
|
||||
return False
|
||||
return self.validate_config(build_dir)
|
||||
|
||||
def run_kernel(self, args=[], timeout=None, build_dir=''):
|
||||
args.extend(['mem=256M'])
|
||||
process = self._ops.linux_bin(args, timeout, build_dir)
|
||||
with open(os.path.join(build_dir, 'test.log'), 'w') as f:
|
||||
for line in process.stdout:
|
||||
f.write(line.rstrip().decode('ascii') + '\n')
|
||||
yield line.rstrip().decode('ascii')
|
||||
def run_kernel(self, args=[], build_dir='', timeout=None):
|
||||
args.extend(['mem=1G'])
|
||||
outfile = 'test.log'
|
||||
self._ops.linux_bin(args, timeout, build_dir, outfile)
|
||||
subprocess.call(['stty', 'sane'])
|
||||
with open(outfile, 'r') as file:
|
||||
for line in file:
|
||||
yield line
|
||||
|
||||
def signal_handler(self, sig, frame):
|
||||
logging.error('Build interruption occurred. Cleaning console.')
|
||||
subprocess.call(['stty', 'sane'])
|
||||
|
@ -46,23 +46,26 @@ class TestStatus(Enum):
|
||||
TEST_CRASHED = auto()
|
||||
NO_TESTS = auto()
|
||||
|
||||
kunit_start_re = re.compile(r'^TAP version [0-9]+$')
|
||||
kunit_end_re = re.compile('List of all partitions:')
|
||||
kunit_start_re = re.compile(r'TAP version [0-9]+$')
|
||||
kunit_end_re = re.compile('(List of all partitions:|'
|
||||
'Kernel panic - not syncing: VFS:|reboot: System halted)')
|
||||
|
||||
def isolate_kunit_output(kernel_output):
|
||||
started = False
|
||||
for line in kernel_output:
|
||||
if kunit_start_re.match(line):
|
||||
if kunit_start_re.search(line):
|
||||
prefix_len = len(line.split('TAP version')[0])
|
||||
started = True
|
||||
yield line
|
||||
elif kunit_end_re.match(line):
|
||||
yield line[prefix_len:] if prefix_len > 0 else line
|
||||
elif kunit_end_re.search(line):
|
||||
break
|
||||
elif started:
|
||||
yield line
|
||||
yield line[prefix_len:] if prefix_len > 0 else line
|
||||
|
||||
def raw_output(kernel_output):
|
||||
for line in kernel_output:
|
||||
print(line)
|
||||
yield line
|
||||
|
||||
DIVIDER = '=' * 60
|
||||
|
||||
@ -91,7 +94,7 @@ def print_log(log):
|
||||
for m in log:
|
||||
print_with_timestamp(m)
|
||||
|
||||
TAP_ENTRIES = re.compile(r'^(TAP|\t?ok|\t?not ok|\t?[0-9]+\.\.[0-9]+|\t?#).*$')
|
||||
TAP_ENTRIES = re.compile(r'^(TAP|[\s]*ok|[\s]*not ok|[\s]*[0-9]+\.\.[0-9]+|[\s]*#).*$')
|
||||
|
||||
def consume_non_diagnositic(lines: List[str]) -> None:
|
||||
while lines and not TAP_ENTRIES.match(lines[0]):
|
||||
@ -104,22 +107,20 @@ def save_non_diagnositic(lines: List[str], test_case: TestCase) -> None:
|
||||
|
||||
OkNotOkResult = namedtuple('OkNotOkResult', ['is_ok','description', 'text'])
|
||||
|
||||
OK_NOT_OK_SUBTEST = re.compile(r'^\t(ok|not ok) [0-9]+ - (.*)$')
|
||||
OK_NOT_OK_SUBTEST = re.compile(r'^[\s]+(ok|not ok) [0-9]+ - (.*)$')
|
||||
|
||||
OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) [0-9]+ - (.*)$')
|
||||
|
||||
def parse_ok_not_ok_test_case(lines: List[str],
|
||||
test_case: TestCase,
|
||||
expecting_test_case: bool) -> bool:
|
||||
def parse_ok_not_ok_test_case(lines: List[str], test_case: TestCase) -> bool:
|
||||
save_non_diagnositic(lines, test_case)
|
||||
if not lines:
|
||||
if expecting_test_case:
|
||||
test_case.status = TestStatus.TEST_CRASHED
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
test_case.status = TestStatus.TEST_CRASHED
|
||||
return True
|
||||
line = lines[0]
|
||||
match = OK_NOT_OK_SUBTEST.match(line)
|
||||
while not match and lines:
|
||||
line = lines.pop(0)
|
||||
match = OK_NOT_OK_SUBTEST.match(line)
|
||||
if match:
|
||||
test_case.log.append(lines.pop(0))
|
||||
test_case.name = match.group(2)
|
||||
@ -133,7 +134,7 @@ def parse_ok_not_ok_test_case(lines: List[str],
|
||||
else:
|
||||
return False
|
||||
|
||||
SUBTEST_DIAGNOSTIC = re.compile(r'^\t# .*?: (.*)$')
|
||||
SUBTEST_DIAGNOSTIC = re.compile(r'^[\s]+# .*?: (.*)$')
|
||||
DIAGNOSTIC_CRASH_MESSAGE = 'kunit test case crashed!'
|
||||
|
||||
def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool:
|
||||
@ -150,17 +151,17 @@ def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool:
|
||||
else:
|
||||
return False
|
||||
|
||||
def parse_test_case(lines: List[str], expecting_test_case: bool) -> TestCase:
|
||||
def parse_test_case(lines: List[str]) -> TestCase:
|
||||
test_case = TestCase()
|
||||
save_non_diagnositic(lines, test_case)
|
||||
while parse_diagnostic(lines, test_case):
|
||||
pass
|
||||
if parse_ok_not_ok_test_case(lines, test_case, expecting_test_case):
|
||||
if parse_ok_not_ok_test_case(lines, test_case):
|
||||
return test_case
|
||||
else:
|
||||
return None
|
||||
|
||||
SUBTEST_HEADER = re.compile(r'^\t# Subtest: (.*)$')
|
||||
SUBTEST_HEADER = re.compile(r'^[\s]+# Subtest: (.*)$')
|
||||
|
||||
def parse_subtest_header(lines: List[str]) -> str:
|
||||
consume_non_diagnositic(lines)
|
||||
@ -173,7 +174,7 @@ def parse_subtest_header(lines: List[str]) -> str:
|
||||
else:
|
||||
return None
|
||||
|
||||
SUBTEST_PLAN = re.compile(r'\t[0-9]+\.\.([0-9]+)')
|
||||
SUBTEST_PLAN = re.compile(r'[\s]+[0-9]+\.\.([0-9]+)')
|
||||
|
||||
def parse_subtest_plan(lines: List[str]) -> int:
|
||||
consume_non_diagnositic(lines)
|
||||
@ -234,11 +235,11 @@ def parse_test_suite(lines: List[str]) -> TestSuite:
|
||||
expected_test_case_num = parse_subtest_plan(lines)
|
||||
if not expected_test_case_num:
|
||||
return None
|
||||
test_case = parse_test_case(lines, expected_test_case_num > 0)
|
||||
expected_test_case_num -= 1
|
||||
while test_case:
|
||||
while expected_test_case_num > 0:
|
||||
test_case = parse_test_case(lines)
|
||||
if not test_case:
|
||||
break
|
||||
test_suite.cases.append(test_case)
|
||||
test_case = parse_test_case(lines, expected_test_case_num > 0)
|
||||
expected_test_case_num -= 1
|
||||
if parse_ok_not_ok_test_suite(lines, test_suite):
|
||||
test_suite.status = bubble_up_test_case_errors(test_suite)
|
||||
|
@ -37,7 +37,7 @@ class KconfigTest(unittest.TestCase):
|
||||
self.assertTrue(kconfig0.is_subset_of(kconfig0))
|
||||
|
||||
kconfig1 = kunit_config.Kconfig()
|
||||
kconfig1.add_entry(kunit_config.KconfigEntry('CONFIG_TEST=y'))
|
||||
kconfig1.add_entry(kunit_config.KconfigEntry('TEST', 'y'))
|
||||
self.assertTrue(kconfig1.is_subset_of(kconfig1))
|
||||
self.assertTrue(kconfig0.is_subset_of(kconfig1))
|
||||
self.assertFalse(kconfig1.is_subset_of(kconfig0))
|
||||
@ -51,15 +51,15 @@ class KconfigTest(unittest.TestCase):
|
||||
|
||||
expected_kconfig = kunit_config.Kconfig()
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_UML=y'))
|
||||
kunit_config.KconfigEntry('UML', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_MMU=y'))
|
||||
kunit_config.KconfigEntry('MMU', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_TEST=y'))
|
||||
kunit_config.KconfigEntry('TEST', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_EXAMPLE_TEST=y'))
|
||||
kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('# CONFIG_MK8 is not set'))
|
||||
kunit_config.KconfigEntry('MK8', 'n'))
|
||||
|
||||
self.assertEqual(kconfig.entries(), expected_kconfig.entries())
|
||||
|
||||
@ -68,15 +68,15 @@ class KconfigTest(unittest.TestCase):
|
||||
|
||||
expected_kconfig = kunit_config.Kconfig()
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_UML=y'))
|
||||
kunit_config.KconfigEntry('UML', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_MMU=y'))
|
||||
kunit_config.KconfigEntry('MMU', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_TEST=y'))
|
||||
kunit_config.KconfigEntry('TEST', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('CONFIG_EXAMPLE_TEST=y'))
|
||||
kunit_config.KconfigEntry('EXAMPLE_TEST', 'y'))
|
||||
expected_kconfig.add_entry(
|
||||
kunit_config.KconfigEntry('# CONFIG_MK8 is not set'))
|
||||
kunit_config.KconfigEntry('MK8', 'n'))
|
||||
|
||||
expected_kconfig.write_to_file(kconfig_path)
|
||||
|
||||
@ -108,6 +108,36 @@ class KUnitParserTest(unittest.TestCase):
|
||||
self.assertContains('ok 1 - example', result)
|
||||
file.close()
|
||||
|
||||
def test_output_with_prefix_isolated_correctly(self):
|
||||
log_path = get_absolute_path(
|
||||
'test_data/test_pound_sign.log')
|
||||
with open(log_path) as file:
|
||||
result = kunit_parser.isolate_kunit_output(file.readlines())
|
||||
self.assertContains('TAP version 14\n', result)
|
||||
self.assertContains(' # Subtest: kunit-resource-test', result)
|
||||
self.assertContains(' 1..5', result)
|
||||
self.assertContains(' ok 1 - kunit_resource_test_init_resources', result)
|
||||
self.assertContains(' ok 2 - kunit_resource_test_alloc_resource', result)
|
||||
self.assertContains(' ok 3 - kunit_resource_test_destroy_resource', result)
|
||||
self.assertContains(' foo bar #', result)
|
||||
self.assertContains(' ok 4 - kunit_resource_test_cleanup_resources', result)
|
||||
self.assertContains(' ok 5 - kunit_resource_test_proper_free_ordering', result)
|
||||
self.assertContains('ok 1 - kunit-resource-test', result)
|
||||
self.assertContains(' foo bar # non-kunit output', result)
|
||||
self.assertContains(' # Subtest: kunit-try-catch-test', result)
|
||||
self.assertContains(' 1..2', result)
|
||||
self.assertContains(' ok 1 - kunit_test_try_catch_successful_try_no_catch',
|
||||
result)
|
||||
self.assertContains(' ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch',
|
||||
result)
|
||||
self.assertContains('ok 2 - kunit-try-catch-test', result)
|
||||
self.assertContains(' # Subtest: string-stream-test', result)
|
||||
self.assertContains(' 1..3', result)
|
||||
self.assertContains(' ok 1 - string_stream_test_empty_on_creation', result)
|
||||
self.assertContains(' ok 2 - string_stream_test_not_empty_after_add', result)
|
||||
self.assertContains(' ok 3 - string_stream_test_get_string', result)
|
||||
self.assertContains('ok 3 - string-stream-test', result)
|
||||
|
||||
def test_parse_successful_test_log(self):
|
||||
all_passed_log = get_absolute_path(
|
||||
'test_data/test_is_test_passed-all_passed.log')
|
||||
@ -150,6 +180,45 @@ class KUnitParserTest(unittest.TestCase):
|
||||
result.status)
|
||||
file.close()
|
||||
|
||||
def test_ignores_prefix_printk_time(self):
|
||||
prefix_log = get_absolute_path(
|
||||
'test_data/test_config_printk_time.log')
|
||||
with open(prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_ignores_multiple_prefixes(self):
|
||||
prefix_log = get_absolute_path(
|
||||
'test_data/test_multiple_prefixes.log')
|
||||
with open(prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_prefix_mixed_kernel_output(self):
|
||||
mixed_prefix_log = get_absolute_path(
|
||||
'test_data/test_interrupted_tap_output.log')
|
||||
with open(mixed_prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_prefix_poundsign(self):
|
||||
pound_log = get_absolute_path('test_data/test_pound_sign.log')
|
||||
with open(pound_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_kernel_panic_end(self):
|
||||
panic_log = get_absolute_path('test_data/test_kernel_panic_interrupt.log')
|
||||
with open(panic_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_pound_no_prefix(self):
|
||||
pound_log = get_absolute_path('test_data/test_pound_no_prefix.log')
|
||||
with open(pound_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
class StrContains(str):
|
||||
def __eq__(self, other):
|
||||
return self in other
|
||||
@ -174,7 +243,8 @@ class KUnitMainTest(unittest.TestCase):
|
||||
kunit.main(['run'], self.linux_source_mock)
|
||||
assert self.linux_source_mock.build_reconfig.call_count == 1
|
||||
assert self.linux_source_mock.run_kernel.call_count == 1
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=300)
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(
|
||||
build_dir='', timeout=300)
|
||||
self.print_mock.assert_any_call(StrContains('Testing complete.'))
|
||||
|
||||
def test_run_passes_args_fail(self):
|
||||
@ -189,25 +259,27 @@ class KUnitMainTest(unittest.TestCase):
|
||||
|
||||
def test_run_raw_output(self):
|
||||
self.linux_source_mock.run_kernel = mock.Mock(return_value=[])
|
||||
kunit.main(['run', '--raw_output'], self.linux_source_mock)
|
||||
with self.assertRaises(SystemExit) as e:
|
||||
kunit.main(['run', '--raw_output'], self.linux_source_mock)
|
||||
assert type(e.exception) == SystemExit
|
||||
assert e.exception.code == 1
|
||||
assert self.linux_source_mock.build_reconfig.call_count == 1
|
||||
assert self.linux_source_mock.run_kernel.call_count == 1
|
||||
for kall in self.print_mock.call_args_list:
|
||||
assert kall != mock.call(StrContains('Testing complete.'))
|
||||
assert kall != mock.call(StrContains(' 0 tests run'))
|
||||
|
||||
def test_run_timeout(self):
|
||||
timeout = 3453
|
||||
kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
|
||||
assert self.linux_source_mock.build_reconfig.call_count == 1
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=timeout)
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(
|
||||
build_dir='', timeout=timeout)
|
||||
self.print_mock.assert_any_call(StrContains('Testing complete.'))
|
||||
|
||||
def test_run_builddir(self):
|
||||
build_dir = '.kunit'
|
||||
kunit.main(['run', '--build_dir', build_dir], self.linux_source_mock)
|
||||
assert self.linux_source_mock.build_reconfig.call_count == 1
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=build_dir, timeout=300)
|
||||
self.linux_source_mock.run_kernel.assert_called_once_with(
|
||||
build_dir=build_dir, timeout=300)
|
||||
self.print_mock.assert_any_call(StrContains('Testing complete.'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
31
tools/testing/kunit/test_data/test_config_printk_time.log
Normal file
31
tools/testing/kunit/test_data/test_config_printk_time.log
Normal file
@ -0,0 +1,31 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000] ok 1 - kunit-resource-test
|
||||
[ 0.060000] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000] 1..2
|
||||
[ 0.060000] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000] # Subtest: string-stream-test
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000] ok 2 - string_stream_test_not_empty_after_add
|
||||
[ 0.060000] ok 3 - string_stream_test_get_string
|
||||
[ 0.060000] ok 3 - string-stream-test
|
||||
[ 0.060000] List of all partitions:
|
||||
[ 0.060000] No filesystem could mount root, tried:
|
||||
[ 0.060000]
|
||||
[ 0.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
@ -0,0 +1,37 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000] kAFS: Red Hat AFS client v0.1 registering.
|
||||
[ 0.060000] FS-Cache: Netfs 'afs' registered for caching
|
||||
[ 0.060000] *** VALIDATE kAFS ***
|
||||
[ 0.060000] Btrfs loaded, crc32c=crc32c-generic, debug=on, assert=on, integrity-checker=on, ref-verify=on
|
||||
[ 0.060000] BTRFS: selftest: sectorsize: 4096 nodesize: 4096
|
||||
[ 0.060000] BTRFS: selftest: running btrfs free space cache tests
|
||||
[ 0.060000] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000] ok 1 - kunit-resource-test
|
||||
[ 0.060000] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000] 1..2
|
||||
[ 0.060000] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000] # Subtest: string-stream-test
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000] ok 2 - string_stream_test_not_empty_after_add
|
||||
[ 0.060000] ok 3 - string_stream_test_get_string
|
||||
[ 0.060000] ok 3 - string-stream-test
|
||||
[ 0.060000] List of all partitions:
|
||||
[ 0.060000] No filesystem could mount root, tried:
|
||||
[ 0.060000]
|
||||
[ 0.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
@ -0,0 +1,25 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000] ok 1 - kunit-resource-test
|
||||
[ 0.060000] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000] 1..2
|
||||
[ 0.060000] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000] # Subtest: string-stream-test
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
31
tools/testing/kunit/test_data/test_multiple_prefixes.log
Normal file
31
tools/testing/kunit/test_data/test_multiple_prefixes.log
Normal file
@ -0,0 +1,31 @@
|
||||
[ 0.060000][ T1] printk: console [mc-1] enabled
|
||||
[ 0.060000][ T1] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000][ T1] TAP version 14
|
||||
[ 0.060000][ T1] # Subtest: kunit-resource-test
|
||||
[ 0.060000][ T1] 1..5
|
||||
[ 0.060000][ T1] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000][ T1] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000][ T1] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000][ T1] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000][ T1] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000][ T1] ok 1 - kunit-resource-test
|
||||
[ 0.060000][ T1] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000][ T1] 1..2
|
||||
[ 0.060000][ T1] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000][ T1] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000][ T1] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000][ T1] # Subtest: string-stream-test
|
||||
[ 0.060000][ T1] 1..3
|
||||
[ 0.060000][ T1] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000][ T1] ok 2 - string_stream_test_not_empty_after_add
|
||||
[ 0.060000][ T1] ok 3 - string_stream_test_get_string
|
||||
[ 0.060000][ T1] ok 3 - string-stream-test
|
||||
[ 0.060000][ T1] List of all partitions:
|
||||
[ 0.060000][ T1] No filesystem could mount root, tried:
|
||||
[ 0.060000][ T1]
|
||||
[ 0.060000][ T1] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000][ T1] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000][ T1] Stack:
|
||||
[ 0.060000][ T1] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000][ T1] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000][ T1] 6005fcec 601bc260 705c0000 3000000010
|
@ -0,0 +1,33 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000] foo bar #
|
||||
[ 0.060000] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000] ok 1 - kunit-resource-test
|
||||
[ 0.060000] foo bar # non-kunit output
|
||||
[ 0.060000] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000] 1..2
|
||||
[ 0.060000] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000] # Subtest: string-stream-test
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000] ok 2 - string_stream_test_not_empty_after_add
|
||||
[ 0.060000] ok 3 - string_stream_test_get_string
|
||||
[ 0.060000] ok 3 - string-stream-test
|
||||
[ 0.060000] List of all partitions:
|
||||
[ 0.060000] No filesystem could mount root, tried:
|
||||
[ 0.060000]
|
||||
[ 0.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
33
tools/testing/kunit/test_data/test_pound_no_prefix.log
Normal file
33
tools/testing/kunit/test_data/test_pound_no_prefix.log
Normal file
@ -0,0 +1,33 @@
|
||||
printk: console [mc-1] enabled
|
||||
random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
TAP version 14
|
||||
# Subtest: kunit-resource-test
|
||||
1..5
|
||||
ok 1 - kunit_resource_test_init_resources
|
||||
ok 2 - kunit_resource_test_alloc_resource
|
||||
ok 3 - kunit_resource_test_destroy_resource
|
||||
foo bar #
|
||||
ok 4 - kunit_resource_test_cleanup_resources
|
||||
ok 5 - kunit_resource_test_proper_free_ordering
|
||||
ok 1 - kunit-resource-test
|
||||
foo bar # non-kunit output
|
||||
# Subtest: kunit-try-catch-test
|
||||
1..2
|
||||
ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
ok 2 - kunit-try-catch-test
|
||||
# Subtest: string-stream-test
|
||||
1..3
|
||||
ok 1 - string_stream_test_empty_on_creation
|
||||
ok 2 - string_stream_test_not_empty_after_add
|
||||
ok 3 - string_stream_test_get_string
|
||||
ok 3 - string-stream-test
|
||||
List of all partitions:
|
||||
No filesystem could mount root, tried:
|
||||
|
||||
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
Stack:
|
||||
602086f8 601bc260 705c0000 705c0000
|
||||
602086f8 6005fcec 705c0000 6002c6ab
|
||||
6005fcec 601bc260 705c0000 3000000010
|
33
tools/testing/kunit/test_data/test_pound_sign.log
Normal file
33
tools/testing/kunit/test_data/test_pound_sign.log
Normal file
@ -0,0 +1,33 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
[ 0.060000] ok 2 - kunit_resource_test_alloc_resource
|
||||
[ 0.060000] ok 3 - kunit_resource_test_destroy_resource
|
||||
[ 0.060000] foo bar #
|
||||
[ 0.060000] ok 4 - kunit_resource_test_cleanup_resources
|
||||
[ 0.060000] ok 5 - kunit_resource_test_proper_free_ordering
|
||||
[ 0.060000] ok 1 - kunit-resource-test
|
||||
[ 0.060000] foo bar # non-kunit output
|
||||
[ 0.060000] # Subtest: kunit-try-catch-test
|
||||
[ 0.060000] 1..2
|
||||
[ 0.060000] ok 1 - kunit_test_try_catch_successful_try_no_catch
|
||||
[ 0.060000] ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch
|
||||
[ 0.060000] ok 2 - kunit-try-catch-test
|
||||
[ 0.060000] # Subtest: string-stream-test
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] ok 1 - string_stream_test_empty_on_creation
|
||||
[ 0.060000] ok 2 - string_stream_test_not_empty_after_add
|
||||
[ 0.060000] ok 3 - string_stream_test_get_string
|
||||
[ 0.060000] ok 3 - string-stream-test
|
||||
[ 0.060000] List of all partitions:
|
||||
[ 0.060000] No filesystem could mount root, tried:
|
||||
[ 0.060000]
|
||||
[ 0.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)
|
||||
[ 0.060000] CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.0-rc1-gea2dd7c0875e-dirty #2
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
Loading…
Reference in New Issue
Block a user