From patchwork Fri Dec 3 04:24:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Harinder Singh X-Patchwork-Id: 521096 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91B0CC433F5 for ; Fri, 3 Dec 2021 04:25:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1378472AbhLCE2s (ORCPT ); Thu, 2 Dec 2021 23:28:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57186 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349062AbhLCE2q (ORCPT ); Thu, 2 Dec 2021 23:28:46 -0500 Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21657C061758 for ; Thu, 2 Dec 2021 20:25:23 -0800 (PST) Received: by mail-qt1-x84a.google.com with SMTP id o12-20020a05622a008c00b002aff5552c89so2130104qtw.23 for ; Thu, 02 Dec 2021 20:25:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=qv4ZcDby6H10jKmKxlfDHAFmkjbWqB+HtzX7AdIIHDk=; b=KQ7GcqMcXXPHS81BYLP5W1MBxDYEu2Uj1cn1r8YR9Xpp6/RKOu3EbqEWuReHC4dGYV gWZdOna9z9blUV4jn8CGeRwrGrGLlkb4g9nrzc2qciFVBTihe7+ePZqsJdFp+LAJcHM9 4jYGqLHjUXII8XwUXJ6Sz+obVBUfyRMrTfkbbU/9G7trkaIawNGvD50gGyPlBF8GpXLI M+UfiyGL5YUsc6b7o3KkhGLDckA+QcHqVaRwnyQ8PCz02APB1wHRQrQvXNa5FbMPhIvE UIWdbkCEIfM5McQcjY+wQjvai0/Zof8qCGElf8fGwpJGbQRnQjS9RukRMzXCS30L3ntd r9oQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=qv4ZcDby6H10jKmKxlfDHAFmkjbWqB+HtzX7AdIIHDk=; b=52X5usyvZNAOUyrdOSx99hHi0N6mg0Nrenwyv68Ich0PL1IvjjEOXVG/MBT2z+igF0 8HBciMeX+4EISeoYocMYGxhfKkUszgxn2v8mBvxJV4rLTAFgS1BUl9Tt09WQSBf/nbPa mEeLSY/yHizk8G/0fhQKR1a1+y1gg6J36xcNA65Kg5ThnLG5h0WGVhY7uUlBcaRDyIEN mnphtTImuxZHCMcuVIVQuDcJZX5/CRNmltZLSWesG9n5bFjGOj4hFADg5Vb4OSXVkvhe NXJ4j+ggRXHjVQtMcNfz1wwfdfwwvlAXoLRXkqJaOC/gYjxqhTLthgc6Hs2+nEDKjTN9 Rsdg== X-Gm-Message-State: AOAM532/W9YsbVOCg/G1qBakNPw1YGV8wTs/iDhSrSrG8D7H2XfUNHwY kbfpyjjVyooI2mUrc2WkmAbCaAZ56rxqHIg= X-Google-Smtp-Source: ABdhPJzKBPju0dWEhgGQnICaKlE18uP57cewz2a7zujgR4vivOkFDJzUcbD5igfUmMG6YUOmWQiKCivHK0/hMDk= X-Received: from sharinder.c.googlers.com ([fda3:e722:ac3:cc00:4f:4b78:c0a8:c73]) (user=sharinder job=sendgmr) by 2002:a05:622a:1cd:: with SMTP id t13mr18554143qtw.31.1638505522325; Thu, 02 Dec 2021 20:25:22 -0800 (PST) Date: Fri, 3 Dec 2021 04:24:33 +0000 In-Reply-To: <20211203042437.740255-1-sharinder@google.com> Message-Id: <20211203042437.740255-4-sharinder@google.com> Mime-Version: 1.0 References: <20211203042437.740255-1-sharinder@google.com> X-Mailer: git-send-email 2.34.0.384.gca35af8252-goog Subject: [PATCH v1 3/7] Documentation: KUnit: Added KUnit Architecture From: Harinder Singh To: davidgow@google.com, brendanhiggins@google.com, shuah@kernel.org, corbet@lwn.net Cc: linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Harinder Singh Precedence: bulk List-ID: X-Mailing-List: linux-kselftest@vger.kernel.org Describe the components of KUnit and how the kernel mode parts interact with kunit_tool. Signed-off-by: Harinder Singh --- .../dev-tools/kunit/architecture.rst | 206 ++++++++++++++++++ Documentation/dev-tools/kunit/index.rst | 2 + .../kunit/kunit_suitememorydiagram.png | Bin 0 -> 24174 bytes Documentation/dev-tools/kunit/start.rst | 1 + 4 files changed, 209 insertions(+) create mode 100644 Documentation/dev-tools/kunit/architecture.rst create mode 100644 Documentation/dev-tools/kunit/kunit_suitememorydiagram.png diff --git a/Documentation/dev-tools/kunit/architecture.rst b/Documentation/dev-tools/kunit/architecture.rst new file mode 100644 index 000000000000..9fced366b300 --- /dev/null +++ b/Documentation/dev-tools/kunit/architecture.rst @@ -0,0 +1,206 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================== +KUnit Architecture +================== + +The KUnit architecture can be divided into two parts: + +- Kernel testing library +- kunit_tool (Command line test harness) + +In-Kernel Testing Framework +=========================== + +The kernel testing library supports KUnit tests written in C using +KUnit. KUnit tests are kernel code. KUnit does several things: + +- Organizes tests +- Reports test results +- Provides test utilities + +Test Cases +---------- + +The fundamental unit in KUnit is the test case. The KUnit test cases are +grouped into KUnit suites. A KUnit test case is a function with type +signature ``void (*)(struct kunit *test)``. +These test case functions are wrapped in a struct called +``struct kunit_case``. For code, see: +https://elixir.bootlin.com/linux/latest/source/include/kunit/test.h#L145 + +It includes: + +- ``run_case``: the function implementing the actual test case. +- ``name``: the test case name. +- ``generate_params``: the parameterized tests generator function. This + is optional for non-parameterised tests. + +Each KUnit test case gets a ``struct kunit`` context +object passed to it that tracks a running test. The KUnit assertion +macros and other KUnit utilities use the ``struct kunit`` context +object. As an exception, there are two fields: + +- ``->priv``: The setup fucntions can use it to store arbitrary test + user data. + +- ``->param_value``: It contains the parameter value which can be + retrieved in the parameterized tests. + +Test Suites +----------- + +A KUnit suite includes a collection of test cases. The KUnit suites +are represented by the ``struct kunit_suite``. For example: + +.. code-block:: c + + static struct kunit_case example_test_cases[] = { + KUNIT_CASE(example_test_foo), + KUNIT_CASE(example_test_bar), + KUNIT_CASE(example_test_baz), + {} + }; + + static struct kunit_suite example_test_suite = { + .name = "example", + .init = example_test_init, + .exit = example_test_exit, + .test_cases = example_test_cases, + }; + kunit_test_suite(example_test_suite); + +In the above example, the test suite ``example_test_suite``, runs the +test cases ``example_test_foo``, ``example_test_bar``, and +``example_test_baz``. Before running the test, the ``example_test_init`` +is called and after running the test, ``example_test_exit`` is called. +The ``kunit_test_suite(example_test_suite)`` registers the test suite +with the KUnit test framework. + +Executor +-------- + +The KUnit executor can list and run built-in KUnit tests on boot. +The Test suites are stored in a linker section +called ``.kunit_test_suites``. For code, see: +https://elixir.bootlin.com/linux/v5.12/source/include/asm-generic/vmlinux.lds.h#L918. +The linker section consists of an array of pointers to +``struct kunit_suite``, and is populated by the ``kunit_test_suites()`` +macro. To run all tests compiled into the kernel, the KUnit executor +iterates over the linker section array. + +.. kernel-figure:: kunit_suitememorydiagram.png + :alt: KUnit Suite Memory + + KUnit Suite Memory Diagram + +On the kernel boot, the KUnit executor uses the start and end addresses +of this section to iterate over and run all tests. For code, see: +https://elixir.bootlin.com/linux/latest/source/lib/kunit/executor.c + +When built as a module, the ``kunit_test_suites()`` macro defines a +``module_init()`` function, which runs all the tests in the compilation +unit instead of utilizing the executor. + +In KUnit tests, some error classes do not affect other tests +or parts of the kernel, each KUnit case executes in a separate thread +context. For code, see: +https://elixir.bootlin.com/linux/latest/source/lib/kunit/try-catch.c#L58 + +Assertion Macros +---------------- + +KUnit tests verify state using expectations/assertions. +All expectations/assertions are formatted as: +``KUNIT_{EXPECT|ASSERT}_[_MSG](kunit, property[, message])`` + +- ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an + expectation. + + - For an expectation, if the check fails, marks the test as failed + and logs the failure. + + - An assertion, on failure, causes the test case to terminate + immediately. + + - Assertions call function: + ``void __noreturn kunit_abort(struct kunit *)``. + + - ``kunit_abort`` calls function: + ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``. + + - ``kunit_try_catch_throw`` calls function: + ``void complete_and_exit(struct completion *, long) __noreturn;`` + and terminates the special thread context. + +- ```` denotes a check with options: ``TRUE`` (supplied property + has the boolean value “true”), ``EQ`` (two supplied properties are + equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not + contain an “err” value). + +- ``[_MSG]`` prints a custom message on failure. + +Test Result Reporting +--------------------- +KUnit prints test results in KTAP format. KTAP is based on TAP14, see: +https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md. +KTAP (yet to be standardized format) works with KUnit and Kselftest. +The KUnit executor prints KTAP results to dmesg, and debugfs +(if configured). + +Parameterized Tests +------------------- + +Each KUnit parameterized test is associated with a collection of +parameters. The test is invoked multiple times, once for each parameter +value and the parameter is stored in the ``param_value`` field. +The test case includes a ``KUNIT_CASE_PARAM()`` macro that accepts a +generator function. +The generator function returns the next parameter given to the +previous parameter in parameterized tests. It also provides a macro to +generate common-case generators based on arrays. + +For code, see: +https://elixir.bootlin.com/linux/v5.12/source/include/kunit/test.h#L1783 + + + + +kunit_tool (Command Line Test Harness) +====================================== + +kunit_tool is a Python script ``(tools/testing/kunit/kunit.py)`` +that can be used to configure, build, exec, parse and run (runs other +commands in order) test results. You can either run KUnit tests using +kunit_tool or can include KUnit in kernel and parse manually. + +- ``configure`` command generates the kernel ``.config`` from a + ``.kunitconfig`` file (and any architecture-specific options). + For some architectures, additional config options are specified in the + ``qemu_config`` Python script + (For example: ``tools/testing/kunit/qemu_configs/powerpc.py``). + It parses both the existing ``.config`` and the ``.kunitconfig`` files + and ensures that ``.config`` is a superset of ``.kunitconfig``. + If this is not the case, it will combine the two and run + ``make olddefconfig`` to regenerate the ``.config`` file. It then + verifies that ``.config`` is now a superset. This checks if all + Kconfig dependencies are correctly specified in ``.kunitconfig``. + ``kunit_config.py`` includes the parsing Kconfigs code. The code which + runs ``make olddefconfig`` is a part of ``kunit_kernel.py``. You can + invoke this command via: ``./tools/testing/kunit/kunit.py config`` and + generate a ``.config`` file. +- ``build`` runs ``make`` on the kernel tree with required options + (depends on the architecture and some options, for example: build_dir) + and reports any errors. + To build a KUnit kernel from the current ``.config``, you can use the + ``build`` argument: ``./tools/testing/kunit/kunit.py build``. +- ``exec`` command executes kernel results either directly (using + User-mode Linux configuration), or via an emulator such + as QEMU. It reads results from the log via standard + output (stdout), and passes them to ``parse`` to be parsed. + If you already have built a kernel with built-in KUnit tests, + you can run the kernel and display the test results with the ``exec`` + argument: ``./tools/testing/kunit/kunit.py exec``. +- ``parse`` extracts the KTAP output from a kernel log, parses + the test results, and prints a summary. For failed tests, any + diagnostic output will be included. diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst index 2ddd01d62406..6712f732307f 100644 --- a/Documentation/dev-tools/kunit/index.rst +++ b/Documentation/dev-tools/kunit/index.rst @@ -9,6 +9,7 @@ KUnit - Linux Kernel Unit Testing :caption: Contents: start + architecture usage kunit-tool api/index @@ -89,6 +90,7 @@ How do I use it? ================ * Documentation/dev-tools/kunit/start.rst - for KUnit new users. +* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. * Documentation/dev-tools/kunit/usage.rst - KUnit features. * Documentation/dev-tools/kunit/tips.rst - best practices with examples. diff --git a/Documentation/dev-tools/kunit/kunit_suitememorydiagram.png b/Documentation/dev-tools/kunit/kunit_suitememorydiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..a1aa7c3b0f63edfea83eb1cef3e2257b47b5ca7b GIT binary patch literal 24174 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