From patchwork Tue Oct 16 23:51:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Brendan Higgins X-Patchwork-Id: 985052 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="b40EjPB9"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="cD87gkTc"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42ZXHT42Fyz9s9J for ; Wed, 17 Oct 2018 10:55:17 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:To:From:Subject:References:Mime-Version :Message-Id:In-Reply-To:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=i/g6FxkmGf30chFOPYxfwAKOvgRpG9IGqJJusajFJxs=; b=b40EjPB9bKlvGs Bu8pW13rEvfYbLfgma9LZ7k9B/QaiJXFy5LGTSy+HjXK6zMKMN+WRijxXJHv7jitiVRdsTfGwfGfh /5HjY7I+ai7fqjwoI2tffGlZqNB0HNC0S1jXpzrko3iUUazEcuq1DB8s5DmqVZrjPSeGcIV+/sonk j0wQ6iHc2mxaId9i/WU3KCrfFs7YhEJ3UUbz+83NrIUX0k9EEG1zq0TmSrQKflU0d+DirIzcsO1KB PgYz3E0QqS0kDGZk+seQ5SfIDGfrlpINYovEG+rV3T3ucl3T1hWyYWJzfTXYuoQHYxax0JIk81nvW e5cEzpco/jF6Fk6cwuxg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gCZB3-0004iP-3c; Tue, 16 Oct 2018 23:55:05 +0000 Received: from mail-qt1-x84a.google.com ([2607:f8b0:4864:20::84a]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gCZAY-0004Il-SN for linux-um@lists.infradead.org; Tue, 16 Oct 2018 23:54:58 +0000 Received: by mail-qt1-x84a.google.com with SMTP id j63-v6so16143258qte.13 for ; Tue, 16 Oct 2018 16:54:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=G8mUMu2GbUg2JX8LWDmnjinAwy7AJF1XWi8Z4EzyP2w=; b=cD87gkTcOY15FVf3OnY9ju2AYChLswyGiPO4qaT8gdvcGVkGIvKvt7wtEHYP80HnD1 QRpEJLRWwfE0WMkD1M1v7egeqhHB1KM1hjHU0LAZynpldBJyOqtN1FQelV07daXW/iuB Yx0kYYsbE5KqlEMvVPWS0iVoCsyt5ypyRX9I81qXLSGh4shAbpO0J0mVaAxfm7AxXkOZ hDoAaEEmWwfU2Ow4n3z99cD+pqTBArGldXauqEFv+4/0TzC5iG/O/pUkWxoY9XUYZZ1R PdknRKzx2mMaPprbC6+0mlMsnjxSjjyY2e9AnkpN5tIdZ5gCh4PyO7fwmvQJ3gnxuSkb sHtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=G8mUMu2GbUg2JX8LWDmnjinAwy7AJF1XWi8Z4EzyP2w=; b=e+t5mKQ7s2RL5JSEuPxOA0684FbUAEFD0RsRgp/BHW/Qszk1uMSYzsqTDi3UPJBfeB nyH/YEcJW0adsRZj5Nz9mUn4tqwReAGBcWOvQc3bNQCzkX+tPLY/hRoLDbmjLT762cjp TXIXsSRUxlzSsSJvFuLbHJIe1vAxuLEBABtyRXW1AIcD6Gi4aQQF8+T0kuXh043d+49M XzvgOr+dN2o7HufhcgSn44hLJur/PWOk3CxMkdSt9uIeq267QQHANr5OqlJAGfTWW/pG onkk9xoL/MAw4PwWioEqsNmPaO1+w/NexbvNtOj9e9LAAqWMVzn0m/HWoOq9s3LaFU5c J2GQ== X-Gm-Message-State: ABuFfohLZrHZe45ftq+ozPySNHLS2SGeVQ3DPIwFluTGhGg9ez6suHDV Y1TVnF30hEyLEM3nnnEt+R40ElFosvsOp/QWS4Qc0g== X-Google-Smtp-Source: ACcGV63goyHFI0Ba5xYbIs9fHChd50SB7jnKKtV9799SecgHVnuGXxqOIClC29aphcr7I+bghKungYtXv51a2aZu1iC9HA== X-Received: by 2002:a0c:d0f2:: with SMTP id b47-v6mr19387561qvh.20.1539734063602; Tue, 16 Oct 2018 16:54:23 -0700 (PDT) Date: Tue, 16 Oct 2018 16:51:04 -0700 In-Reply-To: <20181016235120.138227-1-brendanhiggins@google.com> Message-Id: <20181016235120.138227-16-brendanhiggins@google.com> Mime-Version: 1.0 References: <20181016235120.138227-1-brendanhiggins@google.com> X-Mailer: git-send-email 2.19.1.331.ge82ca0e54c-goog Subject: [RFC v1 15/31] kunit: mock: added basic matchers and actions From: Brendan Higgins To: gregkh@linuxfoundation.org, keescook@google.com, mcgrof@kernel.org, shuah@kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181016_165434_963811_03F83B33 X-CRM114-Status: UNSURE ( 9.83 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -7.6 (-------) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-7.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:84a listed in] [list.dnswl.org] -7.5 USER_IN_DEF_DKIM_WL From: address is in the default DKIM white-list -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_MED DKIMwl.org - Whitelisted Medium sender X-BeenThere: linux-um@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: brakmo@fb.com, richard@nod.at, mpe@ellerman.id.au, Tim.Bird@sony.com, linux-um@lists.infradead.org, linux-kernel@vger.kernel.org, rostedt@goodmis.org, julia.lawall@lip6.fr, joel@jms.id.au, linux-kselftest@vger.kernel.org, khilman@baylibre.com, joe@perches.com, jdike@addtoit.com, Brendan Higgins , kunit-dev@googlegroups.com Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Added basic matchers and actions needed for any kind of mocking to be useful; these matchers and actions are how expectations for mocks are described: what calls the mocks are expected to receive, and what the mock should do under those circumstances. Signed-off-by: Brendan Higgins --- include/kunit/mock.h | 222 +++++++++++++++++++++++++++++++++++ kunit/Makefile | 3 +- kunit/common-mocks.c | 272 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 496 insertions(+), 1 deletion(-) create mode 100644 kunit/common-mocks.c diff --git a/include/kunit/mock.h b/include/kunit/mock.h index 1a35c5702cb15..62e8afcaeab55 100644 --- a/include/kunit/mock.h +++ b/include/kunit/mock.h @@ -122,4 +122,226 @@ struct mock_expectation *mock_add_matcher(struct mock *mock, struct mock_param_matcher *matchers[], int len); +#define CONVERT_TO_ACTUAL_TYPE(type, ptr) (*((type *) ptr)) + +/** + * DOC: Built In Matchers + * + * These are the matchers that can be used when matching arguments in + * :c:func:`EXPECT_CALL` (more can be defined manually). + * + * For example, there's a matcher that matches any arguments: + * + * .. code-block:: c + * + * struct mock_param_matcher *any(struct test *test); + * + * There are matchers for integers based on the binary condition: + * + * * eq: equals to + * * ne: not equal to + * * lt: less than + * * le: less than or equal to + * * gt: greater than + * * ge: greater than or equal to + * + * .. code-block:: c + * + * struct mock_param_matcher *test_int_eq(struct test *test, int expected); + * struct mock_param_matcher *test_int_ne(struct test *test, int expected); + * struct mock_param_matcher *test_int_lt(struct test *test, int expected); + * struct mock_param_matcher *test_int_le(struct test *test, int expected); + * struct mock_param_matcher *test_int_gt(struct test *test, int expected); + * struct mock_param_matcher *test_int_ge(struct test *test, int expected); + * + * For a detailed list, please see + * ``include/linux/mock.h``. + */ + +/* Matches any argument */ +struct mock_param_matcher *test_any(struct test *test); + +/* + * Matches different types of integers, the argument is compared to the + * `expected` field, based on the comparison defined. + */ +struct mock_param_matcher *test_u8_eq(struct test *test, u8 expected); +struct mock_param_matcher *test_u8_ne(struct test *test, u8 expected); +struct mock_param_matcher *test_u8_le(struct test *test, u8 expected); +struct mock_param_matcher *test_u8_lt(struct test *test, u8 expected); +struct mock_param_matcher *test_u8_ge(struct test *test, u8 expected); +struct mock_param_matcher *test_u8_gt(struct test *test, u8 expected); + +struct mock_param_matcher *test_u16_eq(struct test *test, u16 expected); +struct mock_param_matcher *test_u16_ne(struct test *test, u16 expected); +struct mock_param_matcher *test_u16_le(struct test *test, u16 expected); +struct mock_param_matcher *test_u16_lt(struct test *test, u16 expected); +struct mock_param_matcher *test_u16_ge(struct test *test, u16 expected); +struct mock_param_matcher *test_u16_gt(struct test *test, u16 expected); + +struct mock_param_matcher *test_u32_eq(struct test *test, u32 expected); +struct mock_param_matcher *test_u32_ne(struct test *test, u32 expected); +struct mock_param_matcher *test_u32_le(struct test *test, u32 expected); +struct mock_param_matcher *test_u32_lt(struct test *test, u32 expected); +struct mock_param_matcher *test_u32_ge(struct test *test, u32 expected); +struct mock_param_matcher *test_u32_gt(struct test *test, u32 expected); + +struct mock_param_matcher *test_u64_eq(struct test *test, u64 expected); +struct mock_param_matcher *test_u64_ne(struct test *test, u64 expected); +struct mock_param_matcher *test_u64_le(struct test *test, u64 expected); +struct mock_param_matcher *test_u64_lt(struct test *test, u64 expected); +struct mock_param_matcher *test_u64_ge(struct test *test, u64 expected); +struct mock_param_matcher *test_u64_gt(struct test *test, u64 expected); + +struct mock_param_matcher *test_char_eq(struct test *test, char expected); +struct mock_param_matcher *test_char_ne(struct test *test, char expected); +struct mock_param_matcher *test_char_le(struct test *test, char expected); +struct mock_param_matcher *test_char_lt(struct test *test, char expected); +struct mock_param_matcher *test_char_ge(struct test *test, char expected); +struct mock_param_matcher *test_char_gt(struct test *test, char expected); + +struct mock_param_matcher *test_uchar_eq(struct test *test, + unsigned char expected); +struct mock_param_matcher *test_uchar_ne(struct test *test, + unsigned char expected); +struct mock_param_matcher *test_uchar_le(struct test *test, + unsigned char expected); +struct mock_param_matcher *test_uchar_lt(struct test *test, + unsigned char expected); +struct mock_param_matcher *test_uchar_ge(struct test *test, + unsigned char expected); +struct mock_param_matcher *test_uchar_gt(struct test *test, + unsigned char expected); + +struct mock_param_matcher *test_schar_eq(struct test *test, + signed char expected); +struct mock_param_matcher *test_schar_ne(struct test *test, + signed char expected); +struct mock_param_matcher *test_schar_le(struct test *test, + signed char expected); +struct mock_param_matcher *test_schar_lt(struct test *test, + signed char expected); +struct mock_param_matcher *test_schar_ge(struct test *test, + signed char expected); +struct mock_param_matcher *test_schar_gt(struct test *test, + signed char expected); + +struct mock_param_matcher *test_short_eq(struct test *test, short expected); +struct mock_param_matcher *test_short_ne(struct test *test, short expected); +struct mock_param_matcher *test_short_le(struct test *test, short expected); +struct mock_param_matcher *test_short_lt(struct test *test, short expected); +struct mock_param_matcher *test_short_ge(struct test *test, short expected); +struct mock_param_matcher *test_short_gt(struct test *test, short expected); + +struct mock_param_matcher *test_ushort_eq(struct test *test, + unsigned short expected); +struct mock_param_matcher *test_ushort_ne(struct test *test, + unsigned short expected); +struct mock_param_matcher *test_ushort_le(struct test *test, + unsigned short expected); +struct mock_param_matcher *test_ushort_lt(struct test *test, + unsigned short expected); +struct mock_param_matcher *test_ushort_ge(struct test *test, + unsigned short expected); +struct mock_param_matcher *test_ushort_gt(struct test *test, + unsigned short expected); + +struct mock_param_matcher *test_int_eq(struct test *test, int expected); +struct mock_param_matcher *test_int_ne(struct test *test, int expected); +struct mock_param_matcher *test_int_lt(struct test *test, int expected); +struct mock_param_matcher *test_int_le(struct test *test, int expected); +struct mock_param_matcher *test_int_gt(struct test *test, int expected); +struct mock_param_matcher *test_int_ge(struct test *test, int expected); + +struct mock_param_matcher *test_uint_eq(struct test *test, + unsigned int expected); +struct mock_param_matcher *test_uint_ne(struct test *test, + unsigned int expected); +struct mock_param_matcher *test_uint_lt(struct test *test, + unsigned int expected); +struct mock_param_matcher *test_uint_le(struct test *test, + unsigned int expected); +struct mock_param_matcher *test_uint_gt(struct test *test, + unsigned int expected); +struct mock_param_matcher *test_uint_ge(struct test *test, + unsigned int expected); + +struct mock_param_matcher *test_long_eq(struct test *test, long expected); +struct mock_param_matcher *test_long_ne(struct test *test, long expected); +struct mock_param_matcher *test_long_le(struct test *test, long expected); +struct mock_param_matcher *test_long_lt(struct test *test, long expected); +struct mock_param_matcher *test_long_ge(struct test *test, long expected); +struct mock_param_matcher *test_long_gt(struct test *test, long expected); + +struct mock_param_matcher *test_ulong_eq(struct test *test, + unsigned long expected); +struct mock_param_matcher *test_ulong_ne(struct test *test, + unsigned long expected); +struct mock_param_matcher *test_ulong_le(struct test *test, + unsigned long expected); +struct mock_param_matcher *test_ulong_lt(struct test *test, + unsigned long expected); +struct mock_param_matcher *test_ulong_ge(struct test *test, + unsigned long expected); +struct mock_param_matcher *test_ulong_gt(struct test *test, + unsigned long expected); + +struct mock_param_matcher *test_longlong_eq(struct test *test, + long long expected); +struct mock_param_matcher *test_longlong_ne(struct test *test, + long long expected); +struct mock_param_matcher *test_longlong_le(struct test *test, + long long expected); +struct mock_param_matcher *test_longlong_lt(struct test *test, + long long expected); +struct mock_param_matcher *test_longlong_ge(struct test *test, + long long expected); +struct mock_param_matcher *test_longlong_gt(struct test *test, + long long expected); + +struct mock_param_matcher *test_ulonglong_eq(struct test *test, + unsigned long long expected); +struct mock_param_matcher *test_ulonglong_ne(struct test *test, + unsigned long long expected); +struct mock_param_matcher *test_ulonglong_le(struct test *test, + unsigned long long expected); +struct mock_param_matcher *test_ulonglong_lt(struct test *test, + unsigned long long expected); +struct mock_param_matcher *test_ulonglong_ge(struct test *test, + unsigned long long expected); +struct mock_param_matcher *test_ulonglong_gt(struct test *test, + unsigned long long expected); + +/* Matches pointers. */ +struct mock_param_matcher *test_ptr_eq(struct test *test, void *expected); +struct mock_param_matcher *test_ptr_ne(struct test *test, void *expected); +struct mock_param_matcher *test_ptr_lt(struct test *test, void *expected); +struct mock_param_matcher *test_ptr_le(struct test *test, void *expected); +struct mock_param_matcher *test_ptr_gt(struct test *test, void *expected); +struct mock_param_matcher *test_ptr_ge(struct test *test, void *expected); + +/* Matches memory sections and strings. */ +struct mock_param_matcher *test_memeq(struct test *test, + const void *buf, + size_t size); +struct mock_param_matcher *test_streq(struct test *test, const char *str); + +struct mock_action *test_u8_return(struct test *test, u8 ret); +struct mock_action *test_u16_return(struct test *test, u16 ret); +struct mock_action *test_u32_return(struct test *test, u32 ret); +struct mock_action *test_u64_return(struct test *test, u64 ret); +struct mock_action *test_char_return(struct test *test, char ret); +struct mock_action *test_uchar_return(struct test *test, unsigned char ret); +struct mock_action *test_schar_return(struct test *test, signed char ret); +struct mock_action *test_short_return(struct test *test, short ret); +struct mock_action *test_ushort_return(struct test *test, unsigned short ret); +struct mock_action *test_int_return(struct test *test, int ret); +struct mock_action *test_uint_return(struct test *test, unsigned int ret); +struct mock_action *test_long_return(struct test *test, long ret); +struct mock_action *test_ulong_return(struct test *test, unsigned long ret); +struct mock_action *test_longlong_return(struct test *test, long long ret); +struct mock_action *test_ulonglong_return(struct test *test, + unsigned long long ret); +struct mock_action *test_ptr_return(struct test *test, void *ret); + #endif /* _KUNIT_MOCK_H */ diff --git a/kunit/Makefile b/kunit/Makefile index ad58110de695c..52a1da46cbd21 100644 --- a/kunit/Makefile +++ b/kunit/Makefile @@ -1,4 +1,5 @@ -obj-$(CONFIG_KUNIT) += test.o mock.o string-stream.o test-stream.o +obj-$(CONFIG_KUNIT) += test.o mock.o common-mocks.o string-stream.o \ + test-stream.o obj-$(CONFIG_KUNIT_TEST) += \ test-test.o mock-macro-test.o string-stream-test.o obj-$(CONFIG_EXAMPLE_TEST) += example-test.o diff --git a/kunit/common-mocks.c b/kunit/common-mocks.c new file mode 100644 index 0000000000000..ecac9c1c29c0e --- /dev/null +++ b/kunit/common-mocks.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Common KUnit mock call arg matchers and formatters. + * + * Copyright (C) 2018, Google LLC. + * Author: Brendan Higgins + */ + +#include +#include + +static bool match_any(struct mock_param_matcher *pmatcher, + struct test_stream *stream, + const void *actual) +{ + stream->add(stream, "don't care"); + return true; +} + +static struct mock_param_matcher any_matcher = { + .match = match_any, +}; + +struct mock_param_matcher *test_any(struct test *test) +{ + return &any_matcher; +} + +#define DEFINE_MATCHER_STRUCT(type_name, type) \ + struct mock_##type_name##_matcher { \ + struct mock_param_matcher matcher; \ + type expected; \ + }; + +#define DEFINE_TO_MATCHER_STRUCT(type_name) \ + struct mock_##type_name##_matcher * \ + to_mock_##type_name##_matcher( \ + struct mock_param_matcher *matcher) \ + { \ + return container_of(matcher, \ + struct mock_##type_name##_matcher, \ + matcher); \ + } + +#define DEFINE_MATCH_FUNC(type_name, type, op_name, op) \ + bool match_##type_name##_##op_name( \ + struct mock_param_matcher *pmatcher, \ + struct test_stream *stream, \ + const void *pactual) \ + { \ + struct mock_##type_name##_matcher *matcher = \ + to_mock_##type_name##_matcher(pmatcher); \ + type actual = *((type *) pactual); \ + bool matches = actual op matcher->expected; \ + \ + if (matches) \ + stream->add(stream, \ + "%d "#op" %d", \ + actual, \ + matcher->expected); \ + else \ + stream->add(stream, \ + "%d not "#op" %d", \ + actual, \ + matcher->expected); \ + \ + return matches; \ + } + +#define DEFINE_MATCH_FACTORY(type_name, type, op_name) \ + struct mock_param_matcher *test_##type_name##_##op_name( \ + struct test *test, type expected) \ + { \ + struct mock_##type_name##_matcher *matcher; \ + \ + matcher = test_kmalloc(test, \ + sizeof(*matcher), \ + GFP_KERNEL); \ + if (!matcher) \ + return NULL; \ + \ + matcher->matcher.match = match_##type_name##_##op_name;\ + matcher->expected = expected; \ + return &matcher->matcher; \ + } + +#define DEFINE_MATCHER_WITH_TYPENAME(type_name, type) \ + DEFINE_MATCHER_STRUCT(type_name, type) \ + DEFINE_TO_MATCHER_STRUCT(type_name) \ + DEFINE_MATCH_FUNC(type_name, type, eq, ==) \ + DEFINE_MATCH_FACTORY(type_name, type, eq) \ + DEFINE_MATCH_FUNC(type_name, type, ne, !=) \ + DEFINE_MATCH_FACTORY(type_name, type, ne) \ + DEFINE_MATCH_FUNC(type_name, type, le, <=) \ + DEFINE_MATCH_FACTORY(type_name, type, le) \ + DEFINE_MATCH_FUNC(type_name, type, lt, <) \ + DEFINE_MATCH_FACTORY(type_name, type, lt) \ + DEFINE_MATCH_FUNC(type_name, type, ge, >=) \ + DEFINE_MATCH_FACTORY(type_name, type, ge) \ + DEFINE_MATCH_FUNC(type_name, type, gt, >) \ + DEFINE_MATCH_FACTORY(type_name, type, gt) + +#define DEFINE_MATCHER(type) DEFINE_MATCHER_WITH_TYPENAME(type, type) + +DEFINE_MATCHER(u8); +DEFINE_MATCHER(u16); +DEFINE_MATCHER(u32); +DEFINE_MATCHER(u64); +DEFINE_MATCHER(char); +DEFINE_MATCHER_WITH_TYPENAME(uchar, unsigned char); +DEFINE_MATCHER_WITH_TYPENAME(schar, signed char); +DEFINE_MATCHER(short); +DEFINE_MATCHER_WITH_TYPENAME(ushort, unsigned short); +DEFINE_MATCHER(int); +DEFINE_MATCHER_WITH_TYPENAME(uint, unsigned int); +DEFINE_MATCHER(long); +DEFINE_MATCHER_WITH_TYPENAME(ulong, unsigned long); +DEFINE_MATCHER_WITH_TYPENAME(longlong, long long); +DEFINE_MATCHER_WITH_TYPENAME(ulonglong, unsigned long long); + +DEFINE_MATCHER_WITH_TYPENAME(ptr, void *); + +struct mock_memeq_matcher { + struct mock_param_matcher matcher; + const void *expected; + size_t size; +}; + +static bool match_memeq(struct mock_param_matcher *pmatcher, + struct test_stream *stream, + const void *pactual) +{ + struct mock_memeq_matcher *matcher = + container_of(pmatcher, + struct mock_memeq_matcher, + matcher); + const void *actual = CONVERT_TO_ACTUAL_TYPE(const void *, pactual); + bool matches = !memcmp(actual, matcher->expected, matcher->size); + int i; + + for (i = 0; i < matcher->size; i++) + stream->add(stream, "%02x, ", ((const char *) actual)[i]); + if (matches) + stream->add(stream, "== "); + else + stream->add(stream, "!= "); + for (i = 0; i < matcher->size; i++) + stream->add(stream, + "%02x, ", + ((const char *) matcher->expected)[i]); + + return matches; +} + +struct mock_param_matcher *test_memeq(struct test *test, + const void *buf, + size_t size) +{ + struct mock_memeq_matcher *matcher; + + matcher = test_kzalloc(test, sizeof(*matcher), GFP_KERNEL); + if (!matcher) + return NULL; + + matcher->matcher.match = match_memeq; + matcher->expected = buf; + matcher->size = size; + + return &matcher->matcher; +} + +struct mock_streq_matcher { + struct mock_param_matcher matcher; + const char *expected; +}; + +static bool match_streq(struct mock_param_matcher *pmatcher, + struct test_stream *stream, + const void *pactual) +{ + struct mock_streq_matcher *matcher = + container_of(pmatcher, + struct mock_streq_matcher, + matcher); + const char *actual = CONVERT_TO_ACTUAL_TYPE(const char *, pactual); + bool matches = !strcmp(actual, matcher->expected); + + if (matches) + stream->add(stream, "%s == %s", actual, matcher->expected); + else + stream->add(stream, "%s != %s", actual, matcher->expected); + + return matches; +} + +struct mock_param_matcher *test_streq(struct test *test, const char *str) +{ + struct mock_streq_matcher *matcher; + + matcher = test_kzalloc(test, sizeof(*matcher), GFP_KERNEL); + if (!matcher) + return NULL; + + matcher->matcher.match = match_streq; + matcher->expected = str; + + return &matcher->matcher; +} + +#define DEFINE_RETURN_ACTION_STRUCT(type_name, type) \ + struct mock_##type_name##_action { \ + struct mock_action action; \ + type ret; \ + }; + +#define DEFINE_RETURN_ACTION_FUNC(type_name, type) \ + void *do_##type_name##_return(struct mock_action *paction, \ + const void **params, \ + int len) \ + { \ + struct mock_##type_name##_action *action = \ + container_of(paction, \ + struct mock_##type_name##_action,\ + action); \ + \ + return (void *) &action->ret; \ + } + +#define DEFINE_RETURN_ACTION_FACTORY(type_name, type) \ + struct mock_action *test_##type_name##_return( \ + struct test *test, \ + type ret) \ + { \ + struct mock_##type_name##_action *action; \ + \ + action = test_kmalloc(test, \ + sizeof(*action), \ + GFP_KERNEL); \ + if (!action) \ + return NULL; \ + \ + action->action.do_action = do_##type_name##_return; \ + action->ret = ret; \ + \ + return &action->action; \ + } + +#define DEFINE_RETURN_ACTION_WITH_TYPENAME(type_name, type) \ + DEFINE_RETURN_ACTION_STRUCT(type_name, type); \ + DEFINE_RETURN_ACTION_FUNC(type_name, type); \ + DEFINE_RETURN_ACTION_FACTORY(type_name, type); + +#define DEFINE_RETURN_ACTION(type) \ + DEFINE_RETURN_ACTION_WITH_TYPENAME(type, type) + +DEFINE_RETURN_ACTION(u8); +DEFINE_RETURN_ACTION(u16); +DEFINE_RETURN_ACTION(u32); +DEFINE_RETURN_ACTION(u64); +DEFINE_RETURN_ACTION(char); +DEFINE_RETURN_ACTION_WITH_TYPENAME(uchar, unsigned char); +DEFINE_RETURN_ACTION_WITH_TYPENAME(schar, signed char); +DEFINE_RETURN_ACTION(short); +DEFINE_RETURN_ACTION_WITH_TYPENAME(ushort, unsigned short); +DEFINE_RETURN_ACTION(int); +DEFINE_RETURN_ACTION_WITH_TYPENAME(uint, unsigned int); +DEFINE_RETURN_ACTION(long); +DEFINE_RETURN_ACTION_WITH_TYPENAME(ulong, unsigned long); +DEFINE_RETURN_ACTION_WITH_TYPENAME(longlong, long long); +DEFINE_RETURN_ACTION_WITH_TYPENAME(ulonglong, unsigned long long); +DEFINE_RETURN_ACTION_WITH_TYPENAME(ptr, void *); +