// SPDX-License-Identifier: GPL-2.0 /* * KUnit test for mock.h. * * Copyright (C) 2018, Google LLC. * Author: Brendan Higgins */ #include #include #include "test-mock.h" struct mock_test_context { struct MOCK(KUNIT_T) *mock_test; struct mock *mock; }; static void mock_test_do_expect_basic(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -4; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_param_matcher *matchers_any_two[] = {any(trgt), any(trgt)}; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers_any_two, ARRAY_SIZE(matchers_any_two)); expectation->action = int_return(trgt, 5); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, two_param_types, two_params, ARRAY_SIZE(two_params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 5, *((int *) ret)); EXPECT_EQ(test, 1, expectation->times_called); } static void mock_test_ptr_eq(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; void *param0 = ctx, *param1 = trgt; static const char * const two_param_types[] = {"void *", "void *"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_param_matcher *matchers_two_ptrs[] = { ptr_eq(trgt, param0), ptr_eq(trgt, param1) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers_two_ptrs, ARRAY_SIZE(matchers_two_ptrs)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, two_param_types, two_params, ARRAY_SIZE(two_params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 1, expectation->times_called); } static void mock_test_ptr_eq_not_equal(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; void *param0 = ctx, *param1 = trgt; static const char * const two_param_types[] = {"void *", "void *"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_param_matcher *matchers_two_ptrs[] = { ptr_eq(trgt, param0), ptr_eq(trgt, param1 - 1) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers_two_ptrs, ARRAY_SIZE(matchers_two_ptrs)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, two_param_types, two_params, ARRAY_SIZE(two_params)); EXPECT_FALSE(test, ret); EXPECT_EQ(test, 0, expectation->times_called); } /* * In order for us to be able to rely on EXPECT_CALL to validate other behavior, * we need to test that unsatisfied EXPECT_CALL causes a test failure. */ static void mock_test_failed_expect_call_fails_test(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct mock *mock = ctx->mock; /* mock is a pretend mock belonging to our mocked_test */ /* Put an expectation on mocked mock */ EXPECT_CALL(fail(mock, any(mock_get_trgt(mock_test)))); /* * Expect that mock_test will fail because the above won't be satisfied */ EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); /* * Validate expectations of mocked mock, which should fail mocked test */ mock_validate_expectations(mock); /* Validate mock_test's expectations, that is, it should have failed */ mock_validate_expectations(mock_get_ctrl(mock_test)); EXPECT_FALSE(test, mock_get_trgt(mock_test)->success); } static void mock_test_do_expect_default_return(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = NICE_MOCK(ctx->mock_test); struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -5; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_param_matcher *matchers[] = { int_eq(trgt, 5), int_eq(trgt, -4) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "test_printk", test_printk, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 5); EXPECT_EQ(test, 0, expectation->times_called); EXPECT_FALSE(test, mock_set_default_action(mock, "test_printk", test_printk, int_return(trgt, -4))); ret = mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, -4, *((int *) ret)); EXPECT_EQ(test, 0, expectation->times_called); } /** * DOC: Testing the failure condition of different mock types. * * The following tests will test the behaviour of expectations under different * conditions. For example, what happens when an expectation: * - is not satisfied at the end of the test * - is fulfilled but the expected function is called again * - a function is called without expectations set on it * * For each of these conditions, there may be variations between the different * types of mocks: nice mocks, naggy mocks (the default) and strict mocks. * * More information about these mocks can be found in the kernel documentation * under Documentation/test/api/class-and-function-mocking */ /* Method called on strict mock with no expectations will fail */ static void mock_test_strict_no_expectations_will_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -5; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_expectation *expectation; mock->type = MOCK_TYPE_STRICT; mock_set_default_action(mock, "test_printk", test_printk, int_return(trgt, -4)); expectation = EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); mock_validate_expectations(mock); } /* * Method called on naggy mock with no expectations will not fail, but will show * a warning message */ static void mock_test_naggy_no_expectations_no_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -5; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_expectation *expectation; mock->type = MOCK_TYPE_NAGGY; mock_set_default_action(mock, "test_printk", test_printk, int_return(trgt, -4)); expectation = Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), any(test), va_format_cmp(test, str_contains(test, "Method was called with no expectations declared"), any(test)))); mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); mock_validate_expectations(mock); } /* Method called on nice mock with no expectations will do nothing. */ static void mock_test_nice_no_expectations_do_nothing(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -5; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_expectation *expectation; mock->type = MOCK_TYPE_NICE; mock_set_default_action(mock, "test_printk", test_printk, int_return(trgt, -4)); expectation = Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); expectation = Never(EXPECT_CALL(mock_vprintk(mock_get_ctrl(mock_test), any(test), any(test)))); mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); mock_validate_expectations(mock); } /* Test that method called on a mock (of any type) with no matching expectations * will fail test and print all the tried expectations. */ static void run_method_called_but_no_matching_expectation_test(struct KUNIT_T *test, enum mock_type mock_type) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; int param0 = 5, param1 = -5; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_expectation *handle; struct mock_param_matcher *two_matchers[] = { int_eq(trgt, 100), int_eq(trgt, 100) }; mock_add_matcher(mock, "test_printk", test_printk, two_matchers, ARRAY_SIZE(two_matchers)); handle = EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->type = mock_type; mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); } static void mock_test_naggy_no_matching_expectations_fail(struct KUNIT_T *test) { run_method_called_but_no_matching_expectation_test(test, MOCK_TYPE_NAGGY); } static void mock_test_strict_no_matching_expectations_fail(struct KUNIT_T *test) { run_method_called_but_no_matching_expectation_test(test, MOCK_TYPE_STRICT); } static void mock_test_nice_no_matching_expectations_fail(struct KUNIT_T *test) { run_method_called_but_no_matching_expectation_test(test, MOCK_TYPE_NICE); } static void mock_test_mock_validate_expectations(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *matchers[] = { int_eq(trgt, 5), int_eq(trgt, -4) }; struct mock_expectation *expectation; EXPECT_EQ(test, mock_get_trgt(mock_test), mock->test); expectation = mock_add_matcher(mock, "test_printk", test_printk, matchers, ARRAY_SIZE(matchers)); expectation->times_called = 0; expectation->min_calls_expected = 1; expectation->max_calls_expected = 1; EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock_validate_expectations(mock); } static void mock_test_validate_clears_expectations(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *matchers[] = { int_eq(trgt, 5), int_eq(trgt, -4) }; int param0 = 5, param1 = -4; static const char * const two_param_types[] = {"int", "int"}; const void *two_params[] = {¶m0, ¶m1}; struct mock_expectation *expectation; mock->type = MOCK_TYPE_STRICT; /* If all goes well, the mock_test should not fail. */ expectation = Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); /* Add an arbitrary matcher for 0 calls */ expectation = mock_add_matcher(mock, "test_printk", test_printk, matchers, ARRAY_SIZE(matchers)); expectation->times_called = 0; expectation->min_calls_expected = 0; expectation->max_calls_expected = 0; /* Should have 0 calls and should clear the previous expectation */ mock_validate_expectations(mock); /* Add a new matcher for 1 call */ expectation = mock_add_matcher(mock, "test_printk", test_printk, matchers, ARRAY_SIZE(matchers)); expectation->times_called = 0; expectation->min_calls_expected = 1; expectation->max_calls_expected = 1; /* Satisfy previous matcher */ mock->do_expect(mock, "test_printk", test_printk, two_param_types, two_params, ARRAY_SIZE(two_params)); /* * Validate previous satisfy; if we didn't clear the previous * expectation, it would fail the mock_test. */ mock_validate_expectations(mock); } static void mock_stub(int a) { } /* Common references for InSequence tests */ static int param_len = 1; static const char * const param_type[] = {"int"}; static const void *a_params[] = { &(int){1} }; static const void *b_params[] = { &(int){2} }; static const void *c_params[] = { &(int){3} }; /* Simple test of InSequence, a -> b -> c */ static void mock_test_in_sequence_simple_pass(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a, b, c); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); mock_validate_expectations(mock); } static void mock_test_in_sequence_simple_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a, b, c); EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); } /* More complex test of InSequence on two chains in v formation: * a -> c * b -> c */ static void mock_test_in_sequence_abc_success(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a, c); InSequence(test, b, c); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); } static void mock_test_in_sequence_bac_success(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a, c); InSequence(test, b, c); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); } static void mock_test_in_sequence_no_a_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a, c); InSequence(test, b, c); EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); } static void mock_test_in_sequence_retire_on_saturation(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *a_1 = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); struct mock_expectation *a_2 = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); InSequence(test, a_1, b, a_2, c); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); mock_validate_expectations(mock); } static void mock_test_atleast(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); AtLeast(2, a); AtLeast(1, b); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock_validate_expectations(mock); } static void mock_test_atleast_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); AtLeast(2, b); EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock_validate_expectations(mock); } static void mock_test_atmost(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_param_matcher *c_matchers[] = { int_eq(trgt, 3) }; struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); struct mock_expectation *c = mock_add_matcher(mock, "c", mock_stub, c_matchers, param_len); AtMost(2, a); AtMost(1, b); AtMost(2, c); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "c", mock_stub, param_type, c_params, param_len); mock_validate_expectations(mock); } static void mock_test_atmost_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); AtMost(2, b); EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test))); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock_validate_expectations(mock); } static void mock_test_between(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); Between(2, 4, b); Never(EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock_validate_expectations(mock); } static void mock_test_between_fail(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; struct mock_param_matcher *a_matchers[] = { int_eq(trgt, 1) }; struct mock_param_matcher *b_matchers[] = { int_eq(trgt, 2) }; struct mock_expectation *a = mock_add_matcher(mock, "a", mock_stub, a_matchers, param_len); struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub, b_matchers, param_len); Between(2, 3, a); Between(1, 2, b); Times(2, EXPECT_CALL(fail(mock_get_ctrl(mock_test), any(test)))); mock->do_expect(mock, "a", mock_stub, param_type, a_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len); mock_validate_expectations(mock); } void *do_mocked_fail(struct mock_action *this, const void **params, int len) { static const int ret; struct test_stream * const *stream_ptr = params[0]; struct test_stream *stream = *stream_ptr; stream->set_level(stream, KERN_ERR); stream->commit(stream); return (void *) &ret; } static struct mock_action mocked_fail = { .do_action = do_mocked_fail }; static int mock_test_init(struct KUNIT_T *test) { struct mock_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->mock = test_kzalloc(test, sizeof(*ctx->mock), GFP_KERNEL); if (!ctx->mock) return -ENOMEM; mock_init_ctrl(mock_get_trgt(ctx->mock_test), ctx->mock); /* This test suite tests the behaviour of the error messages printed * when mocks fail, which requires the mocked fail to commit the * stream. */ mock_set_default_action(mock_get_ctrl(ctx->mock_test), "fail", fail, &mocked_fail); return 0; } static void mock_test_and_matcher_accept(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { and(test, int_gt(test, 4), int_lt(test, 6)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 1, expectation->times_called); } static void mock_test_and_matcher_reject_left(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { and(test, int_gt(test, 5), int_lt(test, 6)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); EXPECT_FALSE(test, ret); EXPECT_EQ(test, 0, expectation->times_called); } static void mock_test_and_matcher_reject_right(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { and(test, int_gt(test, 4), int_lt(test, 5)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); EXPECT_FALSE(test, ret); EXPECT_EQ(test, 0, expectation->times_called); } static void mock_test_or_matcher_reject(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { or(test, int_lt(test, 4), int_gt(test, 6)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); EXPECT_FALSE(test, ret); EXPECT_EQ(test, 0, expectation->times_called); } static void mock_test_or_matcher_accept_left(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { or(test, int_gt(test, 4), int_gt(test, 6)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 1, expectation->times_called); } static void mock_test_or_matcher_accept_right(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { or(test, int_lt(test, 4), int_lt(test, 6)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 1, expectation->times_called); } static void mock_test_not_matcher_reject(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { not(test, int_eq(test, 5)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); EXPECT_FALSE(test, ret); EXPECT_EQ(test, 0, expectation->times_called); } static void mock_test_not_matcher_accept(struct KUNIT_T *test) { struct mock_test_context *ctx = test->priv; struct MOCK(KUNIT_T) *mock_test = ctx->mock_test; struct KUNIT_T *trgt = mock_get_trgt(mock_test); struct mock *mock = ctx->mock; const int param0 = 5; static const char * const param_types[] = {"int"}; const void *params[] = {¶m0}; struct mock_param_matcher *matchers[] = { not(test, int_eq(test, 100500)) }; struct mock_expectation *expectation; const void *ret; expectation = mock_add_matcher(mock, "", NULL, matchers, ARRAY_SIZE(matchers)); expectation->action = int_return(trgt, 0); EXPECT_EQ(test, 0, expectation->times_called); ret = mock->do_expect(mock, "", NULL, param_types, params, ARRAY_SIZE(params)); ASSERT_NOT_ERR_OR_NULL(test, ret); EXPECT_EQ(test, 1, expectation->times_called); } static struct KUNIT_CASE_T mock_test_cases[] = { TEST_CASE(mock_test_do_expect_basic), TEST_CASE(mock_test_ptr_eq), TEST_CASE(mock_test_ptr_eq_not_equal), TEST_CASE(mock_test_failed_expect_call_fails_test), TEST_CASE(mock_test_do_expect_default_return), TEST_CASE(mock_test_mock_validate_expectations), TEST_CASE(mock_test_strict_no_expectations_will_fail), TEST_CASE(mock_test_naggy_no_expectations_no_fail), TEST_CASE(mock_test_nice_no_expectations_do_nothing), TEST_CASE(mock_test_strict_no_matching_expectations_fail), TEST_CASE(mock_test_naggy_no_matching_expectations_fail), TEST_CASE(mock_test_nice_no_matching_expectations_fail), TEST_CASE(mock_test_validate_clears_expectations), TEST_CASE(mock_test_in_sequence_simple_pass), TEST_CASE(mock_test_in_sequence_simple_fail), TEST_CASE(mock_test_in_sequence_abc_success), TEST_CASE(mock_test_in_sequence_bac_success), TEST_CASE(mock_test_in_sequence_no_a_fail), TEST_CASE(mock_test_in_sequence_retire_on_saturation), TEST_CASE(mock_test_atleast), TEST_CASE(mock_test_atleast_fail), TEST_CASE(mock_test_atmost), TEST_CASE(mock_test_atmost_fail), TEST_CASE(mock_test_between), TEST_CASE(mock_test_between_fail), TEST_CASE(mock_test_and_matcher_accept), TEST_CASE(mock_test_and_matcher_reject_left), TEST_CASE(mock_test_and_matcher_reject_right), TEST_CASE(mock_test_or_matcher_reject), TEST_CASE(mock_test_or_matcher_accept_left), TEST_CASE(mock_test_or_matcher_accept_right), TEST_CASE(mock_test_not_matcher_reject), TEST_CASE(mock_test_not_matcher_accept), {}, }; static struct KUNIT_SUITE_T mock_test_module = { .name = "mock-test", .init = mock_test_init, .test_cases = mock_test_cases, }; module_test(mock_test_module);