linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Muhammad Usama Anjum <usama.anjum@collabora.com>
To: "Maíra Canal" <mairacanal@riseup.net>,
	"Brendan Higgins" <brendanhiggins@google.com>,
	davidgow@google.com, "Daniel Latypov" <dlatypov@google.com>,
	airlied@linux.ie, daniel@ffwll.ch, davem@davemloft.net,
	kuba@kernel.org, jose.exposito89@gmail.com, javierm@redhat.com
Cc: usama.anjum@collabora.com, andrealmeid@riseup.net,
	melissa.srw@gmail.com, siqueirajordao@riseup.net,
	Isabella Basso <isabbasso@riseup.net>,
	magalilemes00@gmail.com, tales.aparecida@gmail.com,
	linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 1/3] kunit: Introduce KUNIT_EXPECT_MEMEQ and KUNIT_EXPECT_MEMNEQ macros
Date: Sat, 6 Aug 2022 19:20:58 +0500	[thread overview]
Message-ID: <1b3298b3-13b5-fbbb-bc8e-f3d0af726d71@collabora.com> (raw)
In-Reply-To: <20220803215855.258704-2-mairacanal@riseup.net>

On 8/4/22 2:58 AM, Maíra Canal wrote:
> Currently, in order to compare memory blocks in KUnit, the KUNIT_EXPECT_EQ
> or KUNIT_EXPECT_FALSE macros are used in conjunction with the memcmp
> function, such as:
>     KUNIT_EXPECT_EQ(test, memcmp(foo, bar, size), 0);
> 
> Although this usage produces correct results for the test cases, when
> the expectation fails, the error message is not very helpful,
> indicating only the return of the memcmp function.
> 
> Therefore, create a new set of macros KUNIT_EXPECT_MEMEQ and
> KUNIT_EXPECT_MEMNEQ that compare memory blocks until a specified size.
> In case of expectation failure, those macros print the hex dump of the
> memory blocks, making it easier to debug test failures for memory blocks.
> 
> That said, the expectation
> 
>     KUNIT_EXPECT_EQ(test, memcmp(foo, bar, size), 0);
> 
> would translate to the expectation
> 
>     KUNIT_EXPECT_MEMEQ(test, foo, bar, size);
> 
> Signed-off-by: Maíra Canal <mairacanal@riseup.net>
> Reviewed-by: Daniel Latypov <dlatypov@google.com>
Reviewed-by: Muhammad Usama Anjum <usama.anjum@collabora.com>

