Skip to content

Commit 05e2006

Browse files
rfvirgilshuahkh
authored andcommitted
kunit: Use string_stream for test log
Replace the fixed-size log buffer with a string_stream so that the log can grow as lines are added. The existing kunit log tests have been updated for using a string_stream as the log. No new test have been added because there are already tests for the underlying string_stream. As the log tests now depend on string_stream functions they cannot build when kunit-test is a module. They have been surrounded by a #if to replace them with skipping version when the test is build as a module. Though this isn't pretty, it avoids moving code to another file while that code is also being changed. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Reviewed-by: David Gow <davidgow@google.com> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
1 parent d1a0d69 commit 05e2006

File tree

4 files changed

+81
-69
lines changed

4 files changed

+81
-69
lines changed

include/kunit/test.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@
3333
DECLARE_STATIC_KEY_FALSE(kunit_running);
3434

3535
struct kunit;
36-
37-
/* Size of log associated with test. */
38-
#define KUNIT_LOG_SIZE 2048
36+
struct string_stream;
3937

4038
/* Maximum size of parameter description string. */
4139
#define KUNIT_PARAM_DESC_SIZE 128
@@ -133,7 +131,7 @@ struct kunit_case {
133131
/* private: internal use only. */
134132
enum kunit_status status;
135133
char *module_name;
136-
char *log;
134+
struct string_stream *log;
137135
};
138136

139137
static inline char *kunit_status_to_ok_not_ok(enum kunit_status status)
@@ -253,7 +251,7 @@ struct kunit_suite {
253251
/* private: internal use only */
254252
char status_comment[KUNIT_STATUS_COMMENT_SIZE];
255253
struct dentry *debugfs;
256-
char *log;
254+
struct string_stream *log;
257255
int suite_init_err;
258256
};
259257

@@ -279,7 +277,7 @@ struct kunit {
279277

280278
/* private: internal use only. */
281279
const char *name; /* Read only after initialization! */
282-
char *log; /* Points at case log after initialization */
280+
struct string_stream *log; /* Points at case log after initialization */
283281
struct kunit_try_catch try_catch;
284282
/* param_value is the current parameter value for a test case. */
285283
const void *param_value;
@@ -315,7 +313,7 @@ const char *kunit_filter_glob(void);
315313
char *kunit_filter(void);
316314
char *kunit_filter_action(void);
317315

318-
void kunit_init_test(struct kunit *test, const char *name, char *log);
316+
void kunit_init_test(struct kunit *test, const char *name, struct string_stream *log);
319317

320318
int kunit_run_tests(struct kunit_suite *suite);
321319

@@ -473,7 +471,7 @@ static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp
473471

474472
void kunit_cleanup(struct kunit *test);
475473

476-
void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...);
474+
void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...);
477475

478476
/**
479477
* kunit_mark_skipped() - Marks @test_or_suite as skipped

lib/kunit/debugfs.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,21 @@ void kunit_debugfs_init(void)
3737
debugfs_rootdir = debugfs_create_dir(KUNIT_DEBUGFS_ROOT, NULL);
3838
}
3939

40-
static void debugfs_print_result(struct seq_file *seq,
41-
struct kunit_suite *suite,
42-
struct kunit_case *test_case)
40+
static void debugfs_print_result(struct seq_file *seq, struct string_stream *log)
4341
{
44-
if (!test_case || !test_case->log)
42+
struct string_stream_fragment *frag_container;
43+
44+
if (!log)
4545
return;
4646

47-
seq_printf(seq, "%s", test_case->log);
47+
/*
48+
* Walk the fragments so we don't need to allocate a temporary
49+
* buffer to hold the entire string.
50+
*/
51+
spin_lock(&log->lock);
52+
list_for_each_entry(frag_container, &log->fragments, node)
53+
seq_printf(seq, "%s", frag_container->fragment);
54+
spin_unlock(&log->lock);
4855
}
4956

