6
6
* Author: Brendan Higgins <brendanhiggins@google.com>
7
7
*/
8
8
9
+ #include <kunit/static_stub.h>
9
10
#include <kunit/test.h>
10
11
#include <linux/slab.h>
11
12
12
13
#include "string-stream.h"
13
14
14
- /* This avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
15
+ struct string_stream_test_priv {
16
+ /* For testing resource-managed free. */
17
+ struct string_stream * expected_free_stream ;
18
+ bool stream_was_freed ;
19
+ bool stream_free_again ;
20
+ };
21
+
22
+ /* Avoids a cast warning if kfree() is passed direct to kunit_add_action(). */
15
23
static void kfree_wrapper (void * p )
16
24
{
17
25
kfree (p );
18
26
}
19
27
28
+ /* Avoids a cast warning if string_stream_destroy() is passed direct to kunit_add_action(). */
29
+ static void cleanup_raw_stream (void * p )
30
+ {
31
+ struct string_stream * stream = p ;
32
+
33
+ string_stream_destroy (stream );
34
+ }
35
+
20
36
static char * get_concatenated_string (struct kunit * test , struct string_stream * stream )
21
37
{
22
38
char * str = string_stream_get_string (stream );
@@ -27,11 +43,12 @@ static char *get_concatenated_string(struct kunit *test, struct string_stream *s
27
43
return str ;
28
44
}
29
45
30
- /* string_stream object is initialized correctly. */
31
- static void string_stream_init_test (struct kunit * test )
46
+ /* Managed string_stream object is initialized correctly. */
47
+ static void string_stream_managed_init_test (struct kunit * test )
32
48
{
33
49
struct string_stream * stream ;
34
50
51
+ /* Resource-managed initialization. */
35
52
stream = kunit_alloc_string_stream (test , GFP_KERNEL );
36
53
KUNIT_ASSERT_NOT_ERR_OR_NULL (test , stream );
37
54
@@ -42,6 +59,109 @@ static void string_stream_init_test(struct kunit *test)
42
59
KUNIT_EXPECT_TRUE (test , string_stream_is_empty (stream ));
43
60
}
44
61
62
+ /* Unmanaged string_stream object is initialized correctly. */
63
+ static void string_stream_unmanaged_init_test (struct kunit * test )
64
+ {
65
+ struct string_stream * stream ;
66
+
67
+ stream = alloc_string_stream (GFP_KERNEL );
68
+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , stream );
69
+ kunit_add_action (test , cleanup_raw_stream , stream );
70
+
71
+ KUNIT_EXPECT_EQ (test , stream -> length , 0 );
72
+ KUNIT_EXPECT_TRUE (test , list_empty (& stream -> fragments ));
73
+ KUNIT_EXPECT_EQ (test , stream -> gfp , GFP_KERNEL );
74
+ KUNIT_EXPECT_FALSE (test , stream -> append_newlines );
75
+
76
+ KUNIT_EXPECT_TRUE (test , string_stream_is_empty (stream ));
77
+ }
78
+
79
+ static void string_stream_destroy_stub (struct string_stream * stream )
80
+ {
81
+ struct kunit * fake_test = kunit_get_current_test ();
82
+ struct string_stream_test_priv * priv = fake_test -> priv ;
83
+
84
+ /* The kunit could own string_streams other than the one we are testing. */
85
+ if (stream == priv -> expected_free_stream ) {
86
+ if (priv -> stream_was_freed )
87
+ priv -> stream_free_again = true;
88
+ else
89
+ priv -> stream_was_freed = true;
90
+ }
91
+
92
+ /*
93
+ * Calling string_stream_destroy() will only call this function again
94
+ * because the redirection stub is still active.
95
+ * Avoid calling deactivate_static_stub() or changing current->kunit_test
96
+ * during cleanup.
97
+ */
98
+ string_stream_clear (stream );
99
+ kfree (stream );
100
+ }
101
+
102
+ /* kunit_free_string_stream() calls string_stream_desrtoy() */
103
+ static void string_stream_managed_free_test (struct kunit * test )
104
+ {
105
+ struct string_stream_test_priv * priv = test -> priv ;
106
+
107
+ priv -> expected_free_stream = NULL ;
108
+ priv -> stream_was_freed = false;
109
+ priv -> stream_free_again = false;
110
+
111
+ kunit_activate_static_stub (test ,
112
+ string_stream_destroy ,
113
+ string_stream_destroy_stub );
114
+
115
+ priv -> expected_free_stream = kunit_alloc_string_stream (test , GFP_KERNEL );
116
+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , priv -> expected_free_stream );
117
+
118
+ /* This should call the stub function. */
119
+ kunit_free_string_stream (test , priv -> expected_free_stream );
120
+
121
+ KUNIT_EXPECT_TRUE (test , priv -> stream_was_freed );
122
+ KUNIT_EXPECT_FALSE (test , priv -> stream_free_again );
123
+ }
124
+
125
+ /* string_stream object is freed when test is cleaned up. */
126
+ static void string_stream_resource_free_test (struct kunit * test )
127
+ {
128
+ struct string_stream_test_priv * priv = test -> priv ;
129
+ struct kunit * fake_test ;
130
+
131
+ fake_test = kunit_kzalloc (test , sizeof (* fake_test ), GFP_KERNEL );
132
+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , fake_test );
133
+
134
+ kunit_init_test (fake_test , "string_stream_fake_test" , NULL );
135
+ fake_test -> priv = priv ;
136
+
137
+ /*
138
+ * Activate stub before creating string_stream so the
139
+ * string_stream will be cleaned up first.
140
+ */
141
+ priv -> expected_free_stream = NULL ;
142
+ priv -> stream_was_freed = false;
143
+ priv -> stream_free_again = false;
144
+
145
+ kunit_activate_static_stub (fake_test ,
146
+ string_stream_destroy ,
147
+ string_stream_destroy_stub );
148
+
149
+ priv -> expected_free_stream = kunit_alloc_string_stream (fake_test , GFP_KERNEL );
150
+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , priv -> expected_free_stream );
151
+
152
+ /* Set current->kunit_test to fake_test so the static stub will be called. */
153
+ current -> kunit_test = fake_test ;
154
+
155
+ /* Cleanup test - the stub function should be called */
156
+ kunit_cleanup (fake_test );
157
+
158
+ /* Set current->kunit_test back to current test. */
159
+ current -> kunit_test = test ;
160
+
161
+ KUNIT_EXPECT_TRUE (test , priv -> stream_was_freed );
162
+ KUNIT_EXPECT_FALSE (test , priv -> stream_free_again );
163
+ }
164
+
45
165
/*
46
166
* Add a series of lines to a string_stream. Check that all lines
47
167
* appear in the correct order and no characters are dropped.
@@ -334,8 +454,24 @@ static void string_stream_auto_newline_test(struct kunit *test)
334
454
"One\nTwo\nThree\nFour\nFive\nSix\nSeven\n\nEight\n" );
335
455
}
336
456
457
+ static int string_stream_test_init (struct kunit * test )
458
+ {
459
+ struct string_stream_test_priv * priv ;
460
+
461
+ priv = kunit_kzalloc (test , sizeof (* priv ), GFP_KERNEL );
462
+ if (!priv )
463
+ return - ENOMEM ;
464
+
465
+ test -> priv = priv ;
466
+
467
+ return 0 ;
468
+ }
469
+
337
470
static struct kunit_case string_stream_test_cases [] = {
338
- KUNIT_CASE (string_stream_init_test ),
471
+ KUNIT_CASE (string_stream_managed_init_test ),
472
+ KUNIT_CASE (string_stream_unmanaged_init_test ),
473
+ KUNIT_CASE (string_stream_managed_free_test ),
474
+ KUNIT_CASE (string_stream_resource_free_test ),
339
475
KUNIT_CASE (string_stream_line_add_test ),
340
476
KUNIT_CASE (string_stream_variable_length_line_test ),
341
477
KUNIT_CASE (string_stream_append_test ),
@@ -348,6 +484,7 @@ static struct kunit_case string_stream_test_cases[] = {
348
484
349
485
static struct kunit_suite string_stream_test_suite = {
350
486
.name = "string-stream-test" ,
351
- .test_cases = string_stream_test_cases
487
+ .test_cases = string_stream_test_cases ,
488
+ .init = string_stream_test_init ,
352
489
};
353
490
kunit_test_suites (& string_stream_test_suite );
0 commit comments