> ---
> v1 -> v2:
> - Change "determinated" to "specified" (Daniel Latypov).
> - Change the macro KUNIT_EXPECT_ARREQ to KUNIT_EXPECT_MEMEQ, in order to make
> it easier for users to infer the right size unit (Daniel Latypov).
> - Mark the different bytes on the failure message with a <> (Daniel Latypov).
> 
> v2 -> v3:
> - Make the bytes aligned at output.
> - Add KUNIT_SUBSUBTEST_INDENT to the output for the indentation (Daniel Latypov).
> - Line up the trailing \ at macros using tabs (Daniel Latypov).
> - Line up the params to the functions (Daniel Latypov).
> ---
>  include/kunit/assert.h | 34 +++++++++++++++++++
>  include/kunit/test.h   | 76 ++++++++++++++++++++++++++++++++++++++++++
>  lib/kunit/assert.c     | 56 +++++++++++++++++++++++++++++++
>  3 files changed, 166 insertions(+)
> 
> diff --git a/include/kunit/assert.h b/include/kunit/assert.h
> index 4b52e12c2ae8..4b817a8eb619 100644
> --- a/include/kunit/assert.h
> +++ b/include/kunit/assert.h
> @@ -256,4 +256,38 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
> 				    const struct va_format *message,
> 				    struct string_stream *stream);
> 
> +#define KUNIT_INIT_MEM_ASSERT_STRUCT(text_, left_val, right_val, size_)   \
> +	{                                                                 \
> +		.assert = { .format = kunit_mem_assert_format },          \
> +		.text = text_,                                            \
> +		.left_value = left_val,                                   \
> +		.right_value = right_val, .size = size_,                  \
> +	}
> +
> +/**
> + * struct kunit_mem_assert - An expectation/assertion that compares two
> + *	memory blocks.
> + * @assert: The parent of this type.
> + * @text: Holds the textual representations of the operands and comparator.
> + * @left_value: The actual evaluated value of the expression in the left slot.
> + * @right_value: The actual evaluated value of the expression in the right slot.
> + * @size: Size of the memory block analysed in bytes.
> + *
> + * Represents an expectation/assertion that compares two memory blocks. For
> + * example, to expect that the first three bytes of foo is equal to the
> + * first three bytes of bar, you can use the expectation
> + * KUNIT_EXPECT_MEMEQ(test, foo, bar, 3);
> + */
> +struct kunit_mem_assert {
> +	struct kunit_assert assert;
> +	const struct kunit_binary_assert_text *text;
> +	const void *left_value;
> +	const void *right_value;
> +	const size_t size;
> +};
> +
> +void kunit_mem_assert_format(const struct kunit_assert *assert,
> +			     const struct va_format *message,
> +			     struct string_stream *stream);
> +
>  #endif /*  _KUNIT_ASSERT_H */
> diff --git a/include/kunit/test.h b/include/kunit/test.h
> index 8ffcd7de9607..02eeaff1c58e 100644
> --- a/include/kunit/test.h
> +++ b/include/kunit/test.h
> @@ -684,6 +684,36 @@ do {									       \
> 			##__VA_ARGS__);					       \
>  } while (0)
> 
> +#define KUNIT_MEM_ASSERTION(test,					       \
> +			    assert_type,				       \
> +			    left,					       \
> +			    op,						       \
> +			    right,					       \
> +			    size,					       \
> +			    fmt,					       \
> +			    ...)					       \
> +do {									       \
> +	const void *__left = (left);					       \
> +	const void *__right = (right);					       \
> +	const size_t __size = (size);					       \
> +	static const struct kunit_binary_assert_text __text = {		       \
> +		.operation = #op,					       \
> +		.left_text = #left,					       \
> +		.right_text = #right,					       \
> +	};								       \
> +									       \
> +	KUNIT_ASSERTION(test,						       \
> +			assert_type,					       \
> +			memcmp(__left, __right, __size) op 0,		       \
> +			kunit_mem_assert,				       \
> +			KUNIT_INIT_MEM_ASSERT_STRUCT(&__text,		       \
> +						     __left,		       \
> +						     __right,		       \
> +						     __size),		       \
> +			fmt,						       \
> +			##__VA_ARGS__);					       \
> +} while (0)
> +
>  #define KUNIT_PTR_NOT_ERR_OR_NULL_MSG_ASSERTION(test,			       \
> 						assert_type,		       \
> 						ptr,			       \
> @@ -952,6 +982,52 @@ do {									       \
> 				   fmt,					       \
> 				   ##__VA_ARGS__)
> 
> +/**
> + * KUNIT_EXPECT_MEMEQ() - Expects that the first @size bytes of @left and @right are equal.
> + * @test: The test context object.
> + * @left: An arbitrary expression that evaluates to the specified size.
> + * @right: An arbitrary expression that evaluates to the specified size.
> + * @size: Number of bytes compared.
> + *
> + * Sets an expectation that the values that @left and @right evaluate to are
> + * equal. This is semantically equivalent to
> + * KUNIT_EXPECT_TRUE(@test, !memcmp((@left), (@right), (@size))). See
> + * KUNIT_EXPECT_TRUE() for more information.
> + */
> +#define KUNIT_EXPECT_MEMEQ(test, left, right, size) \
> +	KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, NULL)
> +
> +#define KUNIT_EXPECT_MEMEQ_MSG(test, left, right, size, fmt, ...)	       \
> +	KUNIT_MEM_ASSERTION(test,					       \
> +			    KUNIT_EXPECTATION,				       \
> +			    left, ==, right,				       \
> +			    size,					       \
> +			    fmt,					       \
> +			    ##__VA_ARGS__)
> +
> +/**
> + * KUNIT_EXPECT_MEMNEQ() - Expects that the first @size bytes of @left and @right are not equal.
> + * @test: The test context object.
> + * @left: An arbitrary expression that evaluates to the specified size.
> + * @right: An arbitrary expression that evaluates to the specified size.
> + * @size: Number of bytes compared.
> + *
> + * Sets an expectation that the values that @left and @right evaluate to are
> + * not equal. This is semantically equivalent to
> + * KUNIT_EXPECT_TRUE(@test, memcmp((@left), (@right), (@size))). See
> + * KUNIT_EXPECT_TRUE() for more information.
> + */
> +#define KUNIT_EXPECT_MEMNEQ(test, left, right, size) \
> +	KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, NULL)
> +
> +#define KUNIT_EXPECT_MEMNEQ_MSG(test, left, right, size, fmt, ...)	       \
> +	KUNIT_MEM_ASSERTION(test,					       \
> +			    KUNIT_EXPECTATION,				       \
> +			    left, !=, right,				       \
> +			    size,					       \
> +			    fmt,					       \
> +			    ##__VA_ARGS__)
> +
>  /**
>   * KUNIT_EXPECT_NULL() - Expects that @ptr is null.
>   * @test: The test context object.
> diff --git a/lib/kunit/assert.c b/lib/kunit/assert.c
> index d00d6d181ee8..c346a8d7fa6e 100644
> --- a/lib/kunit/assert.c
> +++ b/lib/kunit/assert.c
> @@ -204,3 +204,59 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
> 	kunit_assert_print_msg(message, stream);
>  }
>  EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
> +
> +/* Adds a hexdump of a buffer to a string_stream comparing it with
> + * a second buffer. The different bytes are marked with <>.
> + */
> +static void kunit_assert_hexdump(struct string_stream *stream,
> +				 const void *buf,
> +				 const void *compared_buf,
> +				 const size_t len)
> +{
> +	size_t i;
> +	const u8 *buf1 = buf;
> +	const u8 *buf2 = compared_buf;
> +
> +	string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT);
> +
> +	for (i = 0; i < len; ++i) {
> +		if (!(i % 16) && i)
> +			string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT);
> +
> +		if (buf1[i] != buf2[i])
> +			string_stream_add(stream, "<%02x>", buf1[i]);
> +		else
> +			string_stream_add(stream, " %02x ", buf1[i]);
> +	}
> +}
> +
> +void kunit_mem_assert_format(const struct kunit_assert *assert,
> +			     const struct va_format *message,
> +			     struct string_stream *stream)
> +{
> +	struct kunit_mem_assert *mem_assert;
> +
> +	mem_assert = container_of(assert, struct kunit_mem_assert,
> +				  assert);
> +
> +	string_stream_add(stream,
> +			  KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
> +			  mem_assert->text->left_text,
> +			  mem_assert->text->operation,
> +			  mem_assert->text->right_text);
> +
> +	string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
> +			  mem_assert->text->left_text);
> +	kunit_assert_hexdump(stream, mem_assert->left_value,
> +			     mem_assert->right_value, mem_assert->size);
> +
> +	string_stream_add(stream, "\n");
> +
> +	string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
> +			  mem_assert->text->right_text);
> +	kunit_assert_hexdump(stream, mem_assert->right_value,
> +			     mem_assert->left_value, mem_assert->size);
> +
> +	kunit_assert_print_msg(message, stream);
> +}
> +EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
> --
> 2.37.1
> 

