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 11 #include "string-stream.h" 12 13 void kunit_assert_prologue(const struct kunit_loc *loc, 14 enum kunit_assert_type type, 15 struct string_stream *stream) 16 { 17 const char *expect_or_assert = NULL; 18 19 switch (type) { 20 case KUNIT_EXPECTATION: 21 expect_or_assert = "EXPECTATION"; 22 break; 23 case KUNIT_ASSERTION: 24 expect_or_assert = "ASSERTION"; 25 break; 26 } 27 28 string_stream_add(stream, "%s FAILED at %s:%d\n", 29 expect_or_assert, loc->file, loc->line); 30 } 31 EXPORT_SYMBOL_GPL(kunit_assert_prologue); 32 33 static void kunit_assert_print_msg(const struct va_format *message, 34 struct string_stream *stream) 35 { 36 if (message->fmt) 37 string_stream_add(stream, "\n%pV", message); 38 } 39 40 void kunit_fail_assert_format(const struct kunit_assert *assert, 41 const struct va_format *message, 42 struct string_stream *stream) 43 { 44 string_stream_add(stream, "%pV", message); 45 } 46 EXPORT_SYMBOL_GPL(kunit_fail_assert_format); 47 48 void kunit_unary_assert_format(const struct kunit_assert *assert, 49 const struct va_format *message, 50 struct string_stream *stream) 51 { 52 struct kunit_unary_assert *unary_assert; 53 54 unary_assert = container_of(assert, struct kunit_unary_assert, assert); 55 56 if (unary_assert->expected_true) 57 string_stream_add(stream, 58 KUNIT_SUBTEST_INDENT "Expected %s to be true, but is false\n", 59 unary_assert->condition); 60 else 61 string_stream_add(stream, 62 KUNIT_SUBTEST_INDENT "Expected %s to be false, but is true\n", 63 unary_assert->condition); 64 kunit_assert_print_msg(message, stream); 65 } 66 EXPORT_SYMBOL_GPL(kunit_unary_assert_format); 67 68 void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert, 69 const struct va_format *message, 70 struct string_stream *stream) 71 { 72 struct kunit_ptr_not_err_assert *ptr_assert; 73 74 ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert, 75 assert); 76 77 if (!ptr_assert->value) { 78 string_stream_add(stream, 79 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n", 80 ptr_assert->text); 81 } else if (IS_ERR(ptr_assert->value)) { 82 string_stream_add(stream, 83 KUNIT_SUBTEST_INDENT "Expected %s is not error, but is: %ld\n", 84 ptr_assert->text, 85 PTR_ERR(ptr_assert->value)); 86 } 87 kunit_assert_print_msg(message, stream); 88 } 89 EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format); 90 91 /* Checks if `text` is a literal representing `value`, e.g. "5" and 5 */ 92 static bool is_literal(struct kunit *test, const char *text, long long value, 93 gfp_t gfp) 94 { 95 char *buffer; 96 int len; 97 bool ret; 98 99 len = snprintf(NULL, 0, "%lld", value); 100 if (strlen(text) != len) 101 return false; 102 103 buffer = kunit_kmalloc(test, len+1, gfp); 104 if (!buffer) 105 return false; 106 107 snprintf(buffer, len+1, "%lld", value); 108 ret = strncmp(buffer, text, len) == 0; 109 110 kunit_kfree(test, buffer); 111 return ret; 112 } 113 114 void kunit_binary_assert_format(const struct kunit_assert *assert, 115 const struct va_format *message, 116 struct string_stream *stream) 117 { 118 struct kunit_binary_assert *binary_assert; 119 120 binary_assert = container_of(assert, struct kunit_binary_assert, 121 assert); 122 123 string_stream_add(stream, 124 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 125 binary_assert->text->left_text, 126 binary_assert->text->operation, 127 binary_assert->text->right_text); 128 if (!is_literal(stream->test, binary_assert->text->left_text, 129 binary_assert->left_value, stream->gfp)) 130 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n", 131 binary_assert->text->left_text, 132 binary_assert->left_value, 133 binary_assert->left_value); 134 if (!is_literal(stream->test, binary_assert->text->right_text, 135 binary_assert->right_value, stream->gfp)) 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 static 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 static void kunit_assert_hexdump(struct string_stream *stream, 214 const void *buf, 215 const void *compared_buf, 216 const size_t len) 217 { 218 size_t i; 219 const u8 *buf1 = buf; 220 const u8 *buf2 = compared_buf; 221 222 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT); 223 224 for (i = 0; i < len; ++i) { 225 if (!(i % 16) && i) 226 string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT); 227 228 if (buf1[i] != buf2[i]) 229 string_stream_add(stream, "<%02x>", buf1[i]); 230 else 231 string_stream_add(stream, " %02x ", buf1[i]); 232 } 233 } 234 235 void kunit_mem_assert_format(const struct kunit_assert *assert, 236 const struct va_format *message, 237 struct string_stream *stream) 238 { 239 struct kunit_mem_assert *mem_assert; 240 241 mem_assert = container_of(assert, struct kunit_mem_assert, 242 assert); 243 244 if (!mem_assert->left_value) { 245 string_stream_add(stream, 246 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n", 247 mem_assert->text->left_text); 248 } else if (!mem_assert->right_value) { 249 string_stream_add(stream, 250 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n", 251 mem_assert->text->right_text); 252 } else { 253 string_stream_add(stream, 254 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 255 mem_assert->text->left_text, 256 mem_assert->text->operation, 257 mem_assert->text->right_text); 258 259 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 260 mem_assert->text->left_text); 261 kunit_assert_hexdump(stream, mem_assert->left_value, 262 mem_assert->right_value, mem_assert->size); 263 264 string_stream_add(stream, "\n"); 265 266 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 267 mem_assert->text->right_text); 268 kunit_assert_hexdump(stream, mem_assert->right_value, 269 mem_assert->left_value, mem_assert->size); 270 271 kunit_assert_print_msg(message, stream); 272 } 273 } 274 EXPORT_SYMBOL_GPL(kunit_mem_assert_format); 275