From patchwork Wed Jul 17 01:55:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brendan Higgins X-Patchwork-Id: 11047051 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1CF4313BD for ; Wed, 17 Jul 2019 01:57:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C03C286FF for ; Wed, 17 Jul 2019 01:57:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3B2D2870E; Wed, 17 Jul 2019 01:57:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 70313286FF for ; Wed, 17 Jul 2019 01:57:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727796AbfGQB40 (ORCPT ); Tue, 16 Jul 2019 21:56:26 -0400 Received: from mail-pg1-f202.google.com ([209.85.215.202]:40499 "EHLO mail-pg1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727909AbfGQB4Z (ORCPT ); Tue, 16 Jul 2019 21:56:25 -0400 Received: by mail-pg1-f202.google.com with SMTP id u16so1727172pgj.7 for ; Tue, 16 Jul 2019 18:56:24 -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=SC8ggWUk4s8O6cveRCBKCLPEL6KhpOSRPQceQwa9F+U=; b=M+kMNduTSk5Zh8tBancui21U0wSwAy2FLLyl+l5OIKEy3PdL6lDf1K2FTTTTnC/uPF gyThw5P5ykBdbQ2n3ak0yJYLC3/xhBcGMz1HzPjpK6jHne2cnDoDdcV/FbCjJtiOAPo4 cVLMj98Rilmqc7AyEymdooPlhwWgzZKeRfp3rr//T1IcUkaTci17QxvkB0eLFEGHIRFR 5C0My48zxR8Eq9IkBS11mY2bk2AKKYpqQLbW0Os2A6KN6rUQxuZeYYzlUGRrutapfqTT Ym4+meKhCRphPsC+sfjsmripOp889hR5SQOi4nnl5rkGsUxtHclHYQOIzGv9ic/aZ7Qn Nq7A== 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=SC8ggWUk4s8O6cveRCBKCLPEL6KhpOSRPQceQwa9F+U=; b=FdxSrngpxisHa/dvBF8GGzHiOKOP02mgbxlfJ0qzMO1pbrR2h/Puk/ONz0uD4yLQTC uUWSrpfDAWwTjmf2DaHxuvwRU9VilnxP5NVkdXYmuAYSCxSagXDAhQKdNWSrf8HUCnUm iVot/szsCIg2lvzLB16beQTwS4tKEPoMf0DoW2ihUH4xUcCEjYYBm2OeisENJkEhARJ0 CklrwvwFpCKtUibW0XyNsajitIVM96zKFS9LdP7qsmu50vsklK5aztKgSu54kxxoMQKC eFTo1g6KlCLJcewT+JG64aaVp6gtxwpdnoDU4vE5dyMlkgw9Tb6zm0CC/kQo20wQvYUN xyNg== X-Gm-Message-State: APjAAAUOFyF6OxsGxxX77OLNiYW6PLHNmY0alNMAQoB99Vcni6zJPc9X hneh2BxzfqvyYhYSbtvudL36He1hfYrldqvZpTQr+g== X-Google-Smtp-Source: APXvYqy5wT61oalwKlSAWzWVw/bN2m1CRxoKSGb22L7KDQlsFnVf74m7QKwQ0SIvD0lqEC9OcHmpM465UL+5et0VIFADSg== X-Received: by 2002:a65:57ca:: with SMTP id q10mr38925454pgr.52.1563328583057; Tue, 16 Jul 2019 18:56:23 -0700 (PDT) Date: Tue, 16 Jul 2019 18:55:36 -0700 In-Reply-To: <20190717015543.152251-1-brendanhiggins@google.com> Message-Id: <20190717015543.152251-12-brendanhiggins@google.com> Mime-Version: 1.0 References: <20190717015543.152251-1-brendanhiggins@google.com> X-Mailer: git-send-email 2.22.0.510.g264f2c817a-goog Subject: [PATCH v11 11/18] kunit: test: add the concept of assertions 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, Brendan Higgins Sender: linux-kbuild-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kbuild@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add support for assertions which are like expectations except the test terminates if the assertion is not satisfied. The idea with assertions is that you use them to state all the preconditions for your test. Logically speaking, these are the premises of the test case, so if a premise isn't true, there is no point in continuing the test case because there are no conclusions that can be drawn without the premises. Whereas, the expectation is the thing you are trying to prove. It is not used universally in x-unit style test frameworks, but I really like it as a convention. You could still express the idea of a premise using the above idiom, but I think KUNIT_ASSERT_* states the intended idea perfectly. Signed-off-by: Brendan Higgins Reviewed-by: Greg Kroah-Hartman Reviewed-by: Logan Gunthorpe --- include/kunit/test.h | 500 ++++++++++++++++++++++++++++++++++++- kunit/string-stream-test.c | 12 +- kunit/test-test.c | 2 + kunit/test.c | 66 +++++ 4 files changed, 571 insertions(+), 9 deletions(-) diff --git a/include/kunit/test.h b/include/kunit/test.h index 1daa4510bb960..7d14210b18481 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -86,9 +86,10 @@ struct kunit; * @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. + * that makes expectations and assertions (see KUNIT_EXPECT_TRUE() and + * KUNIT_ASSERT_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 @@ -864,4 +865,497 @@ do { \ KUNIT_EXPECT_END(test, !IS_ERR_OR_NULL(__ptr), __stream); \ } while (0) +static inline struct kunit_stream *kunit_assert_start(struct kunit *test, + const char *file, + const char *line) +{ + struct kunit_stream *stream = alloc_kunit_stream(test, KERN_ERR, + GFP_KERNEL); + + kunit_stream_add(stream, "ASSERTION FAILED at %s:%s\n\t", file, line); + + return stream; +} + +static inline void kunit_assert_end(struct kunit *test, + bool success, + struct kunit_stream *stream) +{ + if (!success) { + kunit_fail(test, stream); + kunit_abort(test); + } else { + kunit_stream_clear(stream); + } +} + +#define KUNIT_ASSERT_START(test) \ + kunit_assert_start(test, __FILE__, __stringify(__LINE__)) + +#define KUNIT_ASSERT_END(test, success, stream) \ + kunit_assert_end(test, success, stream) + +#define KUNIT_ASSERT(test, success, message) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + \ + kunit_stream_add(__stream, message); \ + KUNIT_ASSERT_END(test, success, __stream); \ +} while (0) + +#define KUNIT_ASSERT_MSG(test, success, message, fmt, ...) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + \ + kunit_stream_add(__stream, message); \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + KUNIT_ASSERT_END(test, success, __stream); \ +} while (0) + +#define KUNIT_ASSERT_FAILURE(test, fmt, ...) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + KUNIT_ASSERT_END(test, false, __stream); \ +} while (0) + +/** + * KUNIT_ASSERT_TRUE() - Sets an assertion that @condition is true. + * @test: The test context object. + * @condition: an arbitrary boolean expression. The test fails and aborts when + * this does not evaluate to true. + * + * This and assertions of the form `KUNIT_ASSERT_*` will cause the test case to + * fail *and immediately abort* when the specified condition is not met. Unlike + * an expectation failure, it will prevent the test case from continuing to run; + * this is otherwise known as an *assertion failure*. + */ +#define KUNIT_ASSERT_TRUE(test, condition) \ + KUNIT_ASSERT(test, (condition), \ + "Asserted " #condition " is true, but is false\n") + +#define KUNIT_ASSERT_TRUE_MSG(test, condition, fmt, ...) \ + KUNIT_ASSERT_MSG(test, (condition), \ + "Asserted " #condition " is true, but is false\n",\ + fmt, ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_FALSE() - Sets an assertion that @condition is false. + * @test: The test context object. + * @condition: an arbitrary boolean expression. + * + * Sets an assertion that the value that @condition evaluates to is false. This + * is the same as KUNIT_EXPECT_FALSE(), except it causes an assertion failure + * (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_FALSE(test, condition) \ + KUNIT_ASSERT(test, !(condition), \ + "Asserted " #condition " is false, but is true\n") + +#define KUNIT_ASSERT_FALSE_MSG(test, condition, fmt, ...) \ + KUNIT_ASSERT_MSG(test, !(condition), \ + "Asserted " #condition " is false, but is true\n",\ + fmt, ##__VA_ARGS__) + +void kunit_assert_binary_msg(struct kunit *test, + long long left, const char *left_name, + long long right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line, + const char *fmt, ...); + +static inline void kunit_assert_binary(struct kunit *test, + long long left, const char *left_name, + long long right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line) +{ + kunit_assert_binary_msg(test, + left, left_name, + right, right_name, + compare_result, + compare_name, + file, + line, + NULL); +} + +void kunit_assert_ptr_binary_msg(struct kunit *test, + void *left, const char *left_name, + void *right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line, + const char *fmt, ...); + +static inline void kunit_assert_ptr_binary(struct kunit *test, + void *left, const char *left_name, + void *right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line) +{ + kunit_assert_ptr_binary_msg(test, + left, left_name, + right, right_name, + compare_result, + compare_name, + file, + line, + NULL); +} + +/* + * A factory macro for defining the expectations for the basic comparisons + * defined for the built in types. + * + * Unfortunately, there is no common type that all types can be promoted to for + * which all the binary operators behave the same way as for the actual types + * (for example, there is no type that long long and unsigned long long can + * both be cast to where the comparison result is preserved for all values). So + * the best we can do is do the comparison in the original types and then coerce + * everything to long long for printing; this way, the comparison behaves + * correctly and the printed out value usually makes sense without + * interpretation, but can always be interpretted to figure out the actual + * value. + */ +#define KUNIT_ASSERT_BINARY(test, left, condition, right) do { \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + __kunit_typecheck(__left, __right); \ + kunit_assert_binary(test, \ + (long long) __left, #left, \ + (long long) __right, #right, \ + __left condition __right, #condition, \ + __FILE__, __stringify(__LINE__)); \ +} while (0) + +#define KUNIT_ASSERT_BINARY_MSG(test, left, condition, right, fmt, ...) do { \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + __kunit_typecheck(__left, __right); \ + kunit_assert_binary_msg(test, \ + (long long) __left, #left, \ + (long long) __right, #right, \ + __left condition __right, #condition, \ + __FILE__, __stringify(__LINE__), \ + fmt, ##__VA_ARGS__); \ +} while (0) + +/* + * Just like KUNIT_EXPECT_BINARY, but for comparing pointer types. + */ +#define KUNIT_ASSERT_PTR_BINARY(test, left, condition, right) do { \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + __kunit_typecheck(__left, __right); \ + kunit_assert_ptr_binary(test, \ + (void *) __left, #left, \ + (void *) __right, #right, \ + __left condition __right, #condition, \ + __FILE__, __stringify(__LINE__)); \ +} while (0) + +#define KUNIT_ASSERT_PTR_BINARY_MSG(test, left, condition, right, fmt, ...) \ +do { \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + __kunit_typecheck(__left, __right); \ + kunit_assert_ptr_binary_msg(test, \ + (void *) __left, #left, \ + (void *) __right, #right, \ + __left condition __right, #condition, \ + __FILE__, __stringify(__LINE__), \ + fmt, ##__VA_ARGS__); \ +} while (0) + +/** + * KUNIT_ASSERT_EQ() - Sets an assertion that @left and @right are equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the values that @left and @right evaluate to are + * equal. This is the same as KUNIT_EXPECT_EQ(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_EQ(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, ==, right) + +#define KUNIT_ASSERT_EQ_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + ==, \ + right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_PTR_EQ() - Asserts that pointers @left and @right are equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a pointer. + * @right: an arbitrary expression that evaluates to a pointer. + * + * Sets an assertion that the values that @left and @right evaluate to are + * equal. This is the same as KUNIT_EXPECT_EQ(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_PTR_EQ(test, left, right) \ + KUNIT_ASSERT_PTR_BINARY(test, left, ==, right) + +#define KUNIT_ASSERT_PTR_EQ_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_PTR_BINARY_MSG(test, \ + left, \ + ==, \ + right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_NE() - An assertion that @left and @right are not equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the values that @left and @right evaluate to are not + * equal. This is the same as KUNIT_EXPECT_NE(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_NE(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, !=, right) + +#define KUNIT_ASSERT_NE_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + !=, \ + right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_PTR_NE() - Asserts that pointers @left and @right are not equal. + * KUNIT_ASSERT_PTR_EQ() - Asserts that pointers @left and @right are equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a pointer. + * @right: an arbitrary expression that evaluates to a pointer. + * + * Sets an assertion that the values that @left and @right evaluate to are not + * equal. This is the same as KUNIT_EXPECT_NE(), except it causes an assertion + * failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_PTR_NE(test, left, right) \ + KUNIT_ASSERT_PTR_BINARY(test, left, !=, right) + +#define KUNIT_ASSERT_PTR_NE_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_PTR_BINARY_MSG(test, \ + left, \ + !=, \ + right, \ + fmt, \ + ##__VA_ARGS__) +/** + * KUNIT_ASSERT_LT() - An assertion that @left is less than @right. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the value that @left evaluates to is less than the + * value that @right evaluates to. This is the same as KUNIT_EXPECT_LT(), except + * it causes an assertion failure (see KUNIT_ASSERT_TRUE()) when the assertion + * is not met. + */ +#define KUNIT_ASSERT_LT(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, <, right) + +#define KUNIT_ASSERT_LT_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + <, \ + right, \ + fmt, \ + ##__VA_ARGS__) +/** + * KUNIT_ASSERT_LE() - An assertion that @left is less than or equal to @right. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the value that @left evaluates to is less than or + * equal to the value that @right evaluates to. This is the same as + * KUNIT_EXPECT_LE(), except it causes an assertion failure (see + * KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_LE(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, <=, right) + +#define KUNIT_ASSERT_LE_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + <=, \ + right, \ + fmt, \ + ##__VA_ARGS__) +/** + * KUNIT_ASSERT_GT() - An assertion that @left is greater than @right. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the value that @left evaluates to is greater than the + * value that @right evaluates to. This is the same as KUNIT_EXPECT_GT(), except + * it causes an assertion failure (see KUNIT_ASSERT_TRUE()) when the assertion + * is not met. + */ +#define KUNIT_ASSERT_GT(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, >, right) + +#define KUNIT_ASSERT_GT_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + >, \ + right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_GE() - Assertion that @left is greater than or equal to @right. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a primitive C type. + * @right: an arbitrary expression that evaluates to a primitive C type. + * + * Sets an assertion that the value that @left evaluates to is greater than the + * value that @right evaluates to. This is the same as KUNIT_EXPECT_GE(), except + * it causes an assertion failure (see KUNIT_ASSERT_TRUE()) when the assertion + * is not met. + */ +#define KUNIT_ASSERT_GE(test, left, right) \ + KUNIT_ASSERT_BINARY(test, left, >=, right) + +#define KUNIT_ASSERT_GE_MSG(test, left, right, fmt, ...) \ + KUNIT_ASSERT_BINARY_MSG(test, \ + left, \ + >=, \ + right, \ + fmt, \ + ##__VA_ARGS__) + +/** + * KUNIT_ASSERT_STREQ() - An assertion that strings @left and @right are equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a null terminated string. + * @right: an arbitrary expression that evaluates to a null terminated string. + * + * Sets an assertion that the values that @left and @right evaluate to are + * equal. This is the same as KUNIT_EXPECT_STREQ(), except it causes an + * assertion failure (see KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_STREQ(test, left, right) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + \ + kunit_stream_add(__stream, "Asserted " #left " == " #right ", but\n"); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #left, __left); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #right, __right); \ + \ + KUNIT_ASSERT_END(test, !strcmp(left, right), __stream); \ +} while (0) + +#define KUNIT_ASSERT_STREQ_MSG(test, left, right, fmt, ...) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + \ + kunit_stream_add(__stream, "Asserted " #left " == " #right ", but\n"); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #left, __left); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #right, __right); \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + \ + KUNIT_ASSERT_END(test, !strcmp(left, right), __stream); \ +} while (0) + +/** + * KUNIT_ASSERT_STRNEQ() - Expects that strings @left and @right are not equal. + * @test: The test context object. + * @left: an arbitrary expression that evaluates to a null terminated string. + * @right: an arbitrary expression that evaluates to a null terminated string. + * + * Sets an expectation that the values that @left and @right evaluate to are + * not equal. This is semantically equivalent to + * KUNIT_ASSERT_TRUE(@test, strcmp((@left), (@right))). See KUNIT_ASSERT_TRUE() + * for more information. + */ +#define KUNIT_ASSERT_STRNEQ(test, left, right) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + \ + kunit_stream_add(__stream, "Asserted " #left " == " #right ", but\n"); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #left, __left); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #right, __right); \ + \ + KUNIT_ASSERT_END(test, strcmp(left, right), __stream); \ +} while (0) + +#define KUNIT_ASSERT_STRNEQ_MSG(test, left, right, fmt, ...) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(left) __left = (left); \ + typeof(right) __right = (right); \ + \ + kunit_stream_add(__stream, "Asserted " #left " == " #right ", but\n"); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #left, __left); \ + kunit_stream_add(__stream, "\t\t%s == %s\n", #right, __right); \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + \ + KUNIT_ASSERT_END(test, strcmp(left, right), __stream); \ +} while (0) + +/** + * KUNIT_ASSERT_NOT_ERR_OR_NULL() - Assertion that @ptr is not null and not err. + * @test: The test context object. + * @ptr: an arbitrary pointer. + * + * Sets an assertion that the value that @ptr evaluates to is not null and not + * an errno stored in a pointer. This is the same as + * KUNIT_EXPECT_NOT_ERR_OR_NULL(), except it causes an assertion failure (see + * KUNIT_ASSERT_TRUE()) when the assertion is not met. + */ +#define KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(ptr) __ptr = (ptr); \ + \ + if (!__ptr) \ + kunit_stream_add(__stream, \ + "Asserted " #ptr " is not null, but is\n"); \ + if (IS_ERR(__ptr)) \ + kunit_stream_add(__stream, \ + "Asserted " #ptr " is not error, but is: %ld\n",\ + PTR_ERR(__ptr)); \ + \ + KUNIT_ASSERT_END(test, !IS_ERR_OR_NULL(__ptr), __stream); \ +} while (0) + +#define KUNIT_ASSERT_NOT_ERR_OR_NULL_MSG(test, ptr, fmt, ...) do { \ + struct kunit_stream *__stream = KUNIT_ASSERT_START(test); \ + typeof(ptr) __ptr = (ptr); \ + \ + if (!__ptr) { \ + kunit_stream_add(__stream, \ + "Asserted " #ptr " is not null, but is\n"); \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + } \ + if (IS_ERR(__ptr)) { \ + kunit_stream_add(__stream, \ + "Asserted " #ptr " is not error, but is: %ld\n",\ + PTR_ERR(__ptr)); \ + \ + kunit_stream_add(__stream, fmt, ##__VA_ARGS__); \ + } \ + KUNIT_ASSERT_END(test, !IS_ERR_OR_NULL(__ptr), __stream); \ +} while (0) + #endif /* _KUNIT_TEST_H */ diff --git a/kunit/string-stream-test.c b/kunit/string-stream-test.c index 9cf08f9dadf36..fd928ab7d65a8 100644 --- a/kunit/string-stream-test.c +++ b/kunit/string-stream-test.c @@ -35,7 +35,7 @@ static void string_stream_test_get_string(struct kunit *test) string_stream_add(stream, " %s", "bar"); output = string_stream_get_string(stream); - KUNIT_EXPECT_STREQ(test, output, "Foo bar"); + KUNIT_ASSERT_STREQ(test, output, "Foo bar"); } static void string_stream_test_add_and_clear(struct kunit *test) @@ -48,15 +48,15 @@ static void string_stream_test_add_and_clear(struct kunit *test) string_stream_add(stream, "A"); output = string_stream_get_string(stream); - KUNIT_EXPECT_STREQ(test, output, "AAAAAAAAAA"); - KUNIT_EXPECT_EQ(test, stream->length, (size_t)10); - KUNIT_EXPECT_FALSE(test, string_stream_is_empty(stream)); + KUNIT_ASSERT_STREQ(test, output, "AAAAAAAAAA"); + KUNIT_ASSERT_EQ(test, stream->length, (size_t)10); + KUNIT_ASSERT_FALSE(test, string_stream_is_empty(stream)); string_stream_clear(stream); output = string_stream_get_string(stream); - KUNIT_EXPECT_STREQ(test, output, ""); - KUNIT_EXPECT_TRUE(test, string_stream_is_empty(stream)); + KUNIT_ASSERT_STREQ(test, output, ""); + KUNIT_ASSERT_TRUE(test, string_stream_is_empty(stream)); } static struct kunit_case string_stream_test_cases[] = { diff --git a/kunit/test-test.c b/kunit/test-test.c index 88f4cdf03db2a..058f3fb37458a 100644 --- a/kunit/test-test.c +++ b/kunit/test-test.c @@ -78,11 +78,13 @@ static int kunit_try_catch_test_init(struct kunit *test) struct kunit_try_catch_test_context *ctx; ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); test->priv = ctx; ctx->try_catch = kunit_kmalloc(test, sizeof(*ctx->try_catch), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch); return 0; } diff --git a/kunit/test.c b/kunit/test.c index 12db50b221781..2723f7bc04682 100644 --- a/kunit/test.c +++ b/kunit/test.c @@ -499,3 +499,69 @@ void kunit_expect_ptr_binary_msg(struct kunit *test, kunit_expect_end(test, compare_result, stream); } + +void kunit_assert_binary_msg(struct kunit *test, + long long left, const char *left_name, + long long right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line, + const char *fmt, ...) +{ + struct kunit_stream *stream = kunit_assert_start(test, file, line); + struct va_format vaf; + va_list args; + + kunit_stream_add(stream, + "Asserted %s %s %s, but\n", + left_name, compare_name, right_name); + kunit_stream_add(stream, "\t\t%s == %lld\n", left_name, left); + kunit_stream_add(stream, "\t\t%s == %lld\n", right_name, right); + + if (fmt) { + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + kunit_stream_add(stream, "\n%pV", &vaf); + + va_end(args); + } + + kunit_assert_end(test, compare_result, stream); +} + +void kunit_assert_ptr_binary_msg(struct kunit *test, + void *left, const char *left_name, + void *right, const char *right_name, + bool compare_result, + const char *compare_name, + const char *file, + const char *line, + const char *fmt, ...) +{ + struct kunit_stream *stream = kunit_assert_start(test, file, line); + struct va_format vaf; + va_list args; + + kunit_stream_add(stream, + "Asserted %s %s %s, but\n", + left_name, compare_name, right_name); + kunit_stream_add(stream, "\t\t%s == %pK\n", left_name, left); + kunit_stream_add(stream, "\t\t%s == %pK", right_name, right); + + if (fmt) { + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + kunit_stream_add(stream, "\n%pV", &vaf); + + va_end(args); + } + + kunit_assert_end(test, compare_result, stream); +}