66 * Author: Brendan Higgins <brendanhiggins@google.com>
77 */
88
9+ #include <kunit/static_stub.h>
910#include <kunit/test.h>
1011#include <linux/slab.h>
1112
1213#include "string-stream.h"
1314
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(). */
1523static void kfree_wrapper (void * p )
1624{
1725 kfree (p );
1826}
1927
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+
2036static char * get_concatenated_string (struct kunit * test , struct string_stream * stream )
2137{
2238 char * str = string_stream_get_string (stream );
@@ -27,11 +43,12 @@ static char *get_concatenated_string(struct kunit *test, struct string_stream *s
2743 return str ;
2844}
2945
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 )
3248{
3349 struct string_stream * stream ;
3450
51+ /* Resource-managed initialization. */
3552 stream = kunit_alloc_string_stream (test , GFP_KERNEL );
3653 KUNIT_ASSERT_NOT_ERR_OR_NULL (test , stream );
3754
@@ -42,6 +59,109 @@ static void string_stream_init_test(struct kunit *test)
4259 KUNIT_EXPECT_TRUE (test , string_stream_is_empty (stream ));
4360}
4461
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+
45165/*
46166 * Add a series of lines to a string_stream. Check that all lines
47167 * appear in the correct order and no characters are dropped.
@@ -334,8 +454,24 @@ static void string_stream_auto_newline_test(struct kunit *test)
334454 "One\nTwo\nThree\nFour\nFive\nSix\nSeven\n\nEight\n" );
335455}
336456
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+
337470static 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 ),
339475 KUNIT_CASE (string_stream_line_add_test ),
340476 KUNIT_CASE (string_stream_variable_length_line_test ),
341477 KUNIT_CASE (string_stream_append_test ),
@@ -348,6 +484,7 @@ static struct kunit_case string_stream_test_cases[] = {
348484
349485static struct kunit_suite string_stream_test_suite = {
350486 .name = "string-stream-test" ,
351- .test_cases = string_stream_test_cases
487+ .test_cases = string_stream_test_cases ,
488+ .init = string_stream_test_init ,
352489};
353490kunit_test_suites (& string_stream_test_suite );
0 commit comments