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=-9.5 required=3.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, 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 9FD50C3A5A2 for ; Fri, 20 Sep 2019 23:53:39 +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 6AF912073F for ; Fri, 20 Sep 2019 23:53:39 +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="N26H16Pe" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6AF912073F 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 29225202ECFDD; Fri, 20 Sep 2019 16:52:34 -0700 (PDT) Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::d49; helo=mail-io1-xd49.google.com; envelope-from=3jv6fxq4kdfivby7xu7120027c08805y.w86527eh-7fx26652cdc.kl.8b0@flex--brendanhiggins.bounces.google.com; receiver=linux-nvdimm@lists.01.org Received: from mail-io1-xd49.google.com (mail-io1-xd49.google.com [IPv6:2607:f8b0:4864:20::d49]) (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 ECD47202ECFD5 for ; Fri, 20 Sep 2019 16:52:32 -0700 (PDT) Received: by mail-io1-xd49.google.com with SMTP id a22so9098928ioq.23 for ; Fri, 20 Sep 2019 16:53:38 -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=LlDxu00B0OzvuovDosveyIDw8KU4lJ2GOfkiYezINd8=; b=N26H16PeB92Pzl6lPp6nCfT+PilgL6qd85S4+vwAeEm5comxKddmbwGtBxoLj4T1+N T+lecaE+9ZZeldFL3k/DkhRxX8yMw97FJ6x92hwdekFFNniWW1TV5I6GbmogeZ4wfA5+ sUgHP98H+KnzB2pLcRO0rLPv13vj0ttmDpASE8HJdss9c+my2i/GFEmz59rRn088VlUj LYylutT8CRHcSWwLlMZkQFhXEIP5lD9IVGgphY7eWfr93254WKcsCQz8wt6L5oKvqfRh 7H0/ZibYNiEQ5Ps+hZu89r8VJsrEckOJvBqvxLO506mXaqFZkbbaMQ7q27GZQa3VYtFT ZTLg== 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=LlDxu00B0OzvuovDosveyIDw8KU4lJ2GOfkiYezINd8=; b=tI38eZ0QzzTj18St9+ntl645syOF1tM34ct/eWLxuTzQ38NYogtw5Y/Gxep/f2060O Oit/Fx6GQndFyvI8NR2ZGEUePi4xz0ByZhTs0HCrasMyiRMO/kHx7tH87WqtCcj2KNMm wBALdhn9DiviqikyI2pnyJ7WSksAYDAJObseJxNx/tpnkdSSV4R1uckZQuAfJtd2lwXC 8Lt6hwOjEbXOvqa3s2MEhKA+cmFuII+IuwYXITH6sKxtFtWxkkcOwC9XREyBoHXo8ohC qgdIebtjEAsZM7oZNc8+Zad6j7mwoCMVy7NMfxLvLhPwPWFaUkcR7xRY4QgZr32xmBqU 6NFQ== X-Gm-Message-State: APjAAAV6sCEuhG6xKZ9fy8M7rfjovglRNK3UtF/4hQVuc5Ocjy/Ju6km QuVVaOOC9hWeYcw0zRLuRCezm2lOaKD5cp5ujzGhXQ== X-Google-Smtp-Source: APXvYqxYpiSSezL4EG3ijvlKNO9++PDpIPGbhjXWKA9Xrb1cR6wNPpVZ0+z9/2xJ07dTCq1EyvkcGxiw+rsRAZg5Ek5ljA== X-Received: by 2002:a63:d901:: with SMTP id r1mr17831768pgg.159.1569021581598; Fri, 20 Sep 2019 16:19:41 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:05 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-2-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 01/19] kunit: test: add KUnit test runner core 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, linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, 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 core facilities for defining unit tests; this provides a common way to define test cases, functions that execute code which is under test and determine whether the code under test behaves as expected; this also provides a way to group together related test cases in test suites (here we call them test_modules). Just define test cases and how to execute them for now; setting expectations on code will be defined later. Signed-off-by: Brendan Higgins Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Luis Chamberlain Reviewed-by: Stephen Boyd --- include/kunit/test.h | 188 ++++++++++++++++++++++++++++++++++++++++++ lib/kunit/Kconfig | 17 ++++ lib/kunit/Makefile | 1 + lib/kunit/test.c | 191 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+) create mode 100644 include/kunit/test.h create mode 100644 lib/kunit/Kconfig create mode 100644 lib/kunit/Makefile create mode 100644 lib/kunit/test.c diff --git a/include/kunit/test.h b/include/kunit/test.h new file mode 100644 index 000000000000..e30d1bf2fb68 --- /dev/null +++ b/include/kunit/test.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#ifndef _KUNIT_TEST_H +#define _KUNIT_TEST_H + +#include + +struct kunit; + +/** + * struct kunit_case - represents an individual test case. + * + * @run_case: the function representing the actual test case. + * @name: the name of the test case. + * + * A test case is a function with the signature, + * ``void (*)(struct kunit *)`` that makes expectations (see + * KUNIT_EXPECT_TRUE()) about code under test. Each test case is associated + * with a &struct kunit_suite and will be run after the suite's init + * function and followed by the suite's exit function. + * + * A test case should be static and should only be created with the + * KUNIT_CASE() macro; additionally, every array of test cases should be + * terminated with an empty test case. + * + * 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)); + * KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + * KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + * KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + * } + * + * static struct kunit_case example_test_cases[] = { + * KUNIT_CASE(add_test_basic), + * {} + * }; + * + */ +struct kunit_case { + void (*run_case)(struct kunit *test); + const char *name; + + /* private: internal use only. */ + bool success; +}; + +/** + * KUNIT_CASE - A helper for creating a &struct kunit_case + * + * @test_name: a reference to a test case function. + * + * Takes a symbol for a function representing a test case and creates a + * &struct kunit_case object from it. See the documentation for + * &struct kunit_case for an example on how to use it. + */ +#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } + +/** + * struct kunit_suite - describes a related collection of &struct kunit_case + * + * @name: the name of the test. Purely informational. + * @init: called before every test case. + * @exit: called after every test case. + * @test_cases: a null terminated array of test cases. + * + * A kunit_suite is a collection of related &struct kunit_case s, such that + * @init is called before every test case and @exit is called after every + * test case, similar to the notion of a *test fixture* or a *test class* + * in other unit testing frameworks like JUnit or Googletest. + * + * Every &struct kunit_case must be associated with a kunit_suite for KUnit + * to run it. + */ +struct kunit_suite { + const char name[256]; + int (*init)(struct kunit *test); + void (*exit)(struct kunit *test); + struct kunit_case *test_cases; +}; + +/** + * struct kunit - represents a running instance of a test. + * + * @priv: for user to store arbitrary data. Commonly used to pass data + * created in the init function (see &struct kunit_suite). + * + * Used to store information about the current context under which the test + * is running. Most of this data is private and should only be accessed + * indirectly via public functions; the one exception is @priv which can be + * used by the test writer to store arbitrary data. + */ +struct kunit { + void *priv; + + /* private: internal use only. */ + const char *name; /* Read only after initialization! */ + /* + * success starts as true, and may only be set to false during a + * test case; thus, it is safe to update this across multiple + * threads using WRITE_ONCE; however, as a consequence, it may only + * be read after the test case finishes once all threads associated + * with the test case have terminated. + */ + bool success; /* Read only after test_case finishes! */ +}; + +void kunit_init_test(struct kunit *test, const char *name); + +int kunit_run_tests(struct kunit_suite *suite); + +/** + * kunit_test_suite() - used to register a &struct kunit_suite with KUnit. + * + * @suite: a statically allocated &struct kunit_suite. + * + * Registers @suite with the test framework. See &struct kunit_suite for + * more information. + * + * NOTE: Currently KUnit tests are all run as late_initcalls; this means + * that they cannot test anything where tests must run at a different init + * phase. One significant restriction resulting from this is that KUnit + * cannot reliably test anything that is initialize in the late_init phase; + * another is that KUnit is useless to test things that need to be run in + * an earlier init phase. + * + * TODO(brendanhiggins@google.com): Don't run all KUnit tests as + * late_initcalls. I have some future work planned to dispatch all KUnit + * tests from the same place, and at the very least to do so after + * everything else is definitely initialized. + */ +#define kunit_test_suite(suite) \ + static int kunit_suite_init##suite(void) \ + { \ + return kunit_run_tests(&suite); \ + } \ + late_initcall(kunit_suite_init##suite) + +void __printf(3, 4) kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...); + +/** + * kunit_info() - Prints an INFO level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an info level message associated with the test suite being run. + * Takes a variable number of format parameters just like printk(). + */ +#define kunit_info(test, fmt, ...) \ + kunit_printk(KERN_INFO, test, fmt, ##__VA_ARGS__) + +/** + * kunit_warn() - Prints a WARN level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints a warning level message. + */ +#define kunit_warn(test, fmt, ...) \ + kunit_printk(KERN_WARNING, test, fmt, ##__VA_ARGS__) + +/** + * kunit_err() - Prints an ERROR level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an error level message. + */ +#define kunit_err(test, fmt, ...) \ + kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__) + +#endif /* _KUNIT_TEST_H */ diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig new file mode 100644 index 000000000000..330ae83527c2 --- /dev/null +++ b/lib/kunit/Kconfig @@ -0,0 +1,17 @@ +# +# KUnit base configuration +# + +menu "KUnit support" + +config KUNIT + bool "Enable support for unit tests (KUnit)" + help + Enables support for kernel unit tests (KUnit), 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 when using UML. Can also be used on most other + architectures. For more information, please see + Documentation/dev-tools/kunit/. + +endmenu diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile new file mode 100644 index 000000000000..5efdc4dea2c0 --- /dev/null +++ b/lib/kunit/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KUNIT) += test.o diff --git a/lib/kunit/test.c b/lib/kunit/test.c new file mode 100644 index 000000000000..d3dda359f99b --- /dev/null +++ b/lib/kunit/test.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#include +#include + +static void kunit_set_failure(struct kunit *test) +{ + WRITE_ONCE(test->success, false); +} + +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) +{ + return vprintk_emit(0, level, NULL, 0, fmt, args); +} + +static int kunit_printk_emit(int level, const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = kunit_vprintk_emit(level, fmt, args); + va_end(args); + + return ret; +} + +static void kunit_vprintk(const struct kunit *test, + const char *level, + struct va_format *vaf) +{ + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); +} + +static void kunit_print_tap_version(void) +{ + static bool kunit_has_printed_tap_version; + + if (!kunit_has_printed_tap_version) { + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); + kunit_has_printed_tap_version = true; + } +} + +static size_t kunit_test_cases_len(struct kunit_case *test_cases) +{ + struct kunit_case *test_case; + size_t len = 0; + + for (test_case = test_cases; test_case->run_case; test_case++) + len++; + + return len; +} + +static void kunit_print_subtest_start(struct kunit_suite *suite) +{ + kunit_print_tap_version(); + kunit_printk_emit(LOGLEVEL_INFO, "\t# Subtest: %s\n", suite->name); + kunit_printk_emit(LOGLEVEL_INFO, + "\t1..%zd\n", + kunit_test_cases_len(suite->test_cases)); +} + +static void kunit_print_ok_not_ok(bool should_indent, + bool is_ok, + size_t test_number, + const char *description) +{ + const char *indent, *ok_not_ok; + + if (should_indent) + indent = "\t"; + else + indent = ""; + + if (is_ok) + ok_not_ok = "ok"; + else + ok_not_ok = "not ok"; + + kunit_printk_emit(LOGLEVEL_INFO, + "%s%s %zd - %s\n", + indent, ok_not_ok, test_number, description); +} + +static bool kunit_suite_has_succeeded(struct kunit_suite *suite) +{ + const struct kunit_case *test_case; + + for (test_case = suite->test_cases; test_case->run_case; test_case++) + if (!test_case->success) + return false; + + return true; +} + +static void kunit_print_subtest_end(struct kunit_suite *suite) +{ + static size_t kunit_suite_counter = 1; + + kunit_print_ok_not_ok(false, + kunit_suite_has_succeeded(suite), + kunit_suite_counter++, + suite->name); +} + +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, + size_t test_number) +{ + kunit_print_ok_not_ok(true, + test_case->success, + test_number, + test_case->name); +} + +void kunit_init_test(struct kunit *test, const char *name) +{ + test->name = name; + test->success = true; +} + +/* + * Performs all logic to run a test case. + */ +static void kunit_run_case(struct kunit_suite *suite, + struct kunit_case *test_case) +{ + struct kunit test; + + kunit_init_test(&test, test_case->name); + + if (suite->init) { + int ret; + + ret = suite->init(&test); + if (ret) { + kunit_err(&test, "failed to initialize: %d\n", ret); + kunit_set_failure(&test); + test_case->success = test.success; + return; + } + } + + test_case->run_case(&test); + + if (suite->exit) + suite->exit(&test); + + test_case->success = test.success; +} + +int kunit_run_tests(struct kunit_suite *suite) +{ + struct kunit_case *test_case; + size_t test_case_count = 1; + + kunit_print_subtest_start(suite); + + for (test_case = suite->test_cases; test_case->run_case; test_case++) { + kunit_run_case(suite, test_case); + kunit_print_test_case_ok_not_ok(test_case, test_case_count++); + } + + kunit_print_subtest_end(suite); + + return 0; +} + +void kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + kunit_vprintk(test, level, &vaf); + + va_end(args); +} -- 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=-17.4 required=3.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, 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 A7C65C3A5A2 for ; Fri, 20 Sep 2019 23:19:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 627252070C for ; Fri, 20 Sep 2019 23:19:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="N26H16Pe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2436989AbfITXTt (ORCPT ); Fri, 20 Sep 2019 19:19:49 -0400 Received: from mail-pl1-f201.google.com ([209.85.214.201]:44536 "EHLO mail-pl1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2394059AbfITXTo (ORCPT ); Fri, 20 Sep 2019 19:19:44 -0400 Received: by mail-pl1-f201.google.com with SMTP id h11so5394697plt.11 for ; Fri, 20 Sep 2019 16:19:42 -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=LlDxu00B0OzvuovDosveyIDw8KU4lJ2GOfkiYezINd8=; b=N26H16PeB92Pzl6lPp6nCfT+PilgL6qd85S4+vwAeEm5comxKddmbwGtBxoLj4T1+N T+lecaE+9ZZeldFL3k/DkhRxX8yMw97FJ6x92hwdekFFNniWW1TV5I6GbmogeZ4wfA5+ sUgHP98H+KnzB2pLcRO0rLPv13vj0ttmDpASE8HJdss9c+my2i/GFEmz59rRn088VlUj LYylutT8CRHcSWwLlMZkQFhXEIP5lD9IVGgphY7eWfr93254WKcsCQz8wt6L5oKvqfRh 7H0/ZibYNiEQ5Ps+hZu89r8VJsrEckOJvBqvxLO506mXaqFZkbbaMQ7q27GZQa3VYtFT ZTLg== 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=LlDxu00B0OzvuovDosveyIDw8KU4lJ2GOfkiYezINd8=; b=mKEZ+kx4eMiaO1vOqHELVVt/sA0Tzhfs9O2vXwtAkAlD7As5Uc5aFdjlCoCtfZrUNU HVz2JPW0IJIDb+dCNhshM2tnsfJrKrVw0HEcWypNaBBiwAN81o261TBT+CB+LLnb4prd L8FGNiavhrH2kD4gDpytweQ60heBcHDSVP9MnC09yoq+VOqTADHAMkaofgH0RGKip1VC HUDlh0mc7hXes0P9d9pmLZ4YJdP1HISZgvWs6k3U0e7V2bS/18Ljloc75ta6qFcSNYzh 0p+uG9EhfGTkRG0YL8CIh7XGTrsHzmXucfBrg5mwGfsE+61sRleNRB6hmJA2g0W+yzuw AKeg== X-Gm-Message-State: APjAAAXkU8ogMBkfZ9WhDtsGZfPkNyQp5bNNalQ+h52Axj0BGzdbNw15 lymkdPzAEauBe16/Yf35Kcj26s6/OXUFtdq0a6vOiQ== X-Google-Smtp-Source: APXvYqxYpiSSezL4EG3ijvlKNO9++PDpIPGbhjXWKA9Xrb1cR6wNPpVZ0+z9/2xJ07dTCq1EyvkcGxiw+rsRAZg5Ek5ljA== X-Received: by 2002:a63:d901:: with SMTP id r1mr17831768pgg.159.1569021581598; Fri, 20 Sep 2019 16:19:41 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:05 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-2-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 01/19] kunit: test: add KUnit test runner core 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 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 core facilities for defining unit tests; this provides a common way to define test cases, functions that execute code which is under test and determine whether the code under test behaves as expected; this also provides a way to group together related test cases in test suites (here we call them test_modules). Just define test cases and how to execute them for now; setting expectations on code will be defined later. Signed-off-by: Brendan Higgins Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Luis Chamberlain Reviewed-by: Stephen Boyd --- include/kunit/test.h | 188 ++++++++++++++++++++++++++++++++++++++++++ lib/kunit/Kconfig | 17 ++++ lib/kunit/Makefile | 1 + lib/kunit/test.c | 191 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+) create mode 100644 include/kunit/test.h create mode 100644 lib/kunit/Kconfig create mode 100644 lib/kunit/Makefile create mode 100644 lib/kunit/test.c diff --git a/include/kunit/test.h b/include/kunit/test.h new file mode 100644 index 000000000000..e30d1bf2fb68 --- /dev/null +++ b/include/kunit/test.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#ifndef _KUNIT_TEST_H +#define _KUNIT_TEST_H + +#include + +struct kunit; + +/** + * struct kunit_case - represents an individual test case. + * + * @run_case: the function representing the actual test case. + * @name: the name of the test case. + * + * A test case is a function with the signature, + * ``void (*)(struct kunit *)`` that makes expectations (see + * KUNIT_EXPECT_TRUE()) about code under test. Each test case is associated + * with a &struct kunit_suite and will be run after the suite's init + * function and followed by the suite's exit function. + * + * A test case should be static and should only be created with the + * KUNIT_CASE() macro; additionally, every array of test cases should be + * terminated with an empty test case. + * + * 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)); + * KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + * KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + * KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + * } + * + * static struct kunit_case example_test_cases[] = { + * KUNIT_CASE(add_test_basic), + * {} + * }; + * + */ +struct kunit_case { + void (*run_case)(struct kunit *test); + const char *name; + + /* private: internal use only. */ + bool success; +}; + +/** + * KUNIT_CASE - A helper for creating a &struct kunit_case + * + * @test_name: a reference to a test case function. + * + * Takes a symbol for a function representing a test case and creates a + * &struct kunit_case object from it. See the documentation for + * &struct kunit_case for an example on how to use it. + */ +#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } + +/** + * struct kunit_suite - describes a related collection of &struct kunit_case + * + * @name: the name of the test. Purely informational. + * @init: called before every test case. + * @exit: called after every test case. + * @test_cases: a null terminated array of test cases. + * + * A kunit_suite is a collection of related &struct kunit_case s, such that + * @init is called before every test case and @exit is called after every + * test case, similar to the notion of a *test fixture* or a *test class* + * in other unit testing frameworks like JUnit or Googletest. + * + * Every &struct kunit_case must be associated with a kunit_suite for KUnit + * to run it. + */ +struct kunit_suite { + const char name[256]; + int (*init)(struct kunit *test); + void (*exit)(struct kunit *test); + struct kunit_case *test_cases; +}; + +/** + * struct kunit - represents a running instance of a test. + * + * @priv: for user to store arbitrary data. Commonly used to pass data + * created in the init function (see &struct kunit_suite). + * + * Used to store information about the current context under which the test + * is running. Most of this data is private and should only be accessed + * indirectly via public functions; the one exception is @priv which can be + * used by the test writer to store arbitrary data. + */ +struct kunit { + void *priv; + + /* private: internal use only. */ + const char *name; /* Read only after initialization! */ + /* + * success starts as true, and may only be set to false during a + * test case; thus, it is safe to update this across multiple + * threads using WRITE_ONCE; however, as a consequence, it may only + * be read after the test case finishes once all threads associated + * with the test case have terminated. + */ + bool success; /* Read only after test_case finishes! */ +}; + +void kunit_init_test(struct kunit *test, const char *name); + +int kunit_run_tests(struct kunit_suite *suite); + +/** + * kunit_test_suite() - used to register a &struct kunit_suite with KUnit. + * + * @suite: a statically allocated &struct kunit_suite. + * + * Registers @suite with the test framework. See &struct kunit_suite for + * more information. + * + * NOTE: Currently KUnit tests are all run as late_initcalls; this means + * that they cannot test anything where tests must run at a different init + * phase. One significant restriction resulting from this is that KUnit + * cannot reliably test anything that is initialize in the late_init phase; + * another is that KUnit is useless to test things that need to be run in + * an earlier init phase. + * + * TODO(brendanhiggins@google.com): Don't run all KUnit tests as + * late_initcalls. I have some future work planned to dispatch all KUnit + * tests from the same place, and at the very least to do so after + * everything else is definitely initialized. + */ +#define kunit_test_suite(suite) \ + static int kunit_suite_init##suite(void) \ + { \ + return kunit_run_tests(&suite); \ + } \ + late_initcall(kunit_suite_init##suite) + +void __printf(3, 4) kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...); + +/** + * kunit_info() - Prints an INFO level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an info level message associated with the test suite being run. + * Takes a variable number of format parameters just like printk(). + */ +#define kunit_info(test, fmt, ...) \ + kunit_printk(KERN_INFO, test, fmt, ##__VA_ARGS__) + +/** + * kunit_warn() - Prints a WARN level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints a warning level message. + */ +#define kunit_warn(test, fmt, ...) \ + kunit_printk(KERN_WARNING, test, fmt, ##__VA_ARGS__) + +/** + * kunit_err() - Prints an ERROR level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an error level message. + */ +#define kunit_err(test, fmt, ...) \ + kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__) + +#endif /* _KUNIT_TEST_H */ diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig new file mode 100644 index 000000000000..330ae83527c2 --- /dev/null +++ b/lib/kunit/Kconfig @@ -0,0 +1,17 @@ +# +# KUnit base configuration +# + +menu "KUnit support" + +config KUNIT + bool "Enable support for unit tests (KUnit)" + help + Enables support for kernel unit tests (KUnit), 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 when using UML. Can also be used on most other + architectures. For more information, please see + Documentation/dev-tools/kunit/. + +endmenu diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile new file mode 100644 index 000000000000..5efdc4dea2c0 --- /dev/null +++ b/lib/kunit/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KUNIT) += test.o diff --git a/lib/kunit/test.c b/lib/kunit/test.c new file mode 100644 index 000000000000..d3dda359f99b --- /dev/null +++ b/lib/kunit/test.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#include +#include + +static void kunit_set_failure(struct kunit *test) +{ + WRITE_ONCE(test->success, false); +} + +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) +{ + return vprintk_emit(0, level, NULL, 0, fmt, args); +} + +static int kunit_printk_emit(int level, const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = kunit_vprintk_emit(level, fmt, args); + va_end(args); + + return ret; +} + +static void kunit_vprintk(const struct kunit *test, + const char *level, + struct va_format *vaf) +{ + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); +} + +static void kunit_print_tap_version(void) +{ + static bool kunit_has_printed_tap_version; + + if (!kunit_has_printed_tap_version) { + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); + kunit_has_printed_tap_version = true; + } +} + +static size_t kunit_test_cases_len(struct kunit_case *test_cases) +{ + struct kunit_case *test_case; + size_t len = 0; + + for (test_case = test_cases; test_case->run_case; test_case++) + len++; + + return len; +} + +static void kunit_print_subtest_start(struct kunit_suite *suite) +{ + kunit_print_tap_version(); + kunit_printk_emit(LOGLEVEL_INFO, "\t# Subtest: %s\n", suite->name); + kunit_printk_emit(LOGLEVEL_INFO, + "\t1..%zd\n", + kunit_test_cases_len(suite->test_cases)); +} + +static void kunit_print_ok_not_ok(bool should_indent, + bool is_ok, + size_t test_number, + const char *description) +{ + const char *indent, *ok_not_ok; + + if (should_indent) + indent = "\t"; + else + indent = ""; + + if (is_ok) + ok_not_ok = "ok"; + else + ok_not_ok = "not ok"; + + kunit_printk_emit(LOGLEVEL_INFO, + "%s%s %zd - %s\n", + indent, ok_not_ok, test_number, description); +} + +static bool kunit_suite_has_succeeded(struct kunit_suite *suite) +{ + const struct kunit_case *test_case; + + for (test_case = suite->test_cases; test_case->run_case; test_case++) + if (!test_case->success) + return false; + + return true; +} + +static void kunit_print_subtest_end(struct kunit_suite *suite) +{ + static size_t kunit_suite_counter = 1; + + kunit_print_ok_not_ok(false, + kunit_suite_has_succeeded(suite), + kunit_suite_counter++, + suite->name); +} + +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, + size_t test_number) +{ + kunit_print_ok_not_ok(true, + test_case->success, + test_number, + test_case->name); +} + +void kunit_init_test(struct kunit *test, const char *name) +{ + test->name = name; + test->success = true; +} + +/* + * Performs all logic to run a test case. + */ +static void kunit_run_case(struct kunit_suite *suite, + struct kunit_case *test_case) +{ + struct kunit test; + + kunit_init_test(&test, test_case->name); + + if (suite->init) { + int ret; + + ret = suite->init(&test); + if (ret) { + kunit_err(&test, "failed to initialize: %d\n", ret); + kunit_set_failure(&test); + test_case->success = test.success; + return; + } + } + + test_case->run_case(&test); + + if (suite->exit) + suite->exit(&test); + + test_case->success = test.success; +} + +int kunit_run_tests(struct kunit_suite *suite) +{ + struct kunit_case *test_case; + size_t test_case_count = 1; + + kunit_print_subtest_start(suite); + + for (test_case = suite->test_cases; test_case->run_case; test_case++) { + kunit_run_case(suite, test_case); + kunit_print_test_case_ok_not_ok(test_case, test_case_count++); + } + + kunit_print_subtest_end(suite); + + return 0; +} + +void kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + kunit_vprintk(test, level, &vaf); + + va_end(args); +} -- 2.23.0.351.gc4317032e6-goog From mboxrd@z Thu Jan 1 00:00:00 1970 From: Brendan Higgins Subject: [PATCH v16 01/19] kunit: test: add KUnit test runner core Date: Fri, 20 Sep 2019 16:19:05 -0700 Message-ID: <20190920231923.141900-2-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, linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, 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 QWRkIGNvcmUgZmFjaWxpdGllcyBmb3IgZGVmaW5pbmcgdW5pdCB0ZXN0czsgdGhpcyBwcm92aWRl cyBhIGNvbW1vbiB3YXkKdG8gZGVmaW5lIHRlc3QgY2FzZXMsIGZ1bmN0aW9ucyB0aGF0IGV4ZWN1 dGUgY29kZSB3aGljaCBpcyB1bmRlciB0ZXN0CmFuZCBkZXRlcm1pbmUgd2hldGhlciB0aGUgY29k ZSB1bmRlciB0ZXN0IGJlaGF2ZXMgYXMgZXhwZWN0ZWQ7IHRoaXMgYWxzbwpwcm92aWRlcyBhIHdh eSB0byBncm91cCB0b2dldGhlciByZWxhdGVkIHRlc3QgY2FzZXMgaW4gdGVzdCBzdWl0ZXMgKGhl cmUKd2UgY2FsbCB0aGVtIHRlc3RfbW9kdWxlcykuCgpKdXN0IGRlZmluZSB0ZXN0IGNhc2VzIGFu ZCBob3cgdG8gZXhlY3V0ZSB0aGVtIGZvciBub3c7IHNldHRpbmcKZXhwZWN0YXRpb25zIG9uIGNv ZGUgd2lsbCBiZSBkZWZpbmVkIGxhdGVyLgoKU2lnbmVkLW9mZi1ieTogQnJlbmRhbiBIaWdnaW5z IDxicmVuZGFuaGlnZ2luc0Bnb29nbGUuY29tPgpSZXZpZXdlZC1ieTogR3JlZyBLcm9haC1IYXJ0 bWFuIDxncmVna2hAbGludXhmb3VuZGF0aW9uLm9yZz4KUmV2aWV3ZWQtYnk6IExvZ2FuIEd1bnRo b3JwZSA8bG9nYW5nQGRlbHRhdGVlLmNvbT4KUmV2aWV3ZWQtYnk6IEx1aXMgQ2hhbWJlcmxhaW4g PG1jZ3JvZkBrZXJuZWwub3JnPgpSZXZpZXdlZC1ieTogU3RlcGhlbiBCb3lkIDxzYm95ZEBrZXJu ZWwub3JnPgotLS0KIGluY2x1ZGUva3VuaXQvdGVzdC5oIHwgMTg4ICsrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKwogbGliL2t1bml0L0tjb25maWcgICAgfCAgMTcgKysr KwogbGliL2t1bml0L01ha2VmaWxlICAgfCAgIDEgKwogbGliL2t1bml0L3Rlc3QuYyAgICAgfCAx OTEgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogNCBmaWxlcyBj aGFuZ2VkLCAzOTcgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUva3Vu aXQvdGVzdC5oCiBjcmVhdGUgbW9kZSAxMDA2NDQgbGliL2t1bml0L0tjb25maWcKIGNyZWF0ZSBt b2RlIDEwMDY0NCBsaWIva3VuaXQvTWFrZWZpbGUKIGNyZWF0ZSBtb2RlIDEwMDY0NCBsaWIva3Vu aXQvdGVzdC5jCgpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9rdW5pdC90ZXN0LmggYi9pbmNsdWRlL2t1 bml0L3Rlc3QuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMDAuLmUzMGQx YmYyZmI2OAotLS0gL2Rldi9udWxsCisrKyBiL2luY2x1ZGUva3VuaXQvdGVzdC5oCkBAIC0wLDAg KzEsMTg4IEBACisvKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCAqLworLyoKKyAq IEJhc2UgdW5pdCB0ZXN0IChLVW5pdCkgQVBJLgorICoKKyAqIENvcHlyaWdodCAoQykgMjAxOSwg R29vZ2xlIExMQy4KKyAqIEF1dGhvcjogQnJlbmRhbiBIaWdnaW5zIDxicmVuZGFuaGlnZ2luc0Bn b29nbGUuY29tPgorICovCisKKyNpZm5kZWYgX0tVTklUX1RFU1RfSAorI2RlZmluZSBfS1VOSVRf VEVTVF9ICisKKyNpbmNsdWRlIDxsaW51eC90eXBlcy5oPgorCitzdHJ1Y3Qga3VuaXQ7CisKKy8q KgorICogc3RydWN0IGt1bml0X2Nhc2UgLSByZXByZXNlbnRzIGFuIGluZGl2aWR1YWwgdGVzdCBj YXNlLgorICoKKyAqIEBydW5fY2FzZTogdGhlIGZ1bmN0aW9uIHJlcHJlc2VudGluZyB0aGUgYWN0 dWFsIHRlc3QgY2FzZS4KKyAqIEBuYW1lOiAgICAgdGhlIG5hbWUgb2YgdGhlIHRlc3QgY2FzZS4K KyAqCisgKiBBIHRlc3QgY2FzZSBpcyBhIGZ1bmN0aW9uIHdpdGggdGhlIHNpZ25hdHVyZSwKKyAq IGBgdm9pZCAoKikoc3RydWN0IGt1bml0ICopYGAgdGhhdCBtYWtlcyBleHBlY3RhdGlvbnMgKHNl ZQorICogS1VOSVRfRVhQRUNUX1RSVUUoKSkgYWJvdXQgY29kZSB1bmRlciB0ZXN0LiBFYWNoIHRl c3QgY2FzZSBpcyBhc3NvY2lhdGVkCisgKiB3aXRoIGEgJnN0cnVjdCBrdW5pdF9zdWl0ZSBhbmQg d2lsbCBiZSBydW4gYWZ0ZXIgdGhlIHN1aXRlJ3MgaW5pdAorICogZnVuY3Rpb24gYW5kIGZvbGxv d2VkIGJ5IHRoZSBzdWl0ZSdzIGV4aXQgZnVuY3Rpb24uCisgKgorICogQSB0ZXN0IGNhc2Ugc2hv dWxkIGJlIHN0YXRpYyBhbmQgc2hvdWxkIG9ubHkgYmUgY3JlYXRlZCB3aXRoIHRoZQorICogS1VO SVRfQ0FTRSgpIG1hY3JvOyBhZGRpdGlvbmFsbHksIGV2ZXJ5IGFycmF5IG9mIHRlc3QgY2FzZXMg c2hvdWxkIGJlCisgKiB0ZXJtaW5hdGVkIHdpdGggYW4gZW1wdHkgdGVzdCBjYXNlLgorICoKKyAq IEV4YW1wbGU6CisgKgorICogLi4gY29kZS1ibG9jazo6IGMKKyAqCisgKgl2b2lkIGFkZF90ZXN0 X2Jhc2ljKHN0cnVjdCBrdW5pdCAqdGVzdCkKKyAqCXsKKyAqCQlLVU5JVF9FWFBFQ1RfRVEodGVz dCwgMSwgYWRkKDEsIDApKTsKKyAqCQlLVU5JVF9FWFBFQ1RfRVEodGVzdCwgMiwgYWRkKDEsIDEp KTsKKyAqCQlLVU5JVF9FWFBFQ1RfRVEodGVzdCwgMCwgYWRkKC0xLCAxKSk7CisgKgkJS1VOSVRf RVhQRUNUX0VRKHRlc3QsIElOVF9NQVgsIGFkZCgwLCBJTlRfTUFYKSk7CisgKgkJS1VOSVRfRVhQ RUNUX0VRKHRlc3QsIC0xLCBhZGQoSU5UX01BWCwgSU5UX01JTikpOworICoJfQorICoKKyAqCXN0 YXRpYyBzdHJ1Y3Qga3VuaXRfY2FzZSBleGFtcGxlX3Rlc3RfY2FzZXNbXSA9IHsKKyAqCQlLVU5J VF9DQVNFKGFkZF90ZXN0X2Jhc2ljKSwKKyAqCQl7fQorICoJfTsKKyAqCisgKi8KK3N0cnVjdCBr dW5pdF9jYXNlIHsKKwl2b2lkICgqcnVuX2Nhc2UpKHN0cnVjdCBrdW5pdCAqdGVzdCk7CisJY29u c3QgY2hhciAqbmFtZTsKKworCS8qIHByaXZhdGU6IGludGVybmFsIHVzZSBvbmx5LiAqLworCWJv b2wgc3VjY2VzczsKK307CisKKy8qKgorICogS1VOSVRfQ0FTRSAtIEEgaGVscGVyIGZvciBjcmVh dGluZyBhICZzdHJ1Y3Qga3VuaXRfY2FzZQorICoKKyAqIEB0ZXN0X25hbWU6IGEgcmVmZXJlbmNl IHRvIGEgdGVzdCBjYXNlIGZ1bmN0aW9uLgorICoKKyAqIFRha2VzIGEgc3ltYm9sIGZvciBhIGZ1 bmN0aW9uIHJlcHJlc2VudGluZyBhIHRlc3QgY2FzZSBhbmQgY3JlYXRlcyBhCisgKiAmc3RydWN0 IGt1bml0X2Nhc2Ugb2JqZWN0IGZyb20gaXQuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBmb3IKKyAq ICZzdHJ1Y3Qga3VuaXRfY2FzZSBmb3IgYW4gZXhhbXBsZSBvbiBob3cgdG8gdXNlIGl0LgorICov CisjZGVmaW5lIEtVTklUX0NBU0UodGVzdF9uYW1lKSB7IC5ydW5fY2FzZSA9IHRlc3RfbmFtZSwg Lm5hbWUgPSAjdGVzdF9uYW1lIH0KKworLyoqCisgKiBzdHJ1Y3Qga3VuaXRfc3VpdGUgLSBkZXNj cmliZXMgYSByZWxhdGVkIGNvbGxlY3Rpb24gb2YgJnN0cnVjdCBrdW5pdF9jYXNlCisgKgorICog QG5hbWU6CXRoZSBuYW1lIG9mIHRoZSB0ZXN0LiBQdXJlbHkgaW5mb3JtYXRpb25hbC4KKyAqIEBp bml0OgljYWxsZWQgYmVmb3JlIGV2ZXJ5IHRlc3QgY2FzZS4KKyAqIEBleGl0OgljYWxsZWQgYWZ0 ZXIgZXZlcnkgdGVzdCBjYXNlLgorICogQHRlc3RfY2FzZXM6CWEgbnVsbCB0ZXJtaW5hdGVkIGFy cmF5IG9mIHRlc3QgY2FzZXMuCisgKgorICogQSBrdW5pdF9zdWl0ZSBpcyBhIGNvbGxlY3Rpb24g b2YgcmVsYXRlZCAmc3RydWN0IGt1bml0X2Nhc2Ugcywgc3VjaCB0aGF0CisgKiBAaW5pdCBpcyBj YWxsZWQgYmVmb3JlIGV2ZXJ5IHRlc3QgY2FzZSBhbmQgQGV4aXQgaXMgY2FsbGVkIGFmdGVyIGV2 ZXJ5CisgKiB0ZXN0IGNhc2UsIHNpbWlsYXIgdG8gdGhlIG5vdGlvbiBvZiBhICp0ZXN0IGZpeHR1 cmUqIG9yIGEgKnRlc3QgY2xhc3MqCisgKiBpbiBvdGhlciB1bml0IHRlc3RpbmcgZnJhbWV3b3Jr cyBsaWtlIEpVbml0IG9yIEdvb2dsZXRlc3QuCisgKgorICogRXZlcnkgJnN0cnVjdCBrdW5pdF9j YXNlIG11c3QgYmUgYXNzb2NpYXRlZCB3aXRoIGEga3VuaXRfc3VpdGUgZm9yIEtVbml0CisgKiB0 byBydW4gaXQuCisgKi8KK3N0cnVjdCBrdW5pdF9zdWl0ZSB7CisJY29uc3QgY2hhciBuYW1lWzI1 Nl07CisJaW50ICgqaW5pdCkoc3RydWN0IGt1bml0ICp0ZXN0KTsKKwl2b2lkICgqZXhpdCkoc3Ry dWN0IGt1bml0ICp0ZXN0KTsKKwlzdHJ1Y3Qga3VuaXRfY2FzZSAqdGVzdF9jYXNlczsKK307CisK Ky8qKgorICogc3RydWN0IGt1bml0IC0gcmVwcmVzZW50cyBhIHJ1bm5pbmcgaW5zdGFuY2Ugb2Yg YSB0ZXN0LgorICoKKyAqIEBwcml2OiBmb3IgdXNlciB0byBzdG9yZSBhcmJpdHJhcnkgZGF0YS4g Q29tbW9ubHkgdXNlZCB0byBwYXNzIGRhdGEKKyAqCSAgY3JlYXRlZCBpbiB0aGUgaW5pdCBmdW5j dGlvbiAoc2VlICZzdHJ1Y3Qga3VuaXRfc3VpdGUpLgorICoKKyAqIFVzZWQgdG8gc3RvcmUgaW5m b3JtYXRpb24gYWJvdXQgdGhlIGN1cnJlbnQgY29udGV4dCB1bmRlciB3aGljaCB0aGUgdGVzdAor ICogaXMgcnVubmluZy4gTW9zdCBvZiB0aGlzIGRhdGEgaXMgcHJpdmF0ZSBhbmQgc2hvdWxkIG9u bHkgYmUgYWNjZXNzZWQKKyAqIGluZGlyZWN0bHkgdmlhIHB1YmxpYyBmdW5jdGlvbnM7IHRoZSBv bmUgZXhjZXB0aW9uIGlzIEBwcml2IHdoaWNoIGNhbiBiZQorICogdXNlZCBieSB0aGUgdGVzdCB3 cml0ZXIgdG8gc3RvcmUgYXJiaXRyYXJ5IGRhdGEuCisgKi8KK3N0cnVjdCBrdW5pdCB7CisJdm9p ZCAqcHJpdjsKKworCS8qIHByaXZhdGU6IGludGVybmFsIHVzZSBvbmx5LiAqLworCWNvbnN0IGNo YXIgKm5hbWU7IC8qIFJlYWQgb25seSBhZnRlciBpbml0aWFsaXphdGlvbiEgKi8KKwkvKgorCSAq IHN1Y2Nlc3Mgc3RhcnRzIGFzIHRydWUsIGFuZCBtYXkgb25seSBiZSBzZXQgdG8gZmFsc2UgZHVy aW5nIGEKKwkgKiB0ZXN0IGNhc2U7IHRodXMsIGl0IGlzIHNhZmUgdG8gdXBkYXRlIHRoaXMgYWNy b3NzIG11bHRpcGxlCisJICogdGhyZWFkcyB1c2luZyBXUklURV9PTkNFOyBob3dldmVyLCBhcyBh IGNvbnNlcXVlbmNlLCBpdCBtYXkgb25seQorCSAqIGJlIHJlYWQgYWZ0ZXIgdGhlIHRlc3QgY2Fz ZSBmaW5pc2hlcyBvbmNlIGFsbCB0aHJlYWRzIGFzc29jaWF0ZWQKKwkgKiB3aXRoIHRoZSB0ZXN0 IGNhc2UgaGF2ZSB0ZXJtaW5hdGVkLgorCSAqLworCWJvb2wgc3VjY2VzczsgLyogUmVhZCBvbmx5 IGFmdGVyIHRlc3RfY2FzZSBmaW5pc2hlcyEgKi8KK307CisKK3ZvaWQga3VuaXRfaW5pdF90ZXN0 KHN0cnVjdCBrdW5pdCAqdGVzdCwgY29uc3QgY2hhciAqbmFtZSk7CisKK2ludCBrdW5pdF9ydW5f dGVzdHMoc3RydWN0IGt1bml0X3N1aXRlICpzdWl0ZSk7CisKKy8qKgorICoga3VuaXRfdGVzdF9z dWl0ZSgpIC0gdXNlZCB0byByZWdpc3RlciBhICZzdHJ1Y3Qga3VuaXRfc3VpdGUgd2l0aCBLVW5p dC4KKyAqCisgKiBAc3VpdGU6IGEgc3RhdGljYWxseSBhbGxvY2F0ZWQgJnN0cnVjdCBrdW5pdF9z dWl0ZS4KKyAqCisgKiBSZWdpc3RlcnMgQHN1aXRlIHdpdGggdGhlIHRlc3QgZnJhbWV3b3JrLiBT ZWUgJnN0cnVjdCBrdW5pdF9zdWl0ZSBmb3IKKyAqIG1vcmUgaW5mb3JtYXRpb24uCisgKgorICog Tk9URTogQ3VycmVudGx5IEtVbml0IHRlc3RzIGFyZSBhbGwgcnVuIGFzIGxhdGVfaW5pdGNhbGxz OyB0aGlzIG1lYW5zCisgKiB0aGF0IHRoZXkgY2Fubm90IHRlc3QgYW55dGhpbmcgd2hlcmUgdGVz dHMgbXVzdCBydW4gYXQgYSBkaWZmZXJlbnQgaW5pdAorICogcGhhc2UuIE9uZSBzaWduaWZpY2Fu dCByZXN0cmljdGlvbiByZXN1bHRpbmcgZnJvbSB0aGlzIGlzIHRoYXQgS1VuaXQKKyAqIGNhbm5v dCByZWxpYWJseSB0ZXN0IGFueXRoaW5nIHRoYXQgaXMgaW5pdGlhbGl6ZSBpbiB0aGUgbGF0ZV9p bml0IHBoYXNlOworICogYW5vdGhlciBpcyB0aGF0IEtVbml0IGlzIHVzZWxlc3MgdG8gdGVzdCB0 aGluZ3MgdGhhdCBuZWVkIHRvIGJlIHJ1biBpbgorICogYW4gZWFybGllciBpbml0IHBoYXNlLgor ICoKKyAqIFRPRE8oYnJlbmRhbmhpZ2dpbnNAZ29vZ2xlLmNvbSk6IERvbid0IHJ1biBhbGwgS1Vu aXQgdGVzdHMgYXMKKyAqIGxhdGVfaW5pdGNhbGxzLiAgSSBoYXZlIHNvbWUgZnV0dXJlIHdvcmsg cGxhbm5lZCB0byBkaXNwYXRjaCBhbGwgS1VuaXQKKyAqIHRlc3RzIGZyb20gdGhlIHNhbWUgcGxh Y2UsIGFuZCBhdCB0aGUgdmVyeSBsZWFzdCB0byBkbyBzbyBhZnRlcgorICogZXZlcnl0aGluZyBl bHNlIGlzIGRlZmluaXRlbHkgaW5pdGlhbGl6ZWQuCisgKi8KKyNkZWZpbmUga3VuaXRfdGVzdF9z dWl0ZShzdWl0ZSkJCQkJCQkgICAgICAgXAorCXN0YXRpYyBpbnQga3VuaXRfc3VpdGVfaW5pdCMj c3VpdGUodm9pZCkJCQkgICAgICAgXAorCXsJCQkJCQkJCSAgICAgICBcCisJCXJldHVybiBrdW5p dF9ydW5fdGVzdHMoJnN1aXRlKTsJCQkJICAgICAgIFwKKwl9CQkJCQkJCQkgICAgICAgXAorCWxh dGVfaW5pdGNhbGwoa3VuaXRfc3VpdGVfaW5pdCMjc3VpdGUpCisKK3ZvaWQgX19wcmludGYoMywg NCkga3VuaXRfcHJpbnRrKGNvbnN0IGNoYXIgKmxldmVsLAorCQkJCSBjb25zdCBzdHJ1Y3Qga3Vu aXQgKnRlc3QsCisJCQkJIGNvbnN0IGNoYXIgKmZtdCwgLi4uKTsKKworLyoqCisgKiBrdW5pdF9p bmZvKCkgLSBQcmludHMgYW4gSU5GTyBsZXZlbCBtZXNzYWdlIGFzc29jaWF0ZWQgd2l0aCBAdGVz dC4KKyAqCisgKiBAdGVzdDogVGhlIHRlc3QgY29udGV4dCBvYmplY3QuCisgKiBAZm10OiAgQSBw cmludGsoKSBzdHlsZSBmb3JtYXQgc3RyaW5nLgorICoKKyAqIFByaW50cyBhbiBpbmZvIGxldmVs IG1lc3NhZ2UgYXNzb2NpYXRlZCB3aXRoIHRoZSB0ZXN0IHN1aXRlIGJlaW5nIHJ1bi4KKyAqIFRh a2VzIGEgdmFyaWFibGUgbnVtYmVyIG9mIGZvcm1hdCBwYXJhbWV0ZXJzIGp1c3QgbGlrZSBwcmlu dGsoKS4KKyAqLworI2RlZmluZSBrdW5pdF9pbmZvKHRlc3QsIGZtdCwgLi4uKSBcCisJa3VuaXRf cHJpbnRrKEtFUk5fSU5GTywgdGVzdCwgZm10LCAjI19fVkFfQVJHU19fKQorCisvKioKKyAqIGt1 bml0X3dhcm4oKSAtIFByaW50cyBhIFdBUk4gbGV2ZWwgbWVzc2FnZSBhc3NvY2lhdGVkIHdpdGgg QHRlc3QuCisgKgorICogQHRlc3Q6IFRoZSB0ZXN0IGNvbnRleHQgb2JqZWN0LgorICogQGZtdDog IEEgcHJpbnRrKCkgc3R5bGUgZm9ybWF0IHN0cmluZy4KKyAqCisgKiBQcmludHMgYSB3YXJuaW5n IGxldmVsIG1lc3NhZ2UuCisgKi8KKyNkZWZpbmUga3VuaXRfd2Fybih0ZXN0LCBmbXQsIC4uLikg XAorCWt1bml0X3ByaW50ayhLRVJOX1dBUk5JTkcsIHRlc3QsIGZtdCwgIyNfX1ZBX0FSR1NfXykK KworLyoqCisgKiBrdW5pdF9lcnIoKSAtIFByaW50cyBhbiBFUlJPUiBsZXZlbCBtZXNzYWdlIGFz c29jaWF0ZWQgd2l0aCBAdGVzdC4KKyAqCisgKiBAdGVzdDogVGhlIHRlc3QgY29udGV4dCBvYmpl Y3QuCisgKiBAZm10OiAgQSBwcmludGsoKSBzdHlsZSBmb3JtYXQgc3RyaW5nLgorICoKKyAqIFBy aW50cyBhbiBlcnJvciBsZXZlbCBtZXNzYWdlLgorICovCisjZGVmaW5lIGt1bml0X2Vycih0ZXN0 LCBmbXQsIC4uLikgXAorCWt1bml0X3ByaW50ayhLRVJOX0VSUiwgdGVzdCwgZm10LCAjI19fVkFf QVJHU19fKQorCisjZW5kaWYgLyogX0tVTklUX1RFU1RfSCAqLwpkaWZmIC0tZ2l0IGEvbGliL2t1 bml0L0tjb25maWcgYi9saWIva3VuaXQvS2NvbmZpZwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRl eCAwMDAwMDAwMDAwMDAuLjMzMGFlODM1MjdjMgotLS0gL2Rldi9udWxsCisrKyBiL2xpYi9rdW5p dC9LY29uZmlnCkBAIC0wLDAgKzEsMTcgQEAKKyMKKyMgS1VuaXQgYmFzZSBjb25maWd1cmF0aW9u CisjCisKK21lbnUgIktVbml0IHN1cHBvcnQiCisKK2NvbmZpZyBLVU5JVAorCWJvb2wgIkVuYWJs ZSBzdXBwb3J0IGZvciB1bml0IHRlc3RzIChLVW5pdCkiCisJaGVscAorCSAgRW5hYmxlcyBzdXBw b3J0IGZvciBrZXJuZWwgdW5pdCB0ZXN0cyAoS1VuaXQpLCBhIGxpZ2h0d2VpZ2h0IHVuaXQKKwkg IHRlc3RpbmcgYW5kIG1vY2tpbmcgZnJhbWV3b3JrIGZvciB0aGUgTGludXgga2VybmVsLiBUaGVz ZSB0ZXN0cyBhcmUKKwkgIGFibGUgdG8gYmUgcnVuIGxvY2FsbHkgb24gYSBkZXZlbG9wZXIncyB3 b3Jrc3RhdGlvbiB3aXRob3V0IGEgVk0gb3IKKwkgIHNwZWNpYWwgaGFyZHdhcmUgd2hlbiB1c2lu ZyBVTUwuIENhbiBhbHNvIGJlIHVzZWQgb24gbW9zdCBvdGhlcgorCSAgYXJjaGl0ZWN0dXJlcy4g Rm9yIG1vcmUgaW5mb3JtYXRpb24sIHBsZWFzZSBzZWUKKwkgIERvY3VtZW50YXRpb24vZGV2LXRv b2xzL2t1bml0Ly4KKworZW5kbWVudQpkaWZmIC0tZ2l0IGEvbGliL2t1bml0L01ha2VmaWxlIGIv bGliL2t1bml0L01ha2VmaWxlCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAw MC4uNWVmZGM0ZGVhMmMwCi0tLSAvZGV2L251bGwKKysrIGIvbGliL2t1bml0L01ha2VmaWxlCkBA IC0wLDAgKzEgQEAKK29iai0kKENPTkZJR19LVU5JVCkgKz0JCQl0ZXN0Lm8KZGlmZiAtLWdpdCBh L2xpYi9rdW5pdC90ZXN0LmMgYi9saWIva3VuaXQvdGVzdC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0 CmluZGV4IDAwMDAwMDAwMDAwMC4uZDNkZGEzNTlmOTliCi0tLSAvZGV2L251bGwKKysrIGIvbGli L2t1bml0L3Rlc3QuYwpAQCAtMCwwICsxLDE5MSBAQAorLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IEdQTC0yLjAKKy8qCisgKiBCYXNlIHVuaXQgdGVzdCAoS1VuaXQpIEFQSS4KKyAqCisgKiBD b3B5cmlnaHQgKEMpIDIwMTksIEdvb2dsZSBMTEMuCisgKiBBdXRob3I6IEJyZW5kYW4gSGlnZ2lu cyA8YnJlbmRhbmhpZ2dpbnNAZ29vZ2xlLmNvbT4KKyAqLworCisjaW5jbHVkZSA8a3VuaXQvdGVz dC5oPgorI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgorCitzdGF0aWMgdm9pZCBrdW5pdF9zZXRf ZmFpbHVyZShzdHJ1Y3Qga3VuaXQgKnRlc3QpCit7CisJV1JJVEVfT05DRSh0ZXN0LT5zdWNjZXNz LCBmYWxzZSk7Cit9CisKK3N0YXRpYyBpbnQga3VuaXRfdnByaW50a19lbWl0KGludCBsZXZlbCwg Y29uc3QgY2hhciAqZm10LCB2YV9saXN0IGFyZ3MpCit7CisJcmV0dXJuIHZwcmludGtfZW1pdCgw LCBsZXZlbCwgTlVMTCwgMCwgZm10LCBhcmdzKTsKK30KKworc3RhdGljIGludCBrdW5pdF9wcmlu dGtfZW1pdChpbnQgbGV2ZWwsIGNvbnN0IGNoYXIgKmZtdCwgLi4uKQoreworCXZhX2xpc3QgYXJn czsKKwlpbnQgcmV0OworCisJdmFfc3RhcnQoYXJncywgZm10KTsKKwlyZXQgPSBrdW5pdF92cHJp bnRrX2VtaXQobGV2ZWwsIGZtdCwgYXJncyk7CisJdmFfZW5kKGFyZ3MpOworCisJcmV0dXJuIHJl dDsKK30KKworc3RhdGljIHZvaWQga3VuaXRfdnByaW50ayhjb25zdCBzdHJ1Y3Qga3VuaXQgKnRl c3QsCisJCQkgIGNvbnN0IGNoYXIgKmxldmVsLAorCQkJICBzdHJ1Y3QgdmFfZm9ybWF0ICp2YWYp Cit7CisJa3VuaXRfcHJpbnRrX2VtaXQobGV2ZWxbMV0gLSAnMCcsICJcdCMgJXM6ICVwViIsIHRl c3QtPm5hbWUsIHZhZik7Cit9CisKK3N0YXRpYyB2b2lkIGt1bml0X3ByaW50X3RhcF92ZXJzaW9u KHZvaWQpCit7CisJc3RhdGljIGJvb2wga3VuaXRfaGFzX3ByaW50ZWRfdGFwX3ZlcnNpb247CisK KwlpZiAoIWt1bml0X2hhc19wcmludGVkX3RhcF92ZXJzaW9uKSB7CisJCWt1bml0X3ByaW50a19l bWl0KExPR0xFVkVMX0lORk8sICJUQVAgdmVyc2lvbiAxNFxuIik7CisJCWt1bml0X2hhc19wcmlu dGVkX3RhcF92ZXJzaW9uID0gdHJ1ZTsKKwl9Cit9CisKK3N0YXRpYyBzaXplX3Qga3VuaXRfdGVz dF9jYXNlc19sZW4oc3RydWN0IGt1bml0X2Nhc2UgKnRlc3RfY2FzZXMpCit7CisJc3RydWN0IGt1 bml0X2Nhc2UgKnRlc3RfY2FzZTsKKwlzaXplX3QgbGVuID0gMDsKKworCWZvciAodGVzdF9jYXNl ID0gdGVzdF9jYXNlczsgdGVzdF9jYXNlLT5ydW5fY2FzZTsgdGVzdF9jYXNlKyspCisJCWxlbisr OworCisJcmV0dXJuIGxlbjsKK30KKworc3RhdGljIHZvaWQga3VuaXRfcHJpbnRfc3VidGVzdF9z dGFydChzdHJ1Y3Qga3VuaXRfc3VpdGUgKnN1aXRlKQoreworCWt1bml0X3ByaW50X3RhcF92ZXJz aW9uKCk7CisJa3VuaXRfcHJpbnRrX2VtaXQoTE9HTEVWRUxfSU5GTywgIlx0IyBTdWJ0ZXN0OiAl c1xuIiwgc3VpdGUtPm5hbWUpOworCWt1bml0X3ByaW50a19lbWl0KExPR0xFVkVMX0lORk8sCisJ CQkgICJcdDEuLiV6ZFxuIiwKKwkJCSAga3VuaXRfdGVzdF9jYXNlc19sZW4oc3VpdGUtPnRlc3Rf Y2FzZXMpKTsKK30KKworc3RhdGljIHZvaWQga3VuaXRfcHJpbnRfb2tfbm90X29rKGJvb2wgc2hv dWxkX2luZGVudCwKKwkJCQkgIGJvb2wgaXNfb2ssCisJCQkJICBzaXplX3QgdGVzdF9udW1iZXIs CisJCQkJICBjb25zdCBjaGFyICpkZXNjcmlwdGlvbikKK3sKKwljb25zdCBjaGFyICppbmRlbnQs ICpva19ub3Rfb2s7CisKKwlpZiAoc2hvdWxkX2luZGVudCkKKwkJaW5kZW50ID0gIlx0IjsKKwll bHNlCisJCWluZGVudCA9ICIiOworCisJaWYgKGlzX29rKQorCQlva19ub3Rfb2sgPSAib2siOwor CWVsc2UKKwkJb2tfbm90X29rID0gIm5vdCBvayI7CisKKwlrdW5pdF9wcmludGtfZW1pdChMT0dM RVZFTF9JTkZPLAorCQkJICAiJXMlcyAlemQgLSAlc1xuIiwKKwkJCSAgaW5kZW50LCBva19ub3Rf b2ssIHRlc3RfbnVtYmVyLCBkZXNjcmlwdGlvbik7Cit9CisKK3N0YXRpYyBib29sIGt1bml0X3N1 aXRlX2hhc19zdWNjZWVkZWQoc3RydWN0IGt1bml0X3N1aXRlICpzdWl0ZSkKK3sKKwljb25zdCBz dHJ1Y3Qga3VuaXRfY2FzZSAqdGVzdF9jYXNlOworCisJZm9yICh0ZXN0X2Nhc2UgPSBzdWl0ZS0+ dGVzdF9jYXNlczsgdGVzdF9jYXNlLT5ydW5fY2FzZTsgdGVzdF9jYXNlKyspCisJCWlmICghdGVz dF9jYXNlLT5zdWNjZXNzKQorCQkJcmV0dXJuIGZhbHNlOworCisJcmV0dXJuIHRydWU7Cit9CisK K3N0YXRpYyB2b2lkIGt1bml0X3ByaW50X3N1YnRlc3RfZW5kKHN0cnVjdCBrdW5pdF9zdWl0ZSAq c3VpdGUpCit7CisJc3RhdGljIHNpemVfdCBrdW5pdF9zdWl0ZV9jb3VudGVyID0gMTsKKworCWt1 bml0X3ByaW50X29rX25vdF9vayhmYWxzZSwKKwkJCSAgICAgIGt1bml0X3N1aXRlX2hhc19zdWNj ZWVkZWQoc3VpdGUpLAorCQkJICAgICAga3VuaXRfc3VpdGVfY291bnRlcisrLAorCQkJICAgICAg c3VpdGUtPm5hbWUpOworfQorCitzdGF0aWMgdm9pZCBrdW5pdF9wcmludF90ZXN0X2Nhc2Vfb2tf bm90X29rKHN0cnVjdCBrdW5pdF9jYXNlICp0ZXN0X2Nhc2UsCisJCQkJCSAgICBzaXplX3QgdGVz dF9udW1iZXIpCit7CisJa3VuaXRfcHJpbnRfb2tfbm90X29rKHRydWUsCisJCQkgICAgICB0ZXN0 X2Nhc2UtPnN1Y2Nlc3MsCisJCQkgICAgICB0ZXN0X251bWJlciwKKwkJCSAgICAgIHRlc3RfY2Fz ZS0+bmFtZSk7Cit9CisKK3ZvaWQga3VuaXRfaW5pdF90ZXN0KHN0cnVjdCBrdW5pdCAqdGVzdCwg Y29uc3QgY2hhciAqbmFtZSkKK3sKKwl0ZXN0LT5uYW1lID0gbmFtZTsKKwl0ZXN0LT5zdWNjZXNz ID0gdHJ1ZTsKK30KKworLyoKKyAqIFBlcmZvcm1zIGFsbCBsb2dpYyB0byBydW4gYSB0ZXN0IGNh c2UuCisgKi8KK3N0YXRpYyB2b2lkIGt1bml0X3J1bl9jYXNlKHN0cnVjdCBrdW5pdF9zdWl0ZSAq c3VpdGUsCisJCQkgICBzdHJ1Y3Qga3VuaXRfY2FzZSAqdGVzdF9jYXNlKQoreworCXN0cnVjdCBr dW5pdCB0ZXN0OworCisJa3VuaXRfaW5pdF90ZXN0KCZ0ZXN0LCB0ZXN0X2Nhc2UtPm5hbWUpOwor CisJaWYgKHN1aXRlLT5pbml0KSB7CisJCWludCByZXQ7CisKKwkJcmV0ID0gc3VpdGUtPmluaXQo JnRlc3QpOworCQlpZiAocmV0KSB7CisJCQlrdW5pdF9lcnIoJnRlc3QsICJmYWlsZWQgdG8gaW5p dGlhbGl6ZTogJWRcbiIsIHJldCk7CisJCQlrdW5pdF9zZXRfZmFpbHVyZSgmdGVzdCk7CisJCQl0 ZXN0X2Nhc2UtPnN1Y2Nlc3MgPSB0ZXN0LnN1Y2Nlc3M7CisJCQlyZXR1cm47CisJCX0KKwl9CisK Kwl0ZXN0X2Nhc2UtPnJ1bl9jYXNlKCZ0ZXN0KTsKKworCWlmIChzdWl0ZS0+ZXhpdCkKKwkJc3Vp dGUtPmV4aXQoJnRlc3QpOworCisJdGVzdF9jYXNlLT5zdWNjZXNzID0gdGVzdC5zdWNjZXNzOwor fQorCitpbnQga3VuaXRfcnVuX3Rlc3RzKHN0cnVjdCBrdW5pdF9zdWl0ZSAqc3VpdGUpCit7CisJ c3RydWN0IGt1bml0X2Nhc2UgKnRlc3RfY2FzZTsKKwlzaXplX3QgdGVzdF9jYXNlX2NvdW50ID0g MTsKKworCWt1bml0X3ByaW50X3N1YnRlc3Rfc3RhcnQoc3VpdGUpOworCisJZm9yICh0ZXN0X2Nh c2UgPSBzdWl0ZS0+dGVzdF9jYXNlczsgdGVzdF9jYXNlLT5ydW5fY2FzZTsgdGVzdF9jYXNlKysp IHsKKwkJa3VuaXRfcnVuX2Nhc2Uoc3VpdGUsIHRlc3RfY2FzZSk7CisJCWt1bml0X3ByaW50X3Rl c3RfY2FzZV9va19ub3Rfb2sodGVzdF9jYXNlLCB0ZXN0X2Nhc2VfY291bnQrKyk7CisJfQorCisJ a3VuaXRfcHJpbnRfc3VidGVzdF9lbmQoc3VpdGUpOworCisJcmV0dXJuIDA7Cit9CisKK3ZvaWQg a3VuaXRfcHJpbnRrKGNvbnN0IGNoYXIgKmxldmVsLAorCQkgIGNvbnN0IHN0cnVjdCBrdW5pdCAq dGVzdCwKKwkJICBjb25zdCBjaGFyICpmbXQsIC4uLikKK3sKKwlzdHJ1Y3QgdmFfZm9ybWF0IHZh ZjsKKwl2YV9saXN0IGFyZ3M7CisKKwl2YV9zdGFydChhcmdzLCBmbXQpOworCisJdmFmLmZtdCA9 IGZtdDsKKwl2YWYudmEgPSAmYXJnczsKKworCWt1bml0X3ZwcmludGsodGVzdCwgbGV2ZWwsICZ2 YWYpOworCisJdmFfZW5kKGFyZ3MpOworfQotLSAKMi4yMy4wLjM1MS5nYzQzMTcwMzJlNi1nb29n CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmktZGV2 ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9s aXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWw= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x649.google.com ([2607:f8b0:4864:20::649]) by bombadil.infradead.org with esmtps (Exim 4.92.2 #3 (Red Hat Linux)) id 1iBSBp-0003Bk-TU for linux-um@lists.infradead.org; Fri, 20 Sep 2019 23:19:52 +0000 Received: by mail-pl1-x649.google.com with SMTP id p8so5378466plo.16 for ; Fri, 20 Sep 2019 16:19:42 -0700 (PDT) Date: Fri, 20 Sep 2019 16:19:05 -0700 In-Reply-To: <20190920231923.141900-1-brendanhiggins@google.com> Message-Id: <20190920231923.141900-2-brendanhiggins@google.com> Mime-Version: 1.0 References: <20190920231923.141900-1-brendanhiggins@google.com> Subject: [PATCH v16 01/19] kunit: test: add KUnit test runner core 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, linux-nvdimm@lists.01.org, khilman@baylibre.com, knut.omang@oracle.com, 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 core facilities for defining unit tests; this provides a common way to define test cases, functions that execute code which is under test and determine whether the code under test behaves as expected; this also provides a way to group together related test cases in test suites (here we call them test_modules). Just define test cases and how to execute them for now; setting expectations on code will be defined later. Signed-off-by: Brendan Higgins Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe Reviewed-by: Luis Chamberlain Reviewed-by: Stephen Boyd --- include/kunit/test.h | 188 ++++++++++++++++++++++++++++++++++++++++++ lib/kunit/Kconfig | 17 ++++ lib/kunit/Makefile | 1 + lib/kunit/test.c | 191 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 397 insertions(+) create mode 100644 include/kunit/test.h create mode 100644 lib/kunit/Kconfig create mode 100644 lib/kunit/Makefile create mode 100644 lib/kunit/test.c diff --git a/include/kunit/test.h b/include/kunit/test.h new file mode 100644 index 000000000000..e30d1bf2fb68 --- /dev/null +++ b/include/kunit/test.h @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#ifndef _KUNIT_TEST_H +#define _KUNIT_TEST_H + +#include + +struct kunit; + +/** + * struct kunit_case - represents an individual test case. + * + * @run_case: the function representing the actual test case. + * @name: the name of the test case. + * + * A test case is a function with the signature, + * ``void (*)(struct kunit *)`` that makes expectations (see + * KUNIT_EXPECT_TRUE()) about code under test. Each test case is associated + * with a &struct kunit_suite and will be run after the suite's init + * function and followed by the suite's exit function. + * + * A test case should be static and should only be created with the + * KUNIT_CASE() macro; additionally, every array of test cases should be + * terminated with an empty test case. + * + * 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)); + * KUNIT_EXPECT_EQ(test, 0, add(-1, 1)); + * KUNIT_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX)); + * KUNIT_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN)); + * } + * + * static struct kunit_case example_test_cases[] = { + * KUNIT_CASE(add_test_basic), + * {} + * }; + * + */ +struct kunit_case { + void (*run_case)(struct kunit *test); + const char *name; + + /* private: internal use only. */ + bool success; +}; + +/** + * KUNIT_CASE - A helper for creating a &struct kunit_case + * + * @test_name: a reference to a test case function. + * + * Takes a symbol for a function representing a test case and creates a + * &struct kunit_case object from it. See the documentation for + * &struct kunit_case for an example on how to use it. + */ +#define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } + +/** + * struct kunit_suite - describes a related collection of &struct kunit_case + * + * @name: the name of the test. Purely informational. + * @init: called before every test case. + * @exit: called after every test case. + * @test_cases: a null terminated array of test cases. + * + * A kunit_suite is a collection of related &struct kunit_case s, such that + * @init is called before every test case and @exit is called after every + * test case, similar to the notion of a *test fixture* or a *test class* + * in other unit testing frameworks like JUnit or Googletest. + * + * Every &struct kunit_case must be associated with a kunit_suite for KUnit + * to run it. + */ +struct kunit_suite { + const char name[256]; + int (*init)(struct kunit *test); + void (*exit)(struct kunit *test); + struct kunit_case *test_cases; +}; + +/** + * struct kunit - represents a running instance of a test. + * + * @priv: for user to store arbitrary data. Commonly used to pass data + * created in the init function (see &struct kunit_suite). + * + * Used to store information about the current context under which the test + * is running. Most of this data is private and should only be accessed + * indirectly via public functions; the one exception is @priv which can be + * used by the test writer to store arbitrary data. + */ +struct kunit { + void *priv; + + /* private: internal use only. */ + const char *name; /* Read only after initialization! */ + /* + * success starts as true, and may only be set to false during a + * test case; thus, it is safe to update this across multiple + * threads using WRITE_ONCE; however, as a consequence, it may only + * be read after the test case finishes once all threads associated + * with the test case have terminated. + */ + bool success; /* Read only after test_case finishes! */ +}; + +void kunit_init_test(struct kunit *test, const char *name); + +int kunit_run_tests(struct kunit_suite *suite); + +/** + * kunit_test_suite() - used to register a &struct kunit_suite with KUnit. + * + * @suite: a statically allocated &struct kunit_suite. + * + * Registers @suite with the test framework. See &struct kunit_suite for + * more information. + * + * NOTE: Currently KUnit tests are all run as late_initcalls; this means + * that they cannot test anything where tests must run at a different init + * phase. One significant restriction resulting from this is that KUnit + * cannot reliably test anything that is initialize in the late_init phase; + * another is that KUnit is useless to test things that need to be run in + * an earlier init phase. + * + * TODO(brendanhiggins@google.com): Don't run all KUnit tests as + * late_initcalls. I have some future work planned to dispatch all KUnit + * tests from the same place, and at the very least to do so after + * everything else is definitely initialized. + */ +#define kunit_test_suite(suite) \ + static int kunit_suite_init##suite(void) \ + { \ + return kunit_run_tests(&suite); \ + } \ + late_initcall(kunit_suite_init##suite) + +void __printf(3, 4) kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...); + +/** + * kunit_info() - Prints an INFO level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an info level message associated with the test suite being run. + * Takes a variable number of format parameters just like printk(). + */ +#define kunit_info(test, fmt, ...) \ + kunit_printk(KERN_INFO, test, fmt, ##__VA_ARGS__) + +/** + * kunit_warn() - Prints a WARN level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints a warning level message. + */ +#define kunit_warn(test, fmt, ...) \ + kunit_printk(KERN_WARNING, test, fmt, ##__VA_ARGS__) + +/** + * kunit_err() - Prints an ERROR level message associated with @test. + * + * @test: The test context object. + * @fmt: A printk() style format string. + * + * Prints an error level message. + */ +#define kunit_err(test, fmt, ...) \ + kunit_printk(KERN_ERR, test, fmt, ##__VA_ARGS__) + +#endif /* _KUNIT_TEST_H */ diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig new file mode 100644 index 000000000000..330ae83527c2 --- /dev/null +++ b/lib/kunit/Kconfig @@ -0,0 +1,17 @@ +# +# KUnit base configuration +# + +menu "KUnit support" + +config KUNIT + bool "Enable support for unit tests (KUnit)" + help + Enables support for kernel unit tests (KUnit), 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 when using UML. Can also be used on most other + architectures. For more information, please see + Documentation/dev-tools/kunit/. + +endmenu diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile new file mode 100644 index 000000000000..5efdc4dea2c0 --- /dev/null +++ b/lib/kunit/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_KUNIT) += test.o diff --git a/lib/kunit/test.c b/lib/kunit/test.c new file mode 100644 index 000000000000..d3dda359f99b --- /dev/null +++ b/lib/kunit/test.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Base unit test (KUnit) API. + * + * Copyright (C) 2019, Google LLC. + * Author: Brendan Higgins + */ + +#include +#include + +static void kunit_set_failure(struct kunit *test) +{ + WRITE_ONCE(test->success, false); +} + +static int kunit_vprintk_emit(int level, const char *fmt, va_list args) +{ + return vprintk_emit(0, level, NULL, 0, fmt, args); +} + +static int kunit_printk_emit(int level, const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = kunit_vprintk_emit(level, fmt, args); + va_end(args); + + return ret; +} + +static void kunit_vprintk(const struct kunit *test, + const char *level, + struct va_format *vaf) +{ + kunit_printk_emit(level[1] - '0', "\t# %s: %pV", test->name, vaf); +} + +static void kunit_print_tap_version(void) +{ + static bool kunit_has_printed_tap_version; + + if (!kunit_has_printed_tap_version) { + kunit_printk_emit(LOGLEVEL_INFO, "TAP version 14\n"); + kunit_has_printed_tap_version = true; + } +} + +static size_t kunit_test_cases_len(struct kunit_case *test_cases) +{ + struct kunit_case *test_case; + size_t len = 0; + + for (test_case = test_cases; test_case->run_case; test_case++) + len++; + + return len; +} + +static void kunit_print_subtest_start(struct kunit_suite *suite) +{ + kunit_print_tap_version(); + kunit_printk_emit(LOGLEVEL_INFO, "\t# Subtest: %s\n", suite->name); + kunit_printk_emit(LOGLEVEL_INFO, + "\t1..%zd\n", + kunit_test_cases_len(suite->test_cases)); +} + +static void kunit_print_ok_not_ok(bool should_indent, + bool is_ok, + size_t test_number, + const char *description) +{ + const char *indent, *ok_not_ok; + + if (should_indent) + indent = "\t"; + else + indent = ""; + + if (is_ok) + ok_not_ok = "ok"; + else + ok_not_ok = "not ok"; + + kunit_printk_emit(LOGLEVEL_INFO, + "%s%s %zd - %s\n", + indent, ok_not_ok, test_number, description); +} + +static bool kunit_suite_has_succeeded(struct kunit_suite *suite) +{ + const struct kunit_case *test_case; + + for (test_case = suite->test_cases; test_case->run_case; test_case++) + if (!test_case->success) + return false; + + return true; +} + +static void kunit_print_subtest_end(struct kunit_suite *suite) +{ + static size_t kunit_suite_counter = 1; + + kunit_print_ok_not_ok(false, + kunit_suite_has_succeeded(suite), + kunit_suite_counter++, + suite->name); +} + +static void kunit_print_test_case_ok_not_ok(struct kunit_case *test_case, + size_t test_number) +{ + kunit_print_ok_not_ok(true, + test_case->success, + test_number, + test_case->name); +} + +void kunit_init_test(struct kunit *test, const char *name) +{ + test->name = name; + test->success = true; +} + +/* + * Performs all logic to run a test case. + */ +static void kunit_run_case(struct kunit_suite *suite, + struct kunit_case *test_case) +{ + struct kunit test; + + kunit_init_test(&test, test_case->name); + + if (suite->init) { + int ret; + + ret = suite->init(&test); + if (ret) { + kunit_err(&test, "failed to initialize: %d\n", ret); + kunit_set_failure(&test); + test_case->success = test.success; + return; + } + } + + test_case->run_case(&test); + + if (suite->exit) + suite->exit(&test); + + test_case->success = test.success; +} + +int kunit_run_tests(struct kunit_suite *suite) +{ + struct kunit_case *test_case; + size_t test_case_count = 1; + + kunit_print_subtest_start(suite); + + for (test_case = suite->test_cases; test_case->run_case; test_case++) { + kunit_run_case(suite, test_case); + kunit_print_test_case_ok_not_ok(test_case, test_case_count++); + } + + kunit_print_subtest_end(suite); + + return 0; +} + +void kunit_printk(const char *level, + const struct kunit *test, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + kunit_vprintk(test, level, &vaf); + + va_end(args); +} -- 2.23.0.351.gc4317032e6-goog _______________________________________________ linux-um mailing list linux-um@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-um