1 // SPDX-License-Identifier: GPL-2.0 2 /* 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 14 void 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 } 32 EXPORT_SYMBOL_GPL(kunit_assert_prologue); 33 34 VISIBLE_IF_KUNIT 35 void 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 42 void 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 } 48 EXPORT_SYMBOL_GPL(kunit_fail_assert_format); 49 50 void 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 else 63 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 } 68 EXPORT_SYMBOL_GPL(kunit_unary_assert_format); 69 70 void 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 } 91 EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format); 92 93 /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */ 94 VISIBLE_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 116 void 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 } 142 EXPORT_SYMBOL_GPL(kunit_binary_assert_format); 143 144 void 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 } 166 EXPORT_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 */ 171 VISIBLE_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 184 void 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 } 208 EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format); 209 210 /* Adds a hexdump of a buffer to a string_stream comparing it with 211 * a second buffer. The different bytes are marked with <>. 212 */ 213 VISIBLE_IF_KUNIT 214 void 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 else 232 string_stream_add(stream, " %02x ", buf1[i]); 233 } 234 } 235 236 void 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 } 275 EXPORT_SYMBOL_GPL(kunit_mem_assert_format); 276