1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * KUnit test for struct string_stream. |
4 | * |
5 | * Copyright (C) 2019, Google LLC. |
6 | * Author: Brendan Higgins <brendanhiggins@google.com> |
7 | */ |
8 | |
9 | #include <kunit/static_stub.h> |
10 | #include <kunit/test.h> |
11 | #include <linux/ktime.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/timekeeping.h> |
14 | |
15 | #include "string-stream.h" |
16 | |
17 | struct string_stream_test_priv { |
18 | /* For testing resource-managed free. */ |
19 | struct string_stream *expected_free_stream; |
20 | bool stream_was_freed; |
21 | bool stream_free_again; |
22 | }; |
23 | |
24 | /* Avoids a cast warning if kfree() is passed direct to kunit_add_action(). */ |
25 | static void kfree_wrapper(void *p) |
26 | { |
27 | kfree(objp: p); |
28 | } |
29 | |
30 | /* Avoids a cast warning if string_stream_destroy() is passed direct to kunit_add_action(). */ |
31 | static void cleanup_raw_stream(void *p) |
32 | { |
33 | struct string_stream *stream = p; |
34 | |
35 | string_stream_destroy(stream); |
36 | } |
37 | |
38 | static char *get_concatenated_string(struct kunit *test, struct string_stream *stream) |
39 | { |
40 | char *str = string_stream_get_string(stream); |
41 | |
42 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, str); |
43 | kunit_add_action(test, action: kfree_wrapper, ctx: (void *)str); |
44 | |
45 | return str; |
46 | } |
47 | |
48 | /* Managed string_stream object is initialized correctly. */ |
49 | static void string_stream_managed_init_test(struct kunit *test) |
50 | { |
51 | struct string_stream *stream; |
52 | |
53 | /* Resource-managed initialization. */ |
54 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
55 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
56 | |
57 | KUNIT_EXPECT_EQ(test, stream->length, 0); |
58 | KUNIT_EXPECT_TRUE(test, list_empty(&stream->fragments)); |
59 | KUNIT_EXPECT_TRUE(test, (stream->gfp == GFP_KERNEL)); |
60 | KUNIT_EXPECT_FALSE(test, stream->append_newlines); |
61 | KUNIT_EXPECT_TRUE(test, string_stream_is_empty(stream)); |
62 | } |
63 | |
64 | /* Unmanaged string_stream object is initialized correctly. */ |
65 | static void string_stream_unmanaged_init_test(struct kunit *test) |
66 | { |
67 | struct string_stream *stream; |
68 | |
69 | stream = alloc_string_stream(GFP_KERNEL); |
70 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
71 | kunit_add_action(test, action: cleanup_raw_stream, ctx: stream); |
72 | |
73 | KUNIT_EXPECT_EQ(test, stream->length, 0); |
74 | KUNIT_EXPECT_TRUE(test, list_empty(&stream->fragments)); |
75 | KUNIT_EXPECT_TRUE(test, (stream->gfp == GFP_KERNEL)); |
76 | KUNIT_EXPECT_FALSE(test, stream->append_newlines); |
77 | |
78 | KUNIT_EXPECT_TRUE(test, string_stream_is_empty(stream)); |
79 | } |
80 | |
81 | static void string_stream_destroy_stub(struct string_stream *stream) |
82 | { |
83 | struct kunit *fake_test = kunit_get_current_test(); |
84 | struct string_stream_test_priv *priv = fake_test->priv; |
85 | |
86 | /* The kunit could own string_streams other than the one we are testing. */ |
87 | if (stream == priv->expected_free_stream) { |
88 | if (priv->stream_was_freed) |
89 | priv->stream_free_again = true; |
90 | else |
91 | priv->stream_was_freed = true; |
92 | } |
93 | |
94 | /* |
95 | * Calling string_stream_destroy() will only call this function again |
96 | * because the redirection stub is still active. |
97 | * Avoid calling deactivate_static_stub() or changing current->kunit_test |
98 | * during cleanup. |
99 | */ |
100 | string_stream_clear(stream); |
101 | kfree(objp: stream); |
102 | } |
103 | |
104 | /* kunit_free_string_stream() calls string_stream_desrtoy() */ |
105 | static void string_stream_managed_free_test(struct kunit *test) |
106 | { |
107 | struct string_stream_test_priv *priv = test->priv; |
108 | |
109 | priv->expected_free_stream = NULL; |
110 | priv->stream_was_freed = false; |
111 | priv->stream_free_again = false; |
112 | |
113 | kunit_activate_static_stub(test, |
114 | string_stream_destroy, |
115 | string_stream_destroy_stub); |
116 | |
117 | priv->expected_free_stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
118 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->expected_free_stream); |
119 | |
120 | /* This should call the stub function. */ |
121 | kunit_free_string_stream(test, stream: priv->expected_free_stream); |
122 | |
123 | KUNIT_EXPECT_TRUE(test, priv->stream_was_freed); |
124 | KUNIT_EXPECT_FALSE(test, priv->stream_free_again); |
125 | } |
126 | |
127 | /* string_stream object is freed when test is cleaned up. */ |
128 | static void string_stream_resource_free_test(struct kunit *test) |
129 | { |
130 | struct string_stream_test_priv *priv = test->priv; |
131 | struct kunit *fake_test; |
132 | |
133 | fake_test = kunit_kzalloc(test, size: sizeof(*fake_test), GFP_KERNEL); |
134 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fake_test); |
135 | |
136 | kunit_init_test(test: fake_test, name: "string_stream_fake_test" , NULL); |
137 | fake_test->priv = priv; |
138 | |
139 | /* |
140 | * Activate stub before creating string_stream so the |
141 | * string_stream will be cleaned up first. |
142 | */ |
143 | priv->expected_free_stream = NULL; |
144 | priv->stream_was_freed = false; |
145 | priv->stream_free_again = false; |
146 | |
147 | kunit_activate_static_stub(fake_test, |
148 | string_stream_destroy, |
149 | string_stream_destroy_stub); |
150 | |
151 | priv->expected_free_stream = kunit_alloc_string_stream(test: fake_test, GFP_KERNEL); |
152 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->expected_free_stream); |
153 | |
154 | /* Set current->kunit_test to fake_test so the static stub will be called. */ |
155 | current->kunit_test = fake_test; |
156 | |
157 | /* Cleanup test - the stub function should be called */ |
158 | kunit_cleanup(test: fake_test); |
159 | |
160 | /* Set current->kunit_test back to current test. */ |
161 | current->kunit_test = test; |
162 | |
163 | KUNIT_EXPECT_TRUE(test, priv->stream_was_freed); |
164 | KUNIT_EXPECT_FALSE(test, priv->stream_free_again); |
165 | } |
166 | |
167 | /* |
168 | * Add a series of lines to a string_stream. Check that all lines |
169 | * appear in the correct order and no characters are dropped. |
170 | */ |
171 | static void string_stream_line_add_test(struct kunit *test) |
172 | { |
173 | struct string_stream *stream; |
174 | char line[60]; |
175 | char *concat_string, *pos, *string_end; |
176 | size_t len, total_len; |
177 | int num_lines, i; |
178 | |
179 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
180 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
181 | |
182 | /* Add series of sequence numbered lines */ |
183 | total_len = 0; |
184 | for (i = 0; i < 100; ++i) { |
185 | len = snprintf(buf: line, size: sizeof(line), |
186 | fmt: "The quick brown fox jumps over the lazy penguin %d\n" , i); |
187 | |
188 | /* Sanity-check that our test string isn't truncated */ |
189 | KUNIT_ASSERT_LT(test, len, sizeof(line)); |
190 | |
191 | string_stream_add(stream, fmt: line); |
192 | total_len += len; |
193 | } |
194 | num_lines = i; |
195 | |
196 | concat_string = get_concatenated_string(test, stream); |
197 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, concat_string); |
198 | KUNIT_EXPECT_EQ(test, strlen(concat_string), total_len); |
199 | |
200 | /* |
201 | * Split the concatenated string at the newlines and check that |
202 | * all the original added strings are present. |
203 | */ |
204 | pos = concat_string; |
205 | for (i = 0; i < num_lines; ++i) { |
206 | string_end = strchr(pos, '\n'); |
207 | KUNIT_EXPECT_NOT_NULL(test, string_end); |
208 | |
209 | /* Convert to NULL-terminated string */ |
210 | *string_end = '\0'; |
211 | |
212 | snprintf(buf: line, size: sizeof(line), |
213 | fmt: "The quick brown fox jumps over the lazy penguin %d" , i); |
214 | KUNIT_EXPECT_STREQ(test, pos, line); |
215 | |
216 | pos = string_end + 1; |
217 | } |
218 | |
219 | /* There shouldn't be any more data after this */ |
220 | KUNIT_EXPECT_EQ(test, strlen(pos), 0); |
221 | } |
222 | |
223 | /* Add a series of lines of variable length to a string_stream. */ |
224 | static void string_stream_variable_length_line_test(struct kunit *test) |
225 | { |
226 | static const char line[] = |
227 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
228 | " 0123456789!$%^&*()_-+={}[]:;@'~#<>,.?/|" ; |
229 | struct string_stream *stream; |
230 | struct rnd_state rnd; |
231 | char *concat_string, *pos, *string_end; |
232 | size_t offset, total_len; |
233 | int num_lines, i; |
234 | |
235 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
236 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
237 | |
238 | /* |
239 | * Log many lines of varying lengths until we have created |
240 | * many fragments. |
241 | * The "randomness" must be repeatable. |
242 | */ |
243 | prandom_seed_state(state: &rnd, seed: 3141592653589793238ULL); |
244 | total_len = 0; |
245 | for (i = 0; i < 100; ++i) { |
246 | offset = prandom_u32_state(state: &rnd) % (sizeof(line) - 1); |
247 | string_stream_add(stream, fmt: "%s\n" , &line[offset]); |
248 | total_len += sizeof(line) - offset; |
249 | } |
250 | num_lines = i; |
251 | |
252 | concat_string = get_concatenated_string(test, stream); |
253 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, concat_string); |
254 | KUNIT_EXPECT_EQ(test, strlen(concat_string), total_len); |
255 | |
256 | /* |
257 | * Split the concatenated string at the newlines and check that |
258 | * all the original added strings are present. |
259 | */ |
260 | prandom_seed_state(state: &rnd, seed: 3141592653589793238ULL); |
261 | pos = concat_string; |
262 | for (i = 0; i < num_lines; ++i) { |
263 | string_end = strchr(pos, '\n'); |
264 | KUNIT_EXPECT_NOT_NULL(test, string_end); |
265 | |
266 | /* Convert to NULL-terminated string */ |
267 | *string_end = '\0'; |
268 | |
269 | offset = prandom_u32_state(state: &rnd) % (sizeof(line) - 1); |
270 | KUNIT_EXPECT_STREQ(test, pos, &line[offset]); |
271 | |
272 | pos = string_end + 1; |
273 | } |
274 | |
275 | /* There shouldn't be any more data after this */ |
276 | KUNIT_EXPECT_EQ(test, strlen(pos), 0); |
277 | } |
278 | |
279 | /* Appending the content of one string stream to another. */ |
280 | static void string_stream_append_test(struct kunit *test) |
281 | { |
282 | static const char * const strings_1[] = { |
283 | "one" , "two" , "three" , "four" , "five" , "six" , |
284 | "seven" , "eight" , "nine" , "ten" , |
285 | }; |
286 | static const char * const strings_2[] = { |
287 | "Apple" , "Pear" , "Orange" , "Banana" , "Grape" , "Apricot" , |
288 | }; |
289 | struct string_stream *stream_1, *stream_2; |
290 | const char *stream1_content_before_append, *stream_2_content; |
291 | char *combined_content; |
292 | size_t combined_length; |
293 | int i; |
294 | |
295 | stream_1 = kunit_alloc_string_stream(test, GFP_KERNEL); |
296 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_1); |
297 | |
298 | stream_2 = kunit_alloc_string_stream(test, GFP_KERNEL); |
299 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_2); |
300 | |
301 | /* Append content of empty stream to empty stream */ |
302 | string_stream_append(stream: stream_1, other: stream_2); |
303 | KUNIT_EXPECT_EQ(test, strlen(get_concatenated_string(test, stream_1)), 0); |
304 | |
305 | /* Add some data to stream_1 */ |
306 | for (i = 0; i < ARRAY_SIZE(strings_1); ++i) |
307 | string_stream_add(stream: stream_1, fmt: "%s\n" , strings_1[i]); |
308 | |
309 | stream1_content_before_append = get_concatenated_string(test, stream: stream_1); |
310 | |
311 | /* Append content of empty stream to non-empty stream */ |
312 | string_stream_append(stream: stream_1, other: stream_2); |
313 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream_1), |
314 | stream1_content_before_append); |
315 | |
316 | /* Add some data to stream_2 */ |
317 | for (i = 0; i < ARRAY_SIZE(strings_2); ++i) |
318 | string_stream_add(stream: stream_2, fmt: "%s\n" , strings_2[i]); |
319 | |
320 | /* Append content of non-empty stream to non-empty stream */ |
321 | string_stream_append(stream: stream_1, other: stream_2); |
322 | |
323 | /* |
324 | * End result should be the original content of stream_1 plus |
325 | * the content of stream_2. |
326 | */ |
327 | stream_2_content = get_concatenated_string(test, stream: stream_2); |
328 | combined_length = strlen(stream1_content_before_append) + strlen(stream_2_content); |
329 | combined_length++; /* for terminating \0 */ |
330 | combined_content = kunit_kmalloc(test, size: combined_length, GFP_KERNEL); |
331 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, combined_content); |
332 | snprintf(buf: combined_content, size: combined_length, fmt: "%s%s" , |
333 | stream1_content_before_append, stream_2_content); |
334 | |
335 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream_1), combined_content); |
336 | |
337 | /* Append content of non-empty stream to empty stream */ |
338 | kunit_free_string_stream(test, stream: stream_1); |
339 | |
340 | stream_1 = kunit_alloc_string_stream(test, GFP_KERNEL); |
341 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_1); |
342 | |
343 | string_stream_append(stream: stream_1, other: stream_2); |
344 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream_1), stream_2_content); |
345 | } |
346 | |
347 | /* Appending the content of one string stream to one with auto-newlining. */ |
348 | static void string_stream_append_auto_newline_test(struct kunit *test) |
349 | { |
350 | struct string_stream *stream_1, *stream_2; |
351 | |
352 | /* Stream 1 has newline appending enabled */ |
353 | stream_1 = kunit_alloc_string_stream(test, GFP_KERNEL); |
354 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_1); |
355 | string_stream_set_append_newlines(stream: stream_1, append_newlines: true); |
356 | KUNIT_EXPECT_TRUE(test, stream_1->append_newlines); |
357 | |
358 | /* Stream 2 does not append newlines */ |
359 | stream_2 = kunit_alloc_string_stream(test, GFP_KERNEL); |
360 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_2); |
361 | |
362 | /* Appending a stream with a newline should not add another newline */ |
363 | string_stream_add(stream: stream_1, fmt: "Original string\n" ); |
364 | string_stream_add(stream: stream_2, fmt: "Appended content\n" ); |
365 | string_stream_add(stream: stream_2, fmt: "More stuff\n" ); |
366 | string_stream_append(stream: stream_1, other: stream_2); |
367 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream_1), |
368 | "Original string\nAppended content\nMore stuff\n" ); |
369 | |
370 | kunit_free_string_stream(test, stream: stream_2); |
371 | stream_2 = kunit_alloc_string_stream(test, GFP_KERNEL); |
372 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream_2); |
373 | |
374 | /* |
375 | * Appending a stream without newline should add a final newline. |
376 | * The appended string_stream is treated as a single string so newlines |
377 | * should not be inserted between fragments. |
378 | */ |
379 | string_stream_add(stream: stream_2, fmt: "Another" ); |
380 | string_stream_add(stream: stream_2, fmt: "And again" ); |
381 | string_stream_append(stream: stream_1, other: stream_2); |
382 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream_1), |
383 | "Original string\nAppended content\nMore stuff\nAnotherAnd again\n" ); |
384 | } |
385 | |
386 | /* Adding an empty string should not create a fragment. */ |
387 | static void string_stream_append_empty_string_test(struct kunit *test) |
388 | { |
389 | struct string_stream *stream; |
390 | int original_frag_count; |
391 | |
392 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
393 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
394 | |
395 | /* Formatted empty string */ |
396 | string_stream_add(stream, fmt: "%s" , "" ); |
397 | KUNIT_EXPECT_TRUE(test, string_stream_is_empty(stream)); |
398 | KUNIT_EXPECT_TRUE(test, list_empty(&stream->fragments)); |
399 | |
400 | /* Adding an empty string to a non-empty stream */ |
401 | string_stream_add(stream, fmt: "Add this line" ); |
402 | original_frag_count = list_count_nodes(head: &stream->fragments); |
403 | |
404 | string_stream_add(stream, fmt: "%s" , "" ); |
405 | KUNIT_EXPECT_EQ(test, list_count_nodes(&stream->fragments), original_frag_count); |
406 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream), "Add this line" ); |
407 | } |
408 | |
409 | /* Adding strings without automatic newline appending */ |
410 | static void string_stream_no_auto_newline_test(struct kunit *test) |
411 | { |
412 | struct string_stream *stream; |
413 | |
414 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
415 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
416 | |
417 | /* |
418 | * Add some strings with and without newlines. All formatted newlines |
419 | * should be preserved. It should not add any extra newlines. |
420 | */ |
421 | string_stream_add(stream, fmt: "One" ); |
422 | string_stream_add(stream, fmt: "Two\n" ); |
423 | string_stream_add(stream, fmt: "%s\n" , "Three" ); |
424 | string_stream_add(stream, fmt: "%s" , "Four\n" ); |
425 | string_stream_add(stream, fmt: "Five\n%s" , "Six" ); |
426 | string_stream_add(stream, fmt: "Seven\n\n" ); |
427 | string_stream_add(stream, fmt: "Eight" ); |
428 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream), |
429 | "OneTwo\nThree\nFour\nFive\nSixSeven\n\nEight" ); |
430 | } |
431 | |
432 | /* Adding strings with automatic newline appending */ |
433 | static void string_stream_auto_newline_test(struct kunit *test) |
434 | { |
435 | struct string_stream *stream; |
436 | |
437 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
438 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
439 | |
440 | string_stream_set_append_newlines(stream, append_newlines: true); |
441 | KUNIT_EXPECT_TRUE(test, stream->append_newlines); |
442 | |
443 | /* |
444 | * Add some strings with and without newlines. Newlines should |
445 | * be appended to lines that do not end with \n, but newlines |
446 | * resulting from the formatting should not be changed. |
447 | */ |
448 | string_stream_add(stream, fmt: "One" ); |
449 | string_stream_add(stream, fmt: "Two\n" ); |
450 | string_stream_add(stream, fmt: "%s\n" , "Three" ); |
451 | string_stream_add(stream, fmt: "%s" , "Four\n" ); |
452 | string_stream_add(stream, fmt: "Five\n%s" , "Six" ); |
453 | string_stream_add(stream, fmt: "Seven\n\n" ); |
454 | string_stream_add(stream, fmt: "Eight" ); |
455 | KUNIT_EXPECT_STREQ(test, get_concatenated_string(test, stream), |
456 | "One\nTwo\nThree\nFour\nFive\nSix\nSeven\n\nEight\n" ); |
457 | } |
458 | |
459 | /* |
460 | * This doesn't actually "test" anything. It reports time taken |
461 | * and memory used for logging a large number of lines. |
462 | */ |
463 | static void string_stream_performance_test(struct kunit *test) |
464 | { |
465 | struct string_stream_fragment *frag_container; |
466 | struct string_stream *stream; |
467 | char test_line[101]; |
468 | ktime_t start_time, end_time; |
469 | size_t len, bytes_requested, actual_bytes_used, total_string_length; |
470 | int offset, i; |
471 | |
472 | stream = kunit_alloc_string_stream(test, GFP_KERNEL); |
473 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream); |
474 | |
475 | memset(test_line, 'x', sizeof(test_line) - 1); |
476 | test_line[sizeof(test_line) - 1] = '\0'; |
477 | |
478 | start_time = ktime_get(); |
479 | for (i = 0; i < 10000; i++) { |
480 | offset = i % (sizeof(test_line) - 1); |
481 | string_stream_add(stream, fmt: "%s: %d\n" , &test_line[offset], i); |
482 | } |
483 | end_time = ktime_get(); |
484 | |
485 | /* |
486 | * Calculate memory used. This doesn't include invisible |
487 | * overhead due to kernel allocator fragment size rounding. |
488 | */ |
489 | bytes_requested = sizeof(*stream); |
490 | actual_bytes_used = ksize(objp: stream); |
491 | total_string_length = 0; |
492 | |
493 | list_for_each_entry(frag_container, &stream->fragments, node) { |
494 | bytes_requested += sizeof(*frag_container); |
495 | actual_bytes_used += ksize(objp: frag_container); |
496 | |
497 | len = strlen(frag_container->fragment); |
498 | total_string_length += len; |
499 | bytes_requested += len + 1; /* +1 for '\0' */ |
500 | actual_bytes_used += ksize(objp: frag_container->fragment); |
501 | } |
502 | |
503 | kunit_info(test, "Time elapsed: %lld us\n" , |
504 | ktime_us_delta(end_time, start_time)); |
505 | kunit_info(test, "Total string length: %zu\n" , total_string_length); |
506 | kunit_info(test, "Bytes requested: %zu\n" , bytes_requested); |
507 | kunit_info(test, "Actual bytes allocated: %zu\n" , actual_bytes_used); |
508 | } |
509 | |
510 | static int string_stream_test_init(struct kunit *test) |
511 | { |
512 | struct string_stream_test_priv *priv; |
513 | |
514 | priv = kunit_kzalloc(test, size: sizeof(*priv), GFP_KERNEL); |
515 | if (!priv) |
516 | return -ENOMEM; |
517 | |
518 | test->priv = priv; |
519 | |
520 | return 0; |
521 | } |
522 | |
523 | static struct kunit_case string_stream_test_cases[] = { |
524 | KUNIT_CASE(string_stream_managed_init_test), |
525 | KUNIT_CASE(string_stream_unmanaged_init_test), |
526 | KUNIT_CASE(string_stream_managed_free_test), |
527 | KUNIT_CASE(string_stream_resource_free_test), |
528 | KUNIT_CASE(string_stream_line_add_test), |
529 | KUNIT_CASE(string_stream_variable_length_line_test), |
530 | KUNIT_CASE(string_stream_append_test), |
531 | KUNIT_CASE(string_stream_append_auto_newline_test), |
532 | KUNIT_CASE(string_stream_append_empty_string_test), |
533 | KUNIT_CASE(string_stream_no_auto_newline_test), |
534 | KUNIT_CASE(string_stream_auto_newline_test), |
535 | KUNIT_CASE(string_stream_performance_test), |
536 | {} |
537 | }; |
538 | |
539 | static struct kunit_suite string_stream_test_suite = { |
540 | .name = "string-stream-test" , |
541 | .test_cases = string_stream_test_cases, |
542 | .init = string_stream_test_init, |
543 | }; |
544 | kunit_test_suites(&string_stream_test_suite); |
545 | |