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\n", 131 binary_assert->text->left_text, 132 binary_assert->left_value); 133 if (!is_literal(stream->test, binary_assert->text->right_text, 134 binary_assert->right_value, stream->gfp)) 135 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld", 136 binary_assert->text->right_text, 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