Commit d51b1b33 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-kselftest-kunit-5.18-rc1' of...

Merge tag 'linux-kselftest-kunit-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull KUnit updates from Shuah Khan:

 - changes to decrease macro layering string, integer, EQ/NE asserts

 - remove unused macros

 - several cleanups and fixes

 - new list tests for list_del_init_careful(), list_is_head() and
   list_entry_is_head()

* tag 'linux-kselftest-kunit-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  list: test: Add a test for list_entry_is_head()
  list: test: Add a test for list_is_head()
  list: test: Add test for list_del_init_careful()
  kunit: cleanup assertion macro internal variables
  kunit: factor out str constants from binary assertion structs
  kunit: consolidate KUNIT_INIT_BINARY_ASSERT_STRUCT macros
  kunit: remove va_format from kunit_assert
  kunit: tool: drop mostly unused KunitResult.result field
  kunit: decrease macro layering for EQ/NE asserts
  kunit: decrease macro layering for integer asserts
  kunit: reduce layering in string assertion macros
  kunit: drop unused intermediate macros for ptr inequality checks
  kunit: make KUNIT_EXPECT_EQ() use KUNIT_EXPECT_EQ_MSG(), etc.
  kunit: drop unused assert_type from kunit_assert and clean up macros
  kunit: split out part of kunit_assert into a static const
  kunit: factor out kunit_base_assert_format() call into kunit_fail()
  kunit: drop unused kunit* field in kunit_assert
  kunit: move check if assertion passed into the macros
  kunit: add example test case showing off all the expect macros
