요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
===============
Getting Started
===============
This page contains an overview of the kunit_tool and KUnit framework,
teaching how to run existing tests and then how to write a simple test case,
and covers common problems users face when using KUnit for the first time.
Installing Dependencies
=======================
KUnit has the same dependencies as the Linux kernel. As long as you can
build the kernel, you can run KUnit.
Running tests with kunit_tool
=============================
kunit_tool is a Python script, which configures and builds a kernel, runs
tests, and formats the test results. From the kernel repository, you
can run kunit_tool:
.. code-block:: bash
./tools/testing/kunit/kunit.py run
.. note ::
You may see the following error:
"The source tree is not clean, please run 'make ARCH=um mrproper'"
This happens because internally kunit.py specifies ``.kunit``
(default option) as the build directory in the command ``make O=output/dir``
through the argument ``--build_dir``. Hence, before starting an
out-of-tree build, the source tree must be clean.
There is also the same caveat mentioned in the "Build directory for
the kernel" section of the :doc:`admin-guide </admin-guide/README>`,
that is, its use, it must be used for all invocations of ``make``.
The good news is that it can indeed be solved by running
``make ARCH=um mrproper``, just be aware that this will delete the
current configuration and all generated files.
If everything worked correctly, you should see the following:
.. code-block::
Configuring KUnit Kernel ...
Building KUnit Kernel ...
Starting KUnit Kernel ...
The tests will pass or fail.
.. note ::
Because it is building a lot of sources for the first time,
the ``Building KUnit Kernel`` step may take a while.
For detailed information on this wrapper, see:
Documentation/dev-tools/kunit/run_wrapper.rst.
Selecting which tests to run
----------------------------
By default, kunit_tool runs all tests reachable with minimal configuration,
that is, using default values for most of the kconfig options. However,
you can select which tests to run by:
- `Customizing Kconfig`_ used to compile the kernel, or
- `Filtering tests by name`_ to select specifically which compiled tests to run.
Customizing Kconfig
~~~~~~~~~~~~~~~~~~~
A good starting point for the ``.kunitconfig`` is the KUnit default config.
If you didn't run ``kunit.py run`` yet, you can generate it by running:
.. code-block:: bash
cd $PATH_TO_LINUX_REPO
tools/testing/kunit/kunit.py config
cat .kunit/.kunitconfig
.. note ::
``.kunitconfig`` lives in the ``--build_dir`` used by kunit.py, which is
``.kunit`` by default.
Before running the tests, kunit_tool ensures that all config options
set in ``.kunitconfig`` are set in the kernel ``.config``. It will warn
you if you have not included dependencies for the options used.
There are many ways to customize the configurations:
a. Edit ``.kunit/.kunitconfig``. The file should contain the list of kconfig
options required to run the desired tests, including their dependencies.
You may want to remove CONFIG_KUNIT_ALL_TESTS from the ``.kunitconfig`` as
it will enable a number of additional tests that you may not want.
If you need to run on an architecture other than UML see :ref:`kunit-on-qemu`.
b. Enable additional kconfig options on top of ``.kunit/.kunitconfig``.
For example, to include the kernel's linked-list test you can run::
./tools/testing/kunit/kunit.py run \
--kconfig_add CONFIG_LIST_KUNIT_TEST=y
c. Provide the path of one or more .kunitconfig files from the tree.
For example, to run only ``FAT_FS`` and ``EXT4`` tests you can run::
./tools/testing/kunit/kunit.py run \
--kunitconfig ./fs/fat/.kunitconfig \
--kunitconfig ./fs/ext4/.kunitconfig
d. If you change the ``.kunitconfig``, kunit.py will trigger a rebuild of the
``.config`` file. But you can edit the ``.config`` file directly or with
tools like ``make menuconfig O=.kunit``. As long as its a superset of
``.kunitconfig``, kunit.py won't overwrite your changes.
.. note ::
To save a .kunitconfig after finding a satisfactory configuration::
make savedefconfig O=.kunit
cp .kunit/defconfig .kunit/.kunitconfig
Filtering tests by name
~~~~~~~~~~~~~~~~~~~~~~~
If you want to be more specific than Kconfig can provide, it is also possible
to select which tests to execute at boot-time by passing a glob filter
(read instructions regarding the pattern in the manpage :manpage:`glob(7)`).
If there is a ``"."`` (period) in the filter, it will be interpreted as a
separator between the name of the test suite and the test case,
otherwise, it will be interpreted as the name of the test suite.
For example, let's assume we are using the default config:
a. inform the name of a test suite, like ``"kunit_executor_test"``,
to run every test case it contains::
./tools/testing/kunit/kunit.py run "kunit_executor_test"
b. inform the name of a test case prefixed by its test suite,
like ``"example.example_simple_test"``, to run specifically that test case::
./tools/testing/kunit/kunit.py run "example.example_simple_test"
c. use wildcard characters (``*?[``) to run any test case that matches the pattern,
like ``"*.*64*"`` to run test cases containing ``"64"`` in the name inside
any test suite::
./tools/testing/kunit/kunit.py run "*.*64*"
Running Tests without the KUnit Wrapper
=======================================
If you do not want to use the KUnit Wrapper (for example: you want code
under test to integrate with other systems, or use a different/
unsupported architecture or configuration), KUnit can be included in
any kernel, and the results are read out and parsed manually.
.. note ::
``CONFIG_KUNIT`` should not be enabled in a production environment.
Enabling KUnit disables Kernel Address-Space Layout Randomization
(KASLR), and tests may affect the state of the kernel in ways not
suitable for production.
Configuring the Kernel
----------------------
To enable KUnit itself, you need to enable the ``CONFIG_KUNIT`` Kconfig
option (under Kernel Hacking/Kernel Testing and Coverage in
``menuconfig``). From there, you can enable any KUnit tests. They
usually have config options ending in ``_KUNIT_TEST``.
KUnit and KUnit tests can be compiled as modules. The tests in a module
will run when the module is loaded.
Running Tests (without KUnit Wrapper)
-------------------------------------
Build and run your kernel. In the kernel log, the test output is printed
out in the TAP format. This will only happen by default if KUnit/tests
are built-in. Otherwise the module will need to be loaded.
.. note ::
Some lines and/or data may get interspersed in the TAP output.
Writing Your First Test
=======================
In your kernel repository, let's add some code that we can test.
1. Create a file ``drivers/misc/example.h``, which includes:
.. code-block:: c
int misc_example_add(int left, int right);
2. Create a file ``drivers/misc/example.c``, which includes:
.. code-block:: c
#include <linux/errno.h>
#include "example.h"
int misc_example_add(int left, int right)
{
return left + right;
}
3. Add the following lines to ``drivers/misc/Kconfig``:
.. code-block:: kconfig
config MISC_EXAMPLE
bool "My example"
4. Add the following lines to ``drivers/misc/Makefile``:
.. code-block:: make
obj-$(CONFIG_MISC_EXAMPLE) += example.o
Now we are ready to write the test cases.
1. Add the below test case 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);
MODULE_LICENSE("GPL");
2. Add the following lines to ``drivers/misc/Kconfig``:
.. code-block:: kconfig
config MISC_EXAMPLE_TEST
tristate "Test for my example" if !KUNIT_ALL_TESTS
depends on MISC_EXAMPLE && KUNIT
default KUNIT_ALL_TESTS
Note: If your test does not support being built as a loadable module (which is
discouraged), replace tristate by bool, and depend on KUNIT=y instead of KUNIT.
3. Add the following lines to ``drivers/misc/Makefile``:
.. code-block:: make
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example_test.o
4. Add the following lines to ``.kunit/.kunitconfig``:
.. code-block:: none
CONFIG_MISC_EXAMPLE=y
CONFIG_MISC_EXAMPLE_TEST=y
5. Run the test:
.. code-block:: bash
./tools/testing/kunit/kunit.py run
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
==========
If you're interested in using some of the more advanced features of kunit.py,
take a look at Documentation/dev-tools/kunit/run_wrapper.rst
If you'd like to run tests without using kunit.py, check out
Documentation/dev-tools/kunit/run_manual.rst
For more information on writing KUnit tests (including some common techniques
for testing different things), see Documentation/dev-tools/kunit/usage.rst
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
KUnit 시작과 kunit_tool 실행
1-58SPDX 라이선스 식별자: GPL-2.0
시작하기
이 문서는 kunit_tool과 KUnit framework의 개요를 제공합니다. 기존 테스트 실행 방법과 간단한 test case 작성 방법을 차례로 설명하고, 처음 KUnit을 사용하는 사용자가 흔히 겪는 문제도 다룹니다.
Dependency 설치
KUnit의 dependency는 Linux kernel과 같습니다. Kernel을 build할 수 있다면 KUnit도 실행할 수 있습니다.
kunit_tool로 테스트 실행
kunit_tool은 kernel을 configure하고 build한 뒤 테스트를 실행하고 결과를 formatting하는 Python script입니다. Kernel repository에서 다음과 같이 실행합니다.
./tools/testing/kunit/kunit.py run
참고: `The source tree is not clean, please run 'make ARCH=um mrproper'` error가 나타날 수 있습니다.
이 error는 kunit.py가 내부적으로 `--build_dir` argument를 통해 `make O=output/dir` command의 build directory를 기본값인 `.kunit`으로 지정하기 때문에 발생합니다. Out-of-tree build를 시작하기 전에 source tree가 깨끗해야 합니다.
`admin-guide </admin-guide/README>`의 `Build directory for the kernel` 절에도 같은 주의 사항이 있습니다. Build directory를 사용하기 시작했다면 모든 `make` invocation에서 사용해야 합니다.
`make ARCH=um mrproper`로 문제를 해결할 수 있지만, 이 command는 현재 configuration과 생성된 모든 file을 삭제하므로 주의해야 합니다.
정상적으로 동작하면 다음 진행 message가 나타납니다.
Configuring KUnit Kernel ...
Building KUnit Kernel ...
Starting KUnit Kernel ...
그 뒤 각 테스트가 통과하거나 실패합니다.
참고: 첫 실행은 많은 source를 처음 build하므로 `Building KUnit Kernel` 단계가 오래 걸릴 수 있습니다.
Wrapper의 자세한 내용은 `Documentation/dev-tools/kunit/run_wrapper.rst`를 참조하십시오.
기본 run command가 수행하는 주요 단계와 source tree 조건을 나타냅니다.
Kconfig와 이름으로 실행할 테스트 선택
59-147실행할 테스트 선택
기본적으로 kunit_tool은 최소 configuration으로 도달할 수 있는 모든 테스트를 실행합니다. 즉 대부분의 Kconfig option에 default value를 사용합니다.
실행 대상을 바꾸는 방법은 두 가지입니다. Kernel compile에 사용할 Kconfig를 customizing하거나, compile된 테스트 중 실행할 항목을 이름으로 filtering할 수 있습니다.
Kconfig customizing
`.kunitconfig`의 좋은 출발점은 KUnit default config입니다. 아직 `kunit.py run`을 실행하지 않았다면 다음 command로 생성하고 확인합니다.
cd $PATH_TO_LINUX_REPO
tools/testing/kunit/kunit.py config
cat .kunit/.kunitconfig
참고: `.kunitconfig`는 kunit.py가 사용하는 `--build_dir` 안에 있으며 기본 directory는 `.kunit`입니다.
테스트 실행 전 kunit_tool은 `.kunitconfig`에 설정된 모든 option이 kernel `.config`에도 설정되었는지 확인합니다. 사용한 option의 dependency를 포함하지 않았다면 warning을 표시합니다.
Configuration은 다음 여러 방식으로 customizing할 수 있습니다.
a. `.kunit/.kunitconfig`를 직접 편집합니다. 원하는 테스트를 실행하는 데 필요한 Kconfig option과 dependency 목록을 넣어야 합니다. 원하지 않는 추가 테스트를 많이 활성화할 수 있으므로 `CONFIG_KUNIT_ALL_TESTS`를 제거할 수 있습니다. UML 이외 architecture에서 실행하려면 `kunit-on-qemu` reference를 참조하십시오.
b. `.kunit/.kunitconfig` 위에 추가 Kconfig option을 활성화합니다. Kernel linked-list test를 포함하는 예는 다음과 같습니다.
./tools/testing/kunit/kunit.py run \
--kconfig_add CONFIG_LIST_KUNIT_TEST=y
c. Tree 안에 있는 하나 이상의 `.kunitconfig` file path를 제공합니다. `FAT_FS`와 `EXT4` 테스트만 실행하는 예는 다음과 같습니다.
./tools/testing/kunit/kunit.py run \
--kunitconfig ./fs/fat/.kunitconfig \
--kunitconfig ./fs/ext4/.kunitconfig
d. `.kunitconfig`를 변경하면 kunit.py가 `.config` file을 다시 build합니다. 그러나 `.config`를 직접 편집하거나 `make menuconfig O=.kunit` 같은 tool을 사용할 수도 있습니다. `.config`가 `.kunitconfig`의 superset인 한 kunit.py는 변경 내용을 덮어쓰지 않습니다.
참고: 만족스러운 configuration을 찾은 뒤 이를 `.kunitconfig`로 저장하려면 다음 command를 사용합니다.
make savedefconfig O=.kunit
cp .kunit/defconfig .kunit/.kunitconfig
이름으로 테스트 filtering
Kconfig보다 더 구체적으로 선택하려면 glob filter를 전달해 boot time에 실행할 테스트를 지정할 수 있습니다. Pattern 규칙은 `glob(7)` manpage를 참조하십시오.
Filter에 `.` period가 있으면 test suite 이름과 test case 이름의 separator로 해석됩니다. Period가 없으면 전체 filter를 test suite 이름으로 해석합니다. 다음 예는 default config를 사용한다고 가정합니다.
a. `kunit_executor_test` 같은 test suite 이름을 지정하면 그 suite에 포함된 모든 test case를 실행합니다.
./tools/testing/kunit/kunit.py run "kunit_executor_test"
b. `example.example_simple_test`처럼 test suite 이름을 앞에 붙인 test case 이름을 지정하면 해당 case만 실행합니다.
./tools/testing/kunit/kunit.py run "example.example_simple_test"
c. Wildcard character `*?[`를 사용할 수 있습니다. 예를 들어 `*.*64*`는 모든 test suite에서 이름에 `64`가 들어간 test case를 실행합니다.
./tools/testing/kunit/kunit.py run "*.*64*"
Build 대상과 runtime 실행 대상을 정하는 방법을 구분했습니다.
KUnit wrapper 없이 테스트 실행
148-179KUnit wrapper 없이 테스트 실행
KUnit Wrapper를 사용하지 않으려는 경우에도 KUnit을 임의의 kernel에 포함할 수 있으며 결과를 수동으로 읽고 parsing할 수 있습니다. 예를 들어 test 대상 code를 다른 system과 통합하거나, 지원되지 않는 architecture 또는 configuration을 사용할 때 필요합니다.
참고: Production environment에서는 `CONFIG_KUNIT`을 활성화하면 안 됩니다. KUnit을 활성화하면 Kernel Address-Space Layout Randomization, 즉 KASLR이 비활성화되고 테스트가 production에 부적합한 방식으로 kernel state에 영향을 줄 수 있습니다.
Kernel 구성
KUnit 자체를 활성화하려면 `menuconfig`의 Kernel Hacking/Kernel Testing and Coverage 아래에서 `CONFIG_KUNIT` Kconfig option을 활성화합니다. 그 뒤 원하는 KUnit test를 활성화할 수 있습니다. 일반적으로 test option 이름은 `_KUNIT_TEST`로 끝납니다.
KUnit과 KUnit test는 module로 compile할 수 있습니다. Module 안의 테스트는 해당 module을 load할 때 실행됩니다.
KUnit wrapper 없이 테스트 실행
Kernel을 build하고 실행합니다. Kernel log에는 test output이 TAP 형식으로 출력됩니다. 기본적으로 KUnit과 테스트가 built-in일 때만 자동으로 출력되며, module로 build했다면 module을 load해야 합니다.
참고: TAP output 사이에 다른 log line이나 data가 끼어들 수 있습니다.
테스트할 example code 작성
180-216첫 테스트 작성
Kernel repository에 테스트할 간단한 code를 추가합니다.
1. 다음 선언을 포함하는 `drivers/misc/example.h` file을 만듭니다.
int misc_example_add(int left, int right);
2. 다음 구현을 포함하는 `drivers/misc/example.c` file을 만듭니다.
#include <linux/errno.h>
#include "example.h"
int misc_example_add(int left, int right)
{
return left + right;
}
3. `drivers/misc/Kconfig`에 다음 항목을 추가합니다.
config MISC_EXAMPLE
bool "My example"
4. `drivers/misc/Makefile`에 다음 line을 추가합니다.
obj-$(CONFIG_MISC_EXAMPLE) += example.o
이제 두 integer를 더하는 `misc_example_add()`와 이를 build하는 `MISC_EXAMPLE` option이 준비되었으므로 test case를 작성할 수 있습니다.
KUnit test case 구성과 실행
217-2971. `drivers/misc/example_test.c`에 다음 test case를 추가합니다.
#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);
MODULE_LICENSE("GPL");
`misc_example_add_test_basic()`은 `KUNIT_EXPECT_EQ`로 정상 입력, 음수, `INT_MAX`와 `INT_MIN` 경계를 확인합니다. `misc_example_test_failure()`는 `KUNIT_FAIL`을 호출하므로 항상 실패합니다.
두 case를 `misc_example_test_cases` array에 등록하고 `misc-example` 이름의 `kunit_suite`에 연결합니다. `kunit_test_suite()`가 suite를 등록하며 module license는 GPL입니다.
2. `drivers/misc/Kconfig`에 다음 항목을 추가합니다.
config MISC_EXAMPLE_TEST
tristate "Test for my example" if !KUNIT_ALL_TESTS
depends on MISC_EXAMPLE && KUNIT
default KUNIT_ALL_TESTS
참고: 권장되지는 않지만 test가 loadable module build를 지원하지 않는다면 `tristate`를 `bool`로 바꾸고 `KUNIT` 대신 `KUNIT=y`에 dependency를 둡니다.
3. `drivers/misc/Makefile`에 다음 line을 추가합니다.
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example_test.o
4. `.kunit/.kunitconfig`에 다음 line을 추가합니다.
CONFIG_MISC_EXAMPLE=y
CONFIG_MISC_EXAMPLE_TEST=y
5. 테스트를 실행합니다.
./tools/testing/kunit/kunit.py run
기본 addition test는 통과하고 의도적으로 실패하도록 만든 case는 실패하므로 다음 output이 나타나야 합니다.
...
[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.
...
이것으로 첫 KUnit test를 작성했습니다. Failure location과 message가 결과에 함께 표시되므로 실패한 expectation을 바로 찾을 수 있습니다.
Test 대상 code부터 Kconfig, Makefile, suite 등록과 실행까지의 연결 관계입니다.
다음 단계
298-309다음 단계
kunit.py의 고급 기능을 사용하려면 `Documentation/dev-tools/kunit/run_wrapper.rst`를 참조하십시오.
kunit.py 없이 테스트를 실행하려면 `Documentation/dev-tools/kunit/run_manual.rst`를 참조하십시오.
다양한 대상을 테스트하는 일반적인 기법을 포함해 KUnit test 작성 방법을 더 알아보려면 `Documentation/dev-tools/kunit/usage.rst`를 참조하십시오.
요약과 해설
start.rst:1-309KUnit을 처음 사용할 때는 kunit_tool의 기본 run command로 UML kernel을 구성하고 build해 기존 테스트를 실행할 수 있습니다. `.kunitconfig`와 glob filter는 각각 compile 대상과 실제 실행 대상을 제어합니다.
Wrapper를 쓰지 않는 환경에서는 production safety와 module load 조건을 확인해야 합니다. 첫 test 예제는 대상 함수, Kconfig, Makefile, case array, suite registration, `.kunitconfig`가 하나의 실행 가능한 test로 연결되는 전체 과정을 보여 줍니다.