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(const char *text, long long value) 93 { 94 char *buffer; 95 int len; 96 bool ret; 97 98 len = snprintf(NULL, 0, "%lld", value); 99 if (strlen(text) != len) 100 return false; 101 102 buffer = kmalloc(len+1, GFP_KERNEL); 103 if (!buffer) 104 return false; 105 106 snprintf(buffer, len+1, "%lld", value); 107 ret = strncmp(buffer, text, len) == 0; 108 109 kfree(buffer); 110 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(binary_assert->text->left_text, binary_assert->left_value)) 129 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)\n", 130 binary_assert->text->left_text, 131 binary_assert->left_value, 132 binary_assert->left_value); 133 if (!is_literal(binary_assert->text->right_text, binary_assert->right_value)) 134 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld (0x%llx)", 135 binary_assert->text->right_text, 136 binary_assert->right_value, 137 binary_assert->right_value); 138 kunit_assert_print_msg(message, stream); 139 } 140 EXPORT_SYMBOL_GPL(kunit_binary_assert_format); 141 142 void kunit_binary_ptr_assert_format(const struct kunit_assert *assert, 143 const struct va_format *message, 144 struct string_stream *stream) 145 { 146 struct kunit_binary_ptr_assert *binary_assert; 147 148 binary_assert = container_of(assert, struct kunit_binary_ptr_assert, 149 assert); 150 151 string_stream_add(stream, 152 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 153 binary_assert->text->left_text, 154 binary_assert->text->operation, 155 binary_assert->text->right_text); 156 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n", 157 binary_assert->text->left_text, 158 binary_assert->left_value); 159 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px", 160 binary_assert->text->right_text, 161 binary_assert->right_value); 162 kunit_assert_print_msg(message, stream); 163 } 164 EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format); 165 166 /* Checks if KUNIT_EXPECT_STREQ() args were string literals. 167 * Note: `text` will have ""s where as `value` will not. 168 */ 169 static bool is_str_literal(const char *text, const char *value) 170 { 171 int len; 172 173 len = strlen(text); 174 if (len < 2) 175 return false; 176 if (text[0] != '\"' || text[len - 1] != '\"') 177 return false; 178 179 return strncmp(text + 1, value, len - 2) == 0; 180 } 181 182 void kunit_binary_str_assert_format(const struct kunit_assert *assert, 183 const struct va_format *message, 184 struct string_stream *stream) 185 { 186 struct kunit_binary_str_assert *binary_assert; 187 188 binary_assert = container_of(assert, struct kunit_binary_str_assert, 189 assert); 190 191 string_stream_add(stream, 192 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 193 binary_assert->text->left_text, 194 binary_assert->text->operation, 195 binary_assert->text->right_text); 196 if (!is_str_literal(binary_assert->text->left_text, binary_assert->left_value)) 197 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n", 198 binary_assert->text->left_text, 199 binary_assert->left_value); 200 if (!is_str_literal(binary_assert->text->right_text, binary_assert->right_value)) 201 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"", 202 binary_assert->text->right_text, 203 binary_assert->right_value); 204 kunit_assert_print_msg(message, stream); 205 } 206 EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format); 207 208 /* Adds a hexdump of a buffer to a string_stream comparing it with 209 * a second buffer. The different bytes are marked with <>. 210 */ 211 static void kunit_assert_hexdump(struct string_stream *stream, 212 const void *buf, 213 const void *compared_buf, 214 const size_t len) 215 { 216 size_t i; 217 const u8 *buf1 = buf; 218 const u8 *buf2 = compared_buf; 219 220 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT); 221 222 for (i = 0; i < len; ++i) { 223 if (!(i % 16) && i) 224 string_stream_add(stream, "\n" KUNIT_SUBSUBTEST_INDENT); 225 226 if (buf1[i] != buf2[i]) 227 string_stream_add(stream, "<%02x>", buf1[i]); 228 else 229 string_stream_add(stream, " %02x ", buf1[i]); 230 } 231 } 232 233 void kunit_mem_assert_format(const struct kunit_assert *assert, 234 const struct va_format *message, 235 struct string_stream *stream) 236 { 237 struct kunit_mem_assert *mem_assert; 238 239 mem_assert = container_of(assert, struct kunit_mem_assert, 240 assert); 241 242 if (!mem_assert->left_value) { 243 string_stream_add(stream, 244 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n", 245 mem_assert->text->left_text); 246 } else if (!mem_assert->right_value) { 247 string_stream_add(stream, 248 KUNIT_SUBTEST_INDENT "Expected %s is not null, but is\n", 249 mem_assert->text->right_text); 250 } else { 251 string_stream_add(stream, 252 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 253 mem_assert->text->left_text, 254 mem_assert->text->operation, 255 mem_assert->text->right_text); 256 257 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 258 mem_assert->text->left_text); 259 kunit_assert_hexdump(stream, mem_assert->left_value, 260 mem_assert->right_value, mem_assert->size); 261 262 string_stream_add(stream, "\n"); 263 264 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s ==\n", 265 mem_assert->text->right_text); 266 kunit_assert_hexdump(stream, mem_assert->right_value, 267 mem_assert->left_value, mem_assert->size); 268 269 kunit_assert_print_msg(message, stream); 270 } 271 } 272 EXPORT_SYMBOL_GPL(kunit_mem_assert_format); 273