913 lines
29 KiB
C
Executable File
913 lines
29 KiB
C
Executable File
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* KUnit test for mock.h.
|
|
*
|
|
* Copyright (C) 2020, Google LLC.
|
|
* Author: Brendan Higgins <brendanhiggins@google.com>
|
|
*/
|
|
|
|
#include <kunit/test.h>
|
|
#include <kunit/mock.h>
|
|
|
|
// A simple class for unit-testing/example purposes.
|
|
struct adder {
|
|
int (*add)(struct adder *adder, int x, int y);
|
|
};
|
|
|
|
static int real_add(struct adder *adder, int x, int y)
|
|
{
|
|
return x + y;
|
|
}
|
|
|
|
static void adder_real_init(struct adder *adder)
|
|
{
|
|
adder->add = real_add;
|
|
}
|
|
|
|
DECLARE_STRUCT_CLASS_MOCK_PREREQS(adder);
|
|
DEFINE_STRUCT_CLASS_MOCK(METHOD(mock_add), CLASS_MOCK(adder), RETURNS(int),
|
|
PARAMS(struct adder*, int, int));
|
|
DECLARE_STRUCT_CLASS_MOCK_INIT(adder);
|
|
|
|
// This would normally live in the .c file.
|
|
static int adder_mock_init(struct kunit *test, struct MOCK(adder) *mock_adder)
|
|
{
|
|
struct adder *real = mock_get_trgt(mock_adder);
|
|
|
|
adder_real_init(real);
|
|
|
|
real->add = mock_add;
|
|
mock_set_default_action(mock_get_ctrl(mock_adder),
|
|
"mock_add",
|
|
mock_add,
|
|
kunit_int_return(mock_get_test(mock_adder), 0));
|
|
return 0;
|
|
}
|
|
DEFINE_STRUCT_CLASS_MOCK_INIT(adder, adder_mock_init);
|
|
|
|
|
|
/*
|
|
* Note: we create a new `failing_test` so we can validate that failed mock
|
|
* expectations mark tests as failed.
|
|
* Marking the real `test` as failed is obviously problematic.
|
|
*
|
|
* See mock_test_failed_expect_call_fails_test for an example.
|
|
*/
|
|
struct mock_test_context {
|
|
struct kunit *failing_test;
|
|
struct mock *mock;
|
|
};
|
|
|
|
static void mock_test_do_expect_basic(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
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[] = {
|
|
kunit_any(test), kunit_any(test)
|
|
};
|
|
struct mock_expectation *expectation;
|
|
const void *ret;
|
|
|
|
expectation = mock_add_matcher(mock,
|
|
"",
|
|
NULL,
|
|
matchers_any_two,
|
|
ARRAY_SIZE(matchers_any_two));
|
|
expectation->action = kunit_int_return(test, 5);
|
|
KUNIT_EXPECT_EQ(test, 0, expectation->times_called);
|
|
|
|
ret = mock->do_expect(mock,
|
|
"",
|
|
NULL,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
|
|
KUNIT_EXPECT_EQ(test, 5, *((int *) ret));
|
|
KUNIT_EXPECT_EQ(test, 1, expectation->times_called);
|
|
}
|
|
|
|
static void mock_test_ptr_eq(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
void *param0 = ctx, *param1 = failing_test;
|
|
static const char * const two_param_types[] = {"void *", "void *"};
|
|
const void *two_params[] = {¶m0, ¶m1};
|
|
struct mock_param_matcher *matchers_two_ptrs[] = {
|
|
kunit_ptr_eq(test, param0), kunit_ptr_eq(test, param1)
|
|
};
|
|
struct mock_expectation *expectation;
|
|
const void *ret;
|
|
|
|
expectation = mock_add_matcher(mock,
|
|
"",
|
|
NULL,
|
|
matchers_two_ptrs,
|
|
ARRAY_SIZE(matchers_two_ptrs));
|
|
expectation->action = kunit_int_return(test, 0);
|
|
KUNIT_EXPECT_EQ(test, 0, expectation->times_called);
|
|
|
|
ret = mock->do_expect(mock,
|
|
"",
|
|
NULL,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
|
|
KUNIT_EXPECT_EQ(test, 1, expectation->times_called);
|
|
}
|
|
|
|
static void mock_test_ptr_eq_not_equal(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
/* Pick some two pointers, but pass in different values. */
|
|
void *param0 = test, *param1 = failing_test;
|
|
static const char * const two_param_types[] = {"void *", "void *"};
|
|
const void *two_params[] = {¶m0, ¶m1};
|
|
struct mock_param_matcher *matchers_two_ptrs[] = {
|
|
kunit_ptr_eq(failing_test, param0),
|
|
kunit_ptr_eq(failing_test, 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 = kunit_int_return(failing_test, 0);
|
|
KUNIT_EXPECT_EQ(test, 0, expectation->times_called);
|
|
|
|
ret = mock->do_expect(mock,
|
|
"",
|
|
NULL,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
KUNIT_EXPECT_FALSE(test, ret);
|
|
KUNIT_EXPECT_EQ(test, 0, expectation->times_called);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
/*
|
|
* In order for us to be able to rely on KUNIT_EXPECT_CALL to validate other
|
|
* behavior, we need to test that unsatisfied KUNIT_EXPECT_CALL causes a test
|
|
* failure.
|
|
*
|
|
* In order to understand what this test is testing we must first understand how
|
|
* KUNIT_EXPECT_CALL() works conceptually. In theory, a test specifies that it
|
|
* expects some function to be called some number of times (can be zero), with
|
|
* some particular arguments. Hence, KUNIT_EXPECT_CALL() must do two things:
|
|
*
|
|
* 1) Determine whether a function call matches the expectation.
|
|
*
|
|
* 2) Fail if there are too many or too few matches.
|
|
*/
|
|
static void mock_test_failed_expect_call_fails_test(struct kunit *test)
|
|
{
|
|
/*
|
|
* We do not want to fail the real `test` object used to run this test.
|
|
* So we use a separate `failing_test` for KUNIT_EXPECT_CALL().
|
|
*/
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
/*
|
|
* Put an expectation on mock, which we won't satisify.
|
|
*
|
|
* NOTE: it does not actually matter what function we expect here.
|
|
* `mock` does not represent an actual mock on anything; we just need to
|
|
* create some expectation, that we won't satisfy.
|
|
*/
|
|
KUNIT_EXPECT_CALL(mock_add(mock,
|
|
kunit_any(failing_test),
|
|
kunit_any(failing_test)));
|
|
|
|
/*
|
|
* Validate the unsatisfied expectation that we just created. This
|
|
* should cause `failing_test` to fail.
|
|
*/
|
|
mock_validate_expectations(mock);
|
|
|
|
/* Verify that `failing_test` has actually failed. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_do_expect_default_return(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
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[] = {
|
|
kunit_int_eq(test, 5),
|
|
kunit_int_eq(test, -4)
|
|
};
|
|
struct mock_expectation *expectation;
|
|
const void *ret;
|
|
|
|
expectation = mock_add_matcher(mock,
|
|
"add",
|
|
mock_add,
|
|
matchers,
|
|
ARRAY_SIZE(matchers));
|
|
expectation->action = kunit_int_return(test, 5);
|
|
KUNIT_EXPECT_EQ(test, 0, expectation->times_called);
|
|
|
|
KUNIT_EXPECT_FALSE(test,
|
|
mock_set_default_action(mock,
|
|
"add",
|
|
mock_add,
|
|
kunit_int_return(test, -4)));
|
|
|
|
ret = mock->do_expect(mock,
|
|
"add",
|
|
mock_add,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret);
|
|
KUNIT_EXPECT_EQ(test, -4, *((int *) ret));
|
|
KUNIT_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 *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_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};
|
|
|
|
mock->type = MOCK_TYPE_STRICT;
|
|
|
|
mock_set_default_action(mock,
|
|
"add",
|
|
mock_add,
|
|
kunit_int_return(failing_test, -4));
|
|
|
|
mock->do_expect(mock,
|
|
"add",
|
|
mock_add,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
mock_validate_expectations(mock);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
/*
|
|
* 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 *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_expectation *expectation;
|
|
int param0 = 5, param1 = -5;
|
|
static const char * const two_param_types[] = {"int", "int"};
|
|
const void *two_params[] = {¶m0, ¶m1};
|
|
|
|
mock->type = MOCK_TYPE_NAGGY;
|
|
|
|
mock_set_default_action(mock,
|
|
"add",
|
|
real_add,
|
|
kunit_int_return(failing_test, -4));
|
|
|
|
expectation = Never(KUNIT_EXPECT_CALL(mock_add(mock,
|
|
kunit_any(failing_test),
|
|
kunit_any(failing_test))));
|
|
|
|
KUNIT_EXPECT_CALL(mock_add(
|
|
mock,
|
|
kunit_any(failing_test),
|
|
kunit_va_format_cmp(failing_test,
|
|
kunit_str_contains(failing_test,
|
|
"Method was called with no expectations declared"),
|
|
kunit_any(failing_test))));
|
|
|
|
mock->do_expect(mock,
|
|
"add",
|
|
real_add,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
mock_validate_expectations(mock);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
/* Method called on nice mock with no expectations will do nothing. */
|
|
static void mock_test_nice_no_expectations_do_nothing(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_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};
|
|
|
|
mock->type = MOCK_TYPE_NICE;
|
|
|
|
mock->do_expect(mock,
|
|
"add",
|
|
mock_add,
|
|
two_param_types,
|
|
two_params,
|
|
ARRAY_SIZE(two_params));
|
|
mock_validate_expectations(mock);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
/* 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 *test,
|
|
enum mock_type mock_type)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_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 *two_matchers[] = {
|
|
kunit_int_eq(failing_test, 100),
|
|
kunit_int_eq(failing_test, 100)
|
|
};
|
|
|
|
mock_add_matcher(mock, "add", mock_add, two_matchers,
|
|
ARRAY_SIZE(two_matchers));
|
|
|
|
mock->type = mock_type;
|
|
|
|
mock->do_expect(mock, "add", mock_add, two_param_types, two_params,
|
|
ARRAY_SIZE(two_params));
|
|
|
|
/* Even nice mocks should fail if there's an unmet expectation. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_naggy_no_matching_expectations_fail(struct kunit *test)
|
|
{
|
|
run_method_called_but_no_matching_expectation_test(test,
|
|
MOCK_TYPE_NAGGY);
|
|
}
|
|
|
|
static void mock_test_strict_no_matching_expectations_fail(struct kunit *test)
|
|
{
|
|
run_method_called_but_no_matching_expectation_test(test,
|
|
MOCK_TYPE_STRICT);
|
|
}
|
|
|
|
static void mock_test_nice_no_matching_expectations_fail(struct kunit *test)
|
|
{
|
|
run_method_called_but_no_matching_expectation_test(test,
|
|
MOCK_TYPE_NICE);
|
|
}
|
|
|
|
static void mock_test_mock_validate_expectations(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *matchers[] = {
|
|
kunit_int_eq(failing_test, 5),
|
|
kunit_int_eq(failing_test, -4)
|
|
};
|
|
struct mock_expectation *expectation;
|
|
|
|
|
|
expectation = mock_add_matcher(mock,
|
|
"add",
|
|
mock_add,
|
|
matchers,
|
|
ARRAY_SIZE(matchers));
|
|
expectation->times_called = 0;
|
|
expectation->min_calls_expected = 1;
|
|
expectation->max_calls_expected = 1;
|
|
|
|
mock_validate_expectations(mock);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_validate_clears_expectations(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
struct mock_param_matcher *matchers[] = {
|
|
kunit_int_eq(failing_test, 5),
|
|
kunit_int_eq(failing_test, -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;
|
|
|
|
expectation = Never(KUNIT_EXPECT_CALL(mock_add(mock,
|
|
kunit_any(failing_test),
|
|
kunit_any(failing_test))));
|
|
|
|
/* Add an arbitrary matcher for 0 calls */
|
|
expectation = mock_add_matcher(mock, "add", mock_add,
|
|
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, "add", mock_add,
|
|
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, "add", mock_add, 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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
|
|
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 *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_in_sequence_simple_fail(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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);
|
|
|
|
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);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
/* 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 *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_in_sequence_bac_success(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_in_sequence_no_a_fail(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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);
|
|
|
|
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);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_in_sequence_retire_on_saturation(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_atleast(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_atleast_fail(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
|
|
struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub,
|
|
b_matchers, param_len);
|
|
|
|
AtLeast(2, b);
|
|
|
|
mock->do_expect(mock, "b", mock_stub, param_type, b_params, param_len);
|
|
|
|
mock_validate_expectations(mock);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_atmost(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
struct mock_param_matcher *c_matchers[] = { kunit_int_eq(failing_test, 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(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_atmost_fail(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
|
|
struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub,
|
|
b_matchers, param_len);
|
|
|
|
AtMost(2, b);
|
|
|
|
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);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static void mock_test_between(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 2) };
|
|
|
|
struct mock_expectation *b = mock_add_matcher(mock, "b", mock_stub,
|
|
b_matchers, param_len);
|
|
|
|
Between(2, 4, b);
|
|
Never(KUNIT_EXPECT_CALL(mock_add(mock, kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
/* If all goes well, shouldn't fail the test. */
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_SUCCESS);
|
|
}
|
|
|
|
static void mock_test_between_fail(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
struct kunit *failing_test = ctx->failing_test;
|
|
struct mock *mock = ctx->mock;
|
|
|
|
struct mock_param_matcher *a_matchers[] = { kunit_int_eq(failing_test, 1) };
|
|
struct mock_param_matcher *b_matchers[] = { kunit_int_eq(failing_test, 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, KUNIT_EXPECT_CALL(mock_add(mock,
|
|
kunit_any(failing_test),
|
|
kunit_any(failing_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);
|
|
|
|
KUNIT_EXPECT_EQ(test, failing_test->status, KUNIT_FAILURE);
|
|
}
|
|
|
|
static int mock_test_init(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx;
|
|
|
|
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
|
if (!ctx)
|
|
return -ENOMEM;
|
|
test->priv = ctx;
|
|
|
|
ctx->failing_test = kunit_kzalloc(test, sizeof(*ctx->failing_test),
|
|
GFP_KERNEL);
|
|
if (!ctx->failing_test)
|
|
return -EINVAL;
|
|
kunit_init_test(ctx->failing_test, NULL, NULL);
|
|
|
|
ctx->mock = kunit_kzalloc(test, sizeof(*ctx->mock), GFP_KERNEL);
|
|
if (!ctx->mock)
|
|
return -ENOMEM;
|
|
mock_init_ctrl(ctx->failing_test, ctx->mock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mock_test_exit(struct kunit *test)
|
|
{
|
|
struct mock_test_context *ctx = test->priv;
|
|
|
|
kunit_cleanup(ctx->failing_test);
|
|
}
|
|
|
|
static struct kunit_case mock_test_cases[] = {
|
|
KUNIT_CASE(mock_test_do_expect_basic),
|
|
KUNIT_CASE(mock_test_ptr_eq),
|
|
KUNIT_CASE(mock_test_ptr_eq_not_equal),
|
|
KUNIT_CASE(mock_test_failed_expect_call_fails_test),
|
|
KUNIT_CASE(mock_test_do_expect_default_return),
|
|
KUNIT_CASE(mock_test_mock_validate_expectations),
|
|
KUNIT_CASE(mock_test_strict_no_expectations_will_fail),
|
|
KUNIT_CASE(mock_test_naggy_no_expectations_no_fail),
|
|
KUNIT_CASE(mock_test_nice_no_expectations_do_nothing),
|
|
KUNIT_CASE(mock_test_strict_no_matching_expectations_fail),
|
|
KUNIT_CASE(mock_test_naggy_no_matching_expectations_fail),
|
|
KUNIT_CASE(mock_test_nice_no_matching_expectations_fail),
|
|
KUNIT_CASE(mock_test_validate_clears_expectations),
|
|
KUNIT_CASE(mock_test_in_sequence_simple_pass),
|
|
KUNIT_CASE(mock_test_in_sequence_simple_fail),
|
|
KUNIT_CASE(mock_test_in_sequence_abc_success),
|
|
KUNIT_CASE(mock_test_in_sequence_bac_success),
|
|
KUNIT_CASE(mock_test_in_sequence_no_a_fail),
|
|
KUNIT_CASE(mock_test_in_sequence_retire_on_saturation),
|
|
KUNIT_CASE(mock_test_atleast),
|
|
KUNIT_CASE(mock_test_atleast_fail),
|
|
KUNIT_CASE(mock_test_atmost),
|
|
KUNIT_CASE(mock_test_atmost_fail),
|
|
KUNIT_CASE(mock_test_between),
|
|
KUNIT_CASE(mock_test_between_fail),
|
|
{}
|
|
};
|
|
|
|
static struct kunit_suite mock_test_suite = {
|
|
.name = "mock-test",
|
|
.init = mock_test_init,
|
|
.exit = mock_test_exit,
|
|
.test_cases = mock_test_cases,
|
|
};
|
|
|
|
kunit_test_suite(mock_test_suite);
|