Currently, we can run string-stream and assertion tests only when they are built into the kernel (with config options = y), since some of the symbols (string-stream functions and functions from assert.c) are not exported into any of the namespaces, therefore they are not accessible for the modules.
This patch series exports the required symbols into the KUnit namespace. Also, it makes the string-stream test a separate module and removes the log test stub from kunit-test since now we can access the string-stream symbols even if the test which uses it is built as a module.
Additionally, this patch series merges the assertion test suite into the kunit-test, since assert.c (and all of the assertion formatting functions in it) is a part of the KUnit core.
Ivan Orlov (5): kunit: string-stream: export non-static functions kunit: kunit-test: Remove stub for log tests kunit: string-stream-test: Make it a separate module kunit: assert: export non-static functions kunit: Merge assertion test into kunit-test.c
lib/kunit/Kconfig | 8 + lib/kunit/Makefile | 7 +- lib/kunit/assert.c | 4 + lib/kunit/assert_test.c | 388 -------------------------------- lib/kunit/kunit-test.c | 397 +++++++++++++++++++++++++++++++-- lib/kunit/string-stream-test.c | 2 + lib/kunit/string-stream.c | 12 +- 7 files changed, 405 insertions(+), 413 deletions(-) delete mode 100644 lib/kunit/assert_test.c
Export non-static functions from the string-stream.c file into the KUnit namespace in order to be able to access them from the KUnit core tests (when they are loaded as modules).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com --- lib/kunit/string-stream.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/string-stream.c b/lib/kunit/string-stream.c index 54f4fdcbfac8..a5e3339854da 100644 --- a/lib/kunit/string-stream.c +++ b/lib/kunit/string-stream.c @@ -10,7 +10,7 @@ #include <kunit/test.h> #include <linux/list.h> #include <linux/slab.h> - +#include <kunit/visibility.h> #include "string-stream.h"
@@ -86,6 +86,7 @@ int string_stream_vadd(struct string_stream *stream,
return 0; } +EXPORT_SYMBOL_IF_KUNIT(string_stream_vadd);
int string_stream_add(struct string_stream *stream, const char *fmt, ...) { @@ -98,6 +99,7 @@ int string_stream_add(struct string_stream *stream, const char *fmt, ...)
return result; } +EXPORT_SYMBOL_IF_KUNIT(string_stream_add);
void string_stream_clear(struct string_stream *stream) { @@ -113,6 +115,7 @@ void string_stream_clear(struct string_stream *stream) stream->length = 0; spin_unlock(&stream->lock); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_clear);
char *string_stream_get_string(struct string_stream *stream) { @@ -131,6 +134,7 @@ char *string_stream_get_string(struct string_stream *stream)
return buf; } +EXPORT_SYMBOL_IF_KUNIT(string_stream_get_string);
int string_stream_append(struct string_stream *stream, struct string_stream *other) @@ -148,11 +152,13 @@ int string_stream_append(struct string_stream *stream,
return ret; } +EXPORT_SYMBOL_IF_KUNIT(string_stream_append);
bool string_stream_is_empty(struct string_stream *stream) { return list_empty(&stream->fragments); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_is_empty);
struct string_stream *alloc_string_stream(gfp_t gfp) { @@ -168,6 +174,7 @@ struct string_stream *alloc_string_stream(gfp_t gfp)
return stream; } +EXPORT_SYMBOL_IF_KUNIT(alloc_string_stream);
void string_stream_destroy(struct string_stream *stream) { @@ -179,6 +186,7 @@ void string_stream_destroy(struct string_stream *stream) string_stream_clear(stream); kfree(stream); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_destroy);
static void resource_free_string_stream(void *p) { @@ -200,8 +208,10 @@ struct string_stream *kunit_alloc_string_stream(struct kunit *test, gfp_t gfp)
return stream; } +EXPORT_SYMBOL_IF_KUNIT(kunit_alloc_string_stream);
void kunit_free_string_stream(struct kunit *test, struct string_stream *stream) { kunit_release_action(test, resource_free_string_stream, (void *)stream); } +EXPORT_SYMBOL_IF_KUNIT(kunit_free_string_stream);
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Export non-static functions from the string-stream.c file into the KUnit namespace in order to be able to access them from the KUnit core tests (when they are loaded as modules).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Looks good to me, thanks.
It's very slightly hilarious to use EXPORT_SYMBOL_IF_KUNIT() here, because _of course_ KUnit is enabled, but I think it's the right idea nevertheless.
Reviewed-by: David Gow davidgow@google.com
Cheers, -- David
lib/kunit/string-stream.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/string-stream.c b/lib/kunit/string-stream.c index 54f4fdcbfac8..a5e3339854da 100644 --- a/lib/kunit/string-stream.c +++ b/lib/kunit/string-stream.c @@ -10,7 +10,7 @@ #include <kunit/test.h> #include <linux/list.h> #include <linux/slab.h>
+#include <kunit/visibility.h> #include "string-stream.h"
@@ -86,6 +86,7 @@ int string_stream_vadd(struct string_stream *stream,
return 0;
} +EXPORT_SYMBOL_IF_KUNIT(string_stream_vadd);
int string_stream_add(struct string_stream *stream, const char *fmt, ...) { @@ -98,6 +99,7 @@ int string_stream_add(struct string_stream *stream, const char *fmt, ...)
return result;
} +EXPORT_SYMBOL_IF_KUNIT(string_stream_add);
void string_stream_clear(struct string_stream *stream) { @@ -113,6 +115,7 @@ void string_stream_clear(struct string_stream *stream) stream->length = 0; spin_unlock(&stream->lock); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_clear);
char *string_stream_get_string(struct string_stream *stream) { @@ -131,6 +134,7 @@ char *string_stream_get_string(struct string_stream *stream)
return buf;
} +EXPORT_SYMBOL_IF_KUNIT(string_stream_get_string);
int string_stream_append(struct string_stream *stream, struct string_stream *other) @@ -148,11 +152,13 @@ int string_stream_append(struct string_stream *stream,
return ret;
} +EXPORT_SYMBOL_IF_KUNIT(string_stream_append);
bool string_stream_is_empty(struct string_stream *stream) { return list_empty(&stream->fragments); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_is_empty);
struct string_stream *alloc_string_stream(gfp_t gfp) { @@ -168,6 +174,7 @@ struct string_stream *alloc_string_stream(gfp_t gfp)
return stream;
} +EXPORT_SYMBOL_IF_KUNIT(alloc_string_stream);
void string_stream_destroy(struct string_stream *stream) { @@ -179,6 +186,7 @@ void string_stream_destroy(struct string_stream *stream) string_stream_clear(stream); kfree(stream); } +EXPORT_SYMBOL_IF_KUNIT(string_stream_destroy);
static void resource_free_string_stream(void *p) { @@ -200,8 +208,10 @@ struct string_stream *kunit_alloc_string_stream(struct kunit *test, gfp_t gfp)
return stream;
} +EXPORT_SYMBOL_IF_KUNIT(kunit_alloc_string_stream);
void kunit_free_string_stream(struct kunit *test, struct string_stream *stream) { kunit_release_action(test, resource_free_string_stream, (void *)stream); }
+EXPORT_SYMBOL_IF_KUNIT(kunit_free_string_stream);
2.34.1
On 6/8/24 10:20, David Gow wrote:
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Export non-static functions from the string-stream.c file into the KUnit namespace in order to be able to access them from the KUnit core tests (when they are loaded as modules).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Looks good to me, thanks.
It's very slightly hilarious to use EXPORT_SYMBOL_IF_KUNIT() here, because _of course_ KUnit is enabled, but I think it's the right idea nevertheless.
Reviewed-by: David Gow davidgow@google.com
Hi David,
Thank you for the review.
Yes, the name of the EXPORT_SYMBOL_IF_KUNIT macro in this case is a bit confusing... It is used not only to export the symbol conditionally (if CONFIG_KUNIT is enabled), but also to export the symbol into the KUnit namespace (so I used it as a shortcut for this action here) :)
Since now we are exporting string-stream functions into the KUnit namespace, we can safely use them in kunit-test when it is compiled as a module as well. So, remove the stubs used when kunit-test is compiled as a module. Import the KUnit namespace in the test.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com --- lib/kunit/kunit-test.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-)
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index e3412e0ca399..42178d5a97d1 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -577,12 +577,6 @@ static struct kunit_suite kunit_resource_test_suite = { .test_cases = kunit_resource_test_cases, };
-/* - * Log tests call string_stream functions, which aren't exported. So only - * build this code if this test is built-in. - */ -#if IS_BUILTIN(CONFIG_KUNIT_TEST) - /* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */ KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
@@ -637,17 +631,6 @@ static void kunit_log_newline_test(struct kunit *test) kunit_skip(test, "only useful when debugfs is enabled"); } } -#else -static void kunit_log_test(struct kunit *test) -{ - kunit_skip(test, "Log tests only run when built-in"); -} - -static void kunit_log_newline_test(struct kunit *test) -{ - kunit_skip(test, "Log tests only run when built-in"); -} -#endif /* IS_BUILTIN(CONFIG_KUNIT_TEST) */
static struct kunit_case kunit_log_test_cases[] = { KUNIT_CASE(kunit_log_test), @@ -871,4 +854,5 @@ kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, &kunit_current_test_suite, &kunit_device_test_suite, &kunit_fault_test_suite);
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); MODULE_LICENSE("GPL v2");
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Since now we are exporting string-stream functions into the KUnit namespace, we can safely use them in kunit-test when it is compiled as a module as well. So, remove the stubs used when kunit-test is compiled as a module. Import the KUnit namespace in the test.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Nice to see these finally work for modules!
Reviewed-by: David Gow davidgow@google.com
Cheers, -- David
lib/kunit/kunit-test.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-)
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index e3412e0ca399..42178d5a97d1 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -577,12 +577,6 @@ static struct kunit_suite kunit_resource_test_suite = { .test_cases = kunit_resource_test_cases, };
-/*
- Log tests call string_stream functions, which aren't exported. So only
- build this code if this test is built-in.
- */
-#if IS_BUILTIN(CONFIG_KUNIT_TEST)
/* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */ KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
@@ -637,17 +631,6 @@ static void kunit_log_newline_test(struct kunit *test) kunit_skip(test, "only useful when debugfs is enabled"); } } -#else -static void kunit_log_test(struct kunit *test) -{
kunit_skip(test, "Log tests only run when built-in");
-}
-static void kunit_log_newline_test(struct kunit *test) -{
kunit_skip(test, "Log tests only run when built-in");
-} -#endif /* IS_BUILTIN(CONFIG_KUNIT_TEST) */
static struct kunit_case kunit_log_test_cases[] = { KUNIT_CASE(kunit_log_test), @@ -871,4 +854,5 @@ kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, &kunit_current_test_suite, &kunit_device_test_suite, &kunit_fault_test_suite);
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); MODULE_LICENSE("GPL v2"); -- 2.34.1
Currently, the only way to build string-stream-test is by setting CONFIG_KUNIT_TEST=y. However, CONFIG_KUNIT_TEST is a config option for a different test (`kunit-test.c`).
Introduce a new Kconfig entry in order to be able to build the string-stream-test test as a separate module. Import the KUnit namespace in the test so we could have string-stream functions accessible.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com --- lib/kunit/Kconfig | 8 ++++++++ lib/kunit/Makefile | 2 +- lib/kunit/string-stream-test.c | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig index 34d7242d526d..b0713c0f9265 100644 --- a/lib/kunit/Kconfig +++ b/lib/kunit/Kconfig @@ -45,6 +45,14 @@ config KUNIT_TEST purposes by developers interested in testing that KUnit works as expected.
+config KUNIT_STRING_STREAM_TEST + tristate "KUnit test for string-stream" if !KUNIT_ALL_TESTS + default KUNIT_ALL_TESTS + help + Enables the KUnit test for the string-stream (C++ stream style string + builder used in KUnit for building messages). For the string-stream + implementation, see lib/kunit/string-stream.c. + config KUNIT_EXAMPLE_TEST tristate "Example test for KUnit" if !KUNIT_ALL_TESTS default KUNIT_ALL_TESTS diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index 900e6447c8e8..4793a3960f07 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -18,10 +18,10 @@ endif obj-y += hooks.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o +obj-$(CONFIG_KUNIT_STRING_STREAM_TEST) += string-stream-test.o
# string-stream-test compiles built-in only. ifeq ($(CONFIG_KUNIT_TEST),y) -obj-$(CONFIG_KUNIT_TEST) += string-stream-test.o obj-$(CONFIG_KUNIT_TEST) += assert_test.o endif
diff --git a/lib/kunit/string-stream-test.c b/lib/kunit/string-stream-test.c index 7511442ea98f..d03cac934e04 100644 --- a/lib/kunit/string-stream-test.c +++ b/lib/kunit/string-stream-test.c @@ -534,3 +534,5 @@ static struct kunit_suite string_stream_test_suite = { .init = string_stream_test_init, }; kunit_test_suites(&string_stream_test_suite); +MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); +MODULE_LICENSE("GPL");
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Currently, the only way to build string-stream-test is by setting CONFIG_KUNIT_TEST=y. However, CONFIG_KUNIT_TEST is a config option for a different test (`kunit-test.c`).
Introduce a new Kconfig entry in order to be able to build the string-stream-test test as a separate module. Import the KUnit namespace in the test so we could have string-stream functions accessible.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Looks good to me. checkpatch complains about the help text not being long enough, but I personally can't think if what else to sensibly add.
Reviewed-by: David Gow davidgow@google.com
Cheers, -- David
lib/kunit/Kconfig | 8 ++++++++ lib/kunit/Makefile | 2 +- lib/kunit/string-stream-test.c | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig index 34d7242d526d..b0713c0f9265 100644 --- a/lib/kunit/Kconfig +++ b/lib/kunit/Kconfig @@ -45,6 +45,14 @@ config KUNIT_TEST purposes by developers interested in testing that KUnit works as expected.
+config KUNIT_STRING_STREAM_TEST
tristate "KUnit test for string-stream" if !KUNIT_ALL_TESTS
default KUNIT_ALL_TESTS
help
Enables the KUnit test for the string-stream (C++ stream style string
builder used in KUnit for building messages). For the string-stream
implementation, see lib/kunit/string-stream.c.
config KUNIT_EXAMPLE_TEST tristate "Example test for KUnit" if !KUNIT_ALL_TESTS default KUNIT_ALL_TESTS diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index 900e6447c8e8..4793a3960f07 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -18,10 +18,10 @@ endif obj-y += hooks.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o +obj-$(CONFIG_KUNIT_STRING_STREAM_TEST) += string-stream-test.o
# string-stream-test compiles built-in only. ifeq ($(CONFIG_KUNIT_TEST),y) -obj-$(CONFIG_KUNIT_TEST) += string-stream-test.o obj-$(CONFIG_KUNIT_TEST) += assert_test.o endif
diff --git a/lib/kunit/string-stream-test.c b/lib/kunit/string-stream-test.c index 7511442ea98f..d03cac934e04 100644 --- a/lib/kunit/string-stream-test.c +++ b/lib/kunit/string-stream-test.c @@ -534,3 +534,5 @@ static struct kunit_suite string_stream_test_suite = { .init = string_stream_test_init, }; kunit_test_suites(&string_stream_test_suite); +MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_LICENSE("GPL");
2.34.1
Export non-static functions from the assert.c file into the KUnit namespace in order to be able to access them from the tests if they are compiled as modules.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com --- lib/kunit/assert.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c index 867aa5c4bccf..f394e4b8482f 100644 --- a/lib/kunit/assert.c +++ b/lib/kunit/assert.c @@ -38,6 +38,7 @@ void kunit_assert_print_msg(const struct va_format *message, if (message->fmt) string_stream_add(stream, "\n%pV", message); } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -112,6 +113,7 @@ VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
return ret; } +EXPORT_SYMBOL_IF_KUNIT(is_literal);
void kunit_binary_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -180,6 +182,7 @@ VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
return strncmp(text + 1, value, len - 2) == 0; } +EXPORT_SYMBOL_IF_KUNIT(is_str_literal);
void kunit_binary_str_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -232,6 +235,7 @@ void kunit_assert_hexdump(struct string_stream *stream, string_stream_add(stream, " %02x ", buf1[i]); } } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);
void kunit_mem_assert_format(const struct kunit_assert *assert, const struct va_format *message,
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Export non-static functions from the assert.c file into the KUnit namespace in order to be able to access them from the tests if they are compiled as modules.
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
I think this could be merged with patch 5, as it's not useful on its own. Also, a few of the symbol names might be a little too generic to be exported: maybe we should give them a 'kunit_assert' prefix?
Cheers, -- David
lib/kunit/assert.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c index 867aa5c4bccf..f394e4b8482f 100644 --- a/lib/kunit/assert.c +++ b/lib/kunit/assert.c @@ -38,6 +38,7 @@ void kunit_assert_print_msg(const struct va_format *message, if (message->fmt) string_stream_add(stream, "\n%pV", message); } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -112,6 +113,7 @@ VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
return ret;
} +EXPORT_SYMBOL_IF_KUNIT(is_literal);
I'm a bit worried about having such a generic name exported, even conditionally and to a namespace. Maybe we could give this a 'kunit_assert' prefix, or put it in a separate, more specific namespace?
void kunit_binary_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -180,6 +182,7 @@ VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
return strncmp(text + 1, value, len - 2) == 0;
} +EXPORT_SYMBOL_IF_KUNIT(is_str_literal);
I'm a bit worried about having such a generic name exported, even conditionally and to a namespace. Maybe we could give this a 'kunit_assert' prefix, or put it in a separate, more specific namespace?
void kunit_binary_str_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -232,6 +235,7 @@ void kunit_assert_hexdump(struct string_stream *stream, string_stream_add(stream, " %02x ", buf1[i]); } } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);
void kunit_mem_assert_format(const struct kunit_assert *assert, const struct va_format *message, -- 2.34.1
On 6/8/24 10:20, David Gow wrote:
I think this could be merged with patch 5, as it's not useful on its own. Also, a few of the symbol names might be a little too generic to be exported: maybe we should give them a 'kunit_assert' prefix?
Cheers, -- David
Hi David,
Thank you for the review and yes, I agree that it would be more useful in the scope of the next patch (so I'm going to squash it with the next patch in the V2).
lib/kunit/assert.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c index 867aa5c4bccf..f394e4b8482f 100644 --- a/lib/kunit/assert.c +++ b/lib/kunit/assert.c @@ -38,6 +38,7 @@ void kunit_assert_print_msg(const struct va_format *message, if (message->fmt) string_stream_add(stream, "\n%pV", message); } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -112,6 +113,7 @@ VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
return ret;
} +EXPORT_SYMBOL_IF_KUNIT(is_literal);
I'm a bit worried about having such a generic name exported, even conditionally and to a namespace. Maybe we could give this a 'kunit_assert' prefix, or put it in a separate, more specific namespace?
Yeah, makes sense, I'll rename them in the next version of the series. Thank you!
void kunit_binary_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -180,6 +182,7 @@ VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
return strncmp(text + 1, value, len - 2) == 0;
} +EXPORT_SYMBOL_IF_KUNIT(is_str_literal);
I'm a bit worried about having such a generic name exported, even conditionally and to a namespace. Maybe we could give this a 'kunit_assert' prefix, or put it in a separate, more specific namespace?
Same here: will be renamed :)
Thanks!
void kunit_binary_str_assert_format(const struct kunit_assert *assert, const struct va_format *message, @@ -232,6 +235,7 @@ void kunit_assert_hexdump(struct string_stream *stream, string_stream_add(stream, " %02x ", buf1[i]); } } +EXPORT_SYMBOL_IF_KUNIT(kunit_assert_hexdump);
void kunit_mem_assert_format(const struct kunit_assert *assert, const struct va_format *message, -- 2.34.1
Since assert_test covers the part of the KUnit core (the assertion formatting functions), I believe it would be better to have it merged into kunit-test (as it is done for other tests for the KUnit core).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com --- lib/kunit/Makefile | 5 - lib/kunit/assert_test.c | 388 ---------------------------------------- lib/kunit/kunit-test.c | 379 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 378 insertions(+), 394 deletions(-) delete mode 100644 lib/kunit/assert_test.c
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index 4793a3960f07..f41d2eab1f8d 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -20,9 +20,4 @@ obj-y += hooks.o obj-$(CONFIG_KUNIT_TEST) += kunit-test.o obj-$(CONFIG_KUNIT_STRING_STREAM_TEST) += string-stream-test.o
-# string-stream-test compiles built-in only. -ifeq ($(CONFIG_KUNIT_TEST),y) -obj-$(CONFIG_KUNIT_TEST) += assert_test.o -endif - obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test.o diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c deleted file mode 100644 index 4a5967712186..000000000000 --- a/lib/kunit/assert_test.c +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * KUnit test for the assertion formatting functions. - * Author: Ivan Orlov ivan.orlov0322@gmail.com - */ -#include <kunit/test.h> -#include "string-stream.h" - -#define TEST_PTR_EXPECTED_BUF_SIZE 32 -#define HEXDUMP_TEST_BUF_LEN 5 -#define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr)) -#define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr)) - -static void kunit_test_is_literal(struct kunit *test) -{ - KUNIT_EXPECT_TRUE(test, is_literal("5", 5)); - KUNIT_EXPECT_TRUE(test, is_literal("0", 0)); - KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890)); - KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890)); - KUNIT_EXPECT_FALSE(test, is_literal("05", 5)); - KUNIT_EXPECT_FALSE(test, is_literal("", 0)); - KUNIT_EXPECT_FALSE(test, is_literal("-0", 0)); - KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245)); -} - -static void kunit_test_is_str_literal(struct kunit *test) -{ - KUNIT_EXPECT_TRUE(test, is_str_literal(""Hello, World!"", "Hello, World!")); - KUNIT_EXPECT_TRUE(test, is_str_literal("""", "")); - KUNIT_EXPECT_TRUE(test, is_str_literal(""""", """)); - KUNIT_EXPECT_FALSE(test, is_str_literal("", "")); - KUNIT_EXPECT_FALSE(test, is_str_literal(""", """)); - KUNIT_EXPECT_FALSE(test, is_str_literal(""Abacaba", "Abacaba")); - KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba"", "Abacaba")); - KUNIT_EXPECT_FALSE(test, is_str_literal(""Abacaba"", ""Abacaba"")); -} - -KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *); - -/* this function is used to get a "char *" string from the string stream and defer its cleanup */ -static char *get_str_from_stream(struct kunit *test, struct string_stream *stream) -{ - char *str = string_stream_get_string(stream); - - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str); - kunit_add_action(test, kfree_wrapper, (void *)str); - - return str; -} - -static void kunit_test_assert_prologue(struct kunit *test) -{ - struct string_stream *stream; - char *str; - const struct kunit_loc location = { - .file = "testfile.c", - .line = 1337, - }; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - /* Test an expectation fail prologue */ - kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream); - str = get_str_from_stream(test, stream); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION"); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c"); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337"); - - /* Test an assertion fail prologue */ - string_stream_clear(stream); - kunit_assert_prologue(&location, KUNIT_ASSERTION, stream); - str = get_str_from_stream(test, stream); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION"); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c"); - ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337"); -} - -/* - * This function accepts an arbitrary count of parameters and generates a va_format struct, - * which can be used to validate kunit_assert_print_msg function - */ -static void verify_assert_print_msg(struct kunit *test, - struct string_stream *stream, - char *expected, const char *format, ...) -{ - va_list list; - const struct va_format vformat = { - .fmt = format, - .va = &list, - }; - - va_start(list, format); - string_stream_clear(stream); - kunit_assert_print_msg(&vformat, stream); - KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected); -} - -static void kunit_test_assert_print_msg(struct kunit *test) -{ - struct string_stream *stream; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - verify_assert_print_msg(test, stream, "\nTest", "Test"); - verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u", - "Abacaba", -123, 234U); - verify_assert_print_msg(test, stream, "", NULL); -} - -/* - * Further code contains the tests for different assert format functions. - * This helper function accepts the assert format function, executes it and - * validates the result string from the stream by checking that all of the - * substrings exist in the output. - */ -static void validate_assert(assert_format_t format_func, struct kunit *test, - const struct kunit_assert *assert, - struct string_stream *stream, int num_checks, ...) -{ - size_t i; - va_list checks; - char *cur_substr_exp; - struct va_format message = { NULL, NULL }; - - va_start(checks, num_checks); - string_stream_clear(stream); - format_func(assert, &message, stream); - - for (i = 0; i < num_checks; i++) { - cur_substr_exp = va_arg(checks, char *); - ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp); - } -} - -static void kunit_test_unary_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct kunit_assert assert = {}; - struct kunit_unary_assert un_assert = { - .assert = assert, - .condition = "expr", - .expected_true = true, - }; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - validate_assert(kunit_unary_assert_format, test, &un_assert.assert, - stream, 2, "true", "is false"); - - un_assert.expected_true = false; - validate_assert(kunit_unary_assert_format, test, &un_assert.assert, - stream, 2, "false", "is true"); -} - -static void kunit_test_ptr_not_err_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct kunit_assert assert = {}; - struct kunit_ptr_not_err_assert not_err_assert = { - .assert = assert, - .text = "expr", - .value = NULL, - }; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - /* Value is NULL. The corresponding message should be printed out */ - validate_assert(kunit_ptr_not_err_assert_format, test, - ¬_err_assert.assert, - stream, 1, "null"); - - /* Value is not NULL, but looks like an error pointer. Error should be printed out */ - not_err_assert.value = (void *)-12; - validate_assert(kunit_ptr_not_err_assert_format, test, - ¬_err_assert.assert, stream, 2, - "error", "-12"); -} - -static void kunit_test_binary_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct kunit_assert assert = {}; - struct kunit_binary_assert_text text = { - .left_text = "1 + 2", - .operation = "==", - .right_text = "2", - }; - const struct kunit_binary_assert binary_assert = { - .assert = assert, - .text = &text, - .left_value = 3, - .right_value = 2, - }; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - /* - * Printed values should depend on the input we provide: the left text, right text, left - * value and the right value. - */ - validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, - stream, 4, "1 + 2", "2", "3", "=="); - - text.right_text = "4 - 2"; - validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, - stream, 3, "==", "1 + 2", "4 - 2"); - - text.left_text = "3"; - validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, - stream, 4, "3", "4 - 2", "2", "=="); - - text.right_text = "2"; - validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, - stream, 3, "3", "2", "=="); -} - -static void kunit_test_binary_ptr_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct kunit_assert assert = {}; - char *addr_var_a, *addr_var_b; - static const void *var_a = (void *)0xDEADBEEF; - static const void *var_b = (void *)0xBADDCAFE; - struct kunit_binary_assert_text text = { - .left_text = "var_a", - .operation = "==", - .right_text = "var_b", - }; - struct kunit_binary_ptr_assert binary_ptr_assert = { - .assert = assert, - .text = &text, - .left_value = var_a, - .right_value = var_b, - }; - - addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a); - addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b); - /* - * Print the addresses to the buffers first. - * This is necessary as we may have different count of leading zeros in the pointer - * on different architectures. - */ - snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a); - snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b); - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert, - stream, 3, addr_var_a, addr_var_b, "=="); -} - -static void kunit_test_binary_str_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct kunit_assert assert = {}; - static const char *var_a = "abacaba"; - static const char *var_b = "kernel"; - struct kunit_binary_assert_text text = { - .left_text = "var_a", - .operation = "==", - .right_text = "var_b", - }; - struct kunit_binary_str_assert binary_str_assert = { - .assert = assert, - .text = &text, - .left_value = var_a, - .right_value = var_b, - }; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - validate_assert(kunit_binary_str_assert_format, test, - &binary_str_assert.assert, - stream, 5, "var_a", "var_b", ""abacaba"", - ""kernel"", "=="); - - text.left_text = ""abacaba""; - validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert, - stream, 4, ""abacaba"", "var_b", ""kernel"", "=="); - - text.right_text = ""kernel""; - validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert, - stream, 3, ""abacaba"", ""kernel"", "=="); -} - -static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55, - 0x45, 0x9d, 0x47, 0xd6, 0x47, - 0x2, 0x89, 0x8c, 0x81, 0x94, - 0x12, 0xfe, 0x01 }; -static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55, - 0x45, 0x9d, 0x47, 0x21, 0x47, - 0xcd, 0x89, 0x24, 0x50, 0x94, - 0x12, 0xba, 0x01 }; -static void kunit_test_assert_hexdump(struct kunit *test) -{ - struct string_stream *stream; - char *str; - size_t i; - char buf[HEXDUMP_TEST_BUF_LEN]; - - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - /* Check that we are getting output like <xx> for non-matching numbers. */ - kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1)); - str = get_str_from_stream(test, stream); - for (i = 0; i < sizeof(hex_testbuf1); i++) { - snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]); - if (hex_testbuf1[i] != hex_testbuf2[i]) - ASSERT_TEST_EXPECT_CONTAIN(test, str, buf); - } - /* We shouldn't get any <xx> numbers when comparing the buffer with itself. */ - string_stream_clear(stream); - kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1)); - str = get_str_from_stream(test, stream); - ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<"); - ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">"); -} - -static void kunit_test_mem_assert_format(struct kunit *test) -{ - struct string_stream *stream; - struct string_stream *expected_stream; - struct kunit_assert assert = {}; - static const struct kunit_binary_assert_text text = { - .left_text = "hex_testbuf1", - .operation = "==", - .right_text = "hex_testbuf2", - }; - struct kunit_mem_assert mem_assert = { - .assert = assert, - .text = &text, - .left_value = NULL, - .right_value = hex_testbuf2, - .size = sizeof(hex_testbuf1), - }; - - expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream); - stream = kunit_alloc_string_stream(test, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); - - /* The left value is NULL */ - validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, - stream, 2, "hex_testbuf1", "is not null"); - - /* The right value is NULL, the left value is not NULL */ - mem_assert.left_value = hex_testbuf1; - mem_assert.right_value = NULL; - validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, - stream, 2, "hex_testbuf2", "is not null"); - - /* Both arguments are not null */ - mem_assert.left_value = hex_testbuf1; - mem_assert.right_value = hex_testbuf2; - - validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, - stream, 3, "hex_testbuf1", "hex_testbuf2", "=="); -} - -static struct kunit_case assert_test_cases[] = { - KUNIT_CASE(kunit_test_is_literal), - KUNIT_CASE(kunit_test_is_str_literal), - KUNIT_CASE(kunit_test_assert_prologue), - KUNIT_CASE(kunit_test_assert_print_msg), - KUNIT_CASE(kunit_test_unary_assert_format), - KUNIT_CASE(kunit_test_ptr_not_err_assert_format), - KUNIT_CASE(kunit_test_binary_assert_format), - KUNIT_CASE(kunit_test_binary_ptr_assert_format), - KUNIT_CASE(kunit_test_binary_str_assert_format), - KUNIT_CASE(kunit_test_assert_hexdump), - KUNIT_CASE(kunit_test_mem_assert_format), - {} -}; - -static struct kunit_suite assert_test_suite = { - .name = "kunit-assert", - .test_cases = assert_test_cases, -}; - -kunit_test_suites(&assert_test_suite); diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index 42178d5a97d1..efba189442c2 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -849,10 +849,387 @@ static struct kunit_suite kunit_current_test_suite = { .test_cases = kunit_current_test_cases, };
+#define TEST_PTR_EXPECTED_BUF_SIZE 32 +#define HEXDUMP_TEST_BUF_LEN 5 +#define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr)) +#define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr)) + +static void kunit_test_is_literal(struct kunit *test) +{ + KUNIT_EXPECT_TRUE(test, is_literal("5", 5)); + KUNIT_EXPECT_TRUE(test, is_literal("0", 0)); + KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890)); + KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890)); + KUNIT_EXPECT_FALSE(test, is_literal("05", 5)); + KUNIT_EXPECT_FALSE(test, is_literal("", 0)); + KUNIT_EXPECT_FALSE(test, is_literal("-0", 0)); + KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245)); +} + +static void kunit_test_is_str_literal(struct kunit *test) +{ + KUNIT_EXPECT_TRUE(test, is_str_literal(""Hello, World!"", "Hello, World!")); + KUNIT_EXPECT_TRUE(test, is_str_literal("""", "")); + KUNIT_EXPECT_TRUE(test, is_str_literal(""""", """)); + KUNIT_EXPECT_FALSE(test, is_str_literal("", "")); + KUNIT_EXPECT_FALSE(test, is_str_literal(""", """)); + KUNIT_EXPECT_FALSE(test, is_str_literal(""Abacaba", "Abacaba")); + KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba"", "Abacaba")); + KUNIT_EXPECT_FALSE(test, is_str_literal(""Abacaba"", ""Abacaba"")); +} + +/* this function is used to get a "char *" string from the string stream and defer its cleanup */ +static char *get_str_from_stream(struct kunit *test, struct string_stream *stream) +{ + char *str = string_stream_get_string(stream); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str); + kunit_add_action(test, kfree_wrapper, (void *)str); + + return str; +} + +static void kunit_test_assert_prologue(struct kunit *test) +{ + struct string_stream *stream; + char *str; + const struct kunit_loc location = { + .file = "testfile.c", + .line = 1337, + }; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + /* Test an expectation fail prologue */ + kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream); + str = get_str_from_stream(test, stream); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION"); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c"); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337"); + + /* Test an assertion fail prologue */ + string_stream_clear(stream); + kunit_assert_prologue(&location, KUNIT_ASSERTION, stream); + str = get_str_from_stream(test, stream); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION"); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c"); + ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337"); +} + +/* + * This function accepts an arbitrary count of parameters and generates a va_format struct, + * which can be used to validate kunit_assert_print_msg function + */ +static void verify_assert_print_msg(struct kunit *test, + struct string_stream *stream, + char *expected, const char *format, ...) +{ + va_list list; + const struct va_format vformat = { + .fmt = format, + .va = &list, + }; + + va_start(list, format); + string_stream_clear(stream); + kunit_assert_print_msg(&vformat, stream); + KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected); +} + +static void kunit_test_assert_print_msg(struct kunit *test) +{ + struct string_stream *stream; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + verify_assert_print_msg(test, stream, "\nTest", "Test"); + verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u", + "Abacaba", -123, 234U); + verify_assert_print_msg(test, stream, "", NULL); +} + +/* + * Further code contains the tests for different assert format functions. + * This helper function accepts the assert format function, executes it and + * validates the result string from the stream by checking that all of the + * substrings exist in the output. + */ +static void validate_assert(assert_format_t format_func, struct kunit *test, + const struct kunit_assert *assert, + struct string_stream *stream, int num_checks, ...) +{ + size_t i; + va_list checks; + char *cur_substr_exp; + struct va_format message = { NULL, NULL }; + + va_start(checks, num_checks); + string_stream_clear(stream); + format_func(assert, &message, stream); + + for (i = 0; i < num_checks; i++) { + cur_substr_exp = va_arg(checks, char *); + ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp); + } +} + +static void kunit_test_unary_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct kunit_assert assert = {}; + struct kunit_unary_assert un_assert = { + .assert = assert, + .condition = "expr", + .expected_true = true, + }; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + validate_assert(kunit_unary_assert_format, test, &un_assert.assert, + stream, 2, "true", "is false"); + + un_assert.expected_true = false; + validate_assert(kunit_unary_assert_format, test, &un_assert.assert, + stream, 2, "false", "is true"); +} + +static void kunit_test_ptr_not_err_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct kunit_assert assert = {}; + struct kunit_ptr_not_err_assert not_err_assert = { + .assert = assert, + .text = "expr", + .value = NULL, + }; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + /* Value is NULL. The corresponding message should be printed out */ + validate_assert(kunit_ptr_not_err_assert_format, test, + ¬_err_assert.assert, + stream, 1, "null"); + + /* Value is not NULL, but looks like an error pointer. Error should be printed out */ + not_err_assert.value = (void *)-12; + validate_assert(kunit_ptr_not_err_assert_format, test, + ¬_err_assert.assert, stream, 2, + "error", "-12"); +} + +static void kunit_test_binary_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct kunit_assert assert = {}; + struct kunit_binary_assert_text text = { + .left_text = "1 + 2", + .operation = "==", + .right_text = "2", + }; + const struct kunit_binary_assert binary_assert = { + .assert = assert, + .text = &text, + .left_value = 3, + .right_value = 2, + }; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + /* + * Printed values should depend on the input we provide: the left text, right text, left + * value and the right value. + */ + validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, + stream, 4, "1 + 2", "2", "3", "=="); + + text.right_text = "4 - 2"; + validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, + stream, 3, "==", "1 + 2", "4 - 2"); + + text.left_text = "3"; + validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, + stream, 4, "3", "4 - 2", "2", "=="); + + text.right_text = "2"; + validate_assert(kunit_binary_assert_format, test, &binary_assert.assert, + stream, 3, "3", "2", "=="); +} + +static void kunit_test_binary_ptr_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct kunit_assert assert = {}; + char *addr_var_a, *addr_var_b; + static const void *var_a = (void *)0xDEADBEEF; + static const void *var_b = (void *)0xBADDCAFE; + struct kunit_binary_assert_text text = { + .left_text = "var_a", + .operation = "==", + .right_text = "var_b", + }; + struct kunit_binary_ptr_assert binary_ptr_assert = { + .assert = assert, + .text = &text, + .left_value = var_a, + .right_value = var_b, + }; + + addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a); + addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b); + /* + * Print the addresses to the buffers first. + * This is necessary as we may have different count of leading zeros in the pointer + * on different architectures. + */ + snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a); + snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b); + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert, + stream, 3, addr_var_a, addr_var_b, "=="); +} + +static void kunit_test_binary_str_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct kunit_assert assert = {}; + static const char *var_a = "abacaba"; + static const char *var_b = "kernel"; + struct kunit_binary_assert_text text = { + .left_text = "var_a", + .operation = "==", + .right_text = "var_b", + }; + struct kunit_binary_str_assert binary_str_assert = { + .assert = assert, + .text = &text, + .left_value = var_a, + .right_value = var_b, + }; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + validate_assert(kunit_binary_str_assert_format, test, + &binary_str_assert.assert, + stream, 5, "var_a", "var_b", ""abacaba"", + ""kernel"", "=="); + + text.left_text = ""abacaba""; + validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert, + stream, 4, ""abacaba"", "var_b", ""kernel"", "=="); + + text.right_text = ""kernel""; + validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert, + stream, 3, ""abacaba"", ""kernel"", "=="); +} + +static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55, + 0x45, 0x9d, 0x47, 0xd6, 0x47, + 0x2, 0x89, 0x8c, 0x81, 0x94, + 0x12, 0xfe, 0x01 }; +static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55, + 0x45, 0x9d, 0x47, 0x21, 0x47, + 0xcd, 0x89, 0x24, 0x50, 0x94, + 0x12, 0xba, 0x01 }; +static void kunit_test_assert_hexdump(struct kunit *test) +{ + struct string_stream *stream; + char *str; + size_t i; + char buf[HEXDUMP_TEST_BUF_LEN]; + + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + /* Check that we are getting output like <xx> for non-matching numbers. */ + kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1)); + str = get_str_from_stream(test, stream); + for (i = 0; i < sizeof(hex_testbuf1); i++) { + snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]); + if (hex_testbuf1[i] != hex_testbuf2[i]) + ASSERT_TEST_EXPECT_CONTAIN(test, str, buf); + } + /* We shouldn't get any <xx> numbers when comparing the buffer with itself. */ + string_stream_clear(stream); + kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1)); + str = get_str_from_stream(test, stream); + ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<"); + ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">"); +} + +static void kunit_test_mem_assert_format(struct kunit *test) +{ + struct string_stream *stream; + struct string_stream *expected_stream; + struct kunit_assert assert = {}; + static const struct kunit_binary_assert_text text = { + .left_text = "hex_testbuf1", + .operation = "==", + .right_text = "hex_testbuf2", + }; + struct kunit_mem_assert mem_assert = { + .assert = assert, + .text = &text, + .left_value = NULL, + .right_value = hex_testbuf2, + .size = sizeof(hex_testbuf1), + }; + + expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream); + stream = kunit_alloc_string_stream(test, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); + + /* The left value is NULL */ + validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, + stream, 2, "hex_testbuf1", "is not null"); + + /* The right value is NULL, the left value is not NULL */ + mem_assert.left_value = hex_testbuf1; + mem_assert.right_value = NULL; + validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, + stream, 2, "hex_testbuf2", "is not null"); + + /* Both arguments are not null */ + mem_assert.left_value = hex_testbuf1; + mem_assert.right_value = hex_testbuf2; + + validate_assert(kunit_mem_assert_format, test, &mem_assert.assert, + stream, 3, "hex_testbuf1", "hex_testbuf2", "=="); +} + +static struct kunit_case kunit_assert_test_cases[] = { + KUNIT_CASE(kunit_test_is_literal), + KUNIT_CASE(kunit_test_is_str_literal), + KUNIT_CASE(kunit_test_assert_prologue), + KUNIT_CASE(kunit_test_assert_print_msg), + KUNIT_CASE(kunit_test_unary_assert_format), + KUNIT_CASE(kunit_test_ptr_not_err_assert_format), + KUNIT_CASE(kunit_test_binary_assert_format), + KUNIT_CASE(kunit_test_binary_ptr_assert_format), + KUNIT_CASE(kunit_test_binary_str_assert_format), + KUNIT_CASE(kunit_test_assert_hexdump), + KUNIT_CASE(kunit_test_mem_assert_format), + {} +}; + +static struct kunit_suite kunit_assert_test_suite = { + .name = "kunit-assert", + .test_cases = kunit_assert_test_cases, +}; + kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, &kunit_log_test_suite, &kunit_status_test_suite, &kunit_current_test_suite, &kunit_device_test_suite, - &kunit_fault_test_suite); + &kunit_fault_test_suite, &kunit_assert_test_suite);
MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); MODULE_LICENSE("GPL v2");
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Since assert_test covers the part of the KUnit core (the assertion formatting functions), I believe it would be better to have it merged into kunit-test (as it is done for other tests for the KUnit core).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Personally, I don't mind if the assert tests are in a separate file, but do think it's worth having them in the same module.
Do you think it'd be better to keep them as separate source files (but put them in the same module via the Makefile), or is having a single source file cleaner?
Either way, I think this should be merged with the previous patch (see my comments there.)
Cheers, -- David
lib/kunit/Makefile | 5 - lib/kunit/assert_test.c | 388 ---------------------------------------- lib/kunit/kunit-test.c | 379 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 378 insertions(+), 394 deletions(-) delete mode 100644 lib/kunit/assert_test.c
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile index 4793a3960f07..f41d2eab1f8d 100644 --- a/lib/kunit/Makefile +++ b/lib/kunit/Makefile @@ -20,9 +20,4 @@ obj-y += hooks.o obj-$(CONFIG_KUNIT_TEST) += kunit-test.o obj-$(CONFIG_KUNIT_STRING_STREAM_TEST) += string-stream-test.o
-# string-stream-test compiles built-in only. -ifeq ($(CONFIG_KUNIT_TEST),y) -obj-$(CONFIG_KUNIT_TEST) += assert_test.o -endif
obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test.o diff --git a/lib/kunit/assert_test.c b/lib/kunit/assert_test.c deleted file mode 100644 index 4a5967712186..000000000000 --- a/lib/kunit/assert_test.c +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/*
- KUnit test for the assertion formatting functions.
- Author: Ivan Orlov ivan.orlov0322@gmail.com
- */
-#include <kunit/test.h> -#include "string-stream.h"
-#define TEST_PTR_EXPECTED_BUF_SIZE 32 -#define HEXDUMP_TEST_BUF_LEN 5 -#define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr)) -#define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr))
-static void kunit_test_is_literal(struct kunit *test) -{
KUNIT_EXPECT_TRUE(test, is_literal("5", 5));
KUNIT_EXPECT_TRUE(test, is_literal("0", 0));
KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890));
KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890));
KUNIT_EXPECT_FALSE(test, is_literal("05", 5));
KUNIT_EXPECT_FALSE(test, is_literal("", 0));
KUNIT_EXPECT_FALSE(test, is_literal("-0", 0));
KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245));
-}
-static void kunit_test_is_str_literal(struct kunit *test) -{
KUNIT_EXPECT_TRUE(test, is_str_literal("\"Hello, World!\"", "Hello, World!"));
KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"", ""));
KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"\"", "\""));
KUNIT_EXPECT_FALSE(test, is_str_literal("", ""));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"", "\""));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba", "Abacaba"));
KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba\"", "Abacaba"));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba\"", "\"Abacaba\""));
-}
-KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
-/* this function is used to get a "char *" string from the string stream and defer its cleanup */ -static char *get_str_from_stream(struct kunit *test, struct string_stream *stream) -{
char *str = string_stream_get_string(stream);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
kunit_add_action(test, kfree_wrapper, (void *)str);
return str;
-}
-static void kunit_test_assert_prologue(struct kunit *test) -{
struct string_stream *stream;
char *str;
const struct kunit_loc location = {
.file = "testfile.c",
.line = 1337,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Test an expectation fail prologue */
kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream);
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
/* Test an assertion fail prologue */
string_stream_clear(stream);
kunit_assert_prologue(&location, KUNIT_ASSERTION, stream);
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
-}
-/*
- This function accepts an arbitrary count of parameters and generates a va_format struct,
- which can be used to validate kunit_assert_print_msg function
- */
-static void verify_assert_print_msg(struct kunit *test,
struct string_stream *stream,
char *expected, const char *format, ...)
-{
va_list list;
const struct va_format vformat = {
.fmt = format,
.va = &list,
};
va_start(list, format);
string_stream_clear(stream);
kunit_assert_print_msg(&vformat, stream);
KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
-}
-static void kunit_test_assert_print_msg(struct kunit *test) -{
struct string_stream *stream;
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
verify_assert_print_msg(test, stream, "\nTest", "Test");
verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u",
"Abacaba", -123, 234U);
verify_assert_print_msg(test, stream, "", NULL);
-}
-/*
- Further code contains the tests for different assert format functions.
- This helper function accepts the assert format function, executes it and
- validates the result string from the stream by checking that all of the
- substrings exist in the output.
- */
-static void validate_assert(assert_format_t format_func, struct kunit *test,
const struct kunit_assert *assert,
struct string_stream *stream, int num_checks, ...)
-{
size_t i;
va_list checks;
char *cur_substr_exp;
struct va_format message = { NULL, NULL };
va_start(checks, num_checks);
string_stream_clear(stream);
format_func(assert, &message, stream);
for (i = 0; i < num_checks; i++) {
cur_substr_exp = va_arg(checks, char *);
ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp);
}
-}
-static void kunit_test_unary_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_unary_assert un_assert = {
.assert = assert,
.condition = "expr",
.expected_true = true,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
stream, 2, "true", "is false");
un_assert.expected_true = false;
validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
stream, 2, "false", "is true");
-}
-static void kunit_test_ptr_not_err_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_ptr_not_err_assert not_err_assert = {
.assert = assert,
.text = "expr",
.value = NULL,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Value is NULL. The corresponding message should be printed out */
validate_assert(kunit_ptr_not_err_assert_format, test,
¬_err_assert.assert,
stream, 1, "null");
/* Value is not NULL, but looks like an error pointer. Error should be printed out */
not_err_assert.value = (void *)-12;
validate_assert(kunit_ptr_not_err_assert_format, test,
¬_err_assert.assert, stream, 2,
"error", "-12");
-}
-static void kunit_test_binary_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_binary_assert_text text = {
.left_text = "1 + 2",
.operation = "==",
.right_text = "2",
};
const struct kunit_binary_assert binary_assert = {
.assert = assert,
.text = &text,
.left_value = 3,
.right_value = 2,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/*
* Printed values should depend on the input we provide: the left text, right text, left
* value and the right value.
*/
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 4, "1 + 2", "2", "3", "==");
text.right_text = "4 - 2";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 3, "==", "1 + 2", "4 - 2");
text.left_text = "3";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 4, "3", "4 - 2", "2", "==");
text.right_text = "2";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 3, "3", "2", "==");
-}
-static void kunit_test_binary_ptr_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct kunit_assert assert = {};
char *addr_var_a, *addr_var_b;
static const void *var_a = (void *)0xDEADBEEF;
static const void *var_b = (void *)0xBADDCAFE;
struct kunit_binary_assert_text text = {
.left_text = "var_a",
.operation = "==",
.right_text = "var_b",
};
struct kunit_binary_ptr_assert binary_ptr_assert = {
.assert = assert,
.text = &text,
.left_value = var_a,
.right_value = var_b,
};
addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a);
addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b);
/*
* Print the addresses to the buffers first.
* This is necessary as we may have different count of leading zeros in the pointer
* on different architectures.
*/
snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a);
snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b);
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert,
stream, 3, addr_var_a, addr_var_b, "==");
-}
-static void kunit_test_binary_str_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct kunit_assert assert = {};
static const char *var_a = "abacaba";
static const char *var_b = "kernel";
struct kunit_binary_assert_text text = {
.left_text = "var_a",
.operation = "==",
.right_text = "var_b",
};
struct kunit_binary_str_assert binary_str_assert = {
.assert = assert,
.text = &text,
.left_value = var_a,
.right_value = var_b,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_binary_str_assert_format, test,
&binary_str_assert.assert,
stream, 5, "var_a", "var_b", "\"abacaba\"",
"\"kernel\"", "==");
text.left_text = "\"abacaba\"";
validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
stream, 4, "\"abacaba\"", "var_b", "\"kernel\"", "==");
text.right_text = "\"kernel\"";
validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
stream, 3, "\"abacaba\"", "\"kernel\"", "==");
-}
-static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
0x45, 0x9d, 0x47, 0xd6, 0x47,
0x2, 0x89, 0x8c, 0x81, 0x94,
0x12, 0xfe, 0x01 };
-static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
0x45, 0x9d, 0x47, 0x21, 0x47,
0xcd, 0x89, 0x24, 0x50, 0x94,
0x12, 0xba, 0x01 };
-static void kunit_test_assert_hexdump(struct kunit *test) -{
struct string_stream *stream;
char *str;
size_t i;
char buf[HEXDUMP_TEST_BUF_LEN];
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Check that we are getting output like <xx> for non-matching numbers. */
kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1));
str = get_str_from_stream(test, stream);
for (i = 0; i < sizeof(hex_testbuf1); i++) {
snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]);
if (hex_testbuf1[i] != hex_testbuf2[i])
ASSERT_TEST_EXPECT_CONTAIN(test, str, buf);
}
/* We shouldn't get any <xx> numbers when comparing the buffer with itself. */
string_stream_clear(stream);
kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1));
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<");
ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">");
-}
-static void kunit_test_mem_assert_format(struct kunit *test) -{
struct string_stream *stream;
struct string_stream *expected_stream;
struct kunit_assert assert = {};
static const struct kunit_binary_assert_text text = {
.left_text = "hex_testbuf1",
.operation = "==",
.right_text = "hex_testbuf2",
};
struct kunit_mem_assert mem_assert = {
.assert = assert,
.text = &text,
.left_value = NULL,
.right_value = hex_testbuf2,
.size = sizeof(hex_testbuf1),
};
expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream);
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* The left value is NULL */
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 2, "hex_testbuf1", "is not null");
/* The right value is NULL, the left value is not NULL */
mem_assert.left_value = hex_testbuf1;
mem_assert.right_value = NULL;
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 2, "hex_testbuf2", "is not null");
/* Both arguments are not null */
mem_assert.left_value = hex_testbuf1;
mem_assert.right_value = hex_testbuf2;
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 3, "hex_testbuf1", "hex_testbuf2", "==");
-}
-static struct kunit_case assert_test_cases[] = {
KUNIT_CASE(kunit_test_is_literal),
KUNIT_CASE(kunit_test_is_str_literal),
KUNIT_CASE(kunit_test_assert_prologue),
KUNIT_CASE(kunit_test_assert_print_msg),
KUNIT_CASE(kunit_test_unary_assert_format),
KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
KUNIT_CASE(kunit_test_binary_assert_format),
KUNIT_CASE(kunit_test_binary_ptr_assert_format),
KUNIT_CASE(kunit_test_binary_str_assert_format),
KUNIT_CASE(kunit_test_assert_hexdump),
KUNIT_CASE(kunit_test_mem_assert_format),
{}
-};
-static struct kunit_suite assert_test_suite = {
.name = "kunit-assert",
.test_cases = assert_test_cases,
-};
-kunit_test_suites(&assert_test_suite); diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index 42178d5a97d1..efba189442c2 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -849,10 +849,387 @@ static struct kunit_suite kunit_current_test_suite = { .test_cases = kunit_current_test_cases, };
+#define TEST_PTR_EXPECTED_BUF_SIZE 32 +#define HEXDUMP_TEST_BUF_LEN 5 +#define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr)) +#define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr))
+static void kunit_test_is_literal(struct kunit *test) +{
KUNIT_EXPECT_TRUE(test, is_literal("5", 5));
KUNIT_EXPECT_TRUE(test, is_literal("0", 0));
KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890));
KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890));
KUNIT_EXPECT_FALSE(test, is_literal("05", 5));
KUNIT_EXPECT_FALSE(test, is_literal("", 0));
KUNIT_EXPECT_FALSE(test, is_literal("-0", 0));
KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245));
+}
+static void kunit_test_is_str_literal(struct kunit *test) +{
KUNIT_EXPECT_TRUE(test, is_str_literal("\"Hello, World!\"", "Hello, World!"));
KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"", ""));
KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"\"", "\""));
KUNIT_EXPECT_FALSE(test, is_str_literal("", ""));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"", "\""));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba", "Abacaba"));
KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba\"", "Abacaba"));
KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba\"", "\"Abacaba\""));
+}
+/* this function is used to get a "char *" string from the string stream and defer its cleanup */ +static char *get_str_from_stream(struct kunit *test, struct string_stream *stream) +{
char *str = string_stream_get_string(stream);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
kunit_add_action(test, kfree_wrapper, (void *)str);
return str;
+}
+static void kunit_test_assert_prologue(struct kunit *test) +{
struct string_stream *stream;
char *str;
const struct kunit_loc location = {
.file = "testfile.c",
.line = 1337,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Test an expectation fail prologue */
kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream);
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
/* Test an assertion fail prologue */
string_stream_clear(stream);
kunit_assert_prologue(&location, KUNIT_ASSERTION, stream);
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
+}
+/*
- This function accepts an arbitrary count of parameters and generates a va_format struct,
- which can be used to validate kunit_assert_print_msg function
- */
+static void verify_assert_print_msg(struct kunit *test,
struct string_stream *stream,
char *expected, const char *format, ...)
+{
va_list list;
const struct va_format vformat = {
.fmt = format,
.va = &list,
};
va_start(list, format);
string_stream_clear(stream);
kunit_assert_print_msg(&vformat, stream);
KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
+}
+static void kunit_test_assert_print_msg(struct kunit *test) +{
struct string_stream *stream;
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
verify_assert_print_msg(test, stream, "\nTest", "Test");
verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u",
"Abacaba", -123, 234U);
verify_assert_print_msg(test, stream, "", NULL);
+}
+/*
- Further code contains the tests for different assert format functions.
- This helper function accepts the assert format function, executes it and
- validates the result string from the stream by checking that all of the
- substrings exist in the output.
- */
+static void validate_assert(assert_format_t format_func, struct kunit *test,
const struct kunit_assert *assert,
struct string_stream *stream, int num_checks, ...)
+{
size_t i;
va_list checks;
char *cur_substr_exp;
struct va_format message = { NULL, NULL };
va_start(checks, num_checks);
string_stream_clear(stream);
format_func(assert, &message, stream);
for (i = 0; i < num_checks; i++) {
cur_substr_exp = va_arg(checks, char *);
ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp);
}
+}
+static void kunit_test_unary_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_unary_assert un_assert = {
.assert = assert,
.condition = "expr",
.expected_true = true,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
stream, 2, "true", "is false");
un_assert.expected_true = false;
validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
stream, 2, "false", "is true");
+}
+static void kunit_test_ptr_not_err_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_ptr_not_err_assert not_err_assert = {
.assert = assert,
.text = "expr",
.value = NULL,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Value is NULL. The corresponding message should be printed out */
validate_assert(kunit_ptr_not_err_assert_format, test,
¬_err_assert.assert,
stream, 1, "null");
/* Value is not NULL, but looks like an error pointer. Error should be printed out */
not_err_assert.value = (void *)-12;
validate_assert(kunit_ptr_not_err_assert_format, test,
¬_err_assert.assert, stream, 2,
"error", "-12");
+}
+static void kunit_test_binary_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct kunit_assert assert = {};
struct kunit_binary_assert_text text = {
.left_text = "1 + 2",
.operation = "==",
.right_text = "2",
};
const struct kunit_binary_assert binary_assert = {
.assert = assert,
.text = &text,
.left_value = 3,
.right_value = 2,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/*
* Printed values should depend on the input we provide: the left text, right text, left
* value and the right value.
*/
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 4, "1 + 2", "2", "3", "==");
text.right_text = "4 - 2";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 3, "==", "1 + 2", "4 - 2");
text.left_text = "3";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 4, "3", "4 - 2", "2", "==");
text.right_text = "2";
validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
stream, 3, "3", "2", "==");
+}
+static void kunit_test_binary_ptr_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct kunit_assert assert = {};
char *addr_var_a, *addr_var_b;
static const void *var_a = (void *)0xDEADBEEF;
static const void *var_b = (void *)0xBADDCAFE;
struct kunit_binary_assert_text text = {
.left_text = "var_a",
.operation = "==",
.right_text = "var_b",
};
struct kunit_binary_ptr_assert binary_ptr_assert = {
.assert = assert,
.text = &text,
.left_value = var_a,
.right_value = var_b,
};
addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a);
addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b);
/*
* Print the addresses to the buffers first.
* This is necessary as we may have different count of leading zeros in the pointer
* on different architectures.
*/
snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a);
snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b);
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert,
stream, 3, addr_var_a, addr_var_b, "==");
+}
+static void kunit_test_binary_str_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct kunit_assert assert = {};
static const char *var_a = "abacaba";
static const char *var_b = "kernel";
struct kunit_binary_assert_text text = {
.left_text = "var_a",
.operation = "==",
.right_text = "var_b",
};
struct kunit_binary_str_assert binary_str_assert = {
.assert = assert,
.text = &text,
.left_value = var_a,
.right_value = var_b,
};
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
validate_assert(kunit_binary_str_assert_format, test,
&binary_str_assert.assert,
stream, 5, "var_a", "var_b", "\"abacaba\"",
"\"kernel\"", "==");
text.left_text = "\"abacaba\"";
validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
stream, 4, "\"abacaba\"", "var_b", "\"kernel\"", "==");
text.right_text = "\"kernel\"";
validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
stream, 3, "\"abacaba\"", "\"kernel\"", "==");
+}
+static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
0x45, 0x9d, 0x47, 0xd6, 0x47,
0x2, 0x89, 0x8c, 0x81, 0x94,
0x12, 0xfe, 0x01 };
+static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
0x45, 0x9d, 0x47, 0x21, 0x47,
0xcd, 0x89, 0x24, 0x50, 0x94,
0x12, 0xba, 0x01 };
+static void kunit_test_assert_hexdump(struct kunit *test) +{
struct string_stream *stream;
char *str;
size_t i;
char buf[HEXDUMP_TEST_BUF_LEN];
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* Check that we are getting output like <xx> for non-matching numbers. */
kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1));
str = get_str_from_stream(test, stream);
for (i = 0; i < sizeof(hex_testbuf1); i++) {
snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]);
if (hex_testbuf1[i] != hex_testbuf2[i])
ASSERT_TEST_EXPECT_CONTAIN(test, str, buf);
}
/* We shouldn't get any <xx> numbers when comparing the buffer with itself. */
string_stream_clear(stream);
kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1));
str = get_str_from_stream(test, stream);
ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<");
ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">");
+}
+static void kunit_test_mem_assert_format(struct kunit *test) +{
struct string_stream *stream;
struct string_stream *expected_stream;
struct kunit_assert assert = {};
static const struct kunit_binary_assert_text text = {
.left_text = "hex_testbuf1",
.operation = "==",
.right_text = "hex_testbuf2",
};
struct kunit_mem_assert mem_assert = {
.assert = assert,
.text = &text,
.left_value = NULL,
.right_value = hex_testbuf2,
.size = sizeof(hex_testbuf1),
};
expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream);
stream = kunit_alloc_string_stream(test, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
/* The left value is NULL */
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 2, "hex_testbuf1", "is not null");
/* The right value is NULL, the left value is not NULL */
mem_assert.left_value = hex_testbuf1;
mem_assert.right_value = NULL;
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 2, "hex_testbuf2", "is not null");
/* Both arguments are not null */
mem_assert.left_value = hex_testbuf1;
mem_assert.right_value = hex_testbuf2;
validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
stream, 3, "hex_testbuf1", "hex_testbuf2", "==");
+}
+static struct kunit_case kunit_assert_test_cases[] = {
KUNIT_CASE(kunit_test_is_literal),
KUNIT_CASE(kunit_test_is_str_literal),
KUNIT_CASE(kunit_test_assert_prologue),
KUNIT_CASE(kunit_test_assert_print_msg),
KUNIT_CASE(kunit_test_unary_assert_format),
KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
KUNIT_CASE(kunit_test_binary_assert_format),
KUNIT_CASE(kunit_test_binary_ptr_assert_format),
KUNIT_CASE(kunit_test_binary_str_assert_format),
KUNIT_CASE(kunit_test_assert_hexdump),
KUNIT_CASE(kunit_test_mem_assert_format),
{}
+};
+static struct kunit_suite kunit_assert_test_suite = {
.name = "kunit-assert",
.test_cases = kunit_assert_test_cases,
+};
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, &kunit_log_test_suite, &kunit_status_test_suite, &kunit_current_test_suite, &kunit_device_test_suite,
&kunit_fault_test_suite);
&kunit_fault_test_suite, &kunit_assert_test_suite);
MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); MODULE_LICENSE("GPL v2"); -- 2.34.1
On 6/8/24 10:20, David Gow wrote:
On Tue, 4 Jun 2024 at 20:32, Ivan Orlov ivan.orlov0322@gmail.com wrote:
Since assert_test covers the part of the KUnit core (the assertion formatting functions), I believe it would be better to have it merged into kunit-test (as it is done for other tests for the KUnit core).
Signed-off-by: Ivan Orlov ivan.orlov0322@gmail.com
Personally, I don't mind if the assert tests are in a separate file, but do think it's worth having them in the same module.
Do you think it'd be better to keep them as separate source files (but put them in the same module via the Makefile), or is having a single source file cleaner?
Either way, I think this should be merged with the previous patch (see my comments there.)
Hi David,
Thank you for the review and sorry for the late reply.
I believe having the assert test in the same file as other kunit core tests would be more consistent with the existing test structure (otherwise, the tests for other parts of the kunit core should be extracted to separate files as well).
What do you think is more appropriate?
linux-kselftest-mirror@lists.linaro.org