xref: /linux/lib/kunit/assert_test.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * KUnit test for the assertion formatting functions.
4   * Author: Ivan Orlov <ivan.orlov0322@gmail.com>
5   */
6  #include <kunit/test.h>
7  #include "string-stream.h"
8  
9  #define TEST_PTR_EXPECTED_BUF_SIZE 32
10  #define HEXDUMP_TEST_BUF_LEN 5
11  #define ASSERT_TEST_EXPECT_CONTAIN(test, str, substr) KUNIT_EXPECT_TRUE(test, strstr(str, substr))
12  #define ASSERT_TEST_EXPECT_NCONTAIN(test, str, substr) KUNIT_EXPECT_FALSE(test, strstr(str, substr))
13  
kunit_test_is_literal(struct kunit * test)14  static void kunit_test_is_literal(struct kunit *test)
15  {
16  	KUNIT_EXPECT_TRUE(test, is_literal("5", 5));
17  	KUNIT_EXPECT_TRUE(test, is_literal("0", 0));
18  	KUNIT_EXPECT_TRUE(test, is_literal("1234567890", 1234567890));
19  	KUNIT_EXPECT_TRUE(test, is_literal("-1234567890", -1234567890));
20  	KUNIT_EXPECT_FALSE(test, is_literal("05", 5));
21  	KUNIT_EXPECT_FALSE(test, is_literal("", 0));
22  	KUNIT_EXPECT_FALSE(test, is_literal("-0", 0));
23  	KUNIT_EXPECT_FALSE(test, is_literal("12#45", 1245));
24  }
25  
kunit_test_is_str_literal(struct kunit * test)26  static void kunit_test_is_str_literal(struct kunit *test)
27  {
28  	KUNIT_EXPECT_TRUE(test, is_str_literal("\"Hello, World!\"", "Hello, World!"));
29  	KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"", ""));
30  	KUNIT_EXPECT_TRUE(test, is_str_literal("\"\"\"", "\""));
31  	KUNIT_EXPECT_FALSE(test, is_str_literal("", ""));
32  	KUNIT_EXPECT_FALSE(test, is_str_literal("\"", "\""));
33  	KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba", "Abacaba"));
34  	KUNIT_EXPECT_FALSE(test, is_str_literal("Abacaba\"", "Abacaba"));
35  	KUNIT_EXPECT_FALSE(test, is_str_literal("\"Abacaba\"", "\"Abacaba\""));
36  }
37  
38  KUNIT_DEFINE_ACTION_WRAPPER(kfree_wrapper, kfree, const void *);
39  
40  /* this function is used to get a "char *" string from the string stream and defer its cleanup  */
get_str_from_stream(struct kunit * test,struct string_stream * stream)41  static char *get_str_from_stream(struct kunit *test, struct string_stream *stream)
42  {
43  	char *str = string_stream_get_string(stream);
44  
45  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str);
46  	kunit_add_action(test, kfree_wrapper, (void *)str);
47  
48  	return str;
49  }
50  
kunit_test_assert_prologue(struct kunit * test)51  static void kunit_test_assert_prologue(struct kunit *test)
52  {
53  	struct string_stream *stream;
54  	char *str;
55  	const struct kunit_loc location = {
56  		.file = "testfile.c",
57  		.line = 1337,
58  	};
59  
60  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
61  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
62  
63  	/* Test an expectation fail prologue */
64  	kunit_assert_prologue(&location, KUNIT_EXPECTATION, stream);
65  	str = get_str_from_stream(test, stream);
66  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "EXPECTATION");
67  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
68  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
69  
70  	/* Test an assertion fail prologue */
71  	string_stream_clear(stream);
72  	kunit_assert_prologue(&location, KUNIT_ASSERTION, stream);
73  	str = get_str_from_stream(test, stream);
74  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "ASSERTION");
75  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "testfile.c");
76  	ASSERT_TEST_EXPECT_CONTAIN(test, str, "1337");
77  }
78  
79  /*
80   * This function accepts an arbitrary count of parameters and generates a va_format struct,
81   * which can be used to validate kunit_assert_print_msg function
82   */
verify_assert_print_msg(struct kunit * test,struct string_stream * stream,char * expected,const char * format,...)83  static void verify_assert_print_msg(struct kunit *test,
84  				    struct string_stream *stream,
85  				    char *expected, const char *format, ...)
86  {
87  	va_list list;
88  	const struct va_format vformat = {
89  		.fmt = format,
90  		.va = &list,
91  	};
92  
93  	va_start(list, format);
94  	string_stream_clear(stream);
95  	kunit_assert_print_msg(&vformat, stream);
96  	KUNIT_EXPECT_STREQ(test, get_str_from_stream(test, stream), expected);
97  }
98  
kunit_test_assert_print_msg(struct kunit * test)99  static void kunit_test_assert_print_msg(struct kunit *test)
100  {
101  	struct string_stream *stream;
102  
103  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
104  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
105  
106  	verify_assert_print_msg(test, stream, "\nTest", "Test");
107  	verify_assert_print_msg(test, stream, "\nAbacaba -123 234", "%s %d %u",
108  				"Abacaba", -123, 234U);
109  	verify_assert_print_msg(test, stream, "", NULL);
110  }
111  
112  /*
113   * Further code contains the tests for different assert format functions.
114   * This helper function accepts the assert format function, executes it and
115   * validates the result string from the stream by checking that all of the
116   * substrings exist in the output.
117   */
validate_assert(assert_format_t format_func,struct kunit * test,const struct kunit_assert * assert,struct string_stream * stream,int num_checks,...)118  static void validate_assert(assert_format_t format_func, struct kunit *test,
119  			    const struct kunit_assert *assert,
120  			    struct string_stream *stream, int num_checks, ...)
121  {
122  	size_t i;
123  	va_list checks;
124  	char *cur_substr_exp;
125  	struct va_format message = { NULL, NULL };
126  
127  	va_start(checks, num_checks);
128  	string_stream_clear(stream);
129  	format_func(assert, &message, stream);
130  
131  	for (i = 0; i < num_checks; i++) {
132  		cur_substr_exp = va_arg(checks, char *);
133  		ASSERT_TEST_EXPECT_CONTAIN(test, get_str_from_stream(test, stream), cur_substr_exp);
134  	}
135  }
136  
kunit_test_unary_assert_format(struct kunit * test)137  static void kunit_test_unary_assert_format(struct kunit *test)
138  {
139  	struct string_stream *stream;
140  	struct kunit_assert assert = {};
141  	struct kunit_unary_assert un_assert = {
142  		.assert = assert,
143  		.condition = "expr",
144  		.expected_true = true,
145  	};
146  
147  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
148  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
149  
150  	validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
151  			stream, 2, "true", "is false");
152  
153  	un_assert.expected_true = false;
154  	validate_assert(kunit_unary_assert_format, test, &un_assert.assert,
155  			stream, 2, "false", "is true");
156  }
157  
kunit_test_ptr_not_err_assert_format(struct kunit * test)158  static void kunit_test_ptr_not_err_assert_format(struct kunit *test)
159  {
160  	struct string_stream *stream;
161  	struct kunit_assert assert = {};
162  	struct kunit_ptr_not_err_assert not_err_assert = {
163  		.assert = assert,
164  		.text = "expr",
165  		.value = NULL,
166  	};
167  
168  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
169  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
170  
171  	/* Value is NULL. The corresponding message should be printed out */
172  	validate_assert(kunit_ptr_not_err_assert_format, test,
173  			&not_err_assert.assert,
174  			stream, 1, "null");
175  
176  	/* Value is not NULL, but looks like an error pointer. Error should be printed out */
177  	not_err_assert.value = (void *)-12;
178  	validate_assert(kunit_ptr_not_err_assert_format, test,
179  			&not_err_assert.assert, stream, 2,
180  			"error", "-12");
181  }
182  
kunit_test_binary_assert_format(struct kunit * test)183  static void kunit_test_binary_assert_format(struct kunit *test)
184  {
185  	struct string_stream *stream;
186  	struct kunit_assert assert = {};
187  	struct kunit_binary_assert_text text = {
188  		.left_text = "1 + 2",
189  		.operation = "==",
190  		.right_text = "2",
191  	};
192  	const struct kunit_binary_assert binary_assert = {
193  		.assert = assert,
194  		.text = &text,
195  		.left_value = 3,
196  		.right_value = 2,
197  	};
198  
199  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
200  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
201  
202  	/*
203  	 * Printed values should depend on the input we provide: the left text, right text, left
204  	 * value and the right value.
205  	 */
206  	validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
207  			stream, 4, "1 + 2", "2", "3", "==");
208  
209  	text.right_text = "4 - 2";
210  	validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
211  			stream, 3, "==", "1 + 2", "4 - 2");
212  
213  	text.left_text = "3";
214  	validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
215  			stream, 4, "3", "4 - 2", "2", "==");
216  
217  	text.right_text = "2";
218  	validate_assert(kunit_binary_assert_format, test, &binary_assert.assert,
219  			stream, 3, "3", "2", "==");
220  }
221  
kunit_test_binary_ptr_assert_format(struct kunit * test)222  static void kunit_test_binary_ptr_assert_format(struct kunit *test)
223  {
224  	struct string_stream *stream;
225  	struct kunit_assert assert = {};
226  	char *addr_var_a, *addr_var_b;
227  	static const void *var_a = (void *)0xDEADBEEF;
228  	static const void *var_b = (void *)0xBADDCAFE;
229  	struct kunit_binary_assert_text text = {
230  		.left_text = "var_a",
231  		.operation = "==",
232  		.right_text = "var_b",
233  	};
234  	struct kunit_binary_ptr_assert binary_ptr_assert = {
235  		.assert = assert,
236  		.text = &text,
237  		.left_value = var_a,
238  		.right_value = var_b,
239  	};
240  
241  	addr_var_a = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
242  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_a);
243  	addr_var_b = kunit_kzalloc(test, TEST_PTR_EXPECTED_BUF_SIZE, GFP_KERNEL);
244  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, addr_var_b);
245  	/*
246  	 * Print the addresses to the buffers first.
247  	 * This is necessary as we may have different count of leading zeros in the pointer
248  	 * on different architectures.
249  	 */
250  	snprintf(addr_var_a, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_a);
251  	snprintf(addr_var_b, TEST_PTR_EXPECTED_BUF_SIZE, "%px", var_b);
252  
253  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
254  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
255  	validate_assert(kunit_binary_ptr_assert_format, test, &binary_ptr_assert.assert,
256  			stream, 3, addr_var_a, addr_var_b, "==");
257  }
258  
kunit_test_binary_str_assert_format(struct kunit * test)259  static void kunit_test_binary_str_assert_format(struct kunit *test)
260  {
261  	struct string_stream *stream;
262  	struct kunit_assert assert = {};
263  	static const char *var_a = "abacaba";
264  	static const char *var_b = "kernel";
265  	struct kunit_binary_assert_text text = {
266  		.left_text = "var_a",
267  		.operation = "==",
268  		.right_text = "var_b",
269  	};
270  	struct kunit_binary_str_assert binary_str_assert = {
271  		.assert = assert,
272  		.text = &text,
273  		.left_value = var_a,
274  		.right_value = var_b,
275  	};
276  
277  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
278  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
279  
280  	validate_assert(kunit_binary_str_assert_format, test,
281  			&binary_str_assert.assert,
282  			stream, 5, "var_a", "var_b", "\"abacaba\"",
283  			"\"kernel\"", "==");
284  
285  	text.left_text = "\"abacaba\"";
286  	validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
287  			stream, 4, "\"abacaba\"", "var_b", "\"kernel\"", "==");
288  
289  	text.right_text = "\"kernel\"";
290  	validate_assert(kunit_binary_str_assert_format, test, &binary_str_assert.assert,
291  			stream, 3, "\"abacaba\"", "\"kernel\"", "==");
292  }
293  
294  static const u8 hex_testbuf1[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
295  				   0x45, 0x9d, 0x47, 0xd6, 0x47,
296  				   0x2,  0x89, 0x8c, 0x81, 0x94,
297  				   0x12, 0xfe, 0x01 };
298  static const u8 hex_testbuf2[] = { 0x26, 0x74, 0x6b, 0x9c, 0x55,
299  				   0x45, 0x9d, 0x47, 0x21, 0x47,
300  				   0xcd, 0x89, 0x24, 0x50, 0x94,
301  				   0x12, 0xba, 0x01 };
kunit_test_assert_hexdump(struct kunit * test)302  static void kunit_test_assert_hexdump(struct kunit *test)
303  {
304  	struct string_stream *stream;
305  	char *str;
306  	size_t i;
307  	char buf[HEXDUMP_TEST_BUF_LEN];
308  
309  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
310  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
311  	/* Check that we are getting output like <xx> for non-matching numbers. */
312  	kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf2, sizeof(hex_testbuf1));
313  	str = get_str_from_stream(test, stream);
314  	for (i = 0; i < sizeof(hex_testbuf1); i++) {
315  		snprintf(buf, HEXDUMP_TEST_BUF_LEN, "<%02x>", hex_testbuf1[i]);
316  		if (hex_testbuf1[i] != hex_testbuf2[i])
317  			ASSERT_TEST_EXPECT_CONTAIN(test, str, buf);
318  	}
319  	/* We shouldn't get any <xx> numbers when comparing the buffer with itself. */
320  	string_stream_clear(stream);
321  	kunit_assert_hexdump(stream, hex_testbuf1, hex_testbuf1, sizeof(hex_testbuf1));
322  	str = get_str_from_stream(test, stream);
323  	ASSERT_TEST_EXPECT_NCONTAIN(test, str, "<");
324  	ASSERT_TEST_EXPECT_NCONTAIN(test, str, ">");
325  }
326  
kunit_test_mem_assert_format(struct kunit * test)327  static void kunit_test_mem_assert_format(struct kunit *test)
328  {
329  	struct string_stream *stream;
330  	struct string_stream *expected_stream;
331  	struct kunit_assert assert = {};
332  	static const struct kunit_binary_assert_text text = {
333  		.left_text = "hex_testbuf1",
334  		.operation = "==",
335  		.right_text = "hex_testbuf2",
336  	};
337  	struct kunit_mem_assert mem_assert = {
338  		.assert = assert,
339  		.text = &text,
340  		.left_value = NULL,
341  		.right_value = hex_testbuf2,
342  		.size = sizeof(hex_testbuf1),
343  	};
344  
345  	expected_stream = kunit_alloc_string_stream(test, GFP_KERNEL);
346  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_stream);
347  	stream = kunit_alloc_string_stream(test, GFP_KERNEL);
348  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
349  
350  	/* The left value is NULL */
351  	validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
352  			stream, 2, "hex_testbuf1", "is not null");
353  
354  	/* The right value is NULL, the left value is not NULL */
355  	mem_assert.left_value = hex_testbuf1;
356  	mem_assert.right_value = NULL;
357  	validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
358  			stream, 2, "hex_testbuf2", "is not null");
359  
360  	/* Both arguments are not null */
361  	mem_assert.left_value = hex_testbuf1;
362  	mem_assert.right_value = hex_testbuf2;
363  
364  	validate_assert(kunit_mem_assert_format, test, &mem_assert.assert,
365  			stream, 3, "hex_testbuf1", "hex_testbuf2", "==");
366  }
367  
368  static struct kunit_case assert_test_cases[] = {
369  	KUNIT_CASE(kunit_test_is_literal),
370  	KUNIT_CASE(kunit_test_is_str_literal),
371  	KUNIT_CASE(kunit_test_assert_prologue),
372  	KUNIT_CASE(kunit_test_assert_print_msg),
373  	KUNIT_CASE(kunit_test_unary_assert_format),
374  	KUNIT_CASE(kunit_test_ptr_not_err_assert_format),
375  	KUNIT_CASE(kunit_test_binary_assert_format),
376  	KUNIT_CASE(kunit_test_binary_ptr_assert_format),
377  	KUNIT_CASE(kunit_test_binary_str_assert_format),
378  	KUNIT_CASE(kunit_test_assert_hexdump),
379  	KUNIT_CASE(kunit_test_mem_assert_format),
380  	{}
381  };
382  
383  static struct kunit_suite assert_test_suite = {
384  	.name = "kunit-assert",
385  	.test_cases = assert_test_cases,
386  };
387  
388  kunit_test_suites(&assert_test_suite);
389