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_base_assert_format(const struct kunit_assert *assert, 14 struct string_stream *stream) 15 { 16 const char *expect_or_assert = NULL; 17 18 switch (assert->type) { 19 case KUNIT_EXPECTATION: 20 expect_or_assert = "EXPECTATION"; 21 break; 22 case KUNIT_ASSERTION: 23 expect_or_assert = "ASSERTION"; 24 break; 25 } 26 27 string_stream_add(stream, "%s FAILED at %s:%d\n", 28 expect_or_assert, assert->file, assert->line); 29 } 30 EXPORT_SYMBOL_GPL(kunit_base_assert_format); 31 32 void kunit_assert_print_msg(const struct kunit_assert *assert, 33 struct string_stream *stream) 34 { 35 if (assert->message.fmt) 36 string_stream_add(stream, "\n%pV", &assert->message); 37 } 38 EXPORT_SYMBOL_GPL(kunit_assert_print_msg); 39 40 void kunit_fail_assert_format(const struct kunit_assert *assert, 41 struct string_stream *stream) 42 { 43 kunit_base_assert_format(assert, stream); 44 string_stream_add(stream, "%pV", &assert->message); 45 } 46 EXPORT_SYMBOL_GPL(kunit_fail_assert_format); 47 48 void kunit_unary_assert_format(const struct kunit_assert *assert, 49 struct string_stream *stream) 50 { 51 struct kunit_unary_assert *unary_assert; 52 53 unary_assert = container_of(assert, struct kunit_unary_assert, assert); 54 55 kunit_base_assert_format(assert, stream); 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(assert, 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 struct string_stream *stream) 70 { 71 struct kunit_ptr_not_err_assert *ptr_assert; 72 73 ptr_assert = container_of(assert, struct kunit_ptr_not_err_assert, 74 assert); 75 76 kunit_base_assert_format(assert, stream); 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(assert, 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 struct string_stream *stream) 116 { 117 struct kunit_binary_assert *binary_assert; 118 119 binary_assert = container_of(assert, struct kunit_binary_assert, 120 assert); 121 122 kunit_base_assert_format(assert, stream); 123 string_stream_add(stream, 124 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 125 binary_assert->left_text, 126 binary_assert->operation, 127 binary_assert->right_text); 128 if (!is_literal(stream->test, binary_assert->left_text, 129 binary_assert->left_value, stream->gfp)) 130 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld\n", 131 binary_assert->left_text, 132 binary_assert->left_value); 133 if (!is_literal(stream->test, binary_assert->right_text, 134 binary_assert->right_value, stream->gfp)) 135 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %lld", 136 binary_assert->right_text, 137 binary_assert->right_value); 138 kunit_assert_print_msg(assert, stream); 139 } 140 EXPORT_SYMBOL_GPL(kunit_binary_assert_format); 141 142 void kunit_binary_ptr_assert_format(const struct kunit_assert *assert, 143 struct string_stream *stream) 144 { 145 struct kunit_binary_ptr_assert *binary_assert; 146 147 binary_assert = container_of(assert, struct kunit_binary_ptr_assert, 148 assert); 149 150 kunit_base_assert_format(assert, stream); 151 string_stream_add(stream, 152 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 153 binary_assert->left_text, 154 binary_assert->operation, 155 binary_assert->right_text); 156 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px\n", 157 binary_assert->left_text, 158 binary_assert->left_value); 159 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == %px", 160 binary_assert->right_text, 161 binary_assert->right_value); 162 kunit_assert_print_msg(assert, 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 struct string_stream *stream) 184 { 185 struct kunit_binary_str_assert *binary_assert; 186 187 binary_assert = container_of(assert, struct kunit_binary_str_assert, 188 assert); 189 190 kunit_base_assert_format(assert, stream); 191 string_stream_add(stream, 192 KUNIT_SUBTEST_INDENT "Expected %s %s %s, but\n", 193 binary_assert->left_text, 194 binary_assert->operation, 195 binary_assert->right_text); 196 if (!is_str_literal(binary_assert->left_text, binary_assert->left_value)) 197 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"\n", 198 binary_assert->left_text, 199 binary_assert->left_value); 200 if (!is_str_literal(binary_assert->right_text, binary_assert->right_value)) 201 string_stream_add(stream, KUNIT_SUBSUBTEST_INDENT "%s == \"%s\"", 202 binary_assert->right_text, 203 binary_assert->right_value); 204 kunit_assert_print_msg(assert, stream); 205 } 206 EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format); 207