-- 
Muhammad Usama Anjum

  reply	other threads:[~2022-08-06 14:21 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-03 21:58 [PATCH v3 0/3] Introduce KUNIT_EXPECT_MEMEQ and KUNIT_EXPECT_MEMNEQ macros Maíra Canal
2022-08-03 21:58 ` [PATCH v3 1/3] kunit: " Maíra Canal
2022-08-06 14:20   ` Muhammad Usama Anjum [this message]
2022-08-03 21:58 ` [PATCH v3 2/3] kunit: Add KUnit memory block assertions to the example_all_expect_macros_test Maíra Canal
2022-08-03 21:58 ` [PATCH v3 3/3] kunit: Use KUNIT_EXPECT_MEMEQ macro Maíra Canal
2022-08-05  4:44 ` [PATCH v3 0/3] Introduce KUNIT_EXPECT_MEMEQ and KUNIT_EXPECT_MEMNEQ macros David Gow
2022-08-05 12:18   ` Maíra Canal
2022-08-05 22:46     ` David Gow

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1b3298b3-13b5-fbbb-bc8e-f3d0af726d71@collabora.com \
    --to=usama.anjum@collabora.com \
    --cc=airlied@linux.ie \
    --cc=andrealmeid@riseup.net \
    --cc=brendanhiggins@google.com \
    --cc=daniel@ffwll.ch \
    --cc=davem@davemloft.net \
    --cc=davidgow@google.com \
    --cc=dlatypov@google.com \
    --cc=isabbasso@riseup.net \
    --cc=javierm@redhat.com \
    --cc=jose.exposito89@gmail.com \
    --cc=kuba@kernel.org \
    --cc=kunit-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=magalilemes00@gmail.com \
    --cc=mairacanal@riseup.net \
    --cc=melissa.srw@gmail.com \
    --cc=siqueirajordao@riseup.net \
    --cc=tales.aparecida@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).