2019-09-23 09:02:34 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Assertion and expectation serialization API.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2019, Google LLC.
|
|
|
|
* Author: Brendan Higgins <brendanhiggins@google.com>
|
|
|
|
*/
|
|
|
|
#include <kunit/assert.h>
|
2020-03-26 14:25:09 +00:00
|
|
|
#include <kunit/test.h>
|
2019-09-23 09:02:34 +00:00
|
|
|
|
2020-01-06 22:28:18 +00:00
|
|
|
#include "string-stream.h"
|
|
|
|
|
kunit: split out part of kunit_assert into a static const
This is per Linus's suggestion in [1].
The issue there is that every KUNIT_EXPECT/KUNIT_ASSERT puts a
kunit_assert object onto the stack. Normally we rely on compilers to
elide this, but when that doesn't work out, this blows up the stack
usage of kunit test functions.
We can move some data off the stack by making it static.
This change introduces a new `struct kunit_loc` to hold the file and
line number and then just passing assert_type (EXPECT or ASSERT) as an
argument.
In [1], it was suggested to also move out the format string as well, but
users could theoretically craft a format string at runtime, so we can't.
This change leaves a copy of `assert_type` in kunit_assert for now
because cleaning up all the macros to not pass it around is a bit more
involved.
Here's an example of the expanded code for KUNIT_FAIL():
if (__builtin_expect(!!(!(false)), 0)) {
static const struct kunit_loc loc = { .file = ... };
struct kunit_fail_assert __assertion = { .assert = { .type ... };
kunit_do_failed_assertion(test, &loc, KUNIT_EXPECTATION, &__assertion.assert, ...);
};
[1] https://groups.google.com/g/kunit-dev/c/i3fZXgvBrfA/m/VULQg1z6BAAJ
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2022-01-13 16:59:30 +00:00
|
|
|
void kunit_assert_prologue(const struct kunit_loc *loc,
|
|
|
|
enum kunit_assert_type type,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
|
|
|
const char *expect_or_assert = NULL;
|
|
|
|
|
kunit: split out part of kunit_assert into a static const
This is per Linus's suggestion in [1].
The issue there is that every KUNIT_EXPECT/KUNIT_ASSERT puts a
kunit_assert object onto the stack. Normally we rely on compilers to
elide this, but when that doesn't work out, this blows up the stack
usage of kunit test functions.
We can move some data off the stack by making it static.
This change introduces a new `struct kunit_loc` to hold the file and
line number and then just passing assert_type (EXPECT or ASSERT) as an
argument.
In [1], it was suggested to also move out the format string as well, but
users could theoretically craft a format string at runtime, so we can't.
This change leaves a copy of `assert_type` in kunit_assert for now
because cleaning up all the macros to not pass it around is a bit more
involved.
Here's an example of the expanded code for KUNIT_FAIL():
if (__builtin_expect(!!(!(false)), 0)) {
static const struct kunit_loc loc = { .file = ... };
struct kunit_fail_assert __assertion = { .assert = { .type ... };
kunit_do_failed_assertion(test, &loc, KUNIT_EXPECTATION, &__assertion.assert, ...);
};
[1] https://groups.google.com/g/kunit-dev/c/i3fZXgvBrfA/m/VULQg1z6BAAJ
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2022-01-13 16:59:30 +00:00
|
|
|
switch (type) {
|
2019-09-23 09:02:34 +00:00
|
|
|
case KUNIT_EXPECTATION:
|
|
|
|
expect_or_assert = "EXPECTATION";
|
|
|
|
break;
|
|
|
|
case KUNIT_ASSERTION:
|
|
|
|
expect_or_assert = "ASSERTION";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
string_stream_add(stream, "%s FAILED at %s:%d\n",
|
kunit: split out part of kunit_assert into a static const
This is per Linus's suggestion in [1].
The issue there is that every KUNIT_EXPECT/KUNIT_ASSERT puts a
kunit_assert object onto the stack. Normally we rely on compilers to
elide this, but when that doesn't work out, this blows up the stack
usage of kunit test functions.
We can move some data off the stack by making it static.
This change introduces a new `struct kunit_loc` to hold the file and
line number and then just passing assert_type (EXPECT or ASSERT) as an
argument.
In [1], it was suggested to also move out the format string as well, but
users could theoretically craft a format string at runtime, so we can't.
This change leaves a copy of `assert_type` in kunit_assert for now
because cleaning up all the macros to not pass it around is a bit more
involved.
Here's an example of the expanded code for KUNIT_FAIL():
if (__builtin_expect(!!(!(false)), 0)) {
static const struct kunit_loc loc = { .file = ... };
struct kunit_fail_assert __assertion = { .assert = { .type ... };
kunit_do_failed_assertion(test, &loc, KUNIT_EXPECTATION, &__assertion.assert, ...);
};
[1] https://groups.google.com/g/kunit-dev/c/i3fZXgvBrfA/m/VULQg1z6BAAJ
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2022-01-13 16:59:30 +00:00
|
|
|
expect_or_assert, loc->file, loc->line);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
kunit: split out part of kunit_assert into a static const
This is per Linus's suggestion in [1].
The issue there is that every KUNIT_EXPECT/KUNIT_ASSERT puts a
kunit_assert object onto the stack. Normally we rely on compilers to
elide this, but when that doesn't work out, this blows up the stack
usage of kunit test functions.
We can move some data off the stack by making it static.
This change introduces a new `struct kunit_loc` to hold the file and
line number and then just passing assert_type (EXPECT or ASSERT) as an
argument.
In [1], it was suggested to also move out the format string as well, but
users could theoretically craft a format string at runtime, so we can't.
This change leaves a copy of `assert_type` in kunit_assert for now
because cleaning up all the macros to not pass it around is a bit more
involved.
Here's an example of the expanded code for KUNIT_FAIL():
if (__builtin_expect(!!(!(false)), 0)) {
static const struct kunit_loc loc = { .file = ... };
struct kunit_fail_assert __assertion = { .assert = { .type ... };
kunit_do_failed_assertion(test, &loc, KUNIT_EXPECTATION, &__assertion.assert, ...);
};
[1] https://groups.google.com/g/kunit-dev/c/i3fZXgvBrfA/m/VULQg1z6BAAJ
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2022-01-13 16:59:30 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_assert_prologue);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
2022-01-25 21:00:09 +00:00
|
|
|
static void kunit_assert_print_msg(const struct va_format *message,
|
|
|
|
struct string_stream *stream)
|
2019-09-23 09:02:34 +00:00
|
|
|
{
|
2022-01-25 21:00:09 +00:00
|
|
|
if (message->fmt)
|
|
|
|
string_stream_add(stream, "\n%pV", message);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void kunit_fail_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2022-01-25 21:00:09 +00:00
|
|
|
string_stream_add(stream, "%pV", message);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
void kunit_unary_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2021-03-12 19:11:26 +00:00
|
|
|
struct kunit_unary_assert *unary_assert;
|
|
|
|
|
|
|
|
unary_assert = container_of(assert, struct kunit_unary_assert, assert);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
if (unary_assert->expected_true)
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
|
|
|
|
unary_assert->condition);
|
2019-09-23 09:02:34 +00:00
|
|
|
else
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
|
|
|
|
unary_assert->condition);
|
2022-01-25 21:00:09 +00:00
|
|
|
kunit_assert_print_msg(message, stream);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2021-03-12 19:11:26 +00:00
|
|
|
struct kunit_ptr_not_err_assert *ptr_assert;
|
|
|
|
|
|
|
|
ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
|
|
|
|
assert);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
if (!ptr_assert->value) {
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
|
|
|
|
ptr_assert->text);
|
2019-09-23 09:02:34 +00:00
|
|
|
} else if (IS_ERR(ptr_assert->value)) {
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",
|
|
|
|
ptr_assert->text,
|
|
|
|
PTR_ERR(ptr_assert->value));
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2022-01-25 21:00:09 +00:00
|
|
|
kunit_assert_print_msg(message, stream);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
kunit: don't show `1 == 1` in failed assertion messages
Currently, given something (fairly dystopian) like
> KUNIT_EXPECT_EQ(test, 2 + 2, 5)
KUnit will prints a failure message like this.
> Expected 2 + 2 == 5, but
> 2 + 2 == 4
> 5 == 5
With this patch, the output just becomes
> Expected 2 + 2 == 5, but
> 2 + 2 == 4
This patch is slightly hacky, but it's quite common* to compare an
expression to a literal integer value, so this can make KUnit less
chatty in many cases. (This patch also fixes variants like
KUNIT_EXPECT_GT, LE, et al.).
It also allocates an additional string briefly, but given this only
happens on test failures, it doesn't seem too bad a tradeoff.
Also, in most cases it'll realize the lengths are unequal and bail out
before the allocation.
We could save the result of the formatted string to avoid wasting this
extra work, but it felt cleaner to leave it as-is.
Edge case: for something silly and unrealistic like
> KUNIT_EXPECT_EQ(test, 4, 5);
It'll generate this message with a trailing "but"
> Expected 4 == 5, but
> <next line of normal output>
It didn't feel worth adding a check up-front to see if both sides are
literals to handle this better.
*A quick grep suggests 100+ comparisons to an integer literal as the
right hand side.
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Tested-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-02-05 22:14:09 +00:00
|
|
|
/* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
|
|
|
|
static bool is_literal(struct kunit *test, const char *text, long long value,
|
|
|
|
gfp_t gfp)
|
|
|
|
{
|
|
|
|
char *buffer;
|
|
|
|
int len;
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
len = snprintf(NULL, 0, "%lld", value);
|
|
|
|
if (strlen(text) != len)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
buffer = kunit_kmalloc(test, len+1, gfp);
|
|
|
|
if (!buffer)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
snprintf(buffer, len+1, "%lld", value);
|
|
|
|
ret = strncmp(buffer, text, len) == 0;
|
|
|
|
|
|
|
|
kunit_kfree(test, buffer);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-09-23 09:02:34 +00:00
|
|
|
void kunit_binary_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2021-03-12 19:11:26 +00:00
|
|
|
struct kunit_binary_assert *binary_assert;
|
|
|
|
|
|
|
|
binary_assert = container_of(assert, struct kunit_binary_assert,
|
|
|
|
assert);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->operation,
|
|
|
|
binary_assert->right_text);
|
kunit: don't show `1 == 1` in failed assertion messages
Currently, given something (fairly dystopian) like
> KUNIT_EXPECT_EQ(test, 2 + 2, 5)
KUnit will prints a failure message like this.
> Expected 2 + 2 == 5, but
> 2 + 2 == 4
> 5 == 5
With this patch, the output just becomes
> Expected 2 + 2 == 5, but
> 2 + 2 == 4
This patch is slightly hacky, but it's quite common* to compare an
expression to a literal integer value, so this can make KUnit less
chatty in many cases. (This patch also fixes variants like
KUNIT_EXPECT_GT, LE, et al.).
It also allocates an additional string briefly, but given this only
happens on test failures, it doesn't seem too bad a tradeoff.
Also, in most cases it'll realize the lengths are unequal and bail out
before the allocation.
We could save the result of the formatted string to avoid wasting this
extra work, but it felt cleaner to leave it as-is.
Edge case: for something silly and unrealistic like
> KUNIT_EXPECT_EQ(test, 4, 5);
It'll generate this message with a trailing "but"
> Expected 4 == 5, but
> <next line of normal output>
It didn't feel worth adding a check up-front to see if both sides are
literals to handle this better.
*A quick grep suggests 100+ comparisons to an integer literal as the
right hand side.
Signed-off-by: Daniel Latypov <dlatypov@google.com>
Tested-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
2021-02-05 22:14:09 +00:00
|
|
|
if (!is_literal(stream->test, binary_assert->left_text,
|
|
|
|
binary_assert->left_value, stream->gfp))
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->left_value);
|
|
|
|
if (!is_literal(stream->test, binary_assert->right_text,
|
|
|
|
binary_assert->right_value, stream->gfp))
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld",
|
|
|
|
binary_assert->right_text,
|
|
|
|
binary_assert->right_value);
|
2022-01-25 21:00:09 +00:00
|
|
|
kunit_assert_print_msg(message, stream);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2021-03-12 19:11:26 +00:00
|
|
|
struct kunit_binary_ptr_assert *binary_assert;
|
|
|
|
|
|
|
|
binary_assert = container_of(assert, struct kunit_binary_ptr_assert,
|
|
|
|
assert);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->operation,
|
|
|
|
binary_assert->right_text);
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->left_value);
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
|
|
|
|
binary_assert->right_text,
|
|
|
|
binary_assert->right_value);
|
2022-01-25 21:00:09 +00:00
|
|
|
kunit_assert_print_msg(message, stream);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
2021-04-02 19:33:57 +00:00
|
|
|
/* Checks if KUNIT_EXPECT_STREQ() args were string literals.
|
|
|
|
* Note: `text` will have ""s where as `value` will not.
|
|
|
|
*/
|
|
|
|
static bool is_str_literal(const char *text, const char *value)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = strlen(text);
|
|
|
|
if (len < 2)
|
|
|
|
return false;
|
|
|
|
if (text[0] != '\"' || text[len - 1] != '\"')
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return strncmp(text + 1, value, len - 2) == 0;
|
|
|
|
}
|
|
|
|
|
2019-09-23 09:02:34 +00:00
|
|
|
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
|
2022-01-25 21:00:09 +00:00
|
|
|
const struct va_format *message,
|
2019-09-23 09:02:34 +00:00
|
|
|
struct string_stream *stream)
|
|
|
|
{
|
2021-03-12 19:11:26 +00:00
|
|
|
struct kunit_binary_str_assert *binary_assert;
|
|
|
|
|
|
|
|
binary_assert = container_of(assert, struct kunit_binary_str_assert,
|
|
|
|
assert);
|
2019-09-23 09:02:34 +00:00
|
|
|
|
|
|
|
string_stream_add(stream,
|
2020-03-26 14:25:09 +00:00
|
|
|
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->operation,
|
|
|
|
binary_assert->right_text);
|
2021-04-02 19:33:57 +00:00
|
|
|
if (!is_str_literal(binary_assert->left_text, binary_assert->left_value))
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",
|
|
|
|
binary_assert->left_text,
|
|
|
|
binary_assert->left_value);
|
|
|
|
if (!is_str_literal(binary_assert->right_text, binary_assert->right_value))
|
|
|
|
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",
|
|
|
|
binary_assert->right_text,
|
|
|
|
binary_assert->right_value);
|
2022-01-25 21:00:09 +00:00
|
|
|
kunit_assert_print_msg(message, stream);
|
2019-09-23 09:02:34 +00:00
|
|
|
}
|
2020-01-06 22:28:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
|