From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.6 required=3.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 384E8C49ED7 for ; Fri, 20 Sep 2019 23:52:18 +0000 (UTC) Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 064632073F for ; Fri, 20 Sep 2019 23:52:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="RSowU+Bc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 064632073F Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvdimm-bounces@lists.01.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id BF200202ECFD8; Fri, 20 Sep 2019 16:51:12 -0700 (PDT) Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::d4a; helo=mail-io1-xd4a.google.com; envelope-from=3tf6fxq4kdhkyobkaxkefddfkpdlldib.zljifkru-ksafjjifpqp.xy.lod@flex--brendanhiggins.bounces.google.com; receiver=linux-nvdimm@lists.01.org Received: from mail-io1-xd4a.google.com (mail-io1-xd4a.google.com [IPv6:2607:f8b0:4864:20::d4a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5A31B202ECFBD for ; Fri, 20 Sep 2019 16:51:11 -0700 (PDT) Received: by mail-io1-xd4a.google.com with SMTP id a13so12930150ioh.18 for ; Fri, 20 Sep 2019 16:52:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=YkxNaR1uwV/SnBbh2Y1RJPogz/KLgiHTDO7RE/pY9h4=; b=RSowU+BcIgAo8n0SX1VEPwAygI3W6kn50Uvi8cHhHK77+6DDeJpMPmhrPmmof2cQ91 KqEyO4UjIYETm7Hd6FifCn3jumgIALpx35K3uL7P1om6WsN9xTiBGhqM0GDnuXLxQeQm hxbVwrMRvuC39gL/Gkl+2Myz1lKbeCJXpyfz5Fpa7CKyLrzivFQZCVgj9JHiLqjsO8u4 ec8VBN0tkJ3fcYUQ8wZdI8Icj6UWHiU/PrmBVDUk1DOwq4uiOZaUDGunNoNNUKW56c3e HcVQkF9a6REMyu6SSCC7Ja44BuUu7e76uMhzsF81CMVBnTk4RoxZOWtqo7fgAPUF7FIP ONsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=YkxNaR1uwV/SnBbh2Y1RJPogz/KLgiHTDO7RE/pY9h4=; b=DUwxkp5wr2sn3F8qvR6Jd/zIGv0ey8nMfN+zcN9qv635uV8PGRkJiJ3ZQObAhoFjTA S6pbXujACBI4F3eZNNQY1ax8b8Xdwj0fPdmjxP8JrqZlBqN+fJpQX7/S/p3IlW+N0qfa bEZwuK2ccUwVjvo9+y22ArrdrKfbBJ3uXmOaMVEZ6gv/9RbRlj9D1BG7yOsiOWUXwhSI YzJv9xtXsFkcTQ4zmAzSJrJTNayKejUD03rX9ylxUdC8btkHBQvWa6SK8WSd3XopPqrG c9YqJCEIu7Tp91yTeKu0wekZb47cOhHxnxQ3HxRWEqDZDXp/QuqhYOPOdECn8sqHF+ES wDDg== X-Gm-Message-State: APjAAAVn2XXvbuewiaDpSHpv7V8NemhbsyA1sOZAnviAIeyBj8Uob4Q4 ZwrNFpebOqljh/Y/8WszLMHLQpYOlVAt9bzSe+/XiQ== X-Google-Smtp-Source: APXvYqz2FUMCJCuclAnAK2M/LfnnFAyySjIqLjhYfiwxmmUx0dkwHhJJLyNqBG1+1uetgLVnJ9U9WdevBfMeIWMNl2RqgA== X-Received: by 2002:a63:4d4b:: with SMTP id n11mr4040912pgl.409.1569021620451; Fri, 20 Sep 2019 16:20:20 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:19 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-16-brendanhiggins@google.com> Mime-Version: 1.0 References: <20190920231923.141900-1-brendanhiggins@google.com> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog Subject: [PATCH v16 15/19] Documentation: kunit: add documentation for KUnit From: Brendan Higgins To: frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, sboyd@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pmladek@suse.com, linux-doc@vger.kernel.org, amir73il@gmail.com, Brendan Higgins , dri-devel@lists.freedesktop.org, Alexander.Levin@microsoft.com, linux-kselftest@vger.kernel.org, Jonathan Corbet , linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, Felix Guo , wfg@linux.intel.com, joel@jms.id.au, rientjes@google.com, jdike@addtoit.com, dan.carpenter@oracle.com, devicetree@vger.kernel.org, linux-kbuild@vger.kernel.org, Tim.Bird@sony.com, linux-um@lists.infradead.org, rostedt@goodmis.org, julia.lawall@lip6.fr, kunit-dev@googlegroups.com, richard@nod.at, torvalds@linux-foundation.org, rdunlap@infradead.org, linux-kernel@vger.kernel.org, daniel@ffwll.ch, mpe@ellerman.id.au, linux-fsdevel@vger.kernel.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" Add documentation for KUnit, the Linux kernel unit testing framework. - Add intro and usage guide for KUnit - Add API reference Signed-off-by: Felix Guo Signed-off-by: Brendan Higgins Cc: Jonathan Corbet Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Stephen Boyd --- Documentation/dev-tools/index.rst | 1 + Documentation/dev-tools/kunit/api/index.rst | 16 + Documentation/dev-tools/kunit/api/test.rst | 11 + Documentation/dev-tools/kunit/faq.rst | 62 +++ Documentation/dev-tools/kunit/index.rst | 79 +++ Documentation/dev-tools/kunit/start.rst | 180 ++++++ Documentation/dev-tools/kunit/usage.rst | 576 ++++++++++++++++++++ 7 files changed, 925 insertions(+) create mode 100644 Documentation/dev-tools/kunit/api/index.rst create mode 100644 Documentation/dev-tools/kunit/api/test.rst create mode 100644 Documentation/dev-tools/kunit/faq.rst create mode 100644 Documentation/dev-tools/kunit/index.rst create mode 100644 Documentation/dev-tools/kunit/start.rst create mode 100644 Documentation/dev-tools/kunit/usage.rst diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst index b0522a4dd107..09dee10d2592 100644 --- a/Documentation/dev-tools/index.rst +++ b/Documentation/dev-tools/index.rst @@ -24,6 +24,7 @@ whole; patches welcome! gdb-kernel-debugging kgdb kselftest + kunit/index .. only:: subproject and html diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst new file mode 100644 index 000000000000..9b9bffe5d41a --- /dev/null +++ b/Documentation/dev-tools/kunit/api/index.rst @@ -0,0 +1,16 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +API Reference +============= +.. toctree:: + + test + +This section documents the KUnit kernel testing API. It is divided into the +following sections: + +================================= ============================================== +:doc:`test` documents all of the standard testing API + excluding mocking or mocking related features. +================================= ============================================== diff --git a/Documentation/dev-tools/kunit/api/test.rst b/Documentation/dev-tools/kunit/api/test.rst new file mode 100644 index 000000000000..aaa97f17e5b3 --- /dev/null +++ b/Documentation/dev-tools/kunit/api/test.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +Test API +======== + +This file documents all of the standard testing API excluding mocking or mocking +related features. + +.. kernel-doc:: include/kunit/test.h + :internal: diff --git a/Documentation/dev-tools/kunit/faq.rst b/Documentation/dev-tools/kunit/faq.rst new file mode 100644 index 000000000000..bf2095112d89 --- /dev/null +++ b/Documentation/dev-tools/kunit/faq.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Frequently Asked Questions +========================== + +How is this different from Autotest, kselftest, etc? +==================================================== +KUnit is a unit testing framework. Autotest, kselftest (and some others) are +not. + +A `unit test `_ is supposed to +test a single unit of code in isolation, hence the name. A unit test should be +the finest granularity of testing and as such should allow all possible code +paths to be tested in the code under test; this is only possible if the code +under test is very small and does not have any external dependencies outside of +the test's control like hardware. + +There are no testing frameworks currently available for the kernel that do not +require installing the kernel on a test machine or in a VM and all require +tests to be written in userspace and run on the kernel under test; this is true +for Autotest, kselftest, and some others, disqualifying any of them from being +considered unit testing frameworks. + +Does KUnit support running on architectures other than UML? +=========================================================== + +Yes, well, mostly. + +For the most part, the KUnit core framework (what you use to write the tests) +can compile to any architecture; it compiles like just another part of the +kernel and runs when the kernel boots. However, there is some infrastructure, +like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support +other architectures. + +In short, this means that, yes, you can run KUnit on other architectures, but +it might require more work than using KUnit on UML. + +For more information, see :ref:`kunit-on-non-uml`. + +What is the difference between a unit test and these other kinds of tests? +========================================================================== +Most existing tests for the Linux kernel would be categorized as an integration +test, or an end-to-end test. + +- A unit test is supposed to test a single unit of code in isolation, hence the + name. A unit test should be the finest granularity of testing and as such + should allow all possible code paths to be tested in the code under test; this + is only possible if the code under test is very small and does not have any + external dependencies outside of the test's control like hardware. +- An integration test tests the interaction between a minimal set of components, + usually just two or three. For example, someone might write an integration + test to test the interaction between a driver and a piece of hardware, or to + test the interaction between the userspace libraries the kernel provides and + the kernel itself; however, one of these tests would probably not test the + entire kernel along with hardware interactions and interactions with the + userspace. +- An end-to-end test usually tests the entire system from the perspective of the + code under test. For example, someone might write an end-to-end test for the + kernel by installing a production configuration of the kernel on production + hardware with a production userspace and then trying to exercise some behavior + that depends on interactions between the hardware, the kernel, and userspace. diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst new file mode 100644 index 000000000000..26ffb46bdf99 --- /dev/null +++ b/Documentation/dev-tools/kunit/index.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +KUnit - Unit Testing for the Linux Kernel +========================================= + +.. toctree:: + :maxdepth: 2 + + start + usage + api/index + faq + +What is KUnit? +============== + +KUnit is a lightweight unit testing and mocking framework for the Linux kernel. +These tests are able to be run locally on a developer's workstation without a VM +or special hardware. + +KUnit is heavily inspired by JUnit, Python's unittest.mock, and +Googletest/Googlemock for C++. KUnit provides facilities for defining unit test +cases, grouping related test cases into test suites, providing common +infrastructure for running tests, and much more. + +Get started now: :doc:`start` + +Why KUnit? +========== + +A unit test is supposed to test a single unit of code in isolation, hence the +name. A unit test should be the finest granularity of testing and as such should +allow all possible code paths to be tested in the code under test; this is only +possible if the code under test is very small and does not have any external +dependencies outside of the test's control like hardware. + +Outside of KUnit, there are no testing frameworks currently +available for the kernel that do not require installing the kernel on a test +machine or in a VM and all require tests to be written in userspace running on +the kernel; this is true for Autotest, and kselftest, disqualifying +any of them from being considered unit testing frameworks. + +KUnit addresses the problem of being able to run tests without needing a virtual +machine or actual hardware with User Mode Linux. User Mode Linux is a Linux +architecture, like ARM or x86; however, unlike other architectures it compiles +to a standalone program that can be run like any other program directly inside +of a host operating system; to be clear, it does not require any virtualization +support; it is just a regular program. + +KUnit is fast. Excluding build time, from invocation to completion KUnit can run +several dozen tests in only 10 to 20 seconds; this might not sound like a big +deal to some people, but having such fast and easy to run tests fundamentally +changes the way you go about testing and even writing code in the first place. +Linus himself said in his `git talk at Google +`_: + + "... a lot of people seem to think that performance is about doing the + same thing, just doing it faster, and that is not true. That is not what + performance is all about. If you can do something really fast, really + well, people will start using it differently." + +In this context Linus was talking about branching and merging, +but this point also applies to testing. If your tests are slow, unreliable, are +difficult to write, and require a special setup or special hardware to run, +then you wait a lot longer to write tests, and you wait a lot longer to run +tests; this means that tests are likely to break, unlikely to test a lot of +things, and are unlikely to be rerun once they pass. If your tests are really +fast, you run them all the time, every time you make a change, and every time +someone sends you some code. Why trust that someone ran all their tests +correctly on every change when you can just run them yourself in less time than +it takes to read their test log? + +How do I use it? +================ + +* :doc:`start` - for new users of KUnit +* :doc:`usage` - for a more detailed explanation of KUnit features +* :doc:`api/index` - for the list of KUnit APIs used for testing diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst new file mode 100644 index 000000000000..6dc229e46bb3 --- /dev/null +++ b/Documentation/dev-tools/kunit/start.rst @@ -0,0 +1,180 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Getting Started +=============== + +Installing dependencies +======================= +KUnit has the same dependencies as the Linux kernel. As long as you can build +the kernel, you can run KUnit. + +KUnit Wrapper +============= +Included with KUnit is a simple Python wrapper that helps format the output to +easily use and read KUnit output. It handles building and running the kernel, as +well as formatting the output. + +The wrapper can be run with: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py run + +Creating a kunitconfig +====================== +The Python script is a thin wrapper around Kbuild as such, it needs to be +configured with a ``kunitconfig`` file. This file essentially contains the +regular Kernel config, with the specific test targets as well. + +.. code-block:: bash + + git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO + cd $PATH_TO_LINUX_REPO + ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig + +You may want to add kunitconfig to your local gitignore. + +Verifying KUnit Works +--------------------- + +To make sure that everything is set up correctly, simply invoke the Python +wrapper from your kernel repo: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +.. note:: + You may want to run ``make mrproper`` first. + +If everything worked correctly, you should see the following: + +.. code-block:: bash + + Generating .config ... + Building KUnit Kernel ... + Starting KUnit Kernel ... + +followed by a list of tests that are run. All of them should be passing. + +.. note:: + Because it is building a lot of sources for the first time, the ``Building + kunit kernel`` step may take a while. + +Writing your first test +======================= + +In your kernel repo let's add some code that we can test. Create a file +``drivers/misc/example.h`` with the contents: + +.. code-block:: c + + int misc_example_add(int left, int right); + +create a file ``drivers/misc/example.c``: + +.. code-block:: c + + #include + + #include "example.h" + + int misc_example_add(int left, int right) + { + return left + right; + } + +Now add the following lines to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE + bool "My example" + +and the following lines to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE) += example.o + +Now we are ready to write the test. The test will be in +``drivers/misc/example-test.c``: + +.. code-block:: c + + #include + #include "example.h" + + /* Define the test cases. */ + + static void misc_example_add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1)); + KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1)); + KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN)); + } + + static void misc_example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + + static struct kunit_case misc_example_test_cases[] = { + KUNIT_CASE(misc_example_add_test_basic), + KUNIT_CASE(misc_example_test_failure), + {} + }; + + static struct kunit_suite misc_example_test_suite = { + .name = "misc-example", + .test_cases = misc_example_test_cases, + }; + kunit_test_suite(misc_example_test_suite); + +Now add the following to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE_TEST + bool "Test for my example" + depends on MISC_EXAMPLE && KUNIT + +and the following to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o + +Now add it to your ``kunitconfig``: + +.. code-block:: none + + CONFIG_MISC_EXAMPLE=y + CONFIG_MISC_EXAMPLE_TEST=y + +Now you can run the test: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +You should see the following failure: + +.. code-block:: none + + ... + [16:08:57] [PASSED] misc-example:misc_example_add_test_basic + [16:08:57] [FAILED] misc-example:misc_example_test_failure + [16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17 + [16:08:57] This test never passes. + ... + +Congrats! You just wrote your first KUnit test! + +Next Steps +========== +* Check out the :doc:`usage` page for a more + in-depth explanation of KUnit. diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst new file mode 100644 index 000000000000..c6e69634e274 --- /dev/null +++ b/Documentation/dev-tools/kunit/usage.rst @@ -0,0 +1,576 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========== +Using KUnit +=========== + +The purpose of this document is to describe what KUnit is, how it works, how it +is intended to be used, and all the concepts and terminology that are needed to +understand it. This guide assumes a working knowledge of the Linux kernel and +some basic knowledge of testing. + +For a high level introduction to KUnit, including setting up KUnit for your +project, see :doc:`start`. + +Organization of this document +============================= + +This document is organized into two main sections: Testing and Isolating +Behavior. The first covers what a unit test is and how to use KUnit to write +them. The second covers how to use KUnit to isolate code and make it possible +to unit test code that was otherwise un-unit-testable. + +Testing +======= + +What is KUnit? +-------------- + +"K" is short for "kernel" so "KUnit" is the "(Linux) Kernel Unit Testing +Framework." KUnit is intended first and foremost for writing unit tests; it is +general enough that it can be used to write integration tests; however, this is +a secondary goal. KUnit has no ambition of being the only testing framework for +the kernel; for example, it does not intend to be an end-to-end testing +framework. + +What is Unit Testing? +--------------------- + +A `unit test `_ is a test that +tests code at the smallest possible scope, a *unit* of code. In the C +programming language that's a function. + +Unit tests should be written for all the publicly exposed functions in a +compilation unit; so that is all the functions that are exported in either a +*class* (defined below) or all functions which are **not** static. + +Writing Tests +------------- + +Test Cases +~~~~~~~~~~ + +The fundamental unit in KUnit is the test case. A test case is a function with +the signature ``void (*)(struct kunit *test)``. It calls a function to be tested +and then sets *expectations* for what should happen. For example: + +.. code-block:: c + + void example_test_success(struct kunit *test) + { + } + + void example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + +In the above example ``example_test_success`` always passes because it does +nothing; no expectations are set, so all expectations pass. On the other hand +``example_test_failure`` always fails because it calls ``KUNIT_FAIL``, which is +a special expectation that logs a message and causes the test case to fail. + +Expectations +~~~~~~~~~~~~ +An *expectation* is a way to specify that you expect a piece of code to do +something in a test. An expectation is called like a function. A test is made +by setting expectations about the behavior of a piece of code under test; when +one or more of the expectations fail, the test case fails and information about +the failure is logged. For example: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + +In the above example ``add_test_basic`` makes a number of assertions about the +behavior of a function called ``add``; the first parameter is always of type +``struct kunit *``, which contains information about the current test context; +the second parameter, in this case, is what the value is expected to be; the +last value is what the value actually is. If ``add`` passes all of these +expectations, the test case, ``add_test_basic`` will pass; if any one of these +expectations fail, the test case will fail. + +It is important to understand that a test case *fails* when any expectation is +violated; however, the test will continue running, potentially trying other +expectations until the test case ends or is otherwise terminated. This is as +opposed to *assertions* which are discussed later. + +To learn about more expectations supported by KUnit, see :doc:`api/test`. + +.. note:: + A single test case should be pretty short, pretty easy to understand, + focused on a single behavior. + +For example, if we wanted to properly test the add function above, we would +create additional tests cases which would each test a different property that an +add function should have like this: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + + void add_test_negative(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + } + + void add_test_max(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + } + + void add_test_overflow(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MIN, add(INT_MAX, 1)); + } + +Notice how it is immediately obvious what all the properties that we are testing +for are. + +Assertions +~~~~~~~~~~ + +KUnit also has the concept of an *assertion*. An assertion is just like an +expectation except the assertion immediately terminates the test case if it is +not satisfied. + +For example: + +.. code-block:: c + + static void mock_test_do_expect_default_return(struct kunit *test) + { + struct mock_test_context *ctx = test->priv; + struct mock *mock = ctx->mock; + int param0 = 5, param1 = -5; + const char *two_param_types[] = {"int", "int"}; + const void *two_params[] = {¶m0, ¶m1}; + const void *ret; + + ret = mock->do_expect(mock, + "test_printk", test_printk, + two_param_types, two_params, + ARRAY_SIZE(two_params)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_EQ(test, -4, *((int *) ret)); + } + +In this example, the method under test should return a pointer to a value, so +if the pointer returned by the method is null or an errno, we don't want to +bother continuing the test since the following expectation could crash the test +case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us to bail out of the test case if +the appropriate conditions have not been satisfied to complete the test. + +Test Suites +~~~~~~~~~~~ + +Now obviously one unit test isn't very helpful; the power comes from having +many test cases covering all of your behaviors. Consequently it is common to +have many *similar* tests; in order to reduce duplication in these closely +related tests most unit testing frameworks provide the concept of a *test +suite*, in KUnit we call it a *test suite*; all it is is just a collection of +test cases for a unit of code with a set up function that gets invoked before +every test cases and then a tear down function that gets invoked after every +test case completes. + +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``, would run the test +cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``, +each would have ``example_test_init`` called immediately before it and would +have ``example_test_exit`` called immediately after it. +``kunit_test_suite(example_test_suite)`` registers the test suite with the +KUnit test framework. + +.. note:: + A test case will only be run if it is associated with a test suite. + +For a more information on these types of things see the :doc:`api/test`. + +Isolating Behavior +================== + +The most important aspect of unit testing that other forms of testing do not +provide is the ability to limit the amount of code under test to a single unit. +In practice, this is only possible by being able to control what code gets run +when the unit under test calls a function and this is usually accomplished +through some sort of indirection where a function is exposed as part of an API +such that the definition of that function can be changed without affecting the +rest of the code base. In the kernel this primarily comes from two constructs, +classes, structs that contain function pointers that are provided by the +implementer, and architecture specific functions which have definitions selected +at compile time. + +Classes +------- + +Classes are not a construct that is built into the C programming language; +however, it is an easily derived concept. Accordingly, pretty much every project +that does not use a standardized object oriented library (like GNOME's GObject) +has their own slightly different way of doing object oriented programming; the +Linux kernel is no exception. + +The central concept in kernel object oriented programming is the class. In the +kernel, a *class* is a struct that contains function pointers. This creates a +contract between *implementers* and *users* since it forces them to use the +same function signature without having to call the function directly. In order +for it to truly be a class, the function pointers must specify that a pointer +to the class, known as a *class handle*, be one of the parameters; this makes +it possible for the member functions (also known as *methods*) to have access +to member variables (more commonly known as *fields*) allowing the same +implementation to have multiple *instances*. + +Typically a class can be *overridden* by *child classes* by embedding the +*parent class* in the child class. Then when a method provided by the child +class is called, the child implementation knows that the pointer passed to it is +of a parent contained within the child; because of this, the child can compute +the pointer to itself because the pointer to the parent is always a fixed offset +from the pointer to the child; this offset is the offset of the parent contained +in the child struct. For example: + +.. code-block:: c + + struct shape { + int (*area)(struct shape *this); + }; + + struct rectangle { + struct shape parent; + int length; + int width; + }; + + int rectangle_area(struct shape *this) + { + struct rectangle *self = container_of(this, struct shape, parent); + + return self->length * self->width; + }; + + void rectangle_new(struct rectangle *self, int length, int width) + { + self->parent.area = rectangle_area; + self->length = length; + self->width = width; + } + +In this example (as in most kernel code) the operation of computing the pointer +to the child from the pointer to the parent is done by ``container_of``. + +Faking Classes +~~~~~~~~~~~~~~ + +In order to unit test a piece of code that calls a method in a class, the +behavior of the method must be controllable, otherwise the test ceases to be a +unit test and becomes an integration test. + +A fake just provides an implementation of a piece of code that is different than +what runs in a production instance, but behaves identically from the standpoint +of the callers; this is usually done to replace a dependency that is hard to +deal with, or is slow. + +A good example for this might be implementing a fake EEPROM that just stores the +"contents" in an internal buffer. For example, let's assume we have a class that +represents an EEPROM: + +.. code-block:: c + + struct eeprom { + ssize_t (*read)(struct eeprom *this, size_t offset, char *buffer, size_t count); + ssize_t (*write)(struct eeprom *this, size_t offset, const char *buffer, size_t count); + }; + +And we want to test some code that buffers writes to the EEPROM: + +.. code-block:: c + + struct eeprom_buffer { + ssize_t (*write)(struct eeprom_buffer *this, const char *buffer, size_t count); + int flush(struct eeprom_buffer *this); + size_t flush_count; /* Flushes when buffer exceeds flush_count. */ + }; + + struct eeprom_buffer *new_eeprom_buffer(struct eeprom *eeprom); + void destroy_eeprom_buffer(struct eeprom *eeprom); + +We can easily test this code by *faking out* the underlying EEPROM: + +.. code-block:: c + + struct fake_eeprom { + struct eeprom parent; + char contents[FAKE_EEPROM_CONTENTS_SIZE]; + }; + + ssize_t fake_eeprom_read(struct eeprom *parent, size_t offset, char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(buffer, this->contents + offset, count); + + return count; + } + + ssize_t fake_eeprom_write(struct eeprom *this, size_t offset, const char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(this->contents + offset, buffer, count); + + return count; + } + + void fake_eeprom_init(struct fake_eeprom *this) + { + this->parent.read = fake_eeprom_read; + this->parent.write = fake_eeprom_write; + memset(this->contents, 0, FAKE_EEPROM_CONTENTS_SIZE); + } + +We can now use it to test ``struct eeprom_buffer``: + +.. code-block:: c + + struct eeprom_buffer_test { + struct fake_eeprom *fake_eeprom; + struct eeprom_buffer *eeprom_buffer; + }; + + static void eeprom_buffer_test_does_not_write_until_flush(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = SIZE_MAX; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0); + + eeprom_buffer->flush(eeprom_buffer); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_after_flush_count_met(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_increments_of_flush_count(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff, 0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 2); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + /* Should have only flushed the first two bytes. */ + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[2], 0); + } + + static int eeprom_buffer_test_init(struct kunit *test) + { + struct eeprom_buffer_test *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->fake_eeprom = kunit_kzalloc(test, sizeof(*ctx->fake_eeprom), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->fake_eeprom); + fake_eeprom_init(ctx->fake_eeprom); + + ctx->eeprom_buffer = new_eeprom_buffer(&ctx->fake_eeprom->parent); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->eeprom_buffer); + + test->priv = ctx; + + return 0; + } + + static void eeprom_buffer_test_exit(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + + destroy_eeprom_buffer(ctx->eeprom_buffer); + } + +.. _kunit-on-non-uml: + +KUnit on non-UML architectures +============================== + +By default KUnit uses UML as a way to provide dependencies for code under test. +Under most circumstances KUnit's usage of UML should be treated as an +implementation detail of how KUnit works under the hood. Nevertheless, there +are instances where being able to run architecture specific code, or test +against real hardware is desirable. For these reasons KUnit supports running on +other architectures. + +Running existing KUnit tests on non-UML architectures +----------------------------------------------------- + +There are some special considerations when running existing KUnit tests on +non-UML architectures: + +* Hardware may not be deterministic, so a test that always passes or fails + when run under UML may not always do so on real hardware. +* Hardware and VM environments may not be hermetic. KUnit tries its best to + provide a hermetic environment to run tests; however, it cannot manage state + that it doesn't know about outside of the kernel. Consequently, tests that + may be hermetic on UML may not be hermetic on other architectures. +* Some features and tooling may not be supported outside of UML. +* Hardware and VMs are slower than UML. + +None of these are reasons not to run your KUnit tests on real hardware; they are +only things to be aware of when doing so. + +The biggest impediment will likely be that certain KUnit features and +infrastructure may not support your target environment. For example, at this +time the KUnit Wrapper (``tools/testing/kunit/kunit.py``) does not work outside +of UML. Unfortunately, there is no way around this. Using UML (or even just a +particular architecture) allows us to make a lot of assumptions that make it +possible to do things which might otherwise be impossible. + +Nevertheless, all core KUnit framework features are fully supported on all +architectures, and using them is straightforward: all you need to do is to take +your kunitconfig, your Kconfig options for the tests you would like to run, and +merge them into whatever config your are using for your platform. That's it! + +For example, let's say you have the following kunitconfig: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + +If you wanted to run this test on an x86 VM, you might add the following config +options to your ``.config``: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y + +All these new options do is enable support for a common serial console needed +for logging. + +Next, you could build a kernel with these tests as follows: + + +.. code-block:: bash + + make ARCH=x86 olddefconfig + make ARCH=x86 + +Once you have built a kernel, you could run it on QEMU as follows: + +.. code-block:: bash + + qemu-system-x86_64 -enable-kvm \ + -m 1024 \ + -kernel arch/x86_64/boot/bzImage \ + -append 'console=ttyS0' \ + --nographic + +Interspersed in the kernel logs you might see the following: + +.. code-block:: none + + TAP version 14 + # Subtest: example + 1..1 + # example_simple_test: initializing + ok 1 - example_simple_test + ok 1 - example + +Congratulations, you just ran a KUnit test on the x86 architecture! + +Writing new tests for other architectures +----------------------------------------- + +The first thing you must do is ask yourself whether it is necessary to write a +KUnit test for a specific architecture, and then whether it is necessary to +write that test for a particular piece of hardware. In general, writing a test +that depends on having access to a particular piece of hardware or software (not +included in the Linux source repo) should be avoided at all costs. + +Even if you only ever plan on running your KUnit test on your hardware +configuration, other people may want to run your tests and may not have access +to your hardware. If you write your test to run on UML, then anyone can run your +tests without knowing anything about your particular setup, and you can still +run your tests on your hardware setup just by compiling for your architecture. + +.. important:: + Always prefer tests that run on UML to tests that only run under a particular + architecture, and always prefer tests that run under QEMU or another easy + (and monitarily free) to obtain software environment to a specific piece of + hardware. + +Nevertheless, there are still valid reasons to write an architecture or hardware +specific test: for example, you might want to test some code that really belongs +in ``arch/some-arch/*``. Even so, try your best to write the test so that it +does not depend on physical hardware: if some of your test cases don't need the +hardware, only require the hardware for tests that actually need it. + +Now that you have narrowed down exactly what bits are hardware specific, the +actual procedure for writing and running the tests is pretty much the same as +writing normal KUnit tests. One special caveat is that you have to reset +hardware state in between test cases; if this is not possible, you may only be +able to run one test case per invocation. + +.. TODO(brendanhiggins@google.com): Add an actual example of an architecture + dependent KUnit test. -- 2.23.0.351.gc4317032e6-goog _______________________________________________ Linux-nvdimm mailing list Linux-nvdimm@lists.01.org https://lists.01.org/mailman/listinfo/linux-nvdimm From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-22.4 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47C01C3A5A2 for ; Fri, 20 Sep 2019 23:20:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DC28A21928 for ; Fri, 20 Sep 2019 23:20:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="RSowU+Bc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437211AbfITXUy (ORCPT ); Fri, 20 Sep 2019 19:20:54 -0400 Received: from mail-pf1-f201.google.com ([209.85.210.201]:40991 "EHLO mail-pf1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2437099AbfITXUW (ORCPT ); Fri, 20 Sep 2019 19:20:22 -0400 Received: by mail-pf1-f201.google.com with SMTP id g15so5764876pfb.8 for ; Fri, 20 Sep 2019 16:20:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=YkxNaR1uwV/SnBbh2Y1RJPogz/KLgiHTDO7RE/pY9h4=; b=RSowU+BcIgAo8n0SX1VEPwAygI3W6kn50Uvi8cHhHK77+6DDeJpMPmhrPmmof2cQ91 KqEyO4UjIYETm7Hd6FifCn3jumgIALpx35K3uL7P1om6WsN9xTiBGhqM0GDnuXLxQeQm hxbVwrMRvuC39gL/Gkl+2Myz1lKbeCJXpyfz5Fpa7CKyLrzivFQZCVgj9JHiLqjsO8u4 ec8VBN0tkJ3fcYUQ8wZdI8Icj6UWHiU/PrmBVDUk1DOwq4uiOZaUDGunNoNNUKW56c3e HcVQkF9a6REMyu6SSCC7Ja44BuUu7e76uMhzsF81CMVBnTk4RoxZOWtqo7fgAPUF7FIP ONsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=YkxNaR1uwV/SnBbh2Y1RJPogz/KLgiHTDO7RE/pY9h4=; b=JcXmjESv0aj9muc8O3KXdchKKjTpawtIdBBdzeQg1ie/e5ENnzzAMMtDAis9AQuUrW T41paRjKKdNed6pJbekzwBHF7tgZMCp+/IXLGc90JIsmHFlJVxweyBuIGpVIIDNA6av9 FM8dBO2tpf96jNQbqifdv95ST1FhBIyApyUwroxr/mB5g6n+0bPC2UXfM7mZPuF4xwcD lhrFVhRBNJg0IBDJuxRGkHArc6H2dWSoVelUJu+YhKOp/XzedcovNqZjzOPIzWPM1qnL I8zcEhIt3Z6E0aNoqiz4aRAUUvvlrqo/Gk+S9yukKLUKpkQZPO4BRoBY7diQWNEqVoga oS1Q== X-Gm-Message-State: APjAAAW9uKbH2ccIsE9S7ISExBd3uWS/o2g0FqHhnv47OQKpA4c86kMm 4nP96Tu4j9vq/i4qyU8BbK4Lo0eSh63sU+aCDQRRjw== X-Google-Smtp-Source: APXvYqz2FUMCJCuclAnAK2M/LfnnFAyySjIqLjhYfiwxmmUx0dkwHhJJLyNqBG1+1uetgLVnJ9U9WdevBfMeIWMNl2RqgA== X-Received: by 2002:a63:4d4b:: with SMTP id n11mr4040912pgl.409.1569021620451; Fri, 20 Sep 2019 16:20:20 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:19 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-16-brendanhiggins@google.com> Mime-Version: 1.0 References: <20190920231923.141900-1-brendanhiggins@google.com> X-Mailer: git-send-email 2.23.0.351.gc4317032e6-goog Subject: [PATCH v16 15/19] Documentation: kunit: add documentation for KUnit From: Brendan Higgins To: frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, sboyd@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: devicetree@vger.kernel.org, dri-devel@lists.freedesktop.org, kunit-dev@googlegroups.com, linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-nvdimm@lists.01.org, linux-um@lists.infradead.org, Alexander.Levin@microsoft.com, Tim.Bird@sony.com, amir73il@gmail.com, dan.carpenter@oracle.com, daniel@ffwll.ch, jdike@addtoit.com, joel@jms.id.au, julia.lawall@lip6.fr, khilman@baylibre.com, knut.omang@oracle.com, logang@deltatee.com, mpe@ellerman.id.au, pmladek@suse.com, rdunlap@infradead.org, richard@nod.at, rientjes@google.com, rostedt@goodmis.org, wfg@linux.intel.com, torvalds@linux-foundation.org, Brendan Higgins , Felix Guo , Jonathan Corbet Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add documentation for KUnit, the Linux kernel unit testing framework. - Add intro and usage guide for KUnit - Add API reference Signed-off-by: Felix Guo Signed-off-by: Brendan Higgins Cc: Jonathan Corbet Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Stephen Boyd --- Documentation/dev-tools/index.rst | 1 + Documentation/dev-tools/kunit/api/index.rst | 16 + Documentation/dev-tools/kunit/api/test.rst | 11 + Documentation/dev-tools/kunit/faq.rst | 62 +++ Documentation/dev-tools/kunit/index.rst | 79 +++ Documentation/dev-tools/kunit/start.rst | 180 ++++++ Documentation/dev-tools/kunit/usage.rst | 576 ++++++++++++++++++++ 7 files changed, 925 insertions(+) create mode 100644 Documentation/dev-tools/kunit/api/index.rst create mode 100644 Documentation/dev-tools/kunit/api/test.rst create mode 100644 Documentation/dev-tools/kunit/faq.rst create mode 100644 Documentation/dev-tools/kunit/index.rst create mode 100644 Documentation/dev-tools/kunit/start.rst create mode 100644 Documentation/dev-tools/kunit/usage.rst diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst index b0522a4dd107..09dee10d2592 100644 --- a/Documentation/dev-tools/index.rst +++ b/Documentation/dev-tools/index.rst @@ -24,6 +24,7 @@ whole; patches welcome! gdb-kernel-debugging kgdb kselftest + kunit/index .. only:: subproject and html diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst new file mode 100644 index 000000000000..9b9bffe5d41a --- /dev/null +++ b/Documentation/dev-tools/kunit/api/index.rst @@ -0,0 +1,16 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +API Reference +============= +.. toctree:: + + test + +This section documents the KUnit kernel testing API. It is divided into the +following sections: + +================================= ============================================== +:doc:`test` documents all of the standard testing API + excluding mocking or mocking related features. +================================= ============================================== diff --git a/Documentation/dev-tools/kunit/api/test.rst b/Documentation/dev-tools/kunit/api/test.rst new file mode 100644 index 000000000000..aaa97f17e5b3 --- /dev/null +++ b/Documentation/dev-tools/kunit/api/test.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +Test API +======== + +This file documents all of the standard testing API excluding mocking or mocking +related features. + +.. kernel-doc:: include/kunit/test.h + :internal: diff --git a/Documentation/dev-tools/kunit/faq.rst b/Documentation/dev-tools/kunit/faq.rst new file mode 100644 index 000000000000..bf2095112d89 --- /dev/null +++ b/Documentation/dev-tools/kunit/faq.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Frequently Asked Questions +========================== + +How is this different from Autotest, kselftest, etc? +==================================================== +KUnit is a unit testing framework. Autotest, kselftest (and some others) are +not. + +A `unit test `_ is supposed to +test a single unit of code in isolation, hence the name. A unit test should be +the finest granularity of testing and as such should allow all possible code +paths to be tested in the code under test; this is only possible if the code +under test is very small and does not have any external dependencies outside of +the test's control like hardware. + +There are no testing frameworks currently available for the kernel that do not +require installing the kernel on a test machine or in a VM and all require +tests to be written in userspace and run on the kernel under test; this is true +for Autotest, kselftest, and some others, disqualifying any of them from being +considered unit testing frameworks. + +Does KUnit support running on architectures other than UML? +=========================================================== + +Yes, well, mostly. + +For the most part, the KUnit core framework (what you use to write the tests) +can compile to any architecture; it compiles like just another part of the +kernel and runs when the kernel boots. However, there is some infrastructure, +like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support +other architectures. + +In short, this means that, yes, you can run KUnit on other architectures, but +it might require more work than using KUnit on UML. + +For more information, see :ref:`kunit-on-non-uml`. + +What is the difference between a unit test and these other kinds of tests? +========================================================================== +Most existing tests for the Linux kernel would be categorized as an integration +test, or an end-to-end test. + +- A unit test is supposed to test a single unit of code in isolation, hence the + name. A unit test should be the finest granularity of testing and as such + should allow all possible code paths to be tested in the code under test; this + is only possible if the code under test is very small and does not have any + external dependencies outside of the test's control like hardware. +- An integration test tests the interaction between a minimal set of components, + usually just two or three. For example, someone might write an integration + test to test the interaction between a driver and a piece of hardware, or to + test the interaction between the userspace libraries the kernel provides and + the kernel itself; however, one of these tests would probably not test the + entire kernel along with hardware interactions and interactions with the + userspace. +- An end-to-end test usually tests the entire system from the perspective of the + code under test. For example, someone might write an end-to-end test for the + kernel by installing a production configuration of the kernel on production + hardware with a production userspace and then trying to exercise some behavior + that depends on interactions between the hardware, the kernel, and userspace. diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst new file mode 100644 index 000000000000..26ffb46bdf99 --- /dev/null +++ b/Documentation/dev-tools/kunit/index.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +KUnit - Unit Testing for the Linux Kernel +========================================= + +.. toctree:: + :maxdepth: 2 + + start + usage + api/index + faq + +What is KUnit? +============== + +KUnit is a lightweight unit testing and mocking framework for the Linux kernel. +These tests are able to be run locally on a developer's workstation without a VM +or special hardware. + +KUnit is heavily inspired by JUnit, Python's unittest.mock, and +Googletest/Googlemock for C++. KUnit provides facilities for defining unit test +cases, grouping related test cases into test suites, providing common +infrastructure for running tests, and much more. + +Get started now: :doc:`start` + +Why KUnit? +========== + +A unit test is supposed to test a single unit of code in isolation, hence the +name. A unit test should be the finest granularity of testing and as such should +allow all possible code paths to be tested in the code under test; this is only +possible if the code under test is very small and does not have any external +dependencies outside of the test's control like hardware. + +Outside of KUnit, there are no testing frameworks currently +available for the kernel that do not require installing the kernel on a test +machine or in a VM and all require tests to be written in userspace running on +the kernel; this is true for Autotest, and kselftest, disqualifying +any of them from being considered unit testing frameworks. + +KUnit addresses the problem of being able to run tests without needing a virtual +machine or actual hardware with User Mode Linux. User Mode Linux is a Linux +architecture, like ARM or x86; however, unlike other architectures it compiles +to a standalone program that can be run like any other program directly inside +of a host operating system; to be clear, it does not require any virtualization +support; it is just a regular program. + +KUnit is fast. Excluding build time, from invocation to completion KUnit can run +several dozen tests in only 10 to 20 seconds; this might not sound like a big +deal to some people, but having such fast and easy to run tests fundamentally +changes the way you go about testing and even writing code in the first place. +Linus himself said in his `git talk at Google +`_: + + "... a lot of people seem to think that performance is about doing the + same thing, just doing it faster, and that is not true. That is not what + performance is all about. If you can do something really fast, really + well, people will start using it differently." + +In this context Linus was talking about branching and merging, +but this point also applies to testing. If your tests are slow, unreliable, are +difficult to write, and require a special setup or special hardware to run, +then you wait a lot longer to write tests, and you wait a lot longer to run +tests; this means that tests are likely to break, unlikely to test a lot of +things, and are unlikely to be rerun once they pass. If your tests are really +fast, you run them all the time, every time you make a change, and every time +someone sends you some code. Why trust that someone ran all their tests +correctly on every change when you can just run them yourself in less time than +it takes to read their test log? + +How do I use it? +================ + +* :doc:`start` - for new users of KUnit +* :doc:`usage` - for a more detailed explanation of KUnit features +* :doc:`api/index` - for the list of KUnit APIs used for testing diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst new file mode 100644 index 000000000000..6dc229e46bb3 --- /dev/null +++ b/Documentation/dev-tools/kunit/start.rst @@ -0,0 +1,180 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Getting Started +=============== + +Installing dependencies +======================= +KUnit has the same dependencies as the Linux kernel. As long as you can build +the kernel, you can run KUnit. + +KUnit Wrapper +============= +Included with KUnit is a simple Python wrapper that helps format the output to +easily use and read KUnit output. It handles building and running the kernel, as +well as formatting the output. + +The wrapper can be run with: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py run + +Creating a kunitconfig +====================== +The Python script is a thin wrapper around Kbuild as such, it needs to be +configured with a ``kunitconfig`` file. This file essentially contains the +regular Kernel config, with the specific test targets as well. + +.. code-block:: bash + + git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO + cd $PATH_TO_LINUX_REPO + ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig + +You may want to add kunitconfig to your local gitignore. + +Verifying KUnit Works +--------------------- + +To make sure that everything is set up correctly, simply invoke the Python +wrapper from your kernel repo: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +.. note:: + You may want to run ``make mrproper`` first. + +If everything worked correctly, you should see the following: + +.. code-block:: bash + + Generating .config ... + Building KUnit Kernel ... + Starting KUnit Kernel ... + +followed by a list of tests that are run. All of them should be passing. + +.. note:: + Because it is building a lot of sources for the first time, the ``Building + kunit kernel`` step may take a while. + +Writing your first test +======================= + +In your kernel repo let's add some code that we can test. Create a file +``drivers/misc/example.h`` with the contents: + +.. code-block:: c + + int misc_example_add(int left, int right); + +create a file ``drivers/misc/example.c``: + +.. code-block:: c + + #include + + #include "example.h" + + int misc_example_add(int left, int right) + { + return left + right; + } + +Now add the following lines to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE + bool "My example" + +and the following lines to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE) += example.o + +Now we are ready to write the test. The test will be in +``drivers/misc/example-test.c``: + +.. code-block:: c + + #include + #include "example.h" + + /* Define the test cases. */ + + static void misc_example_add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1)); + KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1)); + KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN)); + } + + static void misc_example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + + static struct kunit_case misc_example_test_cases[] = { + KUNIT_CASE(misc_example_add_test_basic), + KUNIT_CASE(misc_example_test_failure), + {} + }; + + static struct kunit_suite misc_example_test_suite = { + .name = "misc-example", + .test_cases = misc_example_test_cases, + }; + kunit_test_suite(misc_example_test_suite); + +Now add the following to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE_TEST + bool "Test for my example" + depends on MISC_EXAMPLE && KUNIT + +and the following to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o + +Now add it to your ``kunitconfig``: + +.. code-block:: none + + CONFIG_MISC_EXAMPLE=y + CONFIG_MISC_EXAMPLE_TEST=y + +Now you can run the test: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +You should see the following failure: + +.. code-block:: none + + ... + [16:08:57] [PASSED] misc-example:misc_example_add_test_basic + [16:08:57] [FAILED] misc-example:misc_example_test_failure + [16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17 + [16:08:57] This test never passes. + ... + +Congrats! You just wrote your first KUnit test! + +Next Steps +========== +* Check out the :doc:`usage` page for a more + in-depth explanation of KUnit. diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst new file mode 100644 index 000000000000..c6e69634e274 --- /dev/null +++ b/Documentation/dev-tools/kunit/usage.rst @@ -0,0 +1,576 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========== +Using KUnit +=========== + +The purpose of this document is to describe what KUnit is, how it works, how it +is intended to be used, and all the concepts and terminology that are needed to +understand it. This guide assumes a working knowledge of the Linux kernel and +some basic knowledge of testing. + +For a high level introduction to KUnit, including setting up KUnit for your +project, see :doc:`start`. + +Organization of this document +============================= + +This document is organized into two main sections: Testing and Isolating +Behavior. The first covers what a unit test is and how to use KUnit to write +them. The second covers how to use KUnit to isolate code and make it possible +to unit test code that was otherwise un-unit-testable. + +Testing +======= + +What is KUnit? +-------------- + +"K" is short for "kernel" so "KUnit" is the "(Linux) Kernel Unit Testing +Framework." KUnit is intended first and foremost for writing unit tests; it is +general enough that it can be used to write integration tests; however, this is +a secondary goal. KUnit has no ambition of being the only testing framework for +the kernel; for example, it does not intend to be an end-to-end testing +framework. + +What is Unit Testing? +--------------------- + +A `unit test `_ is a test that +tests code at the smallest possible scope, a *unit* of code. In the C +programming language that's a function. + +Unit tests should be written for all the publicly exposed functions in a +compilation unit; so that is all the functions that are exported in either a +*class* (defined below) or all functions which are **not** static. + +Writing Tests +------------- + +Test Cases +~~~~~~~~~~ + +The fundamental unit in KUnit is the test case. A test case is a function with +the signature ``void (*)(struct kunit *test)``. It calls a function to be tested +and then sets *expectations* for what should happen. For example: + +.. code-block:: c + + void example_test_success(struct kunit *test) + { + } + + void example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + +In the above example ``example_test_success`` always passes because it does +nothing; no expectations are set, so all expectations pass. On the other hand +``example_test_failure`` always fails because it calls ``KUNIT_FAIL``, which is +a special expectation that logs a message and causes the test case to fail. + +Expectations +~~~~~~~~~~~~ +An *expectation* is a way to specify that you expect a piece of code to do +something in a test. An expectation is called like a function. A test is made +by setting expectations about the behavior of a piece of code under test; when +one or more of the expectations fail, the test case fails and information about +the failure is logged. For example: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + +In the above example ``add_test_basic`` makes a number of assertions about the +behavior of a function called ``add``; the first parameter is always of type +``struct kunit *``, which contains information about the current test context; +the second parameter, in this case, is what the value is expected to be; the +last value is what the value actually is. If ``add`` passes all of these +expectations, the test case, ``add_test_basic`` will pass; if any one of these +expectations fail, the test case will fail. + +It is important to understand that a test case *fails* when any expectation is +violated; however, the test will continue running, potentially trying other +expectations until the test case ends or is otherwise terminated. This is as +opposed to *assertions* which are discussed later. + +To learn about more expectations supported by KUnit, see :doc:`api/test`. + +.. note:: + A single test case should be pretty short, pretty easy to understand, + focused on a single behavior. + +For example, if we wanted to properly test the add function above, we would +create additional tests cases which would each test a different property that an +add function should have like this: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + + void add_test_negative(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + } + + void add_test_max(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + } + + void add_test_overflow(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MIN, add(INT_MAX, 1)); + } + +Notice how it is immediately obvious what all the properties that we are testing +for are. + +Assertions +~~~~~~~~~~ + +KUnit also has the concept of an *assertion*. An assertion is just like an +expectation except the assertion immediately terminates the test case if it is +not satisfied. + +For example: + +.. code-block:: c + + static void mock_test_do_expect_default_return(struct kunit *test) + { + struct mock_test_context *ctx = test->priv; + struct mock *mock = ctx->mock; + int param0 = 5, param1 = -5; + const char *two_param_types[] = {"int", "int"}; + const void *two_params[] = {¶m0, ¶m1}; + const void *ret; + + ret = mock->do_expect(mock, + "test_printk", test_printk, + two_param_types, two_params, + ARRAY_SIZE(two_params)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_EQ(test, -4, *((int *) ret)); + } + +In this example, the method under test should return a pointer to a value, so +if the pointer returned by the method is null or an errno, we don't want to +bother continuing the test since the following expectation could crash the test +case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us to bail out of the test case if +the appropriate conditions have not been satisfied to complete the test. + +Test Suites +~~~~~~~~~~~ + +Now obviously one unit test isn't very helpful; the power comes from having +many test cases covering all of your behaviors. Consequently it is common to +have many *similar* tests; in order to reduce duplication in these closely +related tests most unit testing frameworks provide the concept of a *test +suite*, in KUnit we call it a *test suite*; all it is is just a collection of +test cases for a unit of code with a set up function that gets invoked before +every test cases and then a tear down function that gets invoked after every +test case completes. + +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``, would run the test +cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``, +each would have ``example_test_init`` called immediately before it and would +have ``example_test_exit`` called immediately after it. +``kunit_test_suite(example_test_suite)`` registers the test suite with the +KUnit test framework. + +.. note:: + A test case will only be run if it is associated with a test suite. + +For a more information on these types of things see the :doc:`api/test`. + +Isolating Behavior +================== + +The most important aspect of unit testing that other forms of testing do not +provide is the ability to limit the amount of code under test to a single unit. +In practice, this is only possible by being able to control what code gets run +when the unit under test calls a function and this is usually accomplished +through some sort of indirection where a function is exposed as part of an API +such that the definition of that function can be changed without affecting the +rest of the code base. In the kernel this primarily comes from two constructs, +classes, structs that contain function pointers that are provided by the +implementer, and architecture specific functions which have definitions selected +at compile time. + +Classes +------- + +Classes are not a construct that is built into the C programming language; +however, it is an easily derived concept. Accordingly, pretty much every project +that does not use a standardized object oriented library (like GNOME's GObject) +has their own slightly different way of doing object oriented programming; the +Linux kernel is no exception. + +The central concept in kernel object oriented programming is the class. In the +kernel, a *class* is a struct that contains function pointers. This creates a +contract between *implementers* and *users* since it forces them to use the +same function signature without having to call the function directly. In order +for it to truly be a class, the function pointers must specify that a pointer +to the class, known as a *class handle*, be one of the parameters; this makes +it possible for the member functions (also known as *methods*) to have access +to member variables (more commonly known as *fields*) allowing the same +implementation to have multiple *instances*. + +Typically a class can be *overridden* by *child classes* by embedding the +*parent class* in the child class. Then when a method provided by the child +class is called, the child implementation knows that the pointer passed to it is +of a parent contained within the child; because of this, the child can compute +the pointer to itself because the pointer to the parent is always a fixed offset +from the pointer to the child; this offset is the offset of the parent contained +in the child struct. For example: + +.. code-block:: c + + struct shape { + int (*area)(struct shape *this); + }; + + struct rectangle { + struct shape parent; + int length; + int width; + }; + + int rectangle_area(struct shape *this) + { + struct rectangle *self = container_of(this, struct shape, parent); + + return self->length * self->width; + }; + + void rectangle_new(struct rectangle *self, int length, int width) + { + self->parent.area = rectangle_area; + self->length = length; + self->width = width; + } + +In this example (as in most kernel code) the operation of computing the pointer +to the child from the pointer to the parent is done by ``container_of``. + +Faking Classes +~~~~~~~~~~~~~~ + +In order to unit test a piece of code that calls a method in a class, the +behavior of the method must be controllable, otherwise the test ceases to be a +unit test and becomes an integration test. + +A fake just provides an implementation of a piece of code that is different than +what runs in a production instance, but behaves identically from the standpoint +of the callers; this is usually done to replace a dependency that is hard to +deal with, or is slow. + +A good example for this might be implementing a fake EEPROM that just stores the +"contents" in an internal buffer. For example, let's assume we have a class that +represents an EEPROM: + +.. code-block:: c + + struct eeprom { + ssize_t (*read)(struct eeprom *this, size_t offset, char *buffer, size_t count); + ssize_t (*write)(struct eeprom *this, size_t offset, const char *buffer, size_t count); + }; + +And we want to test some code that buffers writes to the EEPROM: + +.. code-block:: c + + struct eeprom_buffer { + ssize_t (*write)(struct eeprom_buffer *this, const char *buffer, size_t count); + int flush(struct eeprom_buffer *this); + size_t flush_count; /* Flushes when buffer exceeds flush_count. */ + }; + + struct eeprom_buffer *new_eeprom_buffer(struct eeprom *eeprom); + void destroy_eeprom_buffer(struct eeprom *eeprom); + +We can easily test this code by *faking out* the underlying EEPROM: + +.. code-block:: c + + struct fake_eeprom { + struct eeprom parent; + char contents[FAKE_EEPROM_CONTENTS_SIZE]; + }; + + ssize_t fake_eeprom_read(struct eeprom *parent, size_t offset, char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(buffer, this->contents + offset, count); + + return count; + } + + ssize_t fake_eeprom_write(struct eeprom *this, size_t offset, const char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(this->contents + offset, buffer, count); + + return count; + } + + void fake_eeprom_init(struct fake_eeprom *this) + { + this->parent.read = fake_eeprom_read; + this->parent.write = fake_eeprom_write; + memset(this->contents, 0, FAKE_EEPROM_CONTENTS_SIZE); + } + +We can now use it to test ``struct eeprom_buffer``: + +.. code-block:: c + + struct eeprom_buffer_test { + struct fake_eeprom *fake_eeprom; + struct eeprom_buffer *eeprom_buffer; + }; + + static void eeprom_buffer_test_does_not_write_until_flush(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = SIZE_MAX; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0); + + eeprom_buffer->flush(eeprom_buffer); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_after_flush_count_met(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_increments_of_flush_count(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff, 0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 2); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + /* Should have only flushed the first two bytes. */ + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[2], 0); + } + + static int eeprom_buffer_test_init(struct kunit *test) + { + struct eeprom_buffer_test *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->fake_eeprom = kunit_kzalloc(test, sizeof(*ctx->fake_eeprom), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->fake_eeprom); + fake_eeprom_init(ctx->fake_eeprom); + + ctx->eeprom_buffer = new_eeprom_buffer(&ctx->fake_eeprom->parent); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->eeprom_buffer); + + test->priv = ctx; + + return 0; + } + + static void eeprom_buffer_test_exit(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + + destroy_eeprom_buffer(ctx->eeprom_buffer); + } + +.. _kunit-on-non-uml: + +KUnit on non-UML architectures +============================== + +By default KUnit uses UML as a way to provide dependencies for code under test. +Under most circumstances KUnit's usage of UML should be treated as an +implementation detail of how KUnit works under the hood. Nevertheless, there +are instances where being able to run architecture specific code, or test +against real hardware is desirable. For these reasons KUnit supports running on +other architectures. + +Running existing KUnit tests on non-UML architectures +----------------------------------------------------- + +There are some special considerations when running existing KUnit tests on +non-UML architectures: + +* Hardware may not be deterministic, so a test that always passes or fails + when run under UML may not always do so on real hardware. +* Hardware and VM environments may not be hermetic. KUnit tries its best to + provide a hermetic environment to run tests; however, it cannot manage state + that it doesn't know about outside of the kernel. Consequently, tests that + may be hermetic on UML may not be hermetic on other architectures. +* Some features and tooling may not be supported outside of UML. +* Hardware and VMs are slower than UML. + +None of these are reasons not to run your KUnit tests on real hardware; they are +only things to be aware of when doing so. + +The biggest impediment will likely be that certain KUnit features and +infrastructure may not support your target environment. For example, at this +time the KUnit Wrapper (``tools/testing/kunit/kunit.py``) does not work outside +of UML. Unfortunately, there is no way around this. Using UML (or even just a +particular architecture) allows us to make a lot of assumptions that make it +possible to do things which might otherwise be impossible. + +Nevertheless, all core KUnit framework features are fully supported on all +architectures, and using them is straightforward: all you need to do is to take +your kunitconfig, your Kconfig options for the tests you would like to run, and +merge them into whatever config your are using for your platform. That's it! + +For example, let's say you have the following kunitconfig: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + +If you wanted to run this test on an x86 VM, you might add the following config +options to your ``.config``: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y + +All these new options do is enable support for a common serial console needed +for logging. + +Next, you could build a kernel with these tests as follows: + + +.. code-block:: bash + + make ARCH=x86 olddefconfig + make ARCH=x86 + +Once you have built a kernel, you could run it on QEMU as follows: + +.. code-block:: bash + + qemu-system-x86_64 -enable-kvm \ + -m 1024 \ + -kernel arch/x86_64/boot/bzImage \ + -append 'console=ttyS0' \ + --nographic + +Interspersed in the kernel logs you might see the following: + +.. code-block:: none + + TAP version 14 + # Subtest: example + 1..1 + # example_simple_test: initializing + ok 1 - example_simple_test + ok 1 - example + +Congratulations, you just ran a KUnit test on the x86 architecture! + +Writing new tests for other architectures +----------------------------------------- + +The first thing you must do is ask yourself whether it is necessary to write a +KUnit test for a specific architecture, and then whether it is necessary to +write that test for a particular piece of hardware. In general, writing a test +that depends on having access to a particular piece of hardware or software (not +included in the Linux source repo) should be avoided at all costs. + +Even if you only ever plan on running your KUnit test on your hardware +configuration, other people may want to run your tests and may not have access +to your hardware. If you write your test to run on UML, then anyone can run your +tests without knowing anything about your particular setup, and you can still +run your tests on your hardware setup just by compiling for your architecture. + +.. important:: + Always prefer tests that run on UML to tests that only run under a particular + architecture, and always prefer tests that run under QEMU or another easy + (and monitarily free) to obtain software environment to a specific piece of + hardware. + +Nevertheless, there are still valid reasons to write an architecture or hardware +specific test: for example, you might want to test some code that really belongs +in ``arch/some-arch/*``. Even so, try your best to write the test so that it +does not depend on physical hardware: if some of your test cases don't need the +hardware, only require the hardware for tests that actually need it. + +Now that you have narrowed down exactly what bits are hardware specific, the +actual procedure for writing and running the tests is pretty much the same as +writing normal KUnit tests. One special caveat is that you have to reset +hardware state in between test cases; if this is not possible, you may only be +able to run one test case per invocation. + +.. TODO(brendanhiggins@google.com): Add an actual example of an architecture + dependent KUnit test. -- 2.23.0.351.gc4317032e6-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: Brendan Higgins Subject: [PATCH v16 15/19] Documentation: kunit: add documentation for KUnit Date: Fri, 20 Sep 2019 16:19:19 -0700 Message-ID: <20190920231923.141900-16-brendanhiggins@google.com> References: <20190920231923.141900-1-brendanhiggins@google.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, sboyd@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: pmladek@suse.com, linux-doc@vger.kernel.org, amir73il@gmail.com, Brendan Higgins , dri-devel@lists.freedesktop.org, Alexander.Levin@microsoft.com, linux-kselftest@vger.kernel.org, Jonathan Corbet , linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, Felix Guo , wfg@linux.intel.com, joel@jms.id.au, rientjes@google.com, jdike@addtoit.com, dan.carpenter@oracle.com, devicetree@vger.kernel.org, linux-kbuild@vger.kernel.org, Tim.Bird@sony.com, linux-um@lists.infradead.org, rostedt@goodmis.org, julia.lawall@lip6.fr, kunit-dev@googlegroups.com, richard@nod.at, torvalds@linux-foundation.org, rdunlap@infradead.org, linux-kernel@vger.kernel.org, mpe@ellerman.id.au, linux-fsdevel@vger.kernel.org, logang@deltatee.com List-Id: devicetree@vger.kernel.org QWRkIGRvY3VtZW50YXRpb24gZm9yIEtVbml0LCB0aGUgTGludXgga2VybmVsIHVuaXQgdGVzdGlu ZyBmcmFtZXdvcmsuCi0gQWRkIGludHJvIGFuZCB1c2FnZSBndWlkZSBmb3IgS1VuaXQKLSBBZGQg QVBJIHJlZmVyZW5jZQoKU2lnbmVkLW9mZi1ieTogRmVsaXggR3VvIDxmZWxpeGd1b3hpdXBpbmdA Z21haWwuY29tPgpTaWduZWQtb2ZmLWJ5OiBCcmVuZGFuIEhpZ2dpbnMgPGJyZW5kYW5oaWdnaW5z QGdvb2dsZS5jb20+CkNjOiBKb25hdGhhbiBDb3JiZXQgPGNvcmJldEBsd24ubmV0PgpSZXZpZXdl ZC1ieTogR3JlZyBLcm9haC1IYXJ0bWFuIDxncmVna2hAbGludXhmb3VuZGF0aW9uLm9yZz4KUmV2 aWV3ZWQtYnk6IExvZ2FuIEd1bnRob3JwZSA8bG9nYW5nQGRlbHRhdGVlLmNvbT4KUmV2aWV3ZWQt Ynk6IFN0ZXBoZW4gQm95ZCA8c2JveWRAa2VybmVsLm9yZz4KLS0tCiBEb2N1bWVudGF0aW9uL2Rl di10b29scy9pbmRleC5yc3QgICAgICAgICAgIHwgICAxICsKIERvY3VtZW50YXRpb24vZGV2LXRv b2xzL2t1bml0L2FwaS9pbmRleC5yc3QgfCAgMTYgKwogRG9jdW1lbnRhdGlvbi9kZXYtdG9vbHMv a3VuaXQvYXBpL3Rlc3QucnN0ICB8ICAxMSArCiBEb2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5p dC9mYXEucnN0ICAgICAgIHwgIDYyICsrKwogRG9jdW1lbnRhdGlvbi9kZXYtdG9vbHMva3VuaXQv aW5kZXgucnN0ICAgICB8ICA3OSArKysKIERvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L3N0 YXJ0LnJzdCAgICAgfCAxODAgKysrKysrCiBEb2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC91 c2FnZS5yc3QgICAgIHwgNTc2ICsrKysrKysrKysrKysrKysrKysrCiA3IGZpbGVzIGNoYW5nZWQs IDkyNSBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgRG9jdW1lbnRhdGlvbi9kZXYt dG9vbHMva3VuaXQvYXBpL2luZGV4LnJzdAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp b24vZGV2LXRvb2xzL2t1bml0L2FwaS90ZXN0LnJzdAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3Vt ZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L2ZhcS5yc3QKIGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1 bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC9pbmRleC5yc3QKIGNyZWF0ZSBtb2RlIDEwMDY0NCBE b2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC9zdGFydC5yc3QKIGNyZWF0ZSBtb2RlIDEwMDY0 NCBEb2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC91c2FnZS5yc3QKCmRpZmYgLS1naXQgYS9E b2N1bWVudGF0aW9uL2Rldi10b29scy9pbmRleC5yc3QgYi9Eb2N1bWVudGF0aW9uL2Rldi10b29s cy9pbmRleC5yc3QKaW5kZXggYjA1MjJhNGRkMTA3Li4wOWRlZTEwZDI1OTIgMTAwNjQ0Ci0tLSBh L0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2luZGV4LnJzdAorKysgYi9Eb2N1bWVudGF0aW9uL2Rl di10b29scy9pbmRleC5yc3QKQEAgLTI0LDYgKzI0LDcgQEAgd2hvbGU7IHBhdGNoZXMgd2VsY29t ZSEKICAgIGdkYi1rZXJuZWwtZGVidWdnaW5nCiAgICBrZ2RiCiAgICBrc2VsZnRlc3QKKyAgIGt1 bml0L2luZGV4CiAKIAogLi4gb25seTo6ICBzdWJwcm9qZWN0IGFuZCBodG1sCmRpZmYgLS1naXQg YS9Eb2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC9hcGkvaW5kZXgucnN0IGIvRG9jdW1lbnRh dGlvbi9kZXYtdG9vbHMva3VuaXQvYXBpL2luZGV4LnJzdApuZXcgZmlsZSBtb2RlIDEwMDY0NApp bmRleCAwMDAwMDAwMDAwMDAuLjliOWJmZmU1ZDQxYQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3Vt ZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L2FwaS9pbmRleC5yc3QKQEAgLTAsMCArMSwxNiBAQAor Li4gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKKworPT09PT09PT09PT09PQorQVBJ IFJlZmVyZW5jZQorPT09PT09PT09PT09PQorLi4gdG9jdHJlZTo6CisKKwl0ZXN0CisKK1RoaXMg c2VjdGlvbiBkb2N1bWVudHMgdGhlIEtVbml0IGtlcm5lbCB0ZXN0aW5nIEFQSS4gSXQgaXMgZGl2 aWRlZCBpbnRvIHRoZQorZm9sbG93aW5nIHNlY3Rpb25zOgorCis9PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT0gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PQorOmRvYzpgdGVzdGAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50cyBhbGwgb2Yg dGhlIHN0YW5kYXJkIHRlc3RpbmcgQVBJCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgZXhjbHVkaW5nIG1vY2tpbmcgb3IgbW9ja2luZyByZWxhdGVkIGZlYXR1cmVzLgorPT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT0KZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1 bml0L2FwaS90ZXN0LnJzdCBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L2FwaS90ZXN0 LnJzdApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLmFhYTk3ZjE3ZTVi MwotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L2FwaS90 ZXN0LnJzdApAQCAtMCwwICsxLDExIEBACisuLiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BM LTIuMAorCis9PT09PT09PQorVGVzdCBBUEkKKz09PT09PT09CisKK1RoaXMgZmlsZSBkb2N1bWVu dHMgYWxsIG9mIHRoZSBzdGFuZGFyZCB0ZXN0aW5nIEFQSSBleGNsdWRpbmcgbW9ja2luZyBvciBt b2NraW5nCityZWxhdGVkIGZlYXR1cmVzLgorCisuLiBrZXJuZWwtZG9jOjogaW5jbHVkZS9rdW5p dC90ZXN0LmgKKyAgIDppbnRlcm5hbDoKZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2LXRv b2xzL2t1bml0L2ZhcS5yc3QgYi9Eb2N1bWVudGF0aW9uL2Rldi10b29scy9rdW5pdC9mYXEucnN0 Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uYmYyMDk1MTEyZDg5Ci0t LSAvZGV2L251bGwKKysrIGIvRG9jdW1lbnRhdGlvbi9kZXYtdG9vbHMva3VuaXQvZmFxLnJzdApA QCAtMCwwICsxLDYyIEBACisuLiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAorCis9 PT09PT09PT09PT09PT09PT09PT09PT09PQorRnJlcXVlbnRseSBBc2tlZCBRdWVzdGlvbnMKKz09 PT09PT09PT09PT09PT09PT09PT09PT09CisKK0hvdyBpcyB0aGlzIGRpZmZlcmVudCBmcm9tIEF1 dG90ZXN0LCBrc2VsZnRlc3QsIGV0Yz8KKz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT0KK0tVbml0IGlzIGEgdW5pdCB0ZXN0aW5nIGZyYW1ld29yay4g QXV0b3Rlc3QsIGtzZWxmdGVzdCAoYW5kIHNvbWUgb3RoZXJzKSBhcmUKK25vdC4KKworQSBgdW5p dCB0ZXN0IDxodHRwczovL21hcnRpbmZvd2xlci5jb20vYmxpa2kvVW5pdFRlc3QuaHRtbD5gXyBp cyBzdXBwb3NlZCB0bwordGVzdCBhIHNpbmdsZSB1bml0IG9mIGNvZGUgaW4gaXNvbGF0aW9uLCBo ZW5jZSB0aGUgbmFtZS4gQSB1bml0IHRlc3Qgc2hvdWxkIGJlCit0aGUgZmluZXN0IGdyYW51bGFy aXR5IG9mIHRlc3RpbmcgYW5kIGFzIHN1Y2ggc2hvdWxkIGFsbG93IGFsbCBwb3NzaWJsZSBjb2Rl CitwYXRocyB0byBiZSB0ZXN0ZWQgaW4gdGhlIGNvZGUgdW5kZXIgdGVzdDsgdGhpcyBpcyBvbmx5 IHBvc3NpYmxlIGlmIHRoZSBjb2RlCit1bmRlciB0ZXN0IGlzIHZlcnkgc21hbGwgYW5kIGRvZXMg bm90IGhhdmUgYW55IGV4dGVybmFsIGRlcGVuZGVuY2llcyBvdXRzaWRlIG9mCit0aGUgdGVzdCdz IGNvbnRyb2wgbGlrZSBoYXJkd2FyZS4KKworVGhlcmUgYXJlIG5vIHRlc3RpbmcgZnJhbWV3b3Jr cyBjdXJyZW50bHkgYXZhaWxhYmxlIGZvciB0aGUga2VybmVsIHRoYXQgZG8gbm90CityZXF1aXJl IGluc3RhbGxpbmcgdGhlIGtlcm5lbCBvbiBhIHRlc3QgbWFjaGluZSBvciBpbiBhIFZNIGFuZCBh bGwgcmVxdWlyZQordGVzdHMgdG8gYmUgd3JpdHRlbiBpbiB1c2Vyc3BhY2UgYW5kIHJ1biBvbiB0 aGUga2VybmVsIHVuZGVyIHRlc3Q7IHRoaXMgaXMgdHJ1ZQorZm9yIEF1dG90ZXN0LCBrc2VsZnRl c3QsIGFuZCBzb21lIG90aGVycywgZGlzcXVhbGlmeWluZyBhbnkgb2YgdGhlbSBmcm9tIGJlaW5n Citjb25zaWRlcmVkIHVuaXQgdGVzdGluZyBmcmFtZXdvcmtzLgorCitEb2VzIEtVbml0IHN1cHBv cnQgcnVubmluZyBvbiBhcmNoaXRlY3R1cmVzIG90aGVyIHRoYW4gVU1MPworPT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KKworWWVzLCB3 ZWxsLCBtb3N0bHkuCisKK0ZvciB0aGUgbW9zdCBwYXJ0LCB0aGUgS1VuaXQgY29yZSBmcmFtZXdv cmsgKHdoYXQgeW91IHVzZSB0byB3cml0ZSB0aGUgdGVzdHMpCitjYW4gY29tcGlsZSB0byBhbnkg YXJjaGl0ZWN0dXJlOyBpdCBjb21waWxlcyBsaWtlIGp1c3QgYW5vdGhlciBwYXJ0IG9mIHRoZQor a2VybmVsIGFuZCBydW5zIHdoZW4gdGhlIGtlcm5lbCBib290cy4gSG93ZXZlciwgdGhlcmUgaXMg c29tZSBpbmZyYXN0cnVjdHVyZSwKK2xpa2UgdGhlIEtVbml0IFdyYXBwZXIgKGBgdG9vbHMvdGVz dGluZy9rdW5pdC9rdW5pdC5weWBgKSB0aGF0IGRvZXMgbm90IHN1cHBvcnQKK290aGVyIGFyY2hp dGVjdHVyZXMuCisKK0luIHNob3J0LCB0aGlzIG1lYW5zIHRoYXQsIHllcywgeW91IGNhbiBydW4g S1VuaXQgb24gb3RoZXIgYXJjaGl0ZWN0dXJlcywgYnV0CitpdCBtaWdodCByZXF1aXJlIG1vcmUg d29yayB0aGFuIHVzaW5nIEtVbml0IG9uIFVNTC4KKworRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNl ZSA6cmVmOmBrdW5pdC1vbi1ub24tdW1sYC4KKworV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3 ZWVuIGEgdW5pdCB0ZXN0IGFuZCB0aGVzZSBvdGhlciBraW5kcyBvZiB0ZXN0cz8KKz09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09CitNb3N0IGV4aXN0aW5nIHRlc3RzIGZvciB0aGUgTGludXgga2VybmVsIHdvdWxk IGJlIGNhdGVnb3JpemVkIGFzIGFuIGludGVncmF0aW9uCit0ZXN0LCBvciBhbiBlbmQtdG8tZW5k IHRlc3QuCisKKy0gQSB1bml0IHRlc3QgaXMgc3VwcG9zZWQgdG8gdGVzdCBhIHNpbmdsZSB1bml0 IG9mIGNvZGUgaW4gaXNvbGF0aW9uLCBoZW5jZSB0aGUKKyAgbmFtZS4gQSB1bml0IHRlc3Qgc2hv dWxkIGJlIHRoZSBmaW5lc3QgZ3JhbnVsYXJpdHkgb2YgdGVzdGluZyBhbmQgYXMgc3VjaAorICBz aG91bGQgYWxsb3cgYWxsIHBvc3NpYmxlIGNvZGUgcGF0aHMgdG8gYmUgdGVzdGVkIGluIHRoZSBj b2RlIHVuZGVyIHRlc3Q7IHRoaXMKKyAgaXMgb25seSBwb3NzaWJsZSBpZiB0aGUgY29kZSB1bmRl ciB0ZXN0IGlzIHZlcnkgc21hbGwgYW5kIGRvZXMgbm90IGhhdmUgYW55CisgIGV4dGVybmFsIGRl cGVuZGVuY2llcyBvdXRzaWRlIG9mIHRoZSB0ZXN0J3MgY29udHJvbCBsaWtlIGhhcmR3YXJlLgor LSBBbiBpbnRlZ3JhdGlvbiB0ZXN0IHRlc3RzIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGEgbWlu aW1hbCBzZXQgb2YgY29tcG9uZW50cywKKyAgdXN1YWxseSBqdXN0IHR3byBvciB0aHJlZS4gRm9y IGV4YW1wbGUsIHNvbWVvbmUgbWlnaHQgd3JpdGUgYW4gaW50ZWdyYXRpb24KKyAgdGVzdCB0byB0 ZXN0IHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGEgZHJpdmVyIGFuZCBhIHBpZWNlIG9mIGhhcmR3 YXJlLCBvciB0bworICB0ZXN0IHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIHRoZSB1c2Vyc3BhY2Ug bGlicmFyaWVzIHRoZSBrZXJuZWwgcHJvdmlkZXMgYW5kCisgIHRoZSBrZXJuZWwgaXRzZWxmOyBo b3dldmVyLCBvbmUgb2YgdGhlc2UgdGVzdHMgd291bGQgcHJvYmFibHkgbm90IHRlc3QgdGhlCisg IGVudGlyZSBrZXJuZWwgYWxvbmcgd2l0aCBoYXJkd2FyZSBpbnRlcmFjdGlvbnMgYW5kIGludGVy YWN0aW9ucyB3aXRoIHRoZQorICB1c2Vyc3BhY2UuCistIEFuIGVuZC10by1lbmQgdGVzdCB1c3Vh bGx5IHRlc3RzIHRoZSBlbnRpcmUgc3lzdGVtIGZyb20gdGhlIHBlcnNwZWN0aXZlIG9mIHRoZQor ICBjb2RlIHVuZGVyIHRlc3QuIEZvciBleGFtcGxlLCBzb21lb25lIG1pZ2h0IHdyaXRlIGFuIGVu ZC10by1lbmQgdGVzdCBmb3IgdGhlCisgIGtlcm5lbCBieSBpbnN0YWxsaW5nIGEgcHJvZHVjdGlv biBjb25maWd1cmF0aW9uIG9mIHRoZSBrZXJuZWwgb24gcHJvZHVjdGlvbgorICBoYXJkd2FyZSB3 aXRoIGEgcHJvZHVjdGlvbiB1c2Vyc3BhY2UgYW5kIHRoZW4gdHJ5aW5nIHRvIGV4ZXJjaXNlIHNv bWUgYmVoYXZpb3IKKyAgdGhhdCBkZXBlbmRzIG9uIGludGVyYWN0aW9ucyBiZXR3ZWVuIHRoZSBo YXJkd2FyZSwgdGhlIGtlcm5lbCwgYW5kIHVzZXJzcGFjZS4KZGlmZiAtLWdpdCBhL0RvY3VtZW50 YXRpb24vZGV2LXRvb2xzL2t1bml0L2luZGV4LnJzdCBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xz L2t1bml0L2luZGV4LnJzdApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAu LjI2ZmZiNDZiZGY5OQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xz L2t1bml0L2luZGV4LnJzdApAQCAtMCwwICsxLDc5IEBACisuLiBTUERYLUxpY2Vuc2UtSWRlbnRp ZmllcjogR1BMLTIuMAorCis9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PQorS1VuaXQgLSBVbml0IFRlc3RpbmcgZm9yIHRoZSBMaW51eCBLZXJuZWwKKz09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CisKKy4uIHRvY3RyZWU6OgorCTptYXhkZXB0 aDogMgorCisJc3RhcnQKKwl1c2FnZQorCWFwaS9pbmRleAorCWZhcQorCitXaGF0IGlzIEtVbml0 PworPT09PT09PT09PT09PT0KKworS1VuaXQgaXMgYSBsaWdodHdlaWdodCB1bml0IHRlc3Rpbmcg YW5kIG1vY2tpbmcgZnJhbWV3b3JrIGZvciB0aGUgTGludXgga2VybmVsLgorVGhlc2UgdGVzdHMg YXJlIGFibGUgdG8gYmUgcnVuIGxvY2FsbHkgb24gYSBkZXZlbG9wZXIncyB3b3Jrc3RhdGlvbiB3 aXRob3V0IGEgVk0KK29yIHNwZWNpYWwgaGFyZHdhcmUuCisKK0tVbml0IGlzIGhlYXZpbHkgaW5z cGlyZWQgYnkgSlVuaXQsIFB5dGhvbidzIHVuaXR0ZXN0Lm1vY2ssIGFuZAorR29vZ2xldGVzdC9H b29nbGVtb2NrIGZvciBDKysuIEtVbml0IHByb3ZpZGVzIGZhY2lsaXRpZXMgZm9yIGRlZmluaW5n IHVuaXQgdGVzdAorY2FzZXMsIGdyb3VwaW5nIHJlbGF0ZWQgdGVzdCBjYXNlcyBpbnRvIHRlc3Qg c3VpdGVzLCBwcm92aWRpbmcgY29tbW9uCitpbmZyYXN0cnVjdHVyZSBmb3IgcnVubmluZyB0ZXN0 cywgYW5kIG11Y2ggbW9yZS4KKworR2V0IHN0YXJ0ZWQgbm93OiA6ZG9jOmBzdGFydGAKKworV2h5 IEtVbml0PworPT09PT09PT09PQorCitBIHVuaXQgdGVzdCBpcyBzdXBwb3NlZCB0byB0ZXN0IGEg c2luZ2xlIHVuaXQgb2YgY29kZSBpbiBpc29sYXRpb24sIGhlbmNlIHRoZQorbmFtZS4gQSB1bml0 IHRlc3Qgc2hvdWxkIGJlIHRoZSBmaW5lc3QgZ3JhbnVsYXJpdHkgb2YgdGVzdGluZyBhbmQgYXMg c3VjaCBzaG91bGQKK2FsbG93IGFsbCBwb3NzaWJsZSBjb2RlIHBhdGhzIHRvIGJlIHRlc3RlZCBp biB0aGUgY29kZSB1bmRlciB0ZXN0OyB0aGlzIGlzIG9ubHkKK3Bvc3NpYmxlIGlmIHRoZSBjb2Rl IHVuZGVyIHRlc3QgaXMgdmVyeSBzbWFsbCBhbmQgZG9lcyBub3QgaGF2ZSBhbnkgZXh0ZXJuYWwK K2RlcGVuZGVuY2llcyBvdXRzaWRlIG9mIHRoZSB0ZXN0J3MgY29udHJvbCBsaWtlIGhhcmR3YXJl LgorCitPdXRzaWRlIG9mIEtVbml0LCB0aGVyZSBhcmUgbm8gdGVzdGluZyBmcmFtZXdvcmtzIGN1 cnJlbnRseQorYXZhaWxhYmxlIGZvciB0aGUga2VybmVsIHRoYXQgZG8gbm90IHJlcXVpcmUgaW5z dGFsbGluZyB0aGUga2VybmVsIG9uIGEgdGVzdAorbWFjaGluZSBvciBpbiBhIFZNIGFuZCBhbGwg cmVxdWlyZSB0ZXN0cyB0byBiZSB3cml0dGVuIGluIHVzZXJzcGFjZSBydW5uaW5nIG9uCit0aGUg a2VybmVsOyB0aGlzIGlzIHRydWUgZm9yIEF1dG90ZXN0LCBhbmQga3NlbGZ0ZXN0LCBkaXNxdWFs aWZ5aW5nCithbnkgb2YgdGhlbSBmcm9tIGJlaW5nIGNvbnNpZGVyZWQgdW5pdCB0ZXN0aW5nIGZy YW1ld29ya3MuCisKK0tVbml0IGFkZHJlc3NlcyB0aGUgcHJvYmxlbSBvZiBiZWluZyBhYmxlIHRv IHJ1biB0ZXN0cyB3aXRob3V0IG5lZWRpbmcgYSB2aXJ0dWFsCittYWNoaW5lIG9yIGFjdHVhbCBo YXJkd2FyZSB3aXRoIFVzZXIgTW9kZSBMaW51eC4gVXNlciBNb2RlIExpbnV4IGlzIGEgTGludXgK K2FyY2hpdGVjdHVyZSwgbGlrZSBBUk0gb3IgeDg2OyBob3dldmVyLCB1bmxpa2Ugb3RoZXIgYXJj aGl0ZWN0dXJlcyBpdCBjb21waWxlcwordG8gYSBzdGFuZGFsb25lIHByb2dyYW0gdGhhdCBjYW4g YmUgcnVuIGxpa2UgYW55IG90aGVyIHByb2dyYW0gZGlyZWN0bHkgaW5zaWRlCitvZiBhIGhvc3Qg b3BlcmF0aW5nIHN5c3RlbTsgdG8gYmUgY2xlYXIsIGl0IGRvZXMgbm90IHJlcXVpcmUgYW55IHZp cnR1YWxpemF0aW9uCitzdXBwb3J0OyBpdCBpcyBqdXN0IGEgcmVndWxhciBwcm9ncmFtLgorCitL VW5pdCBpcyBmYXN0LiBFeGNsdWRpbmcgYnVpbGQgdGltZSwgZnJvbSBpbnZvY2F0aW9uIHRvIGNv bXBsZXRpb24gS1VuaXQgY2FuIHJ1bgorc2V2ZXJhbCBkb3plbiB0ZXN0cyBpbiBvbmx5IDEwIHRv IDIwIHNlY29uZHM7IHRoaXMgbWlnaHQgbm90IHNvdW5kIGxpa2UgYSBiaWcKK2RlYWwgdG8gc29t ZSBwZW9wbGUsIGJ1dCBoYXZpbmcgc3VjaCBmYXN0IGFuZCBlYXN5IHRvIHJ1biB0ZXN0cyBmdW5k YW1lbnRhbGx5CitjaGFuZ2VzIHRoZSB3YXkgeW91IGdvIGFib3V0IHRlc3RpbmcgYW5kIGV2ZW4g d3JpdGluZyBjb2RlIGluIHRoZSBmaXJzdCBwbGFjZS4KK0xpbnVzIGhpbXNlbGYgc2FpZCBpbiBo aXMgYGdpdCB0YWxrIGF0IEdvb2dsZQorPGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2xvcm4vMTI3 MjY4Ni9yZXZpc2lvbnMjZGlmZi01M2M2NTU3MjEyNzg1NWYxYjAwM2RiNDA2NGE5NDU3M1I4NzQ+ YF86CisKKwkiLi4uIGEgbG90IG9mIHBlb3BsZSBzZWVtIHRvIHRoaW5rIHRoYXQgcGVyZm9ybWFu Y2UgaXMgYWJvdXQgZG9pbmcgdGhlCisJc2FtZSB0aGluZywganVzdCBkb2luZyBpdCBmYXN0ZXIs IGFuZCB0aGF0IGlzIG5vdCB0cnVlLiBUaGF0IGlzIG5vdCB3aGF0CisJcGVyZm9ybWFuY2UgaXMg YWxsIGFib3V0LiBJZiB5b3UgY2FuIGRvIHNvbWV0aGluZyByZWFsbHkgZmFzdCwgcmVhbGx5CisJ d2VsbCwgcGVvcGxlIHdpbGwgc3RhcnQgdXNpbmcgaXQgZGlmZmVyZW50bHkuIgorCitJbiB0aGlz IGNvbnRleHQgTGludXMgd2FzIHRhbGtpbmcgYWJvdXQgYnJhbmNoaW5nIGFuZCBtZXJnaW5nLAor YnV0IHRoaXMgcG9pbnQgYWxzbyBhcHBsaWVzIHRvIHRlc3RpbmcuIElmIHlvdXIgdGVzdHMgYXJl IHNsb3csIHVucmVsaWFibGUsIGFyZQorZGlmZmljdWx0IHRvIHdyaXRlLCBhbmQgcmVxdWlyZSBh IHNwZWNpYWwgc2V0dXAgb3Igc3BlY2lhbCBoYXJkd2FyZSB0byBydW4sCit0aGVuIHlvdSB3YWl0 IGEgbG90IGxvbmdlciB0byB3cml0ZSB0ZXN0cywgYW5kIHlvdSB3YWl0IGEgbG90IGxvbmdlciB0 byBydW4KK3Rlc3RzOyB0aGlzIG1lYW5zIHRoYXQgdGVzdHMgYXJlIGxpa2VseSB0byBicmVhaywg dW5saWtlbHkgdG8gdGVzdCBhIGxvdCBvZgordGhpbmdzLCBhbmQgYXJlIHVubGlrZWx5IHRvIGJl IHJlcnVuIG9uY2UgdGhleSBwYXNzLiBJZiB5b3VyIHRlc3RzIGFyZSByZWFsbHkKK2Zhc3QsIHlv dSBydW4gdGhlbSBhbGwgdGhlIHRpbWUsIGV2ZXJ5IHRpbWUgeW91IG1ha2UgYSBjaGFuZ2UsIGFu ZCBldmVyeSB0aW1lCitzb21lb25lIHNlbmRzIHlvdSBzb21lIGNvZGUuIFdoeSB0cnVzdCB0aGF0 IHNvbWVvbmUgcmFuIGFsbCB0aGVpciB0ZXN0cworY29ycmVjdGx5IG9uIGV2ZXJ5IGNoYW5nZSB3 aGVuIHlvdSBjYW4ganVzdCBydW4gdGhlbSB5b3Vyc2VsZiBpbiBsZXNzIHRpbWUgdGhhbgoraXQg dGFrZXMgdG8gcmVhZCB0aGVpciB0ZXN0IGxvZz8KKworSG93IGRvIEkgdXNlIGl0PworPT09PT09 PT09PT09PT09PQorCisqICAgOmRvYzpgc3RhcnRgIC0gZm9yIG5ldyB1c2VycyBvZiBLVW5pdAor KiAgIDpkb2M6YHVzYWdlYCAtIGZvciBhIG1vcmUgZGV0YWlsZWQgZXhwbGFuYXRpb24gb2YgS1Vu aXQgZmVhdHVyZXMKKyogICA6ZG9jOmBhcGkvaW5kZXhgIC0gZm9yIHRoZSBsaXN0IG9mIEtVbml0 IEFQSXMgdXNlZCBmb3IgdGVzdGluZwpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXYtdG9v bHMva3VuaXQvc3RhcnQucnN0IGIvRG9jdW1lbnRhdGlvbi9kZXYtdG9vbHMva3VuaXQvc3RhcnQu cnN0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uNmRjMjI5ZTQ2YmIz Ci0tLSAvZGV2L251bGwKKysrIGIvRG9jdW1lbnRhdGlvbi9kZXYtdG9vbHMva3VuaXQvc3RhcnQu cnN0CkBAIC0wLDAgKzEsMTgwIEBACisuLiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIu MAorCis9PT09PT09PT09PT09PT0KK0dldHRpbmcgU3RhcnRlZAorPT09PT09PT09PT09PT09CisK K0luc3RhbGxpbmcgZGVwZW5kZW5jaWVzCis9PT09PT09PT09PT09PT09PT09PT09PQorS1VuaXQg aGFzIHRoZSBzYW1lIGRlcGVuZGVuY2llcyBhcyB0aGUgTGludXgga2VybmVsLiBBcyBsb25nIGFz IHlvdSBjYW4gYnVpbGQKK3RoZSBrZXJuZWwsIHlvdSBjYW4gcnVuIEtVbml0LgorCitLVW5pdCBX cmFwcGVyCis9PT09PT09PT09PT09CitJbmNsdWRlZCB3aXRoIEtVbml0IGlzIGEgc2ltcGxlIFB5 dGhvbiB3cmFwcGVyIHRoYXQgaGVscHMgZm9ybWF0IHRoZSBvdXRwdXQgdG8KK2Vhc2lseSB1c2Ug YW5kIHJlYWQgS1VuaXQgb3V0cHV0LiBJdCBoYW5kbGVzIGJ1aWxkaW5nIGFuZCBydW5uaW5nIHRo ZSBrZXJuZWwsIGFzCit3ZWxsIGFzIGZvcm1hdHRpbmcgdGhlIG91dHB1dC4KKworVGhlIHdyYXBw ZXIgY2FuIGJlIHJ1biB3aXRoOgorCisuLiBjb2RlLWJsb2NrOjogYmFzaAorCisgICAuL3Rvb2xz L3Rlc3Rpbmcva3VuaXQva3VuaXQucHkgcnVuCisKK0NyZWF0aW5nIGEga3VuaXRjb25maWcKKz09 PT09PT09PT09PT09PT09PT09PT0KK1RoZSBQeXRob24gc2NyaXB0IGlzIGEgdGhpbiB3cmFwcGVy IGFyb3VuZCBLYnVpbGQgYXMgc3VjaCwgaXQgbmVlZHMgdG8gYmUKK2NvbmZpZ3VyZWQgd2l0aCBh IGBga3VuaXRjb25maWdgYCBmaWxlLiBUaGlzIGZpbGUgZXNzZW50aWFsbHkgY29udGFpbnMgdGhl CityZWd1bGFyIEtlcm5lbCBjb25maWcsIHdpdGggdGhlIHNwZWNpZmljIHRlc3QgdGFyZ2V0cyBh cyB3ZWxsLgorCisuLiBjb2RlLWJsb2NrOjogYmFzaAorCisJZ2l0IGNsb25lIC1iIG1hc3RlciBo dHRwczovL2t1bml0Lmdvb2dsZXNvdXJjZS5jb20va3VuaXRjb25maWcgJFBBVEhfVE9fS1VOSVRD T05GSUdfUkVQTworCWNkICRQQVRIX1RPX0xJTlVYX1JFUE8KKwlsbiAtcyAkUEFUSF9UT19LVU5J VF9DT05GSUdfUkVQTy9rdW5pdGNvbmZpZyBrdW5pdGNvbmZpZworCitZb3UgbWF5IHdhbnQgdG8g YWRkIGt1bml0Y29uZmlnIHRvIHlvdXIgbG9jYWwgZ2l0aWdub3JlLgorCitWZXJpZnlpbmcgS1Vu aXQgV29ya3MKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitUbyBtYWtlIHN1cmUgdGhhdCBldmVy eXRoaW5nIGlzIHNldCB1cCBjb3JyZWN0bHksIHNpbXBseSBpbnZva2UgdGhlIFB5dGhvbgord3Jh cHBlciBmcm9tIHlvdXIga2VybmVsIHJlcG86CisKKy4uIGNvZGUtYmxvY2s6OiBiYXNoCisKKwku L3Rvb2xzL3Rlc3Rpbmcva3VuaXQva3VuaXQucHkKKworLi4gbm90ZTo6CisgICBZb3UgbWF5IHdh bnQgdG8gcnVuIGBgbWFrZSBtcnByb3BlcmBgIGZpcnN0LgorCitJZiBldmVyeXRoaW5nIHdvcmtl ZCBjb3JyZWN0bHksIHlvdSBzaG91bGQgc2VlIHRoZSBmb2xsb3dpbmc6CisKKy4uIGNvZGUtYmxv Y2s6OiBiYXNoCisKKwlHZW5lcmF0aW5nIC5jb25maWcgLi4uCisJQnVpbGRpbmcgS1VuaXQgS2Vy bmVsIC4uLgorCVN0YXJ0aW5nIEtVbml0IEtlcm5lbCAuLi4KKworZm9sbG93ZWQgYnkgYSBsaXN0 IG9mIHRlc3RzIHRoYXQgYXJlIHJ1bi4gQWxsIG9mIHRoZW0gc2hvdWxkIGJlIHBhc3NpbmcuCisK Ky4uIG5vdGU6OgorICAgQmVjYXVzZSBpdCBpcyBidWlsZGluZyBhIGxvdCBvZiBzb3VyY2VzIGZv ciB0aGUgZmlyc3QgdGltZSwgdGhlIGBgQnVpbGRpbmcKKyAgIGt1bml0IGtlcm5lbGBgIHN0ZXAg bWF5IHRha2UgYSB3aGlsZS4KKworV3JpdGluZyB5b3VyIGZpcnN0IHRlc3QKKz09PT09PT09PT09 PT09PT09PT09PT09CisKK0luIHlvdXIga2VybmVsIHJlcG8gbGV0J3MgYWRkIHNvbWUgY29kZSB0 aGF0IHdlIGNhbiB0ZXN0LiBDcmVhdGUgYSBmaWxlCitgYGRyaXZlcnMvbWlzYy9leGFtcGxlLmhg YCB3aXRoIHRoZSBjb250ZW50czoKKworLi4gY29kZS1ibG9jazo6IGMKKworCWludCBtaXNjX2V4 YW1wbGVfYWRkKGludCBsZWZ0LCBpbnQgcmlnaHQpOworCitjcmVhdGUgYSBmaWxlIGBgZHJpdmVy cy9taXNjL2V4YW1wbGUuY2BgOgorCisuLiBjb2RlLWJsb2NrOjogYworCisJI2luY2x1ZGUgPGxp bnV4L2Vycm5vLmg+CisKKwkjaW5jbHVkZSAiZXhhbXBsZS5oIgorCisJaW50IG1pc2NfZXhhbXBs ZV9hZGQoaW50IGxlZnQsIGludCByaWdodCkKKwl7CisJCXJldHVybiBsZWZ0ICsgcmlnaHQ7CisJ fQorCitOb3cgYWRkIHRoZSBmb2xsb3dpbmcgbGluZXMgdG8gYGBkcml2ZXJzL21pc2MvS2NvbmZp Z2BgOgorCisuLiBjb2RlLWJsb2NrOjoga2NvbmZpZworCisJY29uZmlnIE1JU0NfRVhBTVBMRQor CQlib29sICJNeSBleGFtcGxlIgorCithbmQgdGhlIGZvbGxvd2luZyBsaW5lcyB0byBgYGRyaXZl cnMvbWlzYy9NYWtlZmlsZWBgOgorCisuLiBjb2RlLWJsb2NrOjogbWFrZQorCisJb2JqLSQoQ09O RklHX01JU0NfRVhBTVBMRSkgKz0gZXhhbXBsZS5vCisKK05vdyB3ZSBhcmUgcmVhZHkgdG8gd3Jp dGUgdGhlIHRlc3QuIFRoZSB0ZXN0IHdpbGwgYmUgaW4KK2BgZHJpdmVycy9taXNjL2V4YW1wbGUt dGVzdC5jYGA6CisKKy4uIGNvZGUtYmxvY2s6OiBjCisKKwkjaW5jbHVkZSA8a3VuaXQvdGVzdC5o PgorCSNpbmNsdWRlICJleGFtcGxlLmgiCisKKwkvKiBEZWZpbmUgdGhlIHRlc3QgY2FzZXMuICov CisKKwlzdGF0aWMgdm9pZCBtaXNjX2V4YW1wbGVfYWRkX3Rlc3RfYmFzaWMoc3RydWN0IGt1bml0 ICp0ZXN0KQorCXsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIDEsIG1pc2NfZXhhbXBsZV9hZGQo MSwgMCkpOworCQlLVU5JVF9FWFBFQ1RfRVEodGVzdCwgMiwgbWlzY19leGFtcGxlX2FkZCgxLCAx KSk7CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0LCAwLCBtaXNjX2V4YW1wbGVfYWRkKC0xLCAxKSk7 CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0LCBJTlRfTUFYLCBtaXNjX2V4YW1wbGVfYWRkKDAsIElO VF9NQVgpKTsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIC0xLCBtaXNjX2V4YW1wbGVfYWRkKElO VF9NQVgsIElOVF9NSU4pKTsKKwl9CisKKwlzdGF0aWMgdm9pZCBtaXNjX2V4YW1wbGVfdGVzdF9m YWlsdXJlKHN0cnVjdCBrdW5pdCAqdGVzdCkKKwl7CisJCUtVTklUX0ZBSUwodGVzdCwgIlRoaXMg dGVzdCBuZXZlciBwYXNzZXMuIik7CisJfQorCisJc3RhdGljIHN0cnVjdCBrdW5pdF9jYXNlIG1p c2NfZXhhbXBsZV90ZXN0X2Nhc2VzW10gPSB7CisJCUtVTklUX0NBU0UobWlzY19leGFtcGxlX2Fk ZF90ZXN0X2Jhc2ljKSwKKwkJS1VOSVRfQ0FTRShtaXNjX2V4YW1wbGVfdGVzdF9mYWlsdXJlKSwK KwkJe30KKwl9OworCisJc3RhdGljIHN0cnVjdCBrdW5pdF9zdWl0ZSBtaXNjX2V4YW1wbGVfdGVz dF9zdWl0ZSA9IHsKKwkJLm5hbWUgPSAibWlzYy1leGFtcGxlIiwKKwkJLnRlc3RfY2FzZXMgPSBt aXNjX2V4YW1wbGVfdGVzdF9jYXNlcywKKwl9OworCWt1bml0X3Rlc3Rfc3VpdGUobWlzY19leGFt cGxlX3Rlc3Rfc3VpdGUpOworCitOb3cgYWRkIHRoZSBmb2xsb3dpbmcgdG8gYGBkcml2ZXJzL21p c2MvS2NvbmZpZ2BgOgorCisuLiBjb2RlLWJsb2NrOjoga2NvbmZpZworCisJY29uZmlnIE1JU0Nf RVhBTVBMRV9URVNUCisJCWJvb2wgIlRlc3QgZm9yIG15IGV4YW1wbGUiCisJCWRlcGVuZHMgb24g TUlTQ19FWEFNUExFICYmIEtVTklUCisKK2FuZCB0aGUgZm9sbG93aW5nIHRvIGBgZHJpdmVycy9t aXNjL01ha2VmaWxlYGA6CisKKy4uIGNvZGUtYmxvY2s6OiBtYWtlCisKKwlvYmotJChDT05GSUdf TUlTQ19FWEFNUExFX1RFU1QpICs9IGV4YW1wbGUtdGVzdC5vCisKK05vdyBhZGQgaXQgdG8geW91 ciBgYGt1bml0Y29uZmlnYGA6CisKKy4uIGNvZGUtYmxvY2s6OiBub25lCisKKwlDT05GSUdfTUlT Q19FWEFNUExFPXkKKwlDT05GSUdfTUlTQ19FWEFNUExFX1RFU1Q9eQorCitOb3cgeW91IGNhbiBy dW4gdGhlIHRlc3Q6CisKKy4uIGNvZGUtYmxvY2s6OiBiYXNoCisKKwkuL3Rvb2xzL3Rlc3Rpbmcv a3VuaXQva3VuaXQucHkKKworWW91IHNob3VsZCBzZWUgdGhlIGZvbGxvd2luZyBmYWlsdXJlOgor CisuLiBjb2RlLWJsb2NrOjogbm9uZQorCisJLi4uCisJWzE2OjA4OjU3XSBbUEFTU0VEXSBtaXNj LWV4YW1wbGU6bWlzY19leGFtcGxlX2FkZF90ZXN0X2Jhc2ljCisJWzE2OjA4OjU3XSBbRkFJTEVE XSBtaXNjLWV4YW1wbGU6bWlzY19leGFtcGxlX3Rlc3RfZmFpbHVyZQorCVsxNjowODo1N10gRVhQ RUNUQVRJT04gRkFJTEVEIGF0IGRyaXZlcnMvbWlzYy9leGFtcGxlLXRlc3QuYzoxNworCVsxNjow ODo1N10gCVRoaXMgdGVzdCBuZXZlciBwYXNzZXMuCisJLi4uCisKK0NvbmdyYXRzISBZb3UganVz dCB3cm90ZSB5b3VyIGZpcnN0IEtVbml0IHRlc3QhCisKK05leHQgU3RlcHMKKz09PT09PT09PT0K KyogICBDaGVjayBvdXQgdGhlIDpkb2M6YHVzYWdlYCBwYWdlIGZvciBhIG1vcmUKKyAgICBpbi1k ZXB0aCBleHBsYW5hdGlvbiBvZiBLVW5pdC4KZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2 LXRvb2xzL2t1bml0L3VzYWdlLnJzdCBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L3Vz YWdlLnJzdApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLmM2ZTY5NjM0 ZTI3NAotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vZGV2LXRvb2xzL2t1bml0L3Vz YWdlLnJzdApAQCAtMCwwICsxLDU3NiBAQAorLi4gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjAKKworPT09PT09PT09PT0KK1VzaW5nIEtVbml0Cis9PT09PT09PT09PQorCitUaGUgcHVy cG9zZSBvZiB0aGlzIGRvY3VtZW50IGlzIHRvIGRlc2NyaWJlIHdoYXQgS1VuaXQgaXMsIGhvdyBp dCB3b3JrcywgaG93IGl0CitpcyBpbnRlbmRlZCB0byBiZSB1c2VkLCBhbmQgYWxsIHRoZSBjb25j ZXB0cyBhbmQgdGVybWlub2xvZ3kgdGhhdCBhcmUgbmVlZGVkIHRvCit1bmRlcnN0YW5kIGl0LiBU aGlzIGd1aWRlIGFzc3VtZXMgYSB3b3JraW5nIGtub3dsZWRnZSBvZiB0aGUgTGludXgga2VybmVs IGFuZAorc29tZSBiYXNpYyBrbm93bGVkZ2Ugb2YgdGVzdGluZy4KKworRm9yIGEgaGlnaCBsZXZl bCBpbnRyb2R1Y3Rpb24gdG8gS1VuaXQsIGluY2x1ZGluZyBzZXR0aW5nIHVwIEtVbml0IGZvciB5 b3VyCitwcm9qZWN0LCBzZWUgOmRvYzpgc3RhcnRgLgorCitPcmdhbml6YXRpb24gb2YgdGhpcyBk b2N1bWVudAorPT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KKworVGhpcyBkb2N1bWVudCBp cyBvcmdhbml6ZWQgaW50byB0d28gbWFpbiBzZWN0aW9uczogVGVzdGluZyBhbmQgSXNvbGF0aW5n CitCZWhhdmlvci4gVGhlIGZpcnN0IGNvdmVycyB3aGF0IGEgdW5pdCB0ZXN0IGlzIGFuZCBob3cg dG8gdXNlIEtVbml0IHRvIHdyaXRlCit0aGVtLiBUaGUgc2Vjb25kIGNvdmVycyBob3cgdG8gdXNl IEtVbml0IHRvIGlzb2xhdGUgY29kZSBhbmQgbWFrZSBpdCBwb3NzaWJsZQordG8gdW5pdCB0ZXN0 IGNvZGUgdGhhdCB3YXMgb3RoZXJ3aXNlIHVuLXVuaXQtdGVzdGFibGUuCisKK1Rlc3RpbmcKKz09 PT09PT0KKworV2hhdCBpcyBLVW5pdD8KKy0tLS0tLS0tLS0tLS0tCisKKyJLIiBpcyBzaG9ydCBm b3IgImtlcm5lbCIgc28gIktVbml0IiBpcyB0aGUgIihMaW51eCkgS2VybmVsIFVuaXQgVGVzdGlu ZworRnJhbWV3b3JrLiIgS1VuaXQgaXMgaW50ZW5kZWQgZmlyc3QgYW5kIGZvcmVtb3N0IGZvciB3 cml0aW5nIHVuaXQgdGVzdHM7IGl0IGlzCitnZW5lcmFsIGVub3VnaCB0aGF0IGl0IGNhbiBiZSB1 c2VkIHRvIHdyaXRlIGludGVncmF0aW9uIHRlc3RzOyBob3dldmVyLCB0aGlzIGlzCithIHNlY29u ZGFyeSBnb2FsLiBLVW5pdCBoYXMgbm8gYW1iaXRpb24gb2YgYmVpbmcgdGhlIG9ubHkgdGVzdGlu ZyBmcmFtZXdvcmsgZm9yCit0aGUga2VybmVsOyBmb3IgZXhhbXBsZSwgaXQgZG9lcyBub3QgaW50 ZW5kIHRvIGJlIGFuIGVuZC10by1lbmQgdGVzdGluZworZnJhbWV3b3JrLgorCitXaGF0IGlzIFVu aXQgVGVzdGluZz8KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitBIGB1bml0IHRlc3QgPGh0dHBz Oi8vbWFydGluZm93bGVyLmNvbS9ibGlraS9Vbml0VGVzdC5odG1sPmBfIGlzIGEgdGVzdCB0aGF0 Cit0ZXN0cyBjb2RlIGF0IHRoZSBzbWFsbGVzdCBwb3NzaWJsZSBzY29wZSwgYSAqdW5pdCogb2Yg Y29kZS4gSW4gdGhlIEMKK3Byb2dyYW1taW5nIGxhbmd1YWdlIHRoYXQncyBhIGZ1bmN0aW9uLgor CitVbml0IHRlc3RzIHNob3VsZCBiZSB3cml0dGVuIGZvciBhbGwgdGhlIHB1YmxpY2x5IGV4cG9z ZWQgZnVuY3Rpb25zIGluIGEKK2NvbXBpbGF0aW9uIHVuaXQ7IHNvIHRoYXQgaXMgYWxsIHRoZSBm dW5jdGlvbnMgdGhhdCBhcmUgZXhwb3J0ZWQgaW4gZWl0aGVyIGEKKypjbGFzcyogKGRlZmluZWQg YmVsb3cpIG9yIGFsbCBmdW5jdGlvbnMgd2hpY2ggYXJlICoqbm90Kiogc3RhdGljLgorCitXcml0 aW5nIFRlc3RzCistLS0tLS0tLS0tLS0tCisKK1Rlc3QgQ2FzZXMKK35+fn5+fn5+fn4KKworVGhl IGZ1bmRhbWVudGFsIHVuaXQgaW4gS1VuaXQgaXMgdGhlIHRlc3QgY2FzZS4gQSB0ZXN0IGNhc2Ug aXMgYSBmdW5jdGlvbiB3aXRoCit0aGUgc2lnbmF0dXJlIGBgdm9pZCAoKikoc3RydWN0IGt1bml0 ICp0ZXN0KWBgLiBJdCBjYWxscyBhIGZ1bmN0aW9uIHRvIGJlIHRlc3RlZAorYW5kIHRoZW4gc2V0 cyAqZXhwZWN0YXRpb25zKiBmb3Igd2hhdCBzaG91bGQgaGFwcGVuLiBGb3IgZXhhbXBsZToKKwor Li4gY29kZS1ibG9jazo6IGMKKworCXZvaWQgZXhhbXBsZV90ZXN0X3N1Y2Nlc3Moc3RydWN0IGt1 bml0ICp0ZXN0KQorCXsKKwl9CisKKwl2b2lkIGV4YW1wbGVfdGVzdF9mYWlsdXJlKHN0cnVjdCBr dW5pdCAqdGVzdCkKKwl7CisJCUtVTklUX0ZBSUwodGVzdCwgIlRoaXMgdGVzdCBuZXZlciBwYXNz ZXMuIik7CisJfQorCitJbiB0aGUgYWJvdmUgZXhhbXBsZSBgYGV4YW1wbGVfdGVzdF9zdWNjZXNz YGAgYWx3YXlzIHBhc3NlcyBiZWNhdXNlIGl0IGRvZXMKK25vdGhpbmc7IG5vIGV4cGVjdGF0aW9u cyBhcmUgc2V0LCBzbyBhbGwgZXhwZWN0YXRpb25zIHBhc3MuIE9uIHRoZSBvdGhlciBoYW5kCitg YGV4YW1wbGVfdGVzdF9mYWlsdXJlYGAgYWx3YXlzIGZhaWxzIGJlY2F1c2UgaXQgY2FsbHMgYGBL VU5JVF9GQUlMYGAsIHdoaWNoIGlzCithIHNwZWNpYWwgZXhwZWN0YXRpb24gdGhhdCBsb2dzIGEg bWVzc2FnZSBhbmQgY2F1c2VzIHRoZSB0ZXN0IGNhc2UgdG8gZmFpbC4KKworRXhwZWN0YXRpb25z Cit+fn5+fn5+fn5+fn4KK0FuICpleHBlY3RhdGlvbiogaXMgYSB3YXkgdG8gc3BlY2lmeSB0aGF0 IHlvdSBleHBlY3QgYSBwaWVjZSBvZiBjb2RlIHRvIGRvCitzb21ldGhpbmcgaW4gYSB0ZXN0LiBB biBleHBlY3RhdGlvbiBpcyBjYWxsZWQgbGlrZSBhIGZ1bmN0aW9uLiBBIHRlc3QgaXMgbWFkZQor Ynkgc2V0dGluZyBleHBlY3RhdGlvbnMgYWJvdXQgdGhlIGJlaGF2aW9yIG9mIGEgcGllY2Ugb2Yg Y29kZSB1bmRlciB0ZXN0OyB3aGVuCitvbmUgb3IgbW9yZSBvZiB0aGUgZXhwZWN0YXRpb25zIGZh aWwsIHRoZSB0ZXN0IGNhc2UgZmFpbHMgYW5kIGluZm9ybWF0aW9uIGFib3V0Cit0aGUgZmFpbHVy ZSBpcyBsb2dnZWQuIEZvciBleGFtcGxlOgorCisuLiBjb2RlLWJsb2NrOjogYworCisJdm9pZCBh ZGRfdGVzdF9iYXNpYyhzdHJ1Y3Qga3VuaXQgKnRlc3QpCisJeworCQlLVU5JVF9FWFBFQ1RfRVEo dGVzdCwgMSwgYWRkKDEsIDApKTsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIDIsIGFkZCgxLCAx KSk7CisJfQorCitJbiB0aGUgYWJvdmUgZXhhbXBsZSBgYGFkZF90ZXN0X2Jhc2ljYGAgbWFrZXMg YSBudW1iZXIgb2YgYXNzZXJ0aW9ucyBhYm91dCB0aGUKK2JlaGF2aW9yIG9mIGEgZnVuY3Rpb24g Y2FsbGVkIGBgYWRkYGA7IHRoZSBmaXJzdCBwYXJhbWV0ZXIgaXMgYWx3YXlzIG9mIHR5cGUKK2Bg c3RydWN0IGt1bml0ICpgYCwgd2hpY2ggY29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGN1 cnJlbnQgdGVzdCBjb250ZXh0OwordGhlIHNlY29uZCBwYXJhbWV0ZXIsIGluIHRoaXMgY2FzZSwg aXMgd2hhdCB0aGUgdmFsdWUgaXMgZXhwZWN0ZWQgdG8gYmU7IHRoZQorbGFzdCB2YWx1ZSBpcyB3 aGF0IHRoZSB2YWx1ZSBhY3R1YWxseSBpcy4gSWYgYGBhZGRgYCBwYXNzZXMgYWxsIG9mIHRoZXNl CitleHBlY3RhdGlvbnMsIHRoZSB0ZXN0IGNhc2UsIGBgYWRkX3Rlc3RfYmFzaWNgYCB3aWxsIHBh c3M7IGlmIGFueSBvbmUgb2YgdGhlc2UKK2V4cGVjdGF0aW9ucyBmYWlsLCB0aGUgdGVzdCBjYXNl IHdpbGwgZmFpbC4KKworSXQgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgdGhhdCBhIHRlc3Qg Y2FzZSAqZmFpbHMqIHdoZW4gYW55IGV4cGVjdGF0aW9uIGlzCit2aW9sYXRlZDsgaG93ZXZlciwg dGhlIHRlc3Qgd2lsbCBjb250aW51ZSBydW5uaW5nLCBwb3RlbnRpYWxseSB0cnlpbmcgb3RoZXIK K2V4cGVjdGF0aW9ucyB1bnRpbCB0aGUgdGVzdCBjYXNlIGVuZHMgb3IgaXMgb3RoZXJ3aXNlIHRl cm1pbmF0ZWQuIFRoaXMgaXMgYXMKK29wcG9zZWQgdG8gKmFzc2VydGlvbnMqIHdoaWNoIGFyZSBk aXNjdXNzZWQgbGF0ZXIuCisKK1RvIGxlYXJuIGFib3V0IG1vcmUgZXhwZWN0YXRpb25zIHN1cHBv cnRlZCBieSBLVW5pdCwgc2VlIDpkb2M6YGFwaS90ZXN0YC4KKworLi4gbm90ZTo6CisgICBBIHNp bmdsZSB0ZXN0IGNhc2Ugc2hvdWxkIGJlIHByZXR0eSBzaG9ydCwgcHJldHR5IGVhc3kgdG8gdW5k ZXJzdGFuZCwKKyAgIGZvY3VzZWQgb24gYSBzaW5nbGUgYmVoYXZpb3IuCisKK0ZvciBleGFtcGxl LCBpZiB3ZSB3YW50ZWQgdG8gcHJvcGVybHkgdGVzdCB0aGUgYWRkIGZ1bmN0aW9uIGFib3ZlLCB3 ZSB3b3VsZAorY3JlYXRlIGFkZGl0aW9uYWwgdGVzdHMgY2FzZXMgd2hpY2ggd291bGQgZWFjaCB0 ZXN0IGEgZGlmZmVyZW50IHByb3BlcnR5IHRoYXQgYW4KK2FkZCBmdW5jdGlvbiBzaG91bGQgaGF2 ZSBsaWtlIHRoaXM6CisKKy4uIGNvZGUtYmxvY2s6OiBjCisKKwl2b2lkIGFkZF90ZXN0X2Jhc2lj KHN0cnVjdCBrdW5pdCAqdGVzdCkKKwl7CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0LCAxLCBhZGQo MSwgMCkpOworCQlLVU5JVF9FWFBFQ1RfRVEodGVzdCwgMiwgYWRkKDEsIDEpKTsKKwl9CisKKwl2 b2lkIGFkZF90ZXN0X25lZ2F0aXZlKHN0cnVjdCBrdW5pdCAqdGVzdCkKKwl7CisJCUtVTklUX0VY UEVDVF9FUSh0ZXN0LCAwLCBhZGQoLTEsIDEpKTsKKwl9CisKKwl2b2lkIGFkZF90ZXN0X21heChz dHJ1Y3Qga3VuaXQgKnRlc3QpCisJeworCQlLVU5JVF9FWFBFQ1RfRVEodGVzdCwgSU5UX01BWCwg YWRkKDAsIElOVF9NQVgpKTsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIC0xLCBhZGQoSU5UX01B WCwgSU5UX01JTikpOworCX0KKworCXZvaWQgYWRkX3Rlc3Rfb3ZlcmZsb3coc3RydWN0IGt1bml0 ICp0ZXN0KQorCXsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIElOVF9NSU4sIGFkZChJTlRfTUFY LCAxKSk7CisJfQorCitOb3RpY2UgaG93IGl0IGlzIGltbWVkaWF0ZWx5IG9idmlvdXMgd2hhdCBh bGwgdGhlIHByb3BlcnRpZXMgdGhhdCB3ZSBhcmUgdGVzdGluZworZm9yIGFyZS4KKworQXNzZXJ0 aW9ucworfn5+fn5+fn5+fgorCitLVW5pdCBhbHNvIGhhcyB0aGUgY29uY2VwdCBvZiBhbiAqYXNz ZXJ0aW9uKi4gQW4gYXNzZXJ0aW9uIGlzIGp1c3QgbGlrZSBhbgorZXhwZWN0YXRpb24gZXhjZXB0 IHRoZSBhc3NlcnRpb24gaW1tZWRpYXRlbHkgdGVybWluYXRlcyB0aGUgdGVzdCBjYXNlIGlmIGl0 IGlzCitub3Qgc2F0aXNmaWVkLgorCitGb3IgZXhhbXBsZToKKworLi4gY29kZS1ibG9jazo6IGMK KworCXN0YXRpYyB2b2lkIG1vY2tfdGVzdF9kb19leHBlY3RfZGVmYXVsdF9yZXR1cm4oc3RydWN0 IGt1bml0ICp0ZXN0KQorCXsKKwkJc3RydWN0IG1vY2tfdGVzdF9jb250ZXh0ICpjdHggPSB0ZXN0 LT5wcml2OworCQlzdHJ1Y3QgbW9jayAqbW9jayA9IGN0eC0+bW9jazsKKwkJaW50IHBhcmFtMCA9 IDUsIHBhcmFtMSA9IC01OworCQljb25zdCBjaGFyICp0d29fcGFyYW1fdHlwZXNbXSA9IHsiaW50 IiwgImludCJ9OworCQljb25zdCB2b2lkICp0d29fcGFyYW1zW10gPSB7JnBhcmFtMCwgJnBhcmFt MX07CisJCWNvbnN0IHZvaWQgKnJldDsKKworCQlyZXQgPSBtb2NrLT5kb19leHBlY3QobW9jaywK KwkJCQkgICAgICAidGVzdF9wcmludGsiLCB0ZXN0X3ByaW50aywKKwkJCQkgICAgICB0d29fcGFy YW1fdHlwZXMsIHR3b19wYXJhbXMsCisJCQkJICAgICAgQVJSQVlfU0laRSh0d29fcGFyYW1zKSk7 CisJCUtVTklUX0FTU0VSVF9OT1RfRVJSX09SX05VTEwodGVzdCwgcmV0KTsKKwkJS1VOSVRfRVhQ RUNUX0VRKHRlc3QsIC00LCAqKChpbnQgKikgcmV0KSk7CisJfQorCitJbiB0aGlzIGV4YW1wbGUs IHRoZSBtZXRob2QgdW5kZXIgdGVzdCBzaG91bGQgcmV0dXJuIGEgcG9pbnRlciB0byBhIHZhbHVl LCBzbworaWYgdGhlIHBvaW50ZXIgcmV0dXJuZWQgYnkgdGhlIG1ldGhvZCBpcyBudWxsIG9yIGFu IGVycm5vLCB3ZSBkb24ndCB3YW50IHRvCitib3RoZXIgY29udGludWluZyB0aGUgdGVzdCBzaW5j ZSB0aGUgZm9sbG93aW5nIGV4cGVjdGF0aW9uIGNvdWxkIGNyYXNoIHRoZSB0ZXN0CitjYXNlLiBg QVNTRVJUX05PVF9FUlJfT1JfTlVMTCguLi4pYCBhbGxvd3MgdXMgdG8gYmFpbCBvdXQgb2YgdGhl IHRlc3QgY2FzZSBpZgordGhlIGFwcHJvcHJpYXRlIGNvbmRpdGlvbnMgaGF2ZSBub3QgYmVlbiBz YXRpc2ZpZWQgdG8gY29tcGxldGUgdGhlIHRlc3QuCisKK1Rlc3QgU3VpdGVzCit+fn5+fn5+fn5+ fgorCitOb3cgb2J2aW91c2x5IG9uZSB1bml0IHRlc3QgaXNuJ3QgdmVyeSBoZWxwZnVsOyB0aGUg cG93ZXIgY29tZXMgZnJvbSBoYXZpbmcKK21hbnkgdGVzdCBjYXNlcyBjb3ZlcmluZyBhbGwgb2Yg eW91ciBiZWhhdmlvcnMuIENvbnNlcXVlbnRseSBpdCBpcyBjb21tb24gdG8KK2hhdmUgbWFueSAq c2ltaWxhciogdGVzdHM7IGluIG9yZGVyIHRvIHJlZHVjZSBkdXBsaWNhdGlvbiBpbiB0aGVzZSBj bG9zZWx5CityZWxhdGVkIHRlc3RzIG1vc3QgdW5pdCB0ZXN0aW5nIGZyYW1ld29ya3MgcHJvdmlk ZSB0aGUgY29uY2VwdCBvZiBhICp0ZXN0CitzdWl0ZSosIGluIEtVbml0IHdlIGNhbGwgaXQgYSAq dGVzdCBzdWl0ZSo7IGFsbCBpdCBpcyBpcyBqdXN0IGEgY29sbGVjdGlvbiBvZgordGVzdCBjYXNl cyBmb3IgYSB1bml0IG9mIGNvZGUgd2l0aCBhIHNldCB1cCBmdW5jdGlvbiB0aGF0IGdldHMgaW52 b2tlZCBiZWZvcmUKK2V2ZXJ5IHRlc3QgY2FzZXMgYW5kIHRoZW4gYSB0ZWFyIGRvd24gZnVuY3Rp b24gdGhhdCBnZXRzIGludm9rZWQgYWZ0ZXIgZXZlcnkKK3Rlc3QgY2FzZSBjb21wbGV0ZXMuCisK K0V4YW1wbGU6CisKKy4uIGNvZGUtYmxvY2s6OiBjCisKKwlzdGF0aWMgc3RydWN0IGt1bml0X2Nh c2UgZXhhbXBsZV90ZXN0X2Nhc2VzW10gPSB7CisJCUtVTklUX0NBU0UoZXhhbXBsZV90ZXN0X2Zv byksCisJCUtVTklUX0NBU0UoZXhhbXBsZV90ZXN0X2JhciksCisJCUtVTklUX0NBU0UoZXhhbXBs ZV90ZXN0X2JheiksCisJCXt9CisJfTsKKworCXN0YXRpYyBzdHJ1Y3Qga3VuaXRfc3VpdGUgZXhh bXBsZV90ZXN0X3N1aXRlID0geworCQkubmFtZSA9ICJleGFtcGxlIiwKKwkJLmluaXQgPSBleGFt cGxlX3Rlc3RfaW5pdCwKKwkJLmV4aXQgPSBleGFtcGxlX3Rlc3RfZXhpdCwKKwkJLnRlc3RfY2Fz ZXMgPSBleGFtcGxlX3Rlc3RfY2FzZXMsCisJfTsKKwlrdW5pdF90ZXN0X3N1aXRlKGV4YW1wbGVf dGVzdF9zdWl0ZSk7CisKK0luIHRoZSBhYm92ZSBleGFtcGxlIHRoZSB0ZXN0IHN1aXRlLCBgYGV4 YW1wbGVfdGVzdF9zdWl0ZWBgLCB3b3VsZCBydW4gdGhlIHRlc3QKK2Nhc2VzIGBgZXhhbXBsZV90 ZXN0X2Zvb2BgLCBgYGV4YW1wbGVfdGVzdF9iYXJgYCwgYW5kIGBgZXhhbXBsZV90ZXN0X2JhemBg LAorZWFjaCB3b3VsZCBoYXZlIGBgZXhhbXBsZV90ZXN0X2luaXRgYCBjYWxsZWQgaW1tZWRpYXRl bHkgYmVmb3JlIGl0IGFuZCB3b3VsZAoraGF2ZSBgYGV4YW1wbGVfdGVzdF9leGl0YGAgY2FsbGVk IGltbWVkaWF0ZWx5IGFmdGVyIGl0LgorYGBrdW5pdF90ZXN0X3N1aXRlKGV4YW1wbGVfdGVzdF9z dWl0ZSlgYCByZWdpc3RlcnMgdGhlIHRlc3Qgc3VpdGUgd2l0aCB0aGUKK0tVbml0IHRlc3QgZnJh bWV3b3JrLgorCisuLiBub3RlOjoKKyAgIEEgdGVzdCBjYXNlIHdpbGwgb25seSBiZSBydW4gaWYg aXQgaXMgYXNzb2NpYXRlZCB3aXRoIGEgdGVzdCBzdWl0ZS4KKworRm9yIGEgbW9yZSBpbmZvcm1h dGlvbiBvbiB0aGVzZSB0eXBlcyBvZiB0aGluZ3Mgc2VlIHRoZSA6ZG9jOmBhcGkvdGVzdGAuCisK K0lzb2xhdGluZyBCZWhhdmlvcgorPT09PT09PT09PT09PT09PT09CisKK1RoZSBtb3N0IGltcG9y dGFudCBhc3BlY3Qgb2YgdW5pdCB0ZXN0aW5nIHRoYXQgb3RoZXIgZm9ybXMgb2YgdGVzdGluZyBk byBub3QKK3Byb3ZpZGUgaXMgdGhlIGFiaWxpdHkgdG8gbGltaXQgdGhlIGFtb3VudCBvZiBjb2Rl IHVuZGVyIHRlc3QgdG8gYSBzaW5nbGUgdW5pdC4KK0luIHByYWN0aWNlLCB0aGlzIGlzIG9ubHkg cG9zc2libGUgYnkgYmVpbmcgYWJsZSB0byBjb250cm9sIHdoYXQgY29kZSBnZXRzIHJ1bgord2hl biB0aGUgdW5pdCB1bmRlciB0ZXN0IGNhbGxzIGEgZnVuY3Rpb24gYW5kIHRoaXMgaXMgdXN1YWxs eSBhY2NvbXBsaXNoZWQKK3Rocm91Z2ggc29tZSBzb3J0IG9mIGluZGlyZWN0aW9uIHdoZXJlIGEg ZnVuY3Rpb24gaXMgZXhwb3NlZCBhcyBwYXJ0IG9mIGFuIEFQSQorc3VjaCB0aGF0IHRoZSBkZWZp bml0aW9uIG9mIHRoYXQgZnVuY3Rpb24gY2FuIGJlIGNoYW5nZWQgd2l0aG91dCBhZmZlY3Rpbmcg dGhlCityZXN0IG9mIHRoZSBjb2RlIGJhc2UuIEluIHRoZSBrZXJuZWwgdGhpcyBwcmltYXJpbHkg Y29tZXMgZnJvbSB0d28gY29uc3RydWN0cywKK2NsYXNzZXMsIHN0cnVjdHMgdGhhdCBjb250YWlu IGZ1bmN0aW9uIHBvaW50ZXJzIHRoYXQgYXJlIHByb3ZpZGVkIGJ5IHRoZQoraW1wbGVtZW50ZXIs IGFuZCBhcmNoaXRlY3R1cmUgc3BlY2lmaWMgZnVuY3Rpb25zIHdoaWNoIGhhdmUgZGVmaW5pdGlv bnMgc2VsZWN0ZWQKK2F0IGNvbXBpbGUgdGltZS4KKworQ2xhc3NlcworLS0tLS0tLQorCitDbGFz c2VzIGFyZSBub3QgYSBjb25zdHJ1Y3QgdGhhdCBpcyBidWlsdCBpbnRvIHRoZSBDIHByb2dyYW1t aW5nIGxhbmd1YWdlOworaG93ZXZlciwgaXQgaXMgYW4gZWFzaWx5IGRlcml2ZWQgY29uY2VwdC4g QWNjb3JkaW5nbHksIHByZXR0eSBtdWNoIGV2ZXJ5IHByb2plY3QKK3RoYXQgZG9lcyBub3QgdXNl IGEgc3RhbmRhcmRpemVkIG9iamVjdCBvcmllbnRlZCBsaWJyYXJ5IChsaWtlIEdOT01FJ3MgR09i amVjdCkKK2hhcyB0aGVpciBvd24gc2xpZ2h0bHkgZGlmZmVyZW50IHdheSBvZiBkb2luZyBvYmpl Y3Qgb3JpZW50ZWQgcHJvZ3JhbW1pbmc7IHRoZQorTGludXgga2VybmVsIGlzIG5vIGV4Y2VwdGlv bi4KKworVGhlIGNlbnRyYWwgY29uY2VwdCBpbiBrZXJuZWwgb2JqZWN0IG9yaWVudGVkIHByb2dy YW1taW5nIGlzIHRoZSBjbGFzcy4gSW4gdGhlCitrZXJuZWwsIGEgKmNsYXNzKiBpcyBhIHN0cnVj dCB0aGF0IGNvbnRhaW5zIGZ1bmN0aW9uIHBvaW50ZXJzLiBUaGlzIGNyZWF0ZXMgYQorY29udHJh Y3QgYmV0d2VlbiAqaW1wbGVtZW50ZXJzKiBhbmQgKnVzZXJzKiBzaW5jZSBpdCBmb3JjZXMgdGhl bSB0byB1c2UgdGhlCitzYW1lIGZ1bmN0aW9uIHNpZ25hdHVyZSB3aXRob3V0IGhhdmluZyB0byBj YWxsIHRoZSBmdW5jdGlvbiBkaXJlY3RseS4gSW4gb3JkZXIKK2ZvciBpdCB0byB0cnVseSBiZSBh IGNsYXNzLCB0aGUgZnVuY3Rpb24gcG9pbnRlcnMgbXVzdCBzcGVjaWZ5IHRoYXQgYSBwb2ludGVy Cit0byB0aGUgY2xhc3MsIGtub3duIGFzIGEgKmNsYXNzIGhhbmRsZSosIGJlIG9uZSBvZiB0aGUg cGFyYW1ldGVyczsgdGhpcyBtYWtlcworaXQgcG9zc2libGUgZm9yIHRoZSBtZW1iZXIgZnVuY3Rp b25zIChhbHNvIGtub3duIGFzICptZXRob2RzKikgdG8gaGF2ZSBhY2Nlc3MKK3RvIG1lbWJlciB2 YXJpYWJsZXMgKG1vcmUgY29tbW9ubHkga25vd24gYXMgKmZpZWxkcyopIGFsbG93aW5nIHRoZSBz YW1lCitpbXBsZW1lbnRhdGlvbiB0byBoYXZlIG11bHRpcGxlICppbnN0YW5jZXMqLgorCitUeXBp Y2FsbHkgYSBjbGFzcyBjYW4gYmUgKm92ZXJyaWRkZW4qIGJ5ICpjaGlsZCBjbGFzc2VzKiBieSBl bWJlZGRpbmcgdGhlCisqcGFyZW50IGNsYXNzKiBpbiB0aGUgY2hpbGQgY2xhc3MuIFRoZW4gd2hl biBhIG1ldGhvZCBwcm92aWRlZCBieSB0aGUgY2hpbGQKK2NsYXNzIGlzIGNhbGxlZCwgdGhlIGNo aWxkIGltcGxlbWVudGF0aW9uIGtub3dzIHRoYXQgdGhlIHBvaW50ZXIgcGFzc2VkIHRvIGl0IGlz CitvZiBhIHBhcmVudCBjb250YWluZWQgd2l0aGluIHRoZSBjaGlsZDsgYmVjYXVzZSBvZiB0aGlz LCB0aGUgY2hpbGQgY2FuIGNvbXB1dGUKK3RoZSBwb2ludGVyIHRvIGl0c2VsZiBiZWNhdXNlIHRo ZSBwb2ludGVyIHRvIHRoZSBwYXJlbnQgaXMgYWx3YXlzIGEgZml4ZWQgb2Zmc2V0Citmcm9tIHRo ZSBwb2ludGVyIHRvIHRoZSBjaGlsZDsgdGhpcyBvZmZzZXQgaXMgdGhlIG9mZnNldCBvZiB0aGUg cGFyZW50IGNvbnRhaW5lZAoraW4gdGhlIGNoaWxkIHN0cnVjdC4gRm9yIGV4YW1wbGU6CisKKy4u IGNvZGUtYmxvY2s6OiBjCisKKwlzdHJ1Y3Qgc2hhcGUgeworCQlpbnQgKCphcmVhKShzdHJ1Y3Qg c2hhcGUgKnRoaXMpOworCX07CisKKwlzdHJ1Y3QgcmVjdGFuZ2xlIHsKKwkJc3RydWN0IHNoYXBl IHBhcmVudDsKKwkJaW50IGxlbmd0aDsKKwkJaW50IHdpZHRoOworCX07CisKKwlpbnQgcmVjdGFu Z2xlX2FyZWEoc3RydWN0IHNoYXBlICp0aGlzKQorCXsKKwkJc3RydWN0IHJlY3RhbmdsZSAqc2Vs ZiA9IGNvbnRhaW5lcl9vZih0aGlzLCBzdHJ1Y3Qgc2hhcGUsIHBhcmVudCk7CisKKwkJcmV0dXJu IHNlbGYtPmxlbmd0aCAqIHNlbGYtPndpZHRoOworCX07CisKKwl2b2lkIHJlY3RhbmdsZV9uZXco c3RydWN0IHJlY3RhbmdsZSAqc2VsZiwgaW50IGxlbmd0aCwgaW50IHdpZHRoKQorCXsKKwkJc2Vs Zi0+cGFyZW50LmFyZWEgPSByZWN0YW5nbGVfYXJlYTsKKwkJc2VsZi0+bGVuZ3RoID0gbGVuZ3Ro OworCQlzZWxmLT53aWR0aCA9IHdpZHRoOworCX0KKworSW4gdGhpcyBleGFtcGxlIChhcyBpbiBt b3N0IGtlcm5lbCBjb2RlKSB0aGUgb3BlcmF0aW9uIG9mIGNvbXB1dGluZyB0aGUgcG9pbnRlcgor dG8gdGhlIGNoaWxkIGZyb20gdGhlIHBvaW50ZXIgdG8gdGhlIHBhcmVudCBpcyBkb25lIGJ5IGBg Y29udGFpbmVyX29mYGAuCisKK0Zha2luZyBDbGFzc2VzCit+fn5+fn5+fn5+fn5+fgorCitJbiBv cmRlciB0byB1bml0IHRlc3QgYSBwaWVjZSBvZiBjb2RlIHRoYXQgY2FsbHMgYSBtZXRob2QgaW4g YSBjbGFzcywgdGhlCitiZWhhdmlvciBvZiB0aGUgbWV0aG9kIG11c3QgYmUgY29udHJvbGxhYmxl LCBvdGhlcndpc2UgdGhlIHRlc3QgY2Vhc2VzIHRvIGJlIGEKK3VuaXQgdGVzdCBhbmQgYmVjb21l cyBhbiBpbnRlZ3JhdGlvbiB0ZXN0LgorCitBIGZha2UganVzdCBwcm92aWRlcyBhbiBpbXBsZW1l bnRhdGlvbiBvZiBhIHBpZWNlIG9mIGNvZGUgdGhhdCBpcyBkaWZmZXJlbnQgdGhhbgord2hhdCBy dW5zIGluIGEgcHJvZHVjdGlvbiBpbnN0YW5jZSwgYnV0IGJlaGF2ZXMgaWRlbnRpY2FsbHkgZnJv bSB0aGUgc3RhbmRwb2ludAorb2YgdGhlIGNhbGxlcnM7IHRoaXMgaXMgdXN1YWxseSBkb25lIHRv IHJlcGxhY2UgYSBkZXBlbmRlbmN5IHRoYXQgaXMgaGFyZCB0bworZGVhbCB3aXRoLCBvciBpcyBz bG93LgorCitBIGdvb2QgZXhhbXBsZSBmb3IgdGhpcyBtaWdodCBiZSBpbXBsZW1lbnRpbmcgYSBm YWtlIEVFUFJPTSB0aGF0IGp1c3Qgc3RvcmVzIHRoZQorImNvbnRlbnRzIiBpbiBhbiBpbnRlcm5h bCBidWZmZXIuIEZvciBleGFtcGxlLCBsZXQncyBhc3N1bWUgd2UgaGF2ZSBhIGNsYXNzIHRoYXQK K3JlcHJlc2VudHMgYW4gRUVQUk9NOgorCisuLiBjb2RlLWJsb2NrOjogYworCisJc3RydWN0IGVl cHJvbSB7CisJCXNzaXplX3QgKCpyZWFkKShzdHJ1Y3QgZWVwcm9tICp0aGlzLCBzaXplX3Qgb2Zm c2V0LCBjaGFyICpidWZmZXIsIHNpemVfdCBjb3VudCk7CisJCXNzaXplX3QgKCp3cml0ZSkoc3Ry dWN0IGVlcHJvbSAqdGhpcywgc2l6ZV90IG9mZnNldCwgY29uc3QgY2hhciAqYnVmZmVyLCBzaXpl X3QgY291bnQpOworCX07CisKK0FuZCB3ZSB3YW50IHRvIHRlc3Qgc29tZSBjb2RlIHRoYXQgYnVm ZmVycyB3cml0ZXMgdG8gdGhlIEVFUFJPTToKKworLi4gY29kZS1ibG9jazo6IGMKKworCXN0cnVj dCBlZXByb21fYnVmZmVyIHsKKwkJc3NpemVfdCAoKndyaXRlKShzdHJ1Y3QgZWVwcm9tX2J1ZmZl ciAqdGhpcywgY29uc3QgY2hhciAqYnVmZmVyLCBzaXplX3QgY291bnQpOworCQlpbnQgZmx1c2go c3RydWN0IGVlcHJvbV9idWZmZXIgKnRoaXMpOworCQlzaXplX3QgZmx1c2hfY291bnQ7IC8qIEZs dXNoZXMgd2hlbiBidWZmZXIgZXhjZWVkcyBmbHVzaF9jb3VudC4gKi8KKwl9OworCisJc3RydWN0 IGVlcHJvbV9idWZmZXIgKm5ld19lZXByb21fYnVmZmVyKHN0cnVjdCBlZXByb20gKmVlcHJvbSk7 CisJdm9pZCBkZXN0cm95X2VlcHJvbV9idWZmZXIoc3RydWN0IGVlcHJvbSAqZWVwcm9tKTsKKwor V2UgY2FuIGVhc2lseSB0ZXN0IHRoaXMgY29kZSBieSAqZmFraW5nIG91dCogdGhlIHVuZGVybHlp bmcgRUVQUk9NOgorCisuLiBjb2RlLWJsb2NrOjogYworCisJc3RydWN0IGZha2VfZWVwcm9tIHsK KwkJc3RydWN0IGVlcHJvbSBwYXJlbnQ7CisJCWNoYXIgY29udGVudHNbRkFLRV9FRVBST01fQ09O VEVOVFNfU0laRV07CisJfTsKKworCXNzaXplX3QgZmFrZV9lZXByb21fcmVhZChzdHJ1Y3QgZWVw cm9tICpwYXJlbnQsIHNpemVfdCBvZmZzZXQsIGNoYXIgKmJ1ZmZlciwgc2l6ZV90IGNvdW50KQor CXsKKwkJc3RydWN0IGZha2VfZWVwcm9tICp0aGlzID0gY29udGFpbmVyX29mKHBhcmVudCwgc3Ry dWN0IGZha2VfZWVwcm9tLCBwYXJlbnQpOworCisJCWNvdW50ID0gbWluKGNvdW50LCBGQUtFX0VF UFJPTV9DT05URU5UU19TSVpFIC0gb2Zmc2V0KTsKKwkJbWVtY3B5KGJ1ZmZlciwgdGhpcy0+Y29u dGVudHMgKyBvZmZzZXQsIGNvdW50KTsKKworCQlyZXR1cm4gY291bnQ7CisJfQorCisJc3NpemVf dCBmYWtlX2VlcHJvbV93cml0ZShzdHJ1Y3QgZWVwcm9tICp0aGlzLCBzaXplX3Qgb2Zmc2V0LCBj b25zdCBjaGFyICpidWZmZXIsIHNpemVfdCBjb3VudCkKKwl7CisJCXN0cnVjdCBmYWtlX2VlcHJv bSAqdGhpcyA9IGNvbnRhaW5lcl9vZihwYXJlbnQsIHN0cnVjdCBmYWtlX2VlcHJvbSwgcGFyZW50 KTsKKworCQljb3VudCA9IG1pbihjb3VudCwgRkFLRV9FRVBST01fQ09OVEVOVFNfU0laRSAtIG9m ZnNldCk7CisJCW1lbWNweSh0aGlzLT5jb250ZW50cyArIG9mZnNldCwgYnVmZmVyLCBjb3VudCk7 CisKKwkJcmV0dXJuIGNvdW50OworCX0KKworCXZvaWQgZmFrZV9lZXByb21faW5pdChzdHJ1Y3Qg ZmFrZV9lZXByb20gKnRoaXMpCisJeworCQl0aGlzLT5wYXJlbnQucmVhZCA9IGZha2VfZWVwcm9t X3JlYWQ7CisJCXRoaXMtPnBhcmVudC53cml0ZSA9IGZha2VfZWVwcm9tX3dyaXRlOworCQltZW1z ZXQodGhpcy0+Y29udGVudHMsIDAsIEZBS0VfRUVQUk9NX0NPTlRFTlRTX1NJWkUpOworCX0KKwor V2UgY2FuIG5vdyB1c2UgaXQgdG8gdGVzdCBgYHN0cnVjdCBlZXByb21fYnVmZmVyYGA6CisKKy4u IGNvZGUtYmxvY2s6OiBjCisKKwlzdHJ1Y3QgZWVwcm9tX2J1ZmZlcl90ZXN0IHsKKwkJc3RydWN0 IGZha2VfZWVwcm9tICpmYWtlX2VlcHJvbTsKKwkJc3RydWN0IGVlcHJvbV9idWZmZXIgKmVlcHJv bV9idWZmZXI7CisJfTsKKworCXN0YXRpYyB2b2lkIGVlcHJvbV9idWZmZXJfdGVzdF9kb2VzX25v dF93cml0ZV91bnRpbF9mbHVzaChzdHJ1Y3Qga3VuaXQgKnRlc3QpCisJeworCQlzdHJ1Y3QgZWVw cm9tX2J1ZmZlcl90ZXN0ICpjdHggPSB0ZXN0LT5wcml2OworCQlzdHJ1Y3QgZWVwcm9tX2J1ZmZl ciAqZWVwcm9tX2J1ZmZlciA9IGN0eC0+ZWVwcm9tX2J1ZmZlcjsKKwkJc3RydWN0IGZha2VfZWVw cm9tICpmYWtlX2VlcHJvbSA9IGN0eC0+ZmFrZV9lZXByb207CisJCWNoYXIgYnVmZmVyW10gPSB7 MHhmZn07CisKKwkJZWVwcm9tX2J1ZmZlci0+Zmx1c2hfY291bnQgPSBTSVpFX01BWDsKKworCQll ZXByb21fYnVmZmVyLT53cml0ZShlZXByb21fYnVmZmVyLCBidWZmZXIsIDEpOworCQlLVU5JVF9F WFBFQ1RfRVEodGVzdCwgZmFrZV9lZXByb20tPmNvbnRlbnRzWzBdLCAwKTsKKworCQllZXByb21f YnVmZmVyLT53cml0ZShlZXByb21fYnVmZmVyLCBidWZmZXIsIDEpOworCQlLVU5JVF9FWFBFQ1Rf RVEodGVzdCwgZmFrZV9lZXByb20tPmNvbnRlbnRzWzFdLCAwKTsKKworCQllZXByb21fYnVmZmVy LT5mbHVzaChlZXByb21fYnVmZmVyKTsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3QsIGZha2VfZWVw cm9tLT5jb250ZW50c1swXSwgMHhmZik7CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0LCBmYWtlX2Vl cHJvbS0+Y29udGVudHNbMV0sIDB4ZmYpOworCX0KKworCXN0YXRpYyB2b2lkIGVlcHJvbV9idWZm ZXJfdGVzdF9mbHVzaGVzX2FmdGVyX2ZsdXNoX2NvdW50X21ldChzdHJ1Y3Qga3VuaXQgKnRlc3Qp CisJeworCQlzdHJ1Y3QgZWVwcm9tX2J1ZmZlcl90ZXN0ICpjdHggPSB0ZXN0LT5wcml2OworCQlz dHJ1Y3QgZWVwcm9tX2J1ZmZlciAqZWVwcm9tX2J1ZmZlciA9IGN0eC0+ZWVwcm9tX2J1ZmZlcjsK KwkJc3RydWN0IGZha2VfZWVwcm9tICpmYWtlX2VlcHJvbSA9IGN0eC0+ZmFrZV9lZXByb207CisJ CWNoYXIgYnVmZmVyW10gPSB7MHhmZn07CisKKwkJZWVwcm9tX2J1ZmZlci0+Zmx1c2hfY291bnQg PSAyOworCisJCWVlcHJvbV9idWZmZXItPndyaXRlKGVlcHJvbV9idWZmZXIsIGJ1ZmZlciwgMSk7 CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0LCBmYWtlX2VlcHJvbS0+Y29udGVudHNbMF0sIDApOwor CisJCWVlcHJvbV9idWZmZXItPndyaXRlKGVlcHJvbV9idWZmZXIsIGJ1ZmZlciwgMSk7CisJCUtV TklUX0VYUEVDVF9FUSh0ZXN0LCBmYWtlX2VlcHJvbS0+Y29udGVudHNbMF0sIDB4ZmYpOworCQlL VU5JVF9FWFBFQ1RfRVEodGVzdCwgZmFrZV9lZXByb20tPmNvbnRlbnRzWzFdLCAweGZmKTsKKwl9 CisKKwlzdGF0aWMgdm9pZCBlZXByb21fYnVmZmVyX3Rlc3RfZmx1c2hlc19pbmNyZW1lbnRzX29m X2ZsdXNoX2NvdW50KHN0cnVjdCBrdW5pdCAqdGVzdCkKKwl7CisJCXN0cnVjdCBlZXByb21fYnVm ZmVyX3Rlc3QgKmN0eCA9IHRlc3QtPnByaXY7CisJCXN0cnVjdCBlZXByb21fYnVmZmVyICplZXBy b21fYnVmZmVyID0gY3R4LT5lZXByb21fYnVmZmVyOworCQlzdHJ1Y3QgZmFrZV9lZXByb20gKmZh a2VfZWVwcm9tID0gY3R4LT5mYWtlX2VlcHJvbTsKKwkJY2hhciBidWZmZXJbXSA9IHsweGZmLCAw eGZmfTsKKworCQllZXByb21fYnVmZmVyLT5mbHVzaF9jb3VudCA9IDI7CisKKwkJZWVwcm9tX2J1 ZmZlci0+d3JpdGUoZWVwcm9tX2J1ZmZlciwgYnVmZmVyLCAxKTsKKwkJS1VOSVRfRVhQRUNUX0VR KHRlc3QsIGZha2VfZWVwcm9tLT5jb250ZW50c1swXSwgMCk7CisKKwkJZWVwcm9tX2J1ZmZlci0+ d3JpdGUoZWVwcm9tX2J1ZmZlciwgYnVmZmVyLCAyKTsKKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3Qs IGZha2VfZWVwcm9tLT5jb250ZW50c1swXSwgMHhmZik7CisJCUtVTklUX0VYUEVDVF9FUSh0ZXN0 LCBmYWtlX2VlcHJvbS0+Y29udGVudHNbMV0sIDB4ZmYpOworCQkvKiBTaG91bGQgaGF2ZSBvbmx5 IGZsdXNoZWQgdGhlIGZpcnN0IHR3byBieXRlcy4gKi8KKwkJS1VOSVRfRVhQRUNUX0VRKHRlc3Qs IGZha2VfZWVwcm9tLT5jb250ZW50c1syXSwgMCk7CisJfQorCisJc3RhdGljIGludCBlZXByb21f YnVmZmVyX3Rlc3RfaW5pdChzdHJ1Y3Qga3VuaXQgKnRlc3QpCisJeworCQlzdHJ1Y3QgZWVwcm9t X2J1ZmZlcl90ZXN0ICpjdHg7CisKKwkJY3R4ID0ga3VuaXRfa3phbGxvYyh0ZXN0LCBzaXplb2Yo KmN0eCksIEdGUF9LRVJORUwpOworCQlLVU5JVF9BU1NFUlRfTk9UX0VSUl9PUl9OVUxMKHRlc3Qs IGN0eCk7CisKKwkJY3R4LT5mYWtlX2VlcHJvbSA9IGt1bml0X2t6YWxsb2ModGVzdCwgc2l6ZW9m KCpjdHgtPmZha2VfZWVwcm9tKSwgR0ZQX0tFUk5FTCk7CisJCUtVTklUX0FTU0VSVF9OT1RfRVJS X09SX05VTEwodGVzdCwgY3R4LT5mYWtlX2VlcHJvbSk7CisJCWZha2VfZWVwcm9tX2luaXQoY3R4 LT5mYWtlX2VlcHJvbSk7CisKKwkJY3R4LT5lZXByb21fYnVmZmVyID0gbmV3X2VlcHJvbV9idWZm ZXIoJmN0eC0+ZmFrZV9lZXByb20tPnBhcmVudCk7CisJCUtVTklUX0FTU0VSVF9OT1RfRVJSX09S X05VTEwodGVzdCwgY3R4LT5lZXByb21fYnVmZmVyKTsKKworCQl0ZXN0LT5wcml2ID0gY3R4Owor CisJCXJldHVybiAwOworCX0KKworCXN0YXRpYyB2b2lkIGVlcHJvbV9idWZmZXJfdGVzdF9leGl0 KHN0cnVjdCBrdW5pdCAqdGVzdCkKKwl7CisJCXN0cnVjdCBlZXByb21fYnVmZmVyX3Rlc3QgKmN0 eCA9IHRlc3QtPnByaXY7CisKKwkJZGVzdHJveV9lZXByb21fYnVmZmVyKGN0eC0+ZWVwcm9tX2J1 ZmZlcik7CisJfQorCisuLiBfa3VuaXQtb24tbm9uLXVtbDoKKworS1VuaXQgb24gbm9uLVVNTCBh cmNoaXRlY3R1cmVzCis9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KKworQnkgZGVmYXVs dCBLVW5pdCB1c2VzIFVNTCBhcyBhIHdheSB0byBwcm92aWRlIGRlcGVuZGVuY2llcyBmb3IgY29k ZSB1bmRlciB0ZXN0LgorVW5kZXIgbW9zdCBjaXJjdW1zdGFuY2VzIEtVbml0J3MgdXNhZ2Ugb2Yg VU1MIHNob3VsZCBiZSB0cmVhdGVkIGFzIGFuCitpbXBsZW1lbnRhdGlvbiBkZXRhaWwgb2YgaG93 IEtVbml0IHdvcmtzIHVuZGVyIHRoZSBob29kLiBOZXZlcnRoZWxlc3MsIHRoZXJlCithcmUgaW5z dGFuY2VzIHdoZXJlIGJlaW5nIGFibGUgdG8gcnVuIGFyY2hpdGVjdHVyZSBzcGVjaWZpYyBjb2Rl LCBvciB0ZXN0CithZ2FpbnN0IHJlYWwgaGFyZHdhcmUgaXMgZGVzaXJhYmxlLiBGb3IgdGhlc2Ug cmVhc29ucyBLVW5pdCBzdXBwb3J0cyBydW5uaW5nIG9uCitvdGhlciBhcmNoaXRlY3R1cmVzLgor CitSdW5uaW5nIGV4aXN0aW5nIEtVbml0IHRlc3RzIG9uIG5vbi1VTUwgYXJjaGl0ZWN0dXJlcwor LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKwor VGhlcmUgYXJlIHNvbWUgc3BlY2lhbCBjb25zaWRlcmF0aW9ucyB3aGVuIHJ1bm5pbmcgZXhpc3Rp bmcgS1VuaXQgdGVzdHMgb24KK25vbi1VTUwgYXJjaGl0ZWN0dXJlczoKKworKiAgIEhhcmR3YXJl IG1heSBub3QgYmUgZGV0ZXJtaW5pc3RpYywgc28gYSB0ZXN0IHRoYXQgYWx3YXlzIHBhc3NlcyBv ciBmYWlscworICAgIHdoZW4gcnVuIHVuZGVyIFVNTCBtYXkgbm90IGFsd2F5cyBkbyBzbyBvbiBy ZWFsIGhhcmR3YXJlLgorKiAgIEhhcmR3YXJlIGFuZCBWTSBlbnZpcm9ubWVudHMgbWF5IG5vdCBi ZSBoZXJtZXRpYy4gS1VuaXQgdHJpZXMgaXRzIGJlc3QgdG8KKyAgICBwcm92aWRlIGEgaGVybWV0 aWMgZW52aXJvbm1lbnQgdG8gcnVuIHRlc3RzOyBob3dldmVyLCBpdCBjYW5ub3QgbWFuYWdlIHN0 YXRlCisgICAgdGhhdCBpdCBkb2Vzbid0IGtub3cgYWJvdXQgb3V0c2lkZSBvZiB0aGUga2VybmVs LiBDb25zZXF1ZW50bHksIHRlc3RzIHRoYXQKKyAgICBtYXkgYmUgaGVybWV0aWMgb24gVU1MIG1h eSBub3QgYmUgaGVybWV0aWMgb24gb3RoZXIgYXJjaGl0ZWN0dXJlcy4KKyogICBTb21lIGZlYXR1 cmVzIGFuZCB0b29saW5nIG1heSBub3QgYmUgc3VwcG9ydGVkIG91dHNpZGUgb2YgVU1MLgorKiAg IEhhcmR3YXJlIGFuZCBWTXMgYXJlIHNsb3dlciB0aGFuIFVNTC4KKworTm9uZSBvZiB0aGVzZSBh cmUgcmVhc29ucyBub3QgdG8gcnVuIHlvdXIgS1VuaXQgdGVzdHMgb24gcmVhbCBoYXJkd2FyZTsg dGhleSBhcmUKK29ubHkgdGhpbmdzIHRvIGJlIGF3YXJlIG9mIHdoZW4gZG9pbmcgc28uCisKK1Ro ZSBiaWdnZXN0IGltcGVkaW1lbnQgd2lsbCBsaWtlbHkgYmUgdGhhdCBjZXJ0YWluIEtVbml0IGZl YXR1cmVzIGFuZAoraW5mcmFzdHJ1Y3R1cmUgbWF5IG5vdCBzdXBwb3J0IHlvdXIgdGFyZ2V0IGVu dmlyb25tZW50LiBGb3IgZXhhbXBsZSwgYXQgdGhpcwordGltZSB0aGUgS1VuaXQgV3JhcHBlciAo YGB0b29scy90ZXN0aW5nL2t1bml0L2t1bml0LnB5YGApIGRvZXMgbm90IHdvcmsgb3V0c2lkZQor b2YgVU1MLiBVbmZvcnR1bmF0ZWx5LCB0aGVyZSBpcyBubyB3YXkgYXJvdW5kIHRoaXMuIFVzaW5n IFVNTCAob3IgZXZlbiBqdXN0IGEKK3BhcnRpY3VsYXIgYXJjaGl0ZWN0dXJlKSBhbGxvd3MgdXMg dG8gbWFrZSBhIGxvdCBvZiBhc3N1bXB0aW9ucyB0aGF0IG1ha2UgaXQKK3Bvc3NpYmxlIHRvIGRv IHRoaW5ncyB3aGljaCBtaWdodCBvdGhlcndpc2UgYmUgaW1wb3NzaWJsZS4KKworTmV2ZXJ0aGVs ZXNzLCBhbGwgY29yZSBLVW5pdCBmcmFtZXdvcmsgZmVhdHVyZXMgYXJlIGZ1bGx5IHN1cHBvcnRl ZCBvbiBhbGwKK2FyY2hpdGVjdHVyZXMsIGFuZCB1c2luZyB0aGVtIGlzIHN0cmFpZ2h0Zm9yd2Fy ZDogYWxsIHlvdSBuZWVkIHRvIGRvIGlzIHRvIHRha2UKK3lvdXIga3VuaXRjb25maWcsIHlvdXIg S2NvbmZpZyBvcHRpb25zIGZvciB0aGUgdGVzdHMgeW91IHdvdWxkIGxpa2UgdG8gcnVuLCBhbmQK K21lcmdlIHRoZW0gaW50byB3aGF0ZXZlciBjb25maWcgeW91ciBhcmUgdXNpbmcgZm9yIHlvdXIg cGxhdGZvcm0uIFRoYXQncyBpdCEKKworRm9yIGV4YW1wbGUsIGxldCdzIHNheSB5b3UgaGF2ZSB0 aGUgZm9sbG93aW5nIGt1bml0Y29uZmlnOgorCisuLiBjb2RlLWJsb2NrOjogbm9uZQorCisJQ09O RklHX0tVTklUPXkKKwlDT05GSUdfS1VOSVRfRVhBTVBMRV9URVNUPXkKKworSWYgeW91IHdhbnRl ZCB0byBydW4gdGhpcyB0ZXN0IG9uIGFuIHg4NiBWTSwgeW91IG1pZ2h0IGFkZCB0aGUgZm9sbG93 aW5nIGNvbmZpZworb3B0aW9ucyB0byB5b3VyIGBgLmNvbmZpZ2BgOgorCisuLiBjb2RlLWJsb2Nr Ojogbm9uZQorCisJQ09ORklHX0tVTklUPXkKKwlDT05GSUdfS1VOSVRfRVhBTVBMRV9URVNUPXkK KwlDT05GSUdfU0VSSUFMXzgyNTA9eQorCUNPTkZJR19TRVJJQUxfODI1MF9DT05TT0xFPXkKKwor QWxsIHRoZXNlIG5ldyBvcHRpb25zIGRvIGlzIGVuYWJsZSBzdXBwb3J0IGZvciBhIGNvbW1vbiBz ZXJpYWwgY29uc29sZSBuZWVkZWQKK2ZvciBsb2dnaW5nLgorCitOZXh0LCB5b3UgY291bGQgYnVp bGQgYSBrZXJuZWwgd2l0aCB0aGVzZSB0ZXN0cyBhcyBmb2xsb3dzOgorCisKKy4uIGNvZGUtYmxv Y2s6OiBiYXNoCisKKwltYWtlIEFSQ0g9eDg2IG9sZGRlZmNvbmZpZworCW1ha2UgQVJDSD14ODYK KworT25jZSB5b3UgaGF2ZSBidWlsdCBhIGtlcm5lbCwgeW91IGNvdWxkIHJ1biBpdCBvbiBRRU1V IGFzIGZvbGxvd3M6CisKKy4uIGNvZGUtYmxvY2s6OiBiYXNoCisKKwlxZW11LXN5c3RlbS14ODZf NjQgLWVuYWJsZS1rdm0gXAorCQkJICAgLW0gMTAyNCBcCisJCQkgICAta2VybmVsIGFyY2gveDg2 XzY0L2Jvb3QvYnpJbWFnZSBcCisJCQkgICAtYXBwZW5kICdjb25zb2xlPXR0eVMwJyBcCisJCQkg ICAtLW5vZ3JhcGhpYworCitJbnRlcnNwZXJzZWQgaW4gdGhlIGtlcm5lbCBsb2dzIHlvdSBtaWdo dCBzZWUgdGhlIGZvbGxvd2luZzoKKworLi4gY29kZS1ibG9jazo6IG5vbmUKKworCVRBUCB2ZXJz aW9uIDE0CisJCSMgU3VidGVzdDogZXhhbXBsZQorCQkxLi4xCisJCSMgZXhhbXBsZV9zaW1wbGVf dGVzdDogaW5pdGlhbGl6aW5nCisJCW9rIDEgLSBleGFtcGxlX3NpbXBsZV90ZXN0CisJb2sgMSAt IGV4YW1wbGUKKworQ29uZ3JhdHVsYXRpb25zLCB5b3UganVzdCByYW4gYSBLVW5pdCB0ZXN0IG9u IHRoZSB4ODYgYXJjaGl0ZWN0dXJlIQorCitXcml0aW5nIG5ldyB0ZXN0cyBmb3Igb3RoZXIgYXJj aGl0ZWN0dXJlcworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKwor VGhlIGZpcnN0IHRoaW5nIHlvdSBtdXN0IGRvIGlzIGFzayB5b3Vyc2VsZiB3aGV0aGVyIGl0IGlz IG5lY2Vzc2FyeSB0byB3cml0ZSBhCitLVW5pdCB0ZXN0IGZvciBhIHNwZWNpZmljIGFyY2hpdGVj dHVyZSwgYW5kIHRoZW4gd2hldGhlciBpdCBpcyBuZWNlc3NhcnkgdG8KK3dyaXRlIHRoYXQgdGVz dCBmb3IgYSBwYXJ0aWN1bGFyIHBpZWNlIG9mIGhhcmR3YXJlLiBJbiBnZW5lcmFsLCB3cml0aW5n IGEgdGVzdAordGhhdCBkZXBlbmRzIG9uIGhhdmluZyBhY2Nlc3MgdG8gYSBwYXJ0aWN1bGFyIHBp ZWNlIG9mIGhhcmR3YXJlIG9yIHNvZnR3YXJlIChub3QKK2luY2x1ZGVkIGluIHRoZSBMaW51eCBz b3VyY2UgcmVwbykgc2hvdWxkIGJlIGF2b2lkZWQgYXQgYWxsIGNvc3RzLgorCitFdmVuIGlmIHlv dSBvbmx5IGV2ZXIgcGxhbiBvbiBydW5uaW5nIHlvdXIgS1VuaXQgdGVzdCBvbiB5b3VyIGhhcmR3 YXJlCitjb25maWd1cmF0aW9uLCBvdGhlciBwZW9wbGUgbWF5IHdhbnQgdG8gcnVuIHlvdXIgdGVz dHMgYW5kIG1heSBub3QgaGF2ZSBhY2Nlc3MKK3RvIHlvdXIgaGFyZHdhcmUuIElmIHlvdSB3cml0 ZSB5b3VyIHRlc3QgdG8gcnVuIG9uIFVNTCwgdGhlbiBhbnlvbmUgY2FuIHJ1biB5b3VyCit0ZXN0 cyB3aXRob3V0IGtub3dpbmcgYW55dGhpbmcgYWJvdXQgeW91ciBwYXJ0aWN1bGFyIHNldHVwLCBh bmQgeW91IGNhbiBzdGlsbAorcnVuIHlvdXIgdGVzdHMgb24geW91ciBoYXJkd2FyZSBzZXR1cCBq dXN0IGJ5IGNvbXBpbGluZyBmb3IgeW91ciBhcmNoaXRlY3R1cmUuCisKKy4uIGltcG9ydGFudDo6 CisgICBBbHdheXMgcHJlZmVyIHRlc3RzIHRoYXQgcnVuIG9uIFVNTCB0byB0ZXN0cyB0aGF0IG9u bHkgcnVuIHVuZGVyIGEgcGFydGljdWxhcgorICAgYXJjaGl0ZWN0dXJlLCBhbmQgYWx3YXlzIHBy ZWZlciB0ZXN0cyB0aGF0IHJ1biB1bmRlciBRRU1VIG9yIGFub3RoZXIgZWFzeQorICAgKGFuZCBt b25pdGFyaWx5IGZyZWUpIHRvIG9idGFpbiBzb2Z0d2FyZSBlbnZpcm9ubWVudCB0byBhIHNwZWNp ZmljIHBpZWNlIG9mCisgICBoYXJkd2FyZS4KKworTmV2ZXJ0aGVsZXNzLCB0aGVyZSBhcmUgc3Rp bGwgdmFsaWQgcmVhc29ucyB0byB3cml0ZSBhbiBhcmNoaXRlY3R1cmUgb3IgaGFyZHdhcmUKK3Nw ZWNpZmljIHRlc3Q6IGZvciBleGFtcGxlLCB5b3UgbWlnaHQgd2FudCB0byB0ZXN0IHNvbWUgY29k ZSB0aGF0IHJlYWxseSBiZWxvbmdzCitpbiBgYGFyY2gvc29tZS1hcmNoLypgYC4gRXZlbiBzbywg dHJ5IHlvdXIgYmVzdCB0byB3cml0ZSB0aGUgdGVzdCBzbyB0aGF0IGl0Citkb2VzIG5vdCBkZXBl bmQgb24gcGh5c2ljYWwgaGFyZHdhcmU6IGlmIHNvbWUgb2YgeW91ciB0ZXN0IGNhc2VzIGRvbid0 IG5lZWQgdGhlCitoYXJkd2FyZSwgb25seSByZXF1aXJlIHRoZSBoYXJkd2FyZSBmb3IgdGVzdHMg dGhhdCBhY3R1YWxseSBuZWVkIGl0LgorCitOb3cgdGhhdCB5b3UgaGF2ZSBuYXJyb3dlZCBkb3du IGV4YWN0bHkgd2hhdCBiaXRzIGFyZSBoYXJkd2FyZSBzcGVjaWZpYywgdGhlCithY3R1YWwgcHJv Y2VkdXJlIGZvciB3cml0aW5nIGFuZCBydW5uaW5nIHRoZSB0ZXN0cyBpcyBwcmV0dHkgbXVjaCB0 aGUgc2FtZSBhcword3JpdGluZyBub3JtYWwgS1VuaXQgdGVzdHMuIE9uZSBzcGVjaWFsIGNhdmVh dCBpcyB0aGF0IHlvdSBoYXZlIHRvIHJlc2V0CitoYXJkd2FyZSBzdGF0ZSBpbiBiZXR3ZWVuIHRl c3QgY2FzZXM7IGlmIHRoaXMgaXMgbm90IHBvc3NpYmxlLCB5b3UgbWF5IG9ubHkgYmUKK2FibGUg dG8gcnVuIG9uZSB0ZXN0IGNhc2UgcGVyIGludm9jYXRpb24uCisKKy4uIFRPRE8oYnJlbmRhbmhp Z2dpbnNAZ29vZ2xlLmNvbSk6IEFkZCBhbiBhY3R1YWwgZXhhbXBsZSBvZiBhbiBhcmNoaXRlY3R1 cmUKKyAgIGRlcGVuZGVudCBLVW5pdCB0ZXN0LgotLSAKMi4yMy4wLjM1MS5nYzQzMTcwMzJlNi1n b29nCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmkt ZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6 Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWw= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x449.google.com ([2607:f8b0:4864:20::449]) by bombadil.infradead.org with esmtps (Exim 4.92.2 #3 (Red Hat Linux)) id 1iBSCM-0004ip-9s for linux-um@lists.infradead.org; Fri, 20 Sep 2019 23:20:25 +0000 Received: by mail-pf1-x449.google.com with SMTP id z4so5783797pfn.0 for ; Fri, 20 Sep 2019 16:20:21 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:19 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-16-brendanhiggins@google.com> Mime-Version: 1.0 References: <20190920231923.141900-1-brendanhiggins@google.com> Subject: [PATCH v16 15/19] Documentation: kunit: add documentation for KUnit From: Brendan Higgins List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-um" Errors-To: linux-um-bounces+geert=linux-m68k.org@lists.infradead.org To: frowand.list@gmail.com, gregkh@linuxfoundation.org, jpoimboe@redhat.com, keescook@google.com, kieran.bingham@ideasonboard.com, mcgrof@kernel.org, peterz@infradead.org, robh@kernel.org, sboyd@kernel.org, shuah@kernel.org, tytso@mit.edu, yamada.masahiro@socionext.com Cc: pmladek@suse.com, linux-doc@vger.kernel.org, amir73il@gmail.com, Brendan Higgins , dri-devel@lists.freedesktop.org, Alexander.Levin@microsoft.com, linux-kselftest@vger.kernel.org, Jonathan Corbet , linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, Felix Guo , wfg@linux.intel.com, joel@jms.id.au, rientjes@google.com, jdike@addtoit.com, dan.carpenter@oracle.com, devicetree@vger.kernel.org, linux-kbuild@vger.kernel.org, Tim.Bird@sony.com, linux-um@lists.infradead.org, rostedt@goodmis.org, julia.lawall@lip6.fr, kunit-dev@googlegroups.com, richard@nod.at, torvalds@linux-foundation.org, rdunlap@infradead.org, linux-kernel@vger.kernel.org, daniel@ffwll.ch, mpe@ellerman.id.au, linux-fsdevel@vger.kernel.org, logang@deltatee.com Add documentation for KUnit, the Linux kernel unit testing framework. - Add intro and usage guide for KUnit - Add API reference Signed-off-by: Felix Guo Signed-off-by: Brendan Higgins Cc: Jonathan Corbet Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Stephen Boyd --- Documentation/dev-tools/index.rst | 1 + Documentation/dev-tools/kunit/api/index.rst | 16 + Documentation/dev-tools/kunit/api/test.rst | 11 + Documentation/dev-tools/kunit/faq.rst | 62 +++ Documentation/dev-tools/kunit/index.rst | 79 +++ Documentation/dev-tools/kunit/start.rst | 180 ++++++ Documentation/dev-tools/kunit/usage.rst | 576 ++++++++++++++++++++ 7 files changed, 925 insertions(+) create mode 100644 Documentation/dev-tools/kunit/api/index.rst create mode 100644 Documentation/dev-tools/kunit/api/test.rst create mode 100644 Documentation/dev-tools/kunit/faq.rst create mode 100644 Documentation/dev-tools/kunit/index.rst create mode 100644 Documentation/dev-tools/kunit/start.rst create mode 100644 Documentation/dev-tools/kunit/usage.rst diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst index b0522a4dd107..09dee10d2592 100644 --- a/Documentation/dev-tools/index.rst +++ b/Documentation/dev-tools/index.rst @@ -24,6 +24,7 @@ whole; patches welcome! gdb-kernel-debugging kgdb kselftest + kunit/index .. only:: subproject and html diff --git a/Documentation/dev-tools/kunit/api/index.rst b/Documentation/dev-tools/kunit/api/index.rst new file mode 100644 index 000000000000..9b9bffe5d41a --- /dev/null +++ b/Documentation/dev-tools/kunit/api/index.rst @@ -0,0 +1,16 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +API Reference +============= +.. toctree:: + + test + +This section documents the KUnit kernel testing API. It is divided into the +following sections: + +================================= ============================================== +:doc:`test` documents all of the standard testing API + excluding mocking or mocking related features. +================================= ============================================== diff --git a/Documentation/dev-tools/kunit/api/test.rst b/Documentation/dev-tools/kunit/api/test.rst new file mode 100644 index 000000000000..aaa97f17e5b3 --- /dev/null +++ b/Documentation/dev-tools/kunit/api/test.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +Test API +======== + +This file documents all of the standard testing API excluding mocking or mocking +related features. + +.. kernel-doc:: include/kunit/test.h + :internal: diff --git a/Documentation/dev-tools/kunit/faq.rst b/Documentation/dev-tools/kunit/faq.rst new file mode 100644 index 000000000000..bf2095112d89 --- /dev/null +++ b/Documentation/dev-tools/kunit/faq.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Frequently Asked Questions +========================== + +How is this different from Autotest, kselftest, etc? +==================================================== +KUnit is a unit testing framework. Autotest, kselftest (and some others) are +not. + +A `unit test `_ is supposed to +test a single unit of code in isolation, hence the name. A unit test should be +the finest granularity of testing and as such should allow all possible code +paths to be tested in the code under test; this is only possible if the code +under test is very small and does not have any external dependencies outside of +the test's control like hardware. + +There are no testing frameworks currently available for the kernel that do not +require installing the kernel on a test machine or in a VM and all require +tests to be written in userspace and run on the kernel under test; this is true +for Autotest, kselftest, and some others, disqualifying any of them from being +considered unit testing frameworks. + +Does KUnit support running on architectures other than UML? +=========================================================== + +Yes, well, mostly. + +For the most part, the KUnit core framework (what you use to write the tests) +can compile to any architecture; it compiles like just another part of the +kernel and runs when the kernel boots. However, there is some infrastructure, +like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support +other architectures. + +In short, this means that, yes, you can run KUnit on other architectures, but +it might require more work than using KUnit on UML. + +For more information, see :ref:`kunit-on-non-uml`. + +What is the difference between a unit test and these other kinds of tests? +========================================================================== +Most existing tests for the Linux kernel would be categorized as an integration +test, or an end-to-end test. + +- A unit test is supposed to test a single unit of code in isolation, hence the + name. A unit test should be the finest granularity of testing and as such + should allow all possible code paths to be tested in the code under test; this + is only possible if the code under test is very small and does not have any + external dependencies outside of the test's control like hardware. +- An integration test tests the interaction between a minimal set of components, + usually just two or three. For example, someone might write an integration + test to test the interaction between a driver and a piece of hardware, or to + test the interaction between the userspace libraries the kernel provides and + the kernel itself; however, one of these tests would probably not test the + entire kernel along with hardware interactions and interactions with the + userspace. +- An end-to-end test usually tests the entire system from the perspective of the + code under test. For example, someone might write an end-to-end test for the + kernel by installing a production configuration of the kernel on production + hardware with a production userspace and then trying to exercise some behavior + that depends on interactions between the hardware, the kernel, and userspace. diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst new file mode 100644 index 000000000000..26ffb46bdf99 --- /dev/null +++ b/Documentation/dev-tools/kunit/index.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================================= +KUnit - Unit Testing for the Linux Kernel +========================================= + +.. toctree:: + :maxdepth: 2 + + start + usage + api/index + faq + +What is KUnit? +============== + +KUnit is a lightweight unit testing and mocking framework for the Linux kernel. +These tests are able to be run locally on a developer's workstation without a VM +or special hardware. + +KUnit is heavily inspired by JUnit, Python's unittest.mock, and +Googletest/Googlemock for C++. KUnit provides facilities for defining unit test +cases, grouping related test cases into test suites, providing common +infrastructure for running tests, and much more. + +Get started now: :doc:`start` + +Why KUnit? +========== + +A unit test is supposed to test a single unit of code in isolation, hence the +name. A unit test should be the finest granularity of testing and as such should +allow all possible code paths to be tested in the code under test; this is only +possible if the code under test is very small and does not have any external +dependencies outside of the test's control like hardware. + +Outside of KUnit, there are no testing frameworks currently +available for the kernel that do not require installing the kernel on a test +machine or in a VM and all require tests to be written in userspace running on +the kernel; this is true for Autotest, and kselftest, disqualifying +any of them from being considered unit testing frameworks. + +KUnit addresses the problem of being able to run tests without needing a virtual +machine or actual hardware with User Mode Linux. User Mode Linux is a Linux +architecture, like ARM or x86; however, unlike other architectures it compiles +to a standalone program that can be run like any other program directly inside +of a host operating system; to be clear, it does not require any virtualization +support; it is just a regular program. + +KUnit is fast. Excluding build time, from invocation to completion KUnit can run +several dozen tests in only 10 to 20 seconds; this might not sound like a big +deal to some people, but having such fast and easy to run tests fundamentally +changes the way you go about testing and even writing code in the first place. +Linus himself said in his `git talk at Google +`_: + + "... a lot of people seem to think that performance is about doing the + same thing, just doing it faster, and that is not true. That is not what + performance is all about. If you can do something really fast, really + well, people will start using it differently." + +In this context Linus was talking about branching and merging, +but this point also applies to testing. If your tests are slow, unreliable, are +difficult to write, and require a special setup or special hardware to run, +then you wait a lot longer to write tests, and you wait a lot longer to run +tests; this means that tests are likely to break, unlikely to test a lot of +things, and are unlikely to be rerun once they pass. If your tests are really +fast, you run them all the time, every time you make a change, and every time +someone sends you some code. Why trust that someone ran all their tests +correctly on every change when you can just run them yourself in less time than +it takes to read their test log? + +How do I use it? +================ + +* :doc:`start` - for new users of KUnit +* :doc:`usage` - for a more detailed explanation of KUnit features +* :doc:`api/index` - for the list of KUnit APIs used for testing diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst new file mode 100644 index 000000000000..6dc229e46bb3 --- /dev/null +++ b/Documentation/dev-tools/kunit/start.rst @@ -0,0 +1,180 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +Getting Started +=============== + +Installing dependencies +======================= +KUnit has the same dependencies as the Linux kernel. As long as you can build +the kernel, you can run KUnit. + +KUnit Wrapper +============= +Included with KUnit is a simple Python wrapper that helps format the output to +easily use and read KUnit output. It handles building and running the kernel, as +well as formatting the output. + +The wrapper can be run with: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py run + +Creating a kunitconfig +====================== +The Python script is a thin wrapper around Kbuild as such, it needs to be +configured with a ``kunitconfig`` file. This file essentially contains the +regular Kernel config, with the specific test targets as well. + +.. code-block:: bash + + git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO + cd $PATH_TO_LINUX_REPO + ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig + +You may want to add kunitconfig to your local gitignore. + +Verifying KUnit Works +--------------------- + +To make sure that everything is set up correctly, simply invoke the Python +wrapper from your kernel repo: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +.. note:: + You may want to run ``make mrproper`` first. + +If everything worked correctly, you should see the following: + +.. code-block:: bash + + Generating .config ... + Building KUnit Kernel ... + Starting KUnit Kernel ... + +followed by a list of tests that are run. All of them should be passing. + +.. note:: + Because it is building a lot of sources for the first time, the ``Building + kunit kernel`` step may take a while. + +Writing your first test +======================= + +In your kernel repo let's add some code that we can test. Create a file +``drivers/misc/example.h`` with the contents: + +.. code-block:: c + + int misc_example_add(int left, int right); + +create a file ``drivers/misc/example.c``: + +.. code-block:: c + + #include + + #include "example.h" + + int misc_example_add(int left, int right) + { + return left + right; + } + +Now add the following lines to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE + bool "My example" + +and the following lines to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE) += example.o + +Now we are ready to write the test. The test will be in +``drivers/misc/example-test.c``: + +.. code-block:: c + + #include + #include "example.h" + + /* Define the test cases. */ + + static void misc_example_add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1)); + KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1)); + KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN)); + } + + static void misc_example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + + static struct kunit_case misc_example_test_cases[] = { + KUNIT_CASE(misc_example_add_test_basic), + KUNIT_CASE(misc_example_test_failure), + {} + }; + + static struct kunit_suite misc_example_test_suite = { + .name = "misc-example", + .test_cases = misc_example_test_cases, + }; + kunit_test_suite(misc_example_test_suite); + +Now add the following to ``drivers/misc/Kconfig``: + +.. code-block:: kconfig + + config MISC_EXAMPLE_TEST + bool "Test for my example" + depends on MISC_EXAMPLE && KUNIT + +and the following to ``drivers/misc/Makefile``: + +.. code-block:: make + + obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o + +Now add it to your ``kunitconfig``: + +.. code-block:: none + + CONFIG_MISC_EXAMPLE=y + CONFIG_MISC_EXAMPLE_TEST=y + +Now you can run the test: + +.. code-block:: bash + + ./tools/testing/kunit/kunit.py + +You should see the following failure: + +.. code-block:: none + + ... + [16:08:57] [PASSED] misc-example:misc_example_add_test_basic + [16:08:57] [FAILED] misc-example:misc_example_test_failure + [16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17 + [16:08:57] This test never passes. + ... + +Congrats! You just wrote your first KUnit test! + +Next Steps +========== +* Check out the :doc:`usage` page for a more + in-depth explanation of KUnit. diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst new file mode 100644 index 000000000000..c6e69634e274 --- /dev/null +++ b/Documentation/dev-tools/kunit/usage.rst @@ -0,0 +1,576 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========== +Using KUnit +=========== + +The purpose of this document is to describe what KUnit is, how it works, how it +is intended to be used, and all the concepts and terminology that are needed to +understand it. This guide assumes a working knowledge of the Linux kernel and +some basic knowledge of testing. + +For a high level introduction to KUnit, including setting up KUnit for your +project, see :doc:`start`. + +Organization of this document +============================= + +This document is organized into two main sections: Testing and Isolating +Behavior. The first covers what a unit test is and how to use KUnit to write +them. The second covers how to use KUnit to isolate code and make it possible +to unit test code that was otherwise un-unit-testable. + +Testing +======= + +What is KUnit? +-------------- + +"K" is short for "kernel" so "KUnit" is the "(Linux) Kernel Unit Testing +Framework." KUnit is intended first and foremost for writing unit tests; it is +general enough that it can be used to write integration tests; however, this is +a secondary goal. KUnit has no ambition of being the only testing framework for +the kernel; for example, it does not intend to be an end-to-end testing +framework. + +What is Unit Testing? +--------------------- + +A `unit test `_ is a test that +tests code at the smallest possible scope, a *unit* of code. In the C +programming language that's a function. + +Unit tests should be written for all the publicly exposed functions in a +compilation unit; so that is all the functions that are exported in either a +*class* (defined below) or all functions which are **not** static. + +Writing Tests +------------- + +Test Cases +~~~~~~~~~~ + +The fundamental unit in KUnit is the test case. A test case is a function with +the signature ``void (*)(struct kunit *test)``. It calls a function to be tested +and then sets *expectations* for what should happen. For example: + +.. code-block:: c + + void example_test_success(struct kunit *test) + { + } + + void example_test_failure(struct kunit *test) + { + KUNIT_FAIL(test, "This test never passes."); + } + +In the above example ``example_test_success`` always passes because it does +nothing; no expectations are set, so all expectations pass. On the other hand +``example_test_failure`` always fails because it calls ``KUNIT_FAIL``, which is +a special expectation that logs a message and causes the test case to fail. + +Expectations +~~~~~~~~~~~~ +An *expectation* is a way to specify that you expect a piece of code to do +something in a test. An expectation is called like a function. A test is made +by setting expectations about the behavior of a piece of code under test; when +one or more of the expectations fail, the test case fails and information about +the failure is logged. For example: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + +In the above example ``add_test_basic`` makes a number of assertions about the +behavior of a function called ``add``; the first parameter is always of type +``struct kunit *``, which contains information about the current test context; +the second parameter, in this case, is what the value is expected to be; the +last value is what the value actually is. If ``add`` passes all of these +expectations, the test case, ``add_test_basic`` will pass; if any one of these +expectations fail, the test case will fail. + +It is important to understand that a test case *fails* when any expectation is +violated; however, the test will continue running, potentially trying other +expectations until the test case ends or is otherwise terminated. This is as +opposed to *assertions* which are discussed later. + +To learn about more expectations supported by KUnit, see :doc:`api/test`. + +.. note:: + A single test case should be pretty short, pretty easy to understand, + focused on a single behavior. + +For example, if we wanted to properly test the add function above, we would +create additional tests cases which would each test a different property that an +add function should have like this: + +.. code-block:: c + + void add_test_basic(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 1, add(1, 0)); + KUNIT_EXPECT_EQ(test, 2, add(1, 1)); + } + + void add_test_negative(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + } + + void add_test_max(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + } + + void add_test_overflow(struct kunit *test) + { + KUNIT_EXPECT_EQ(test, INT_MIN, add(INT_MAX, 1)); + } + +Notice how it is immediately obvious what all the properties that we are testing +for are. + +Assertions +~~~~~~~~~~ + +KUnit also has the concept of an *assertion*. An assertion is just like an +expectation except the assertion immediately terminates the test case if it is +not satisfied. + +For example: + +.. code-block:: c + + static void mock_test_do_expect_default_return(struct kunit *test) + { + struct mock_test_context *ctx = test->priv; + struct mock *mock = ctx->mock; + int param0 = 5, param1 = -5; + const char *two_param_types[] = {"int", "int"}; + const void *two_params[] = {¶m0, ¶m1}; + const void *ret; + + ret = mock->do_expect(mock, + "test_printk", test_printk, + two_param_types, two_params, + ARRAY_SIZE(two_params)); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_EQ(test, -4, *((int *) ret)); + } + +In this example, the method under test should return a pointer to a value, so +if the pointer returned by the method is null or an errno, we don't want to +bother continuing the test since the following expectation could crash the test +case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us to bail out of the test case if +the appropriate conditions have not been satisfied to complete the test. + +Test Suites +~~~~~~~~~~~ + +Now obviously one unit test isn't very helpful; the power comes from having +many test cases covering all of your behaviors. Consequently it is common to +have many *similar* tests; in order to reduce duplication in these closely +related tests most unit testing frameworks provide the concept of a *test +suite*, in KUnit we call it a *test suite*; all it is is just a collection of +test cases for a unit of code with a set up function that gets invoked before +every test cases and then a tear down function that gets invoked after every +test case completes. + +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``, would run the test +cases ``example_test_foo``, ``example_test_bar``, and ``example_test_baz``, +each would have ``example_test_init`` called immediately before it and would +have ``example_test_exit`` called immediately after it. +``kunit_test_suite(example_test_suite)`` registers the test suite with the +KUnit test framework. + +.. note:: + A test case will only be run if it is associated with a test suite. + +For a more information on these types of things see the :doc:`api/test`. + +Isolating Behavior +================== + +The most important aspect of unit testing that other forms of testing do not +provide is the ability to limit the amount of code under test to a single unit. +In practice, this is only possible by being able to control what code gets run +when the unit under test calls a function and this is usually accomplished +through some sort of indirection where a function is exposed as part of an API +such that the definition of that function can be changed without affecting the +rest of the code base. In the kernel this primarily comes from two constructs, +classes, structs that contain function pointers that are provided by the +implementer, and architecture specific functions which have definitions selected +at compile time. + +Classes +------- + +Classes are not a construct that is built into the C programming language; +however, it is an easily derived concept. Accordingly, pretty much every project +that does not use a standardized object oriented library (like GNOME's GObject) +has their own slightly different way of doing object oriented programming; the +Linux kernel is no exception. + +The central concept in kernel object oriented programming is the class. In the +kernel, a *class* is a struct that contains function pointers. This creates a +contract between *implementers* and *users* since it forces them to use the +same function signature without having to call the function directly. In order +for it to truly be a class, the function pointers must specify that a pointer +to the class, known as a *class handle*, be one of the parameters; this makes +it possible for the member functions (also known as *methods*) to have access +to member variables (more commonly known as *fields*) allowing the same +implementation to have multiple *instances*. + +Typically a class can be *overridden* by *child classes* by embedding the +*parent class* in the child class. Then when a method provided by the child +class is called, the child implementation knows that the pointer passed to it is +of a parent contained within the child; because of this, the child can compute +the pointer to itself because the pointer to the parent is always a fixed offset +from the pointer to the child; this offset is the offset of the parent contained +in the child struct. For example: + +.. code-block:: c + + struct shape { + int (*area)(struct shape *this); + }; + + struct rectangle { + struct shape parent; + int length; + int width; + }; + + int rectangle_area(struct shape *this) + { + struct rectangle *self = container_of(this, struct shape, parent); + + return self->length * self->width; + }; + + void rectangle_new(struct rectangle *self, int length, int width) + { + self->parent.area = rectangle_area; + self->length = length; + self->width = width; + } + +In this example (as in most kernel code) the operation of computing the pointer +to the child from the pointer to the parent is done by ``container_of``. + +Faking Classes +~~~~~~~~~~~~~~ + +In order to unit test a piece of code that calls a method in a class, the +behavior of the method must be controllable, otherwise the test ceases to be a +unit test and becomes an integration test. + +A fake just provides an implementation of a piece of code that is different than +what runs in a production instance, but behaves identically from the standpoint +of the callers; this is usually done to replace a dependency that is hard to +deal with, or is slow. + +A good example for this might be implementing a fake EEPROM that just stores the +"contents" in an internal buffer. For example, let's assume we have a class that +represents an EEPROM: + +.. code-block:: c + + struct eeprom { + ssize_t (*read)(struct eeprom *this, size_t offset, char *buffer, size_t count); + ssize_t (*write)(struct eeprom *this, size_t offset, const char *buffer, size_t count); + }; + +And we want to test some code that buffers writes to the EEPROM: + +.. code-block:: c + + struct eeprom_buffer { + ssize_t (*write)(struct eeprom_buffer *this, const char *buffer, size_t count); + int flush(struct eeprom_buffer *this); + size_t flush_count; /* Flushes when buffer exceeds flush_count. */ + }; + + struct eeprom_buffer *new_eeprom_buffer(struct eeprom *eeprom); + void destroy_eeprom_buffer(struct eeprom *eeprom); + +We can easily test this code by *faking out* the underlying EEPROM: + +.. code-block:: c + + struct fake_eeprom { + struct eeprom parent; + char contents[FAKE_EEPROM_CONTENTS_SIZE]; + }; + + ssize_t fake_eeprom_read(struct eeprom *parent, size_t offset, char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(buffer, this->contents + offset, count); + + return count; + } + + ssize_t fake_eeprom_write(struct eeprom *this, size_t offset, const char *buffer, size_t count) + { + struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent); + + count = min(count, FAKE_EEPROM_CONTENTS_SIZE - offset); + memcpy(this->contents + offset, buffer, count); + + return count; + } + + void fake_eeprom_init(struct fake_eeprom *this) + { + this->parent.read = fake_eeprom_read; + this->parent.write = fake_eeprom_write; + memset(this->contents, 0, FAKE_EEPROM_CONTENTS_SIZE); + } + +We can now use it to test ``struct eeprom_buffer``: + +.. code-block:: c + + struct eeprom_buffer_test { + struct fake_eeprom *fake_eeprom; + struct eeprom_buffer *eeprom_buffer; + }; + + static void eeprom_buffer_test_does_not_write_until_flush(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = SIZE_MAX; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0); + + eeprom_buffer->flush(eeprom_buffer); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_after_flush_count_met(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + } + + static void eeprom_buffer_test_flushes_increments_of_flush_count(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + struct eeprom_buffer *eeprom_buffer = ctx->eeprom_buffer; + struct fake_eeprom *fake_eeprom = ctx->fake_eeprom; + char buffer[] = {0xff, 0xff}; + + eeprom_buffer->flush_count = 2; + + eeprom_buffer->write(eeprom_buffer, buffer, 1); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0); + + eeprom_buffer->write(eeprom_buffer, buffer, 2); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[0], 0xff); + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[1], 0xff); + /* Should have only flushed the first two bytes. */ + KUNIT_EXPECT_EQ(test, fake_eeprom->contents[2], 0); + } + + static int eeprom_buffer_test_init(struct kunit *test) + { + struct eeprom_buffer_test *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->fake_eeprom = kunit_kzalloc(test, sizeof(*ctx->fake_eeprom), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->fake_eeprom); + fake_eeprom_init(ctx->fake_eeprom); + + ctx->eeprom_buffer = new_eeprom_buffer(&ctx->fake_eeprom->parent); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->eeprom_buffer); + + test->priv = ctx; + + return 0; + } + + static void eeprom_buffer_test_exit(struct kunit *test) + { + struct eeprom_buffer_test *ctx = test->priv; + + destroy_eeprom_buffer(ctx->eeprom_buffer); + } + +.. _kunit-on-non-uml: + +KUnit on non-UML architectures +============================== + +By default KUnit uses UML as a way to provide dependencies for code under test. +Under most circumstances KUnit's usage of UML should be treated as an +implementation detail of how KUnit works under the hood. Nevertheless, there +are instances where being able to run architecture specific code, or test +against real hardware is desirable. For these reasons KUnit supports running on +other architectures. + +Running existing KUnit tests on non-UML architectures +----------------------------------------------------- + +There are some special considerations when running existing KUnit tests on +non-UML architectures: + +* Hardware may not be deterministic, so a test that always passes or fails + when run under UML may not always do so on real hardware. +* Hardware and VM environments may not be hermetic. KUnit tries its best to + provide a hermetic environment to run tests; however, it cannot manage state + that it doesn't know about outside of the kernel. Consequently, tests that + may be hermetic on UML may not be hermetic on other architectures. +* Some features and tooling may not be supported outside of UML. +* Hardware and VMs are slower than UML. + +None of these are reasons not to run your KUnit tests on real hardware; they are +only things to be aware of when doing so. + +The biggest impediment will likely be that certain KUnit features and +infrastructure may not support your target environment. For example, at this +time the KUnit Wrapper (``tools/testing/kunit/kunit.py``) does not work outside +of UML. Unfortunately, there is no way around this. Using UML (or even just a +particular architecture) allows us to make a lot of assumptions that make it +possible to do things which might otherwise be impossible. + +Nevertheless, all core KUnit framework features are fully supported on all +architectures, and using them is straightforward: all you need to do is to take +your kunitconfig, your Kconfig options for the tests you would like to run, and +merge them into whatever config your are using for your platform. That's it! + +For example, let's say you have the following kunitconfig: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + +If you wanted to run this test on an x86 VM, you might add the following config +options to your ``.config``: + +.. code-block:: none + + CONFIG_KUNIT=y + CONFIG_KUNIT_EXAMPLE_TEST=y + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y + +All these new options do is enable support for a common serial console needed +for logging. + +Next, you could build a kernel with these tests as follows: + + +.. code-block:: bash + + make ARCH=x86 olddefconfig + make ARCH=x86 + +Once you have built a kernel, you could run it on QEMU as follows: + +.. code-block:: bash + + qemu-system-x86_64 -enable-kvm \ + -m 1024 \ + -kernel arch/x86_64/boot/bzImage \ + -append 'console=ttyS0' \ + --nographic + +Interspersed in the kernel logs you might see the following: + +.. code-block:: none + + TAP version 14 + # Subtest: example + 1..1 + # example_simple_test: initializing + ok 1 - example_simple_test + ok 1 - example + +Congratulations, you just ran a KUnit test on the x86 architecture! + +Writing new tests for other architectures +----------------------------------------- + +The first thing you must do is ask yourself whether it is necessary to write a +KUnit test for a specific architecture, and then whether it is necessary to +write that test for a particular piece of hardware. In general, writing a test +that depends on having access to a particular piece of hardware or software (not +included in the Linux source repo) should be avoided at all costs. + +Even if you only ever plan on running your KUnit test on your hardware +configuration, other people may want to run your tests and may not have access +to your hardware. If you write your test to run on UML, then anyone can run your +tests without knowing anything about your particular setup, and you can still +run your tests on your hardware setup just by compiling for your architecture. + +.. important:: + Always prefer tests that run on UML to tests that only run under a particular + architecture, and always prefer tests that run under QEMU or another easy + (and monitarily free) to obtain software environment to a specific piece of + hardware. + +Nevertheless, there are still valid reasons to write an architecture or hardware +specific test: for example, you might want to test some code that really belongs +in ``arch/some-arch/*``. Even so, try your best to write the test so that it +does not depend on physical hardware: if some of your test cases don't need the +hardware, only require the hardware for tests that actually need it. + +Now that you have narrowed down exactly what bits are hardware specific, the +actual procedure for writing and running the tests is pretty much the same as +writing normal KUnit tests. One special caveat is that you have to reset +hardware state in between test cases; if this is not possible, you may only be +able to run one test case per invocation. + +.. TODO(brendanhiggins@google.com): Add an actual example of an architecture + dependent KUnit test. -- 2.23.0.351.gc4317032e6-goog _______________________________________________ linux-um mailing list linux-um@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-um