5057
/*
@@ -69,10 +76,9 @@ static int debugfs_print_results(struct seq_file *seq, void *v)
6976
seq_printf(seq, KUNIT_SUBTEST_INDENT "1..%zd\n", kunit_suite_num_test_cases(suite));
7077

7178
kunit_suite_for_each_test_case(suite, test_case)
72-
debugfs_print_result(seq, suite, test_case);
79+
debugfs_print_result(seq, test_case->log);
7380

74-
if (suite->log)
75-
seq_printf(seq, "%s", suite->log);
81+
debugfs_print_result(seq, suite->log);
7682

7783
seq_printf(seq, "%s %d %s\n",
7884
kunit_status_to_ok_not_ok(success), 1, suite->name);
@@ -105,9 +111,13 @@ void kunit_debugfs_create_suite(struct kunit_suite *suite)
105111
struct kunit_case *test_case;
106112

107113
/* Allocate logs before creating debugfs representation. */
108-
suite->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
109-
kunit_suite_for_each_test_case(suite, test_case)
110-
test_case->log = kzalloc(KUNIT_LOG_SIZE, GFP_KERNEL);
114+
suite->log = alloc_string_stream(GFP_KERNEL);
115+
string_stream_set_append_newlines(suite->log, true);
116+
117+
kunit_suite_for_each_test_case(suite, test_case) {
118+
test_case->log = alloc_string_stream(GFP_KERNEL);
119+
string_stream_set_append_newlines(test_case->log, true);
120+
}
111121

112122
suite->debugfs = debugfs_create_dir(suite->name, debugfs_rootdir);
113123

@@ -121,7 +131,7 @@ void kunit_debugfs_destroy_suite(struct kunit_suite *suite)
121131
struct kunit_case *test_case;
122132

123133
debugfs_remove_recursive(suite->debugfs);
124-
kfree(suite->log);
134+
string_stream_destroy(suite->log);
125135
kunit_suite_for_each_test_case(suite, test_case)
126-
kfree(test_case->log);
136+
string_stream_destroy(test_case->log);
127137
}

lib/kunit/kunit-test.c

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <kunit/test.h>
99
#include <kunit/test-bug.h>
1010

11+
#include "string-stream.h"
1112
#include "try-catch-impl.h"
1213

