16b229e59SBrendan Higgins // SPDX-License-Identifier: GPL-2.0
26b229e59SBrendan Higgins /*
36b229e59SBrendan Higgins * Assertion and expectation serialization API.
46b229e59SBrendan Higgins *
56b229e59SBrendan Higgins * Copyright (C) 2019, Google LLC.
66b229e59SBrendan Higgins * Author: Brendan Higgins <[email protected]>
76b229e59SBrendan Higgins */
86b229e59SBrendan Higgins #include <kunit/assert.h>
9c3bba690SAlan Maguire #include <kunit/test.h>
10*2c7afc2aSIvan Orlov #include <kunit/visibility.h>
116b229e59SBrendan Higgins
12109fb06fSAlan Maguire #include "string-stream.h"
13109fb06fSAlan Maguire
kunit_assert_prologue(const struct kunit_loc * loc,enum kunit_assert_type type,struct string_stream * stream)1421957f90SDaniel Latypov void kunit_assert_prologue(const struct kunit_loc *loc,
1521957f90SDaniel Latypov enum kunit_assert_type type,
166b229e59SBrendan Higgins struct string_stream *stream)
176b229e59SBrendan Higgins {
186b229e59SBrendan Higgins const char *expect_or_assert = NULL;
196b229e59SBrendan Higgins
2021957f90SDaniel Latypov switch (type) {
216b229e59SBrendan Higgins case KUNIT_EXPECTATION:
226b229e59SBrendan Higgins expect_or_assert = "EXPECTATION";
236b229e59SBrendan Higgins break;
246b229e59SBrendan Higgins case KUNIT_ASSERTION:
256b229e59SBrendan Higgins expect_or_assert = "ASSERTION";
266b229e59SBrendan Higgins break;
276b229e59SBrendan Higgins }
286b229e59SBrendan Higgins
296b229e59SBrendan Higgins string_stream_add(stream, "%s FAILED at %s:%d\n",
3021957f90SDaniel Latypov expect_or_assert, loc->file, loc->line);
316b229e59SBrendan Higgins }
3221957f90SDaniel Latypov EXPORT_SYMBOL_GPL(kunit_assert_prologue);
336b229e59SBrendan Higgins
34*2c7afc2aSIvan Orlov VISIBLE_IF_KUNIT
kunit_assert_print_msg(const struct va_format * message,struct string_stream * stream)35*2c7afc2aSIvan Orlov void kunit_assert_print_msg(const struct va_format *message,
366b229e59SBrendan Higgins struct string_stream *stream)
376b229e59SBrendan Higgins {
386419abb8SDaniel Latypov if (message->fmt)
396419abb8SDaniel Latypov string_stream_add(stream, "\n%pV", message);
406b229e59SBrendan Higgins }
416b229e59SBrendan Higgins
kunit_fail_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)426b229e59SBrendan Higgins void kunit_fail_assert_format(const struct kunit_assert *assert,
436419abb8SDaniel Latypov const struct va_format *message,
446b229e59SBrendan Higgins struct string_stream *stream)
456b229e59SBrendan Higgins {
466419abb8SDaniel Latypov string_stream_add(stream, "%pV", message);
476b229e59SBrendan Higgins }
48c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
496b229e59SBrendan Higgins
kunit_unary_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)506b229e59SBrendan Higgins void kunit_unary_assert_format(const struct kunit_assert *assert,
516419abb8SDaniel Latypov const struct va_format *message,
526b229e59SBrendan Higgins struct string_stream *stream)
536b229e59SBrendan Higgins {
542f9f21cdSLucas Stankus struct kunit_unary_assert *unary_assert;
552f9f21cdSLucas Stankus
562f9f21cdSLucas Stankus unary_assert = container_of(assert, struct kunit_unary_assert, assert);
576b229e59SBrendan Higgins
586b229e59SBrendan Higgins if (unary_assert->expected_true)
596b229e59SBrendan Higgins string_stream_add(stream,
60c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
616b229e59SBrendan Higgins unary_assert->condition);
626b229e59SBrendan Higgins else
636b229e59SBrendan Higgins string_stream_add(stream,
64c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
656b229e59SBrendan Higgins unary_assert->condition);
666419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
676b229e59SBrendan Higgins }
68c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
696b229e59SBrendan Higgins
kunit_ptr_not_err_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)706b229e59SBrendan Higgins void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
716419abb8SDaniel Latypov const struct va_format *message,
726b229e59SBrendan Higgins struct string_stream *stream)
736b229e59SBrendan Higgins {
742f9f21cdSLucas Stankus struct kunit_ptr_not_err_assert *ptr_assert;
752f9f21cdSLucas Stankus
762f9f21cdSLucas Stankus ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
772f9f21cdSLucas Stankus assert);
786b229e59SBrendan Higgins
796b229e59SBrendan Higgins if (!ptr_assert->value) {
806b229e59SBrendan Higgins string_stream_add(stream,
81c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
826b229e59SBrendan Higgins ptr_assert->text);
836b229e59SBrendan Higgins } else if (IS_ERR(ptr_assert->value)) {
846b229e59SBrendan Higgins string_stream_add(stream,
85c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",
866b229e59SBrendan Higgins ptr_assert->text,
876b229e59SBrendan Higgins PTR_ERR(ptr_assert->value));
886b229e59SBrendan Higgins }
896419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
906b229e59SBrendan Higgins }
91c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
926b229e59SBrendan Higgins
9365af9b96SDaniel Latypov /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
is_literal(const char * text,long long value)94*2c7afc2aSIvan Orlov VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)
9565af9b96SDaniel Latypov {
9665af9b96SDaniel Latypov char *buffer;
9765af9b96SDaniel Latypov int len;
9865af9b96SDaniel Latypov bool ret;
9965af9b96SDaniel Latypov
10065af9b96SDaniel Latypov len = snprintf(NULL, 0, "%lld", value);
10165af9b96SDaniel Latypov if (strlen(text) != len)
10265af9b96SDaniel Latypov return false;
10365af9b96SDaniel Latypov
1047b4481cbSRichard Fitzgerald buffer = kmalloc(len+1, GFP_KERNEL);
10565af9b96SDaniel Latypov if (!buffer)
10665af9b96SDaniel Latypov return false;
10765af9b96SDaniel Latypov
10865af9b96SDaniel Latypov snprintf(buffer, len+1, "%lld", value);
10965af9b96SDaniel Latypov ret = strncmp(buffer, text, len) == 0;
11065af9b96SDaniel Latypov
1117b4481cbSRichard Fitzgerald kfree(buffer);
1127b4481cbSRichard Fitzgerald
11365af9b96SDaniel Latypov return ret;
11465af9b96SDaniel Latypov }
11565af9b96SDaniel Latypov
kunit_binary_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)1166b229e59SBrendan Higgins void kunit_binary_assert_format(const struct kunit_assert *assert,
1176419abb8SDaniel Latypov const struct va_format *message,
1186b229e59SBrendan Higgins struct string_stream *stream)
1196b229e59SBrendan Higgins {
1202f9f21cdSLucas Stankus struct kunit_binary_assert *binary_assert;
1212f9f21cdSLucas Stankus
1222f9f21cdSLucas Stankus binary_assert = container_of(assert, struct kunit_binary_assert,
1232f9f21cdSLucas Stankus assert);
1246b229e59SBrendan Higgins
1256b229e59SBrendan Higgins string_stream_add(stream,
126c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
1272b6861e2SDaniel Latypov binary_assert->text->left_text,
1282b6861e2SDaniel Latypov binary_assert->text->operation,
1292b6861e2SDaniel Latypov binary_assert->text->right_text);
1307b4481cbSRichard Fitzgerald if (!is_literal(binary_assert->text->left_text, binary_assert->left_value))
1317b1dd2cfSMark Rutland string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n",
1322b6861e2SDaniel Latypov binary_assert->text->left_text,
1337b1dd2cfSMark Rutland binary_assert->left_value,
1346b229e59SBrendan Higgins binary_assert->left_value);
1357b4481cbSRichard Fitzgerald if (!is_literal(binary_assert->text->right_text, binary_assert->right_value))
1367b1dd2cfSMark Rutland string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)",
1372b6861e2SDaniel Latypov binary_assert->text->right_text,
1387b1dd2cfSMark Rutland binary_assert->right_value,
1396b229e59SBrendan Higgins binary_assert->right_value);
1406419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
1416b229e59SBrendan Higgins }
142c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
1436b229e59SBrendan Higgins
kunit_binary_ptr_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)1446b229e59SBrendan Higgins void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
1456419abb8SDaniel Latypov const struct va_format *message,
1466b229e59SBrendan Higgins struct string_stream *stream)
1476b229e59SBrendan Higgins {
1482f9f21cdSLucas Stankus struct kunit_binary_ptr_assert *binary_assert;
1492f9f21cdSLucas Stankus
1502f9f21cdSLucas Stankus binary_assert = container_of(assert, struct kunit_binary_ptr_assert,
1512f9f21cdSLucas Stankus assert);
1526b229e59SBrendan Higgins
1536b229e59SBrendan Higgins string_stream_add(stream,
154c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
1552b6861e2SDaniel Latypov binary_assert->text->left_text,
1562b6861e2SDaniel Latypov binary_assert->text->operation,
1572b6861e2SDaniel Latypov binary_assert->text->right_text);
158c3bba690SAlan Maguire string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",
1592b6861e2SDaniel Latypov binary_assert->text->left_text,
1606b229e59SBrendan Higgins binary_assert->left_value);
161c3bba690SAlan Maguire string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",
1622b6861e2SDaniel Latypov binary_assert->text->right_text,
1636b229e59SBrendan Higgins binary_assert->right_value);
1646419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
1656b229e59SBrendan Higgins }
166c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
1676b229e59SBrendan Higgins
168acd97625SDaniel Latypov /* Checks if KUNIT_EXPECT_STREQ() args were string literals.
169acd97625SDaniel Latypov * Note: `text` will have ""s where as `value` will not.
170acd97625SDaniel Latypov */
is_str_literal(const char * text,const char * value)171*2c7afc2aSIvan Orlov VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)
172acd97625SDaniel Latypov {
173acd97625SDaniel Latypov int len;
174acd97625SDaniel Latypov
175acd97625SDaniel Latypov len = strlen(text);
176acd97625SDaniel Latypov if (len < 2)
177acd97625SDaniel Latypov return false;
178acd97625SDaniel Latypov if (text[0] != '\"' || text[len - 1] != '\"')
179acd97625SDaniel Latypov return false;
180acd97625SDaniel Latypov
181acd97625SDaniel Latypov return strncmp(text + 1, value, len - 2) == 0;
182acd97625SDaniel Latypov }
183acd97625SDaniel Latypov
kunit_binary_str_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)1846b229e59SBrendan Higgins void kunit_binary_str_assert_format(const struct kunit_assert *assert,
1856419abb8SDaniel Latypov const struct va_format *message,
1866b229e59SBrendan Higgins struct string_stream *stream)
1876b229e59SBrendan Higgins {
1882f9f21cdSLucas Stankus struct kunit_binary_str_assert *binary_assert;
1892f9f21cdSLucas Stankus
1902f9f21cdSLucas Stankus binary_assert = container_of(assert, struct kunit_binary_str_assert,
1912f9f21cdSLucas Stankus assert);
1926b229e59SBrendan Higgins
1936b229e59SBrendan Higgins string_stream_add(stream,
194c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
1952b6861e2SDaniel Latypov binary_assert->text->left_text,
1962b6861e2SDaniel Latypov binary_assert->text->operation,
1972b6861e2SDaniel Latypov binary_assert->text->right_text);
1982b6861e2SDaniel Latypov if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value))
199acd97625SDaniel Latypov string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",
2002b6861e2SDaniel Latypov binary_assert->text->left_text,
2016b229e59SBrendan Higgins binary_assert->left_value);
2022b6861e2SDaniel Latypov if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value))
203acd97625SDaniel Latypov string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",
2042b6861e2SDaniel Latypov binary_assert->text->right_text,
2056b229e59SBrendan Higgins binary_assert->right_value);
2066419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
2076b229e59SBrendan Higgins }
208c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);
209b8a926beSMaíra Canal
210b8a926beSMaíra Canal /* Adds a hexdump of a buffer to a string_stream comparing it with
211b8a926beSMaíra Canal * a second buffer. The different bytes are marked with <>.
212b8a926beSMaíra Canal */
213*2c7afc2aSIvan Orlov VISIBLE_IF_KUNIT
kunit_assert_hexdump(struct string_stream * stream,const void * buf,const void * compared_buf,const size_t len)214*2c7afc2aSIvan Orlov void kunit_assert_hexdump(struct string_stream *stream,
215b8a926beSMaíra Canal const void *buf,
216b8a926beSMaíra Canal const void *compared_buf,
217b8a926beSMaíra Canal const size_t len)
218b8a926beSMaíra Canal {
219b8a926beSMaíra Canal size_t i;
220b8a926beSMaíra Canal const u8 *buf1 = buf;
221b8a926beSMaíra Canal const u8 *buf2 = compared_buf;
222b8a926beSMaíra Canal
223b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT);
224b8a926beSMaíra Canal
225b8a926beSMaíra Canal for (i = 0; i < len; ++i) {
226b8a926beSMaíra Canal if (!(i % 16) && i)
227b8a926beSMaíra Canal string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT);
228b8a926beSMaíra Canal
229b8a926beSMaíra Canal if (buf1[i] != buf2[i])
230b8a926beSMaíra Canal string_stream_add(stream, "<%02x>", buf1[i]);
231b8a926beSMaíra Canal else
232b8a926beSMaíra Canal string_stream_add(stream, " %02x ", buf1[i]);
233b8a926beSMaíra Canal }
234b8a926beSMaíra Canal }
235b8a926beSMaíra Canal
kunit_mem_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)236b8a926beSMaíra Canal void kunit_mem_assert_format(const struct kunit_assert *assert,
237b8a926beSMaíra Canal const struct va_format *message,
238b8a926beSMaíra Canal struct string_stream *stream)
239b8a926beSMaíra Canal {
240b8a926beSMaíra Canal struct kunit_mem_assert *mem_assert;
241b8a926beSMaíra Canal
242b8a926beSMaíra Canal mem_assert = container_of(assert, struct kunit_mem_assert,
243b8a926beSMaíra Canal assert);
244b8a926beSMaíra Canal
245dd2f0a0aSRae Moar if (!mem_assert->left_value) {
246dd2f0a0aSRae Moar string_stream_add(stream,
247dd2f0a0aSRae Moar KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
248dd2f0a0aSRae Moar mem_assert->text->left_text);
249dd2f0a0aSRae Moar } else if (!mem_assert->right_value) {
250dd2f0a0aSRae Moar string_stream_add(stream,
251dd2f0a0aSRae Moar KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
252dd2f0a0aSRae Moar mem_assert->text->right_text);
253dd2f0a0aSRae Moar } else {
254b8a926beSMaíra Canal string_stream_add(stream,
255b8a926beSMaíra Canal KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
256b8a926beSMaíra Canal mem_assert->text->left_text,
257b8a926beSMaíra Canal mem_assert->text->operation,
258b8a926beSMaíra Canal mem_assert->text->right_text);
259b8a926beSMaíra Canal
260b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
261b8a926beSMaíra Canal mem_assert->text->left_text);
262b8a926beSMaíra Canal kunit_assert_hexdump(stream, mem_assert->left_value,
263b8a926beSMaíra Canal mem_assert->right_value, mem_assert->size);
264b8a926beSMaíra Canal
265b8a926beSMaíra Canal string_stream_add(stream, "\n");
266b8a926beSMaíra Canal
267b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
268b8a926beSMaíra Canal mem_assert->text->right_text);
269b8a926beSMaíra Canal kunit_assert_hexdump(stream, mem_assert->right_value,
270b8a926beSMaíra Canal mem_assert->left_value, mem_assert->size);
271b8a926beSMaíra Canal
272b8a926beSMaíra Canal kunit_assert_print_msg(message, stream);
273b8a926beSMaíra Canal }
274dd2f0a0aSRae Moar }
275b8a926beSMaíra Canal EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
276