| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * KUnit test for struct test_stream. |
| * |
| * Copyright (C) 2018, Google LLC. |
| * Author: Brendan Higgins <brendanhiggins@google.com> |
| */ |
| |
| #include <test/test.h> |
| #include <test/mock.h> |
| #include <test/test-stream.h> |
| |
| #include "test-mock.h" |
| |
| struct test_stream_test_context { |
| struct MOCK(KUNIT_T) *mock_test; |
| struct test_stream *stream; |
| }; |
| |
| static void test_stream_test_add(struct KUNIT_T *test) |
| { |
| struct test_stream_test_context *ctx = test->priv; |
| struct MOCK(KUNIT_T) *mock_test = NICE_MOCK(ctx->mock_test); |
| struct test_stream *stream = ctx->stream; |
| |
| stream->add(stream, "Foo"); |
| stream->add(stream, " %s", "bar"); |
| stream->set_level(stream, KERN_INFO); |
| |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, "Foo bar"), |
| any(test)))); |
| |
| stream->commit(stream); |
| } |
| |
| static void test_stream_test_append(struct KUNIT_T *test) |
| { |
| struct test_stream_test_context *ctx = test->priv; |
| struct MOCK(KUNIT_T) *mock_test = NICE_MOCK(ctx->mock_test); |
| struct test_stream *stream = ctx->stream; |
| struct test_stream *other_stream; |
| |
| stream->add(stream, "Foo"); |
| stream->set_level(stream, KERN_INFO); |
| other_stream = test_new_stream(mock_get_trgt(mock_test)); |
| other_stream->add(other_stream, " %s", "bar"); |
| |
| stream->append(stream, other_stream); |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, "Foo bar"), |
| any(test)))); |
| |
| stream->commit(stream); |
| } |
| |
| static void test_stream_error_message_when_no_level_set(struct KUNIT_T *test) |
| { |
| struct test_stream_test_context *ctx = test->priv; |
| struct MOCK(KUNIT_T) *mock_test = NICE_MOCK(ctx->mock_test); |
| struct test_stream *stream = ctx->stream; |
| struct test_stream *other_stream; |
| |
| stream->add(stream, "Foo bar"); |
| other_stream = test_new_stream(mock_get_trgt(mock_test)); |
| |
| stream->append(stream, other_stream); |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, |
| "Stream was committed without a specified log level."), |
| any(test)))); |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, "Foo bar"), |
| any(test)))); |
| stream->commit(stream); |
| } |
| |
| static int test_stream_test_init(struct KUNIT_T *test) |
| { |
| struct mock_struct_formatter_entry *entries; |
| struct test_stream_test_context *ctx; |
| |
| ctx = test_kzalloc(test, sizeof(*ctx), GFP_KERNEL); |
| if (!ctx) |
| return -ENOMEM; |
| test->priv = ctx; |
| |
| ctx->mock_test = CONSTRUCT_MOCK(KUNIT_T, test); |
| if (!ctx->mock_test) |
| return -EINVAL; |
| |
| ctx->stream = test_new_stream(mock_get_trgt(ctx->mock_test)); |
| if (!ctx->stream) |
| return -ENOMEM; |
| |
| entries = test_kzalloc(test, sizeof(*entries) * 3, GFP_KERNEL); |
| if (!entries) { |
| test_warn(test, |
| "Could not allocate arg formatter for struct va_format"); |
| return 0; |
| } |
| |
| INIT_MOCK_STRUCT_FORMATTER_ENTRY(&entries[0], |
| struct va_format, |
| fmt, |
| FORMATTER_FROM_TYPE(const char *)); |
| INIT_MOCK_STRUCT_FORMATTER_ENTRY(&entries[1], |
| struct va_format, |
| va, |
| unknown_formatter); |
| INIT_MOCK_STRUCT_FORMATTER_ENTRY_LAST(&entries[2]); |
| |
| mock_register_formatter(mock_struct_formatter(test, |
| "struct va_format *", |
| entries)); |
| |
| return 0; |
| } |
| |
| static void test_stream_test_commits_any_uncommitted_when_cleanup( |
| struct KUNIT_T *test) |
| { |
| struct test_stream_test_context *ctx = test->priv; |
| struct MOCK(KUNIT_T) *mock_test = NICE_MOCK(ctx->mock_test); |
| struct test_stream *stream = ctx->stream; |
| |
| stream->add(stream, "Hello World"); |
| stream->set_level(stream, KERN_WARNING); |
| |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, |
| "End of test case reached with uncommitted stream entries."), |
| any(test)))); |
| EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), |
| any(test), |
| va_format_cmp(test, |
| streq(test, "Hello World"), |
| any(test)))); |
| test_cleanup(mock_get_trgt(mock_test)); |
| } |
| |
| static void test_stream_test_exit(struct KUNIT_T *test) |
| { |
| mock_unregister_formatter(mock_find_formatter("struct va_format *")); |
| } |
| |
| static struct KUNIT_CASE_T test_stream_test_cases[] = { |
| TEST_CASE(test_stream_test_add), |
| TEST_CASE(test_stream_test_append), |
| TEST_CASE(test_stream_test_commits_any_uncommitted_when_cleanup), |
| TEST_CASE(test_stream_error_message_when_no_level_set), |
| {}, |
| }; |
| |
| static struct KUNIT_SUITE_T test_stream_test_module = { |
| .name = "test-stream-test", |
| .init = test_stream_test_init, |
| .exit = test_stream_test_exit, |
| .test_cases = test_stream_test_cases, |
| }; |
| module_test(test_stream_test_module); |