parents 23d1dea5 5debe5bf
This diff is collapsed.
This diff is collapsed.
......@@ -10,12 +10,13 @@
#include "string-stream.h"
void kunit_base_assert_format(const struct kunit_assert *assert,
void kunit_assert_prologue(const struct kunit_loc *loc,
enum kunit_assert_type type,
struct string_stream *stream)
{
const char *expect_or_assert = NULL;
switch (assert->type) {
switch (type) {
case KUNIT_EXPECTATION:
expect_or_assert = "EXPECTATION";
break;
......@@ -25,34 +26,33 @@ void kunit_base_assert_format(const struct kunit_assert *assert,
}
string_stream_add(stream, "%s FAILED at %s:%d\n",
expect_or_assert, assert->file, assert->line);
expect_or_assert, loc->file, loc->line);
}
EXPORT_SYMBOL_GPL(kunit_base_assert_format);
EXPORT_SYMBOL_GPL(kunit_assert_prologue);
void kunit_assert_print_msg(const struct kunit_assert *assert,
struct string_stream *stream)
static void kunit_assert_print_msg(const struct va_format *message,
struct string_stream *stream)
{
if (assert->message.fmt)
string_stream_add(stream, "\n%pV", &assert->message);
if (message->fmt)
string_stream_add(stream, "\n%pV", message);
}
EXPORT_SYMBOL_GPL(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
kunit_base_assert_format(assert, stream);
string_stream_add(stream, "%pV", &assert->message);
string_stream_add(stream, "%pV", message);
}
EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
void kunit_unary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
struct kunit_unary_assert *unary_assert;
unary_assert = container_of(assert, struct kunit_unary_assert, assert);
kunit_base_assert_format(assert, stream);
if (unary_assert->expected_true)
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
......@@ -61,11 +61,12 @@ void kunit_unary_assert_format(const struct kunit_assert *assert,
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
unary_assert->condition);
kunit_assert_print_msg(assert, stream);
kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
struct kunit_ptr_not_err_assert *ptr_assert;
......@@ -73,7 +74,6 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
assert);
kunit_base_assert_format(assert, stream);
if (!ptr_assert->value) {
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
......@@ -84,7 +84,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
ptr_assert->text,
PTR_ERR(ptr_assert->value));
}
kunit_assert_print_msg(assert, stream);
kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
......@@ -112,6 +112,7 @@ static bool is_literal(struct kunit *test, const char *text, long long value,
}
void kunit_binary_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_assert *binary_assert;
......@@ -119,27 +120,27 @@ void kunit_binary_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_assert,
assert);
kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
binary_assert->left_text,
binary_assert->operation,
binary_assert->right_text);
if (!is_literal(stream->test, binary_assert->left_text,
binary_assert->text->left_text,
binary_assert->text->operation,
binary_assert->text->right_text);
if (!is_literal(stream->test, binary_assert->text->left_text,
binary_assert->left_value, stream->gfp))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n",
binary_assert->left_text,
binary_assert->text->left_text,
binary_assert->left_value);
if (!is_literal(stream->test, binary_assert->right_text,
if (!is_literal(stream->test, binary_assert->text->right_text,
binary_assert->right_value, stream->gfp))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld",
binary_assert->right_text,
binary_assert->text->right_text,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_ptr_assert *binary_assert;
......@@ -147,19 +148,18 @@ void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_ptr_assert,
assert);
kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
binary_assert->left_text,
binary_assert->operation,
binary_assert->right_text);
binary_assert->text->left_text,
binary_assert->text->operation,
binary_assert->text->right_text);
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
binary_assert->left_text,
binary_assert->text->left_text,
binary_assert->left_value);
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
binary_assert->right_text,
binary_assert->text->right_text,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
......@@ -180,6 +180,7 @@ static bool is_str_literal(const char *text, const char *value)
}
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
const struct va_format *message,
struct string_stream *stream)
{
struct kunit_binary_str_assert *binary_assert;
......@@ -187,20 +188,19 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
binary_assert = container_of(assert, struct kunit_binary_str_assert,
assert);
kunit_base_assert_format(assert, stream);
string_stream_add(stream,
KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
binary_assert->left_text,
binary_assert->operation,
binary_assert->right_text);
if (!is_str_literal(binary_assert->left_text, binary_assert->left_value))
binary_assert->text->left_text,
binary_assert->text->operation,
binary_assert->text->right_text);
if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",
binary_assert->left_text,
binary_assert->text->left_text,
binary_assert->left_value);
if (!is_str_literal(binary_assert->right_text, binary_assert->right_value))
if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value))
string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",
binary_assert->right_text,
binary_assert->text->right_text,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
kunit_assert_print_msg(message, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
......@@ -69,6 +69,47 @@ static void example_mark_skipped_test(struct kunit *test)
/* This line should run */
kunit_info(test, "You should see this line.");
}
/*
* This test shows off all the types of KUNIT_EXPECT macros.
*/
static void example_all_expect_macros_test(struct kunit *test)
{
/* Boolean assertions */
KUNIT_EXPECT_TRUE(test, true);
KUNIT_EXPECT_FALSE(test, false);
/* Integer assertions */
KUNIT_EXPECT_EQ(test, 1, 1); /* check == */
KUNIT_EXPECT_GE(test, 1, 1); /* check >= */
KUNIT_EXPECT_LE(test, 1, 1); /* check <= */
KUNIT_EXPECT_NE(test, 1, 0); /* check != */
KUNIT_EXPECT_GT(test, 1, 0); /* check > */
KUNIT_EXPECT_LT(test, 0, 1); /* check < */
/* Pointer assertions */
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, test);
KUNIT_EXPECT_PTR_EQ(test, NULL, NULL);
KUNIT_EXPECT_PTR_NE(test, test, NULL);
/* String assertions */
KUNIT_EXPECT_STREQ(test, "hi", "hi");
KUNIT_EXPECT_STRNEQ(test, "hi", "bye");
/*
* There are also ASSERT variants of all of the above that abort test
* execution if they fail. Useful for memory allocations, etc.
*/
KUNIT_ASSERT_GT(test, sizeof(char), 0);
/*
* There are also _MSG variants of all of the above that let you include
* additional text on failure.
*/
KUNIT_EXPECT_GT_MSG(test, sizeof(int), 0, "Your ints are 0-bit?!");
KUNIT_ASSERT_GT_MSG(test, sizeof(int), 0, "Your ints are 0-bit?!");
}
/*
* Here we make a list of all the test cases we want to add to the test suite
* below.
......@@ -83,6 +124,7 @@ static struct kunit_case example_test_cases[] = {
KUNIT_CASE(example_simple_test),
KUNIT_CASE(example_skip_test),
KUNIT_CASE(example_mark_skipped_test),
KUNIT_CASE(example_all_expect_macros_test),
{}
};
......
......@@ -240,7 +240,9 @@ static void kunit_print_string_stream(struct kunit *test,
}
}
static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
static void kunit_fail(struct kunit *test, const struct kunit_loc *loc,
enum kunit_assert_type type, struct kunit_assert *assert,
const struct va_format *message)
{
struct string_stream *stream;
......@@ -250,12 +252,13 @@ static void kunit_fail(struct kunit *test, struct kunit_assert *assert)
if (!stream) {
WARN(true,
"Could not allocate stream to print failed assertion in %s:%d\n",
assert->file,
assert->line);
loc->file,
loc->line);
return;
}
assert->format(assert, stream);
kunit_assert_prologue(loc, type, stream);
assert->format(assert, message, stream);
kunit_print_string_stream(test, stream);
......@@ -275,29 +278,27 @@ static void __noreturn kunit_abort(struct kunit *test)
WARN_ONCE(true, "Throw could not abort from test!\n");
}
void kunit_do_assertion(struct kunit *test,
struct kunit_assert *assert,
bool pass,
const char *fmt, ...)
void kunit_do_failed_assertion(struct kunit *test,
const struct kunit_loc *loc,
enum kunit_assert_type type,
struct kunit_assert *assert,
const char *fmt, ...)
{
va_list args;
if (pass)
return;
struct va_format message;
va_start(args, fmt);
assert->message.fmt = fmt;
assert->message.va = &args;
message.fmt = fmt;
message.va = &args;
kunit_fail(test, assert);
kunit_fail(test, loc, type, assert, &message);
va_end(args);
if (assert->type == KUNIT_ASSERTION)
if (type == KUNIT_ASSERTION)
kunit_abort(test);
}
EXPORT_SYMBOL_GPL(kunit_do_assertion);
EXPORT_SYMBOL_GPL(kunit_do_failed_assertion);
void kunit_init_test(struct kunit *test, const char *name, char *log)
{
......
......@@ -161,6 +161,26 @@ static void list_test_list_del_init(struct kunit *test)
KUNIT_EXPECT_TRUE(test, list_empty_careful(&a));
}
static void list_test_list_del_init_careful(struct kunit *test)
{
/* NOTE: This test only checks the behaviour of this function in
* isolation. It does not verify memory model guarantees.
*/
struct list_head a, b;
LIST_HEAD(list);
list_add_tail(&a, &list);
list_add_tail(&b, &list);
/* before: [list] -> a -> b */
list_del_init_careful(&a);
/* after: [list] -> b, a initialised */
KUNIT_EXPECT_PTR_EQ(test, list.next, &b);
KUNIT_EXPECT_PTR_EQ(test, b.prev, &list);
KUNIT_EXPECT_TRUE(test, list_empty_careful(&a));
}
static void list_test_list_move(struct kunit *test)
{
struct list_head a, b;
......@@ -234,6 +254,24 @@ static void list_test_list_bulk_move_tail(struct kunit *test)
KUNIT_EXPECT_EQ(test, i, 2);
}
static void list_test_list_is_head(struct kunit *test)
{
struct list_head a, b, c;
/* Two lists: [a] -> b, [c] */
INIT_LIST_HEAD(&a);
INIT_LIST_HEAD(&c);
list_add_tail(&b, &a);
KUNIT_EXPECT_TRUE_MSG(test, list_is_head(&a, &a),
"Head element of same list");
KUNIT_EXPECT_FALSE_MSG(test, list_is_head(&a, &b),
"Non-head element of same list");
KUNIT_EXPECT_FALSE_MSG(test, list_is_head(&a, &c),
"Head element of different list");
}
static void list_test_list_is_first(struct kunit *test)
{
struct list_head a, b;
......@@ -511,6 +549,26 @@ static void list_test_list_entry(struct kunit *test)
struct list_test_struct, list));
}
static void list_test_list_entry_is_head(struct kunit *test)
{
struct list_test_struct test_struct1, test_struct2, test_struct3;
INIT_LIST_HEAD(&test_struct1.list);
INIT_LIST_HEAD(&test_struct3.list);
list_add_tail(&test_struct2.list, &test_struct1.list);
KUNIT_EXPECT_TRUE_MSG(test,
list_entry_is_head((&test_struct1), &test_struct1.list, list),
"Head element of same list");
KUNIT_EXPECT_FALSE_MSG(test,
list_entry_is_head((&test_struct2), &test_struct1.list, list),
"Non-head element of same list");
KUNIT_EXPECT_FALSE_MSG(test,
list_entry_is_head((&test_struct3), &test_struct1.list, list),
"Head element of different list");
}
static void list_test_list_first_entry(struct kunit *test)
{
struct list_test_struct test_struct1, test_struct2;
......@@ -707,9 +765,11 @@ static struct kunit_case list_test_cases[] = {
KUNIT_CASE(list_test_list_replace_init),
KUNIT_CASE(list_test_list_swap),
KUNIT_CASE(list_test_list_del_init),
KUNIT_CASE(list_test_list_del_init_careful),
KUNIT_CASE(list_test_list_move),
KUNIT_CASE(list_test_list_move_tail),
KUNIT_CASE(list_test_list_bulk_move_tail),
KUNIT_CASE(list_test_list_is_head),
KUNIT_CASE(list_test_list_is_first),
KUNIT_CASE(list_test_list_is_last),
KUNIT_CASE(list_test_list_empty),
......@@ -724,6 +784,7 @@ static struct kunit_case list_test_cases[] = {
KUNIT_CASE(list_test_list_splice_init),
KUNIT_CASE(list_test_list_splice_tail_init),
KUNIT_CASE(list_test_list_entry),
KUNIT_CASE(list_test_list_entry_is_head),
KUNIT_CASE(list_test_list_first_entry),
KUNIT_CASE(list_test_list_last_entry),
KUNIT_CASE(list_test_list_first_entry_or_null),
......
......@@ -17,7 +17,7 @@ assert sys.version_info >= (3, 7), "Python version is too old"
from dataclasses import dataclass
from enum import Enum, auto
from typing import Any, Iterable, Sequence, List, Optional
from typing import Iterable, List, Optional, Sequence, Tuple
import kunit_json
import kunit_kernel
......@@ -32,7 +32,6 @@ class KunitStatus(Enum):
@dataclass
class KunitResult:
status: KunitStatus
result: Any
elapsed_time: float
@dataclass
......@@ -82,10 +81,8 @@ def config_tests(linux: kunit_kernel.LinuxSourceTree,
config_end = time.time()
if not success:
return KunitResult(KunitStatus.CONFIG_FAILURE,
'could not configure kernel',
config_end - config_start)
return KunitResult(KunitStatus.SUCCESS,
'configured kernel successfully',
config_end - config_start)
def build_tests(linux: kunit_kernel.LinuxSourceTree,
......@@ -100,14 +97,11 @@ def build_tests(linux: kunit_kernel.LinuxSourceTree,
build_end = time.time()
if not success:
return KunitResult(KunitStatus.BUILD_FAILURE,
'could not build kernel',
build_end - build_start)
if not success:
return KunitResult(KunitStatus.BUILD_FAILURE,
'could not build kernel',
build_end - build_start)
return KunitResult(KunitStatus.SUCCESS,
'built kernel successfully',
build_end - build_start)
def config_and_build_tests(linux: kunit_kernel.LinuxSourceTree,
......@@ -173,14 +167,14 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) -
filter_glob=filter_glob,
build_dir=request.build_dir)
result = parse_tests(request, run_result)
_, test_result = parse_tests(request, run_result)
# run_kernel() doesn't block on the kernel exiting.
# That only happens after we get the last line of output from `run_result`.
# So exec_time here actually contains parsing + execution time, which is fine.
test_end = time.time()
exec_time += test_end - test_start
test_counts.add_subtest_counts(result.result.counts)
test_counts.add_subtest_counts(test_result.counts)
if len(filter_globs) == 1 and test_counts.crashed > 0:
bd = request.build_dir
......@@ -189,7 +183,7 @@ def exec_tests(linux: kunit_kernel.LinuxSourceTree, request: KunitExecRequest) -
bd, bd, kunit_kernel.get_outfile_path(bd), bd, sys.argv[0]))
kunit_status = _map_to_overall_status(test_counts.get_status())
return KunitResult(status=kunit_status, result=result, elapsed_time=exec_time)
return KunitResult(status=kunit_status, elapsed_time=exec_time)
def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus:
if test_status in (kunit_parser.TestStatus.SUCCESS, kunit_parser.TestStatus.SKIPPED):
......@@ -197,7 +191,7 @@ def _map_to_overall_status(test_status: kunit_parser.TestStatus) -> KunitStatus:
else:
return KunitStatus.TEST_FAILURE
def parse_tests(request: KunitParseRequest, input_data: Iterable[str]) -> KunitResult:
def parse_tests(request: KunitParseRequest, input_data: Iterable[str]) -> Tuple[KunitResult, kunit_parser.Test]:
parse_start = time.time()
test_result = kunit_parser.Test()
......@@ -231,11 +225,9 @@ def parse_tests(request: KunitParseRequest, input_data: Iterable[str]) -> KunitR
print(json_obj)
if test_result.status != kunit_parser.TestStatus.SUCCESS:
return KunitResult(KunitStatus.TEST_FAILURE, test_result,
parse_end - parse_start)
return KunitResult(KunitStatus.TEST_FAILURE, parse_end - parse_start), test_result
return KunitResult(KunitStatus.SUCCESS, test_result,
parse_end - parse_start)
return KunitResult(KunitStatus.SUCCESS, parse_end - parse_start), test_result
def run_tests(linux: kunit_kernel.LinuxSourceTree,
request: KunitRequest) -> KunitResult:
......@@ -513,7 +505,7 @@ def main(argv, linux=None):
request = KunitParseRequest(raw_output=cli_args.raw_output,
build_dir='',
json=cli_args.json)
result = parse_tests(request, kunit_output)
result, _ = parse_tests(request, kunit_output)
if result.status != KunitStatus.SUCCESS:
sys.exit(1)
else:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment