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 <brendanhiggins@google.com>
76b229e59SBrendan Higgins */
86b229e59SBrendan Higgins #include <kunit/assert.h>
9c3bba690SAlan Maguire #include <kunit/test.h>
106b229e59SBrendan Higgins
11109fb06fSAlan Maguire #include "string-stream.h"
12109fb06fSAlan Maguire
kunit_assert_prologue(const struct kunit_loc * loc,enum kunit_assert_type type,struct string_stream * stream)1321957f90SDaniel Latypov void kunit_assert_prologue(const struct kunit_loc *loc,
1421957f90SDaniel Latypov enum kunit_assert_type type,
156b229e59SBrendan Higgins struct string_stream *stream)
166b229e59SBrendan Higgins {
176b229e59SBrendan Higgins const char *expect_or_assert = NULL;
186b229e59SBrendan Higgins
1921957f90SDaniel Latypov switch (type) {
206b229e59SBrendan Higgins case KUNIT_EXPECTATION:
216b229e59SBrendan Higgins expect_or_assert = "EXPECTATION";
226b229e59SBrendan Higgins break;
236b229e59SBrendan Higgins case KUNIT_ASSERTION:
246b229e59SBrendan Higgins expect_or_assert = "ASSERTION";
256b229e59SBrendan Higgins break;
266b229e59SBrendan Higgins }
276b229e59SBrendan Higgins
286b229e59SBrendan Higgins string_stream_add(stream, "%s FAILED at %s:%d\n",
2921957f90SDaniel Latypov expect_or_assert, loc->file, loc->line);
306b229e59SBrendan Higgins }
3121957f90SDaniel Latypov EXPORT_SYMBOL_GPL(kunit_assert_prologue);
326b229e59SBrendan Higgins
kunit_assert_print_msg(const struct va_format * message,struct string_stream * stream)336419abb8SDaniel Latypov static void kunit_assert_print_msg(const struct va_format *message,
346b229e59SBrendan Higgins struct string_stream *stream)
356b229e59SBrendan Higgins {
366419abb8SDaniel Latypov if (message->fmt)
376419abb8SDaniel Latypov string_stream_add(stream, "\n%pV", message);
386b229e59SBrendan Higgins }
396b229e59SBrendan Higgins
kunit_fail_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)406b229e59SBrendan Higgins void kunit_fail_assert_format(const struct kunit_assert *assert,
416419abb8SDaniel Latypov const struct va_format *message,
426b229e59SBrendan Higgins struct string_stream *stream)
436b229e59SBrendan Higgins {
446419abb8SDaniel Latypov string_stream_add(stream, "%pV", message);
456b229e59SBrendan Higgins }
46c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
476b229e59SBrendan Higgins
kunit_unary_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)486b229e59SBrendan Higgins void kunit_unary_assert_format(const struct kunit_assert *assert,
496419abb8SDaniel Latypov const struct va_format *message,
506b229e59SBrendan Higgins struct string_stream *stream)
516b229e59SBrendan Higgins {
522f9f21cdSLucas Stankus struct kunit_unary_assert *unary_assert;
532f9f21cdSLucas Stankus
542f9f21cdSLucas Stankus unary_assert = container_of(assert, struct kunit_unary_assert, assert);
556b229e59SBrendan Higgins
566b229e59SBrendan Higgins if (unary_assert->expected_true)
576b229e59SBrendan Higgins string_stream_add(stream,
58c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",
596b229e59SBrendan Higgins unary_assert->condition);
606b229e59SBrendan Higgins else
616b229e59SBrendan Higgins string_stream_add(stream,
62c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",
636b229e59SBrendan Higgins unary_assert->condition);
646419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
656b229e59SBrendan Higgins }
66c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
676b229e59SBrendan Higgins
kunit_ptr_not_err_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)686b229e59SBrendan Higgins void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
696419abb8SDaniel Latypov const struct va_format *message,
706b229e59SBrendan Higgins struct string_stream *stream)
716b229e59SBrendan Higgins {
722f9f21cdSLucas Stankus struct kunit_ptr_not_err_assert *ptr_assert;
732f9f21cdSLucas Stankus
742f9f21cdSLucas Stankus ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,
752f9f21cdSLucas Stankus assert);
766b229e59SBrendan Higgins
776b229e59SBrendan Higgins if (!ptr_assert->value) {
786b229e59SBrendan Higgins string_stream_add(stream,
79c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
806b229e59SBrendan Higgins ptr_assert->text);
816b229e59SBrendan Higgins } else if (IS_ERR(ptr_assert->value)) {
826b229e59SBrendan Higgins string_stream_add(stream,
83c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",
846b229e59SBrendan Higgins ptr_assert->text,
856b229e59SBrendan Higgins PTR_ERR(ptr_assert->value));
866b229e59SBrendan Higgins }
876419abb8SDaniel Latypov kunit_assert_print_msg(message, stream);
886b229e59SBrendan Higgins }
89c475c77dSAlan Maguire EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
906b229e59SBrendan Higgins
9165af9b96SDaniel Latypov /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */
is_literal(struct kunit * test,const char * text,long long value,gfp_t gfp)9265af9b96SDaniel Latypov static bool is_literal(struct kunit *test, const char *text, long long value,
9365af9b96SDaniel Latypov gfp_t gfp)
9465af9b96SDaniel Latypov {
9565af9b96SDaniel Latypov char *buffer;
9665af9b96SDaniel Latypov int len;
9765af9b96SDaniel Latypov bool ret;
9865af9b96SDaniel Latypov
9965af9b96SDaniel Latypov len = snprintf(NULL, 0, "%lld", value);
10065af9b96SDaniel Latypov if (strlen(text) != len)
10165af9b96SDaniel Latypov return false;
10265af9b96SDaniel Latypov
10365af9b96SDaniel Latypov buffer = kunit_kmalloc(test, len+1, gfp);
10465af9b96SDaniel Latypov if (!buffer)
10565af9b96SDaniel Latypov return false;
10665af9b96SDaniel Latypov
10765af9b96SDaniel Latypov snprintf(buffer, len+1, "%lld", value);
10865af9b96SDaniel Latypov ret = strncmp(buffer, text, len) == 0;
10965af9b96SDaniel Latypov
11065af9b96SDaniel Latypov kunit_kfree(test, buffer);
11165af9b96SDaniel Latypov return ret;
11265af9b96SDaniel Latypov }
11365af9b96SDaniel Latypov
kunit_binary_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)1146b229e59SBrendan Higgins void kunit_binary_assert_format(const struct kunit_assert *assert,
1156419abb8SDaniel Latypov const struct va_format *message,
1166b229e59SBrendan Higgins struct string_stream *stream)
1176b229e59SBrendan Higgins {
1182f9f21cdSLucas Stankus struct kunit_binary_assert *binary_assert;
1192f9f21cdSLucas Stankus
1202f9f21cdSLucas Stankus binary_assert = container_of(assert, struct kunit_binary_assert,
1212f9f21cdSLucas Stankus assert);
1226b229e59SBrendan Higgins
1236b229e59SBrendan Higgins string_stream_add(stream,
124c3bba690SAlan Maguire KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
1252b6861e2SDaniel Latypov binary_assert->text->left_text,
1262b6861e2SDaniel Latypov binary_assert->text->operation,
1272b6861e2SDaniel Latypov binary_assert->text->right_text);
1282b6861e2SDaniel Latypov if (!is_literal(stream->test, binary_assert->text->left_text,
12965af9b96SDaniel Latypov binary_assert->left_value, stream->gfp))
1307b1dd2cfSMark Rutland string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n",
1312b6861e2SDaniel Latypov binary_assert->text->left_text,
1327b1dd2cfSMark Rutland binary_assert->left_value,
1336b229e59SBrendan Higgins binary_assert->left_value);
1342b6861e2SDaniel Latypov if (!is_literal(stream->test, binary_assert->text->right_text,
13565af9b96SDaniel Latypov binary_assert->right_value, stream->gfp))
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)171acd97625SDaniel Latypov static 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 */
kunit_assert_hexdump(struct string_stream * stream,const void * buf,const void * compared_buf,const size_t len)213b8a926beSMaíra Canal static void kunit_assert_hexdump(struct string_stream *stream,
214b8a926beSMaíra Canal const void *buf,
215b8a926beSMaíra Canal const void *compared_buf,
216b8a926beSMaíra Canal const size_t len)
217b8a926beSMaíra Canal {
218b8a926beSMaíra Canal size_t i;
219b8a926beSMaíra Canal const u8 *buf1 = buf;
220b8a926beSMaíra Canal const u8 *buf2 = compared_buf;
221b8a926beSMaíra Canal
222b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT);
223b8a926beSMaíra Canal
224b8a926beSMaíra Canal for (i = 0; i < len; ++i) {
225b8a926beSMaíra Canal if (!(i % 16) && i)
226b8a926beSMaíra Canal string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT);
227b8a926beSMaíra Canal
228b8a926beSMaíra Canal if (buf1[i] != buf2[i])
229b8a926beSMaíra Canal string_stream_add(stream, "<%02x>", buf1[i]);
230b8a926beSMaíra Canal else
231b8a926beSMaíra Canal string_stream_add(stream, " %02x ", buf1[i]);
232b8a926beSMaíra Canal }
233b8a926beSMaíra Canal }
234b8a926beSMaíra Canal
kunit_mem_assert_format(const struct kunit_assert * assert,const struct va_format * message,struct string_stream * stream)235b8a926beSMaíra Canal void kunit_mem_assert_format(const struct kunit_assert *assert,
236b8a926beSMaíra Canal const struct va_format *message,
237b8a926beSMaíra Canal struct string_stream *stream)
238b8a926beSMaíra Canal {
239b8a926beSMaíra Canal struct kunit_mem_assert *mem_assert;
240b8a926beSMaíra Canal
241b8a926beSMaíra Canal mem_assert = container_of(assert, struct kunit_mem_assert,
242b8a926beSMaíra Canal assert);
243b8a926beSMaíra Canal
244*dd2f0a0aSRae Moar if (!mem_assert->left_value) {
245*dd2f0a0aSRae Moar string_stream_add(stream,
246*dd2f0a0aSRae Moar KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
247*dd2f0a0aSRae Moar mem_assert->text->left_text);
248*dd2f0a0aSRae Moar } else if (!mem_assert->right_value) {
249*dd2f0a0aSRae Moar string_stream_add(stream,
250*dd2f0a0aSRae Moar KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",
251*dd2f0a0aSRae Moar mem_assert->text->right_text);
252*dd2f0a0aSRae Moar } else {
253b8a926beSMaíra Canal string_stream_add(stream,
254b8a926beSMaíra Canal KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",
255b8a926beSMaíra Canal mem_assert->text->left_text,
256b8a926beSMaíra Canal mem_assert->text->operation,
257b8a926beSMaíra Canal mem_assert->text->right_text);
258b8a926beSMaíra Canal
259b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
260b8a926beSMaíra Canal mem_assert->text->left_text);
261b8a926beSMaíra Canal kunit_assert_hexdump(stream, mem_assert->left_value,
262b8a926beSMaíra Canal mem_assert->right_value, mem_assert->size);
263b8a926beSMaíra Canal
264b8a926beSMaíra Canal string_stream_add(stream, "\n");
265b8a926beSMaíra Canal
266b8a926beSMaíra Canal string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",
267b8a926beSMaíra Canal mem_assert->text->right_text);
268b8a926beSMaíra Canal kunit_assert_hexdump(stream, mem_assert->right_value,
269b8a926beSMaíra Canal mem_assert->left_value, mem_assert->size);
270b8a926beSMaíra Canal
271b8a926beSMaíra Canal kunit_assert_print_msg(message, stream);
272b8a926beSMaíra Canal }
273*dd2f0a0aSRae Moar }
274b8a926beSMaíra Canal EXPORT_SYMBOL_GPL(kunit_mem_assert_format);
275