1314
struct kunit_try_catch_test_context {
@@ -530,43 +531,80 @@ static struct kunit_suite kunit_resource_test_suite = {
530531
.test_cases = kunit_resource_test_cases,
531532
};
532533

534+
/*
535+
* Log tests call string_stream functions, which aren't exported. So only
536+
* build this code if this test is built-in.
537+
*/
538+
#if IS_BUILTIN(CONFIG_KUNIT_TEST)
539+
540+
/* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
541+
static void kfree_wrapper(void *p)
542+
{
543+
kfree(p);
544+
}
545+
533546
static void kunit_log_test(struct kunit *test)
534547
{
535548
struct kunit_suite suite;
536-
537-
suite.log = kunit_kzalloc(test, KUNIT_LOG_SIZE, GFP_KERNEL);
549+
#ifdef CONFIG_KUNIT_DEBUGFS
550+
char *full_log;
551+
#endif
552+
suite.log = kunit_alloc_string_stream(test, GFP_KERNEL);
538553
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, suite.log);
554+
string_stream_set_append_newlines(suite.log, true);
539555

540556
kunit_log(KERN_INFO, test, "put this in log.");
541557
kunit_log(KERN_INFO, test, "this too.");
542558
kunit_log(KERN_INFO, &suite, "add to suite log.");
543559
kunit_log(KERN_INFO, &suite, "along with this.");
544560

545561
#ifdef CONFIG_KUNIT_DEBUGFS
562+
KUNIT_EXPECT_TRUE(test, test->log->append_newlines);
563+
564+
full_log = string_stream_get_string(test->log);
565+
kunit_add_action(test, (kunit_action_t *)kfree, full_log);
546566
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
547-
strstr(test->log, "put this in log."));
567+
strstr(full_log, "put this in log."));
548568
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
549-
strstr(test->log, "this too."));
569+
strstr(full_log, "this too."));
570+
571+
full_log = string_stream_get_string(suite.log);
572+
kunit_add_action(test, kfree_wrapper, full_log);
550573
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
551-
strstr(suite.log, "add to suite log."));
574+
strstr(full_log, "add to suite log."));
552575
KUNIT_EXPECT_NOT_ERR_OR_NULL(test,
553-
strstr(suite.log, "along with this."));
576+
strstr(full_log, "along with this."));
554577
#else
555578
KUNIT_EXPECT_NULL(test, test->log);
556579
#endif
557580
}
558581

559582
static void kunit_log_newline_test(struct kunit *test)
560583
{
584+
char *full_log;
585+
561586
kunit_info(test, "Add newline\n");
562587
if (test->log) {
563-
KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(test->log, "Add newline\n"),
564-
"Missing log line, full log:\n%s", test->log);
565-
KUNIT_EXPECT_NULL(test, strstr(test->log, "Add newline\n\n"));
588+
full_log = string_stream_get_string(test->log);
589+
kunit_add_action(test, kfree_wrapper, full_log);
590+
KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(full_log, "Add newline\n"),
591+
"Missing log line, full log:\n%s", full_log);
592+
KUNIT_EXPECT_NULL(test, strstr(full_log, "Add newline\n\n"));
566593
} else {
567594
kunit_skip(test, "only useful when debugfs is enabled");
568595
}
569596
}
597+
#else
598+
static void kunit_log_test(struct kunit *test)
599+
{
600+
kunit_skip(test, "Log tests only run when built-in");
601+
}
602+
603+
static void kunit_log_newline_test(struct kunit *test)
604+
{
605+
kunit_skip(test, "Log tests only run when built-in");
606+
}
607+
#endif /* IS_BUILTIN(CONFIG_KUNIT_TEST) */
570608

571609
static struct kunit_case kunit_log_test_cases[] = {
572610
KUNIT_CASE(kunit_log_test),

lib/kunit/test.c

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -109,51 +109,17 @@ static void kunit_print_test_stats(struct kunit *test,
109109
stats.total);
110110
}
111111

112-
/**
113-
* kunit_log_newline() - Add newline to the end of log if one is not
114-
* already present.
115-
* @log: The log to add the newline to.
116-
*/
117-
static void kunit_log_newline(char *log)
118-
{
119-
int log_len, len_left;
120-
121-
log_len = strlen(log);
122-
len_left = KUNIT_LOG_SIZE - log_len - 1;
123-
124-
if (log_len > 0 && log[log_len - 1] != '\n')
125-
strncat(log, "\n", len_left);
126-
}
127-
128-
/*
129-
* Append formatted message to log, size of which is limited to
130-
* KUNIT_LOG_SIZE bytes (including null terminating byte).
131-
*/
132-
void kunit_log_append(char *log, const char *fmt, ...)
112+
/* Append formatted message to log. */
113+
void kunit_log_append(struct string_stream *log, const char *fmt, ...)
133114
{
134115
va_list args;
135-
int len, log_len, len_left;
136116

137117
if (!log)
138118
return;
139119

140-
log_len = strlen(log);
141-
len_left = KUNIT_LOG_SIZE - log_len - 1;
142-
if (len_left <= 0)
143-
return;
144-
145-
/* Evaluate length of line to add to log */
146120
va_start(args, fmt);
147-
len = vsnprintf(NULL, 0, fmt, args) + 1;
121+
string_stream_vadd(log, fmt, args);
148122
va_end(args);
149-
150-
/* Print formatted line to the log */
151-
va_start(args, fmt);
152-
vsnprintf(log + log_len, min(len, len_left), fmt, args);
153-
va_end(args);
154-
155-
/* Add newline to end of log if not already present. */
156-
kunit_log_newline(log);
157123
}
158124
EXPORT_SYMBOL_GPL(kunit_log_append);
159125

@@ -359,14 +325,14 @@ void __kunit_do_failed_assertion(struct kunit *test,
359325
}
360326
EXPORT_SYMBOL_GPL(__kunit_do_failed_assertion);
361327

362-
void kunit_init_test(struct kunit *test, const char *name, char *log)
328+
void kunit_init_test(struct kunit *test, const char *name, struct string_stream *log)
363329
{
364330
spin_lock_init(&test->lock);
365331
INIT_LIST_HEAD(&test->resources);
366332
test->name = name;
367333
test->log = log;
368334
if (test->log)
369-
test->log[0] = '\0';
335+
string_stream_clear(log);
370336
test->status = KUNIT_SUCCESS;
371337
test->status_comment[0] = '\0';
372338
}

0 commit comments

Comments
 (0)