276 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Assertion and expectation serialization API.4 *5 * Copyright (C) 2019, Google LLC.6 * Author: Brendan Higgins <brendanhiggins@google.com>7 */8#include <kunit/assert.h>9#include <kunit/test.h>10#include <kunit/visibility.h>11 12#include "string-stream.h"13 14void kunit_assert_prologue(const struct kunit_loc *loc,15 enum kunit_assert_type type,16 struct string_stream *stream)17{18 const char *expect_or_assert = NULL;19 20 switch (type) {21 case KUNIT_EXPECTATION:22 expect_or_assert = "EXPECTATION";23 break;24 case KUNIT_ASSERTION:25 expect_or_assert = "ASSERTION";26 break;27 }28 29 string_stream_add(stream, "%s FAILED at %s:%d\n",30 expect_or_assert, loc->file, loc->line);31}32EXPORT_SYMBOL_GPL(kunit_assert_prologue);33 34VISIBLE_IF_KUNIT35void kunit_assert_print_msg(const struct va_format *message,36 struct string_stream *stream)37{38 if (message->fmt)39 string_stream_add(stream, "\n%pV", message);40}41 42void kunit_fail_assert_format(const struct kunit_assert *assert,43 const struct va_format *message,44 struct string_stream *stream)45{46 string_stream_add(stream, "%pV", message);47}48EXPORT_SYMBOL_GPL(kunit_fail_assert_format);49 50void kunit_unary_assert_format(const struct kunit_assert *assert,51 const struct va_format *message,52 struct string_stream *stream)53{54 struct kunit_unary_assert *unary_assert;55 56 unary_assert = container_of(assert, struct kunit_unary_assert, assert);57 58 if (unary_assert->expected_true)59 string_stream_add(stream,60 KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n",61 unary_assert->condition);62 else63 string_stream_add(stream,64 KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n",65 unary_assert->condition);66 kunit_assert_print_msg(message, stream);67}68EXPORT_SYMBOL_GPL(kunit_unary_assert_format);69 70void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,71 const struct va_format *message,72 struct string_stream *stream)73{74 struct kunit_ptr_not_err_assert *ptr_assert;75 76 ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert,77 assert);78 79 if (!ptr_assert->value) {80 string_stream_add(stream,81 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",82 ptr_assert->text);83 } else if (IS_ERR(ptr_assert->value)) {84 string_stream_add(stream,85 KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n",86 ptr_assert->text,87 PTR_ERR(ptr_assert->value));88 }89 kunit_assert_print_msg(message, stream);90}91EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);92 93/* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */94VISIBLE_IF_KUNIT bool is_literal(const char *text, long long value)95{96 char *buffer;97 int len;98 bool ret;99 100 len = snprintf(NULL, 0, "%lld", value);101 if (strlen(text) != len)102 return false;103 104 buffer = kmalloc(len+1, GFP_KERNEL);105 if (!buffer)106 return false;107 108 snprintf(buffer, len+1, "%lld", value);109 ret = strncmp(buffer, text, len) == 0;110 111 kfree(buffer);112 113 return ret;114}115 116void kunit_binary_assert_format(const struct kunit_assert *assert,117 const struct va_format *message,118 struct string_stream *stream)119{120 struct kunit_binary_assert *binary_assert;121 122 binary_assert = container_of(assert, struct kunit_binary_assert,123 assert);124 125 string_stream_add(stream,126 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",127 binary_assert->text->left_text,128 binary_assert->text->operation,129 binary_assert->text->right_text);130 if (!is_literal(binary_assert->text->left_text, binary_assert->left_value))131 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n",132 binary_assert->text->left_text,133 binary_assert->left_value,134 binary_assert->left_value);135 if (!is_literal(binary_assert->text->right_text, binary_assert->right_value))136 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)",137 binary_assert->text->right_text,138 binary_assert->right_value,139 binary_assert->right_value);140 kunit_assert_print_msg(message, stream);141}142EXPORT_SYMBOL_GPL(kunit_binary_assert_format);143 144void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,145 const struct va_format *message,146 struct string_stream *stream)147{148 struct kunit_binary_ptr_assert *binary_assert;149 150 binary_assert = container_of(assert, struct kunit_binary_ptr_assert,151 assert);152 153 string_stream_add(stream,154 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",155 binary_assert->text->left_text,156 binary_assert->text->operation,157 binary_assert->text->right_text);158 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n",159 binary_assert->text->left_text,160 binary_assert->left_value);161 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px",162 binary_assert->text->right_text,163 binary_assert->right_value);164 kunit_assert_print_msg(message, stream);165}166EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);167 168/* Checks if KUNIT_EXPECT_STREQ() args were string literals.169 * Note: `text` will have ""s where as `value` will not.170 */171VISIBLE_IF_KUNIT bool is_str_literal(const char *text, const char *value)172{173 int len;174 175 len = strlen(text);176 if (len < 2)177 return false;178 if (text[0] != '\"' || text[len - 1] != '\"')179 return false;180 181 return strncmp(text + 1, value, len - 2) == 0;182}183 184void kunit_binary_str_assert_format(const struct kunit_assert *assert,185 const struct va_format *message,186 struct string_stream *stream)187{188 struct kunit_binary_str_assert *binary_assert;189 190 binary_assert = container_of(assert, struct kunit_binary_str_assert,191 assert);192 193 string_stream_add(stream,194 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",195 binary_assert->text->left_text,196 binary_assert->text->operation,197 binary_assert->text->right_text);198 if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value))199 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n",200 binary_assert->text->left_text,201 binary_assert->left_value);202 if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value))203 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"",204 binary_assert->text->right_text,205 binary_assert->right_value);206 kunit_assert_print_msg(message, stream);207}208EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);209 210/* Adds a hexdump of a buffer to a string_stream comparing it with211 * a second buffer. The different bytes are marked with <>.212 */213VISIBLE_IF_KUNIT214void kunit_assert_hexdump(struct string_stream *stream,215 const void *buf,216 const void *compared_buf,217 const size_t len)218{219 size_t i;220 const u8 *buf1 = buf;221 const u8 *buf2 = compared_buf;222 223 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT);224 225 for (i = 0; i < len; ++i) {226 if (!(i % 16) && i)227 string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT);228 229 if (buf1[i] != buf2[i])230 string_stream_add(stream, "<%02x>", buf1[i]);231 else232 string_stream_add(stream, " %02x ", buf1[i]);233 }234}235 236void kunit_mem_assert_format(const struct kunit_assert *assert,237 const struct va_format *message,238 struct string_stream *stream)239{240 struct kunit_mem_assert *mem_assert;241 242 mem_assert = container_of(assert, struct kunit_mem_assert,243 assert);244 245 if (!mem_assert->left_value) {246 string_stream_add(stream,247 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",248 mem_assert->text->left_text);249 } else if (!mem_assert->right_value) {250 string_stream_add(stream,251 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n",252 mem_assert->text->right_text);253 } else {254 string_stream_add(stream,255 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n",256 mem_assert->text->left_text,257 mem_assert->text->operation,258 mem_assert->text->right_text);259 260 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",261 mem_assert->text->left_text);262 kunit_assert_hexdump(stream, mem_assert->left_value,263 mem_assert->right_value, mem_assert->size);264 265 string_stream_add(stream, "\n");266 267 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n",268 mem_assert->text->right_text);269 kunit_assert_hexdump(stream, mem_assert->right_value,270 mem_assert->left_value, mem_assert->size);271 272 kunit_assert_print_msg(message, stream);273 }274}275EXPORT_SYMBOL_GPL(kunit_mem_assert_format);276