1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <info/fatal_message.h>
17
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <test.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <sys/wait.h>
26
27 #define EXPECT_TRUE(c) \
28 do \
29 { \
30 if (!(c)) \
31 t_error("[%s] failed\n"); \
32 } while (0)
33
34 #define FORK(fpid) \
35 do \
36 { \
37 if (fpid < 0) { \
38 t_error("error in fork!");\
39 } \
40 } while (0)
41
42 typedef void (*TEST_FUN)(void);
43 static const int WAIT_TIME = 1;
44
45 /**
46 * @tc.name : get_fatal_message
47 * @tc.desc : Test the function of get_fatal_message.
48 * @tc.level : Level 0
49 */
fatal_message_0010(void)50 static void fatal_message_0010(void)
51 {
52 fatal_msg_t *fatal_message = get_fatal_message();
53 EXPECT_TRUE(fatal_message == NULL);
54 }
55
56 /**
57 * @tc.name : set_fatal_message
58 * @tc.desc : Test the function of set_fatal_message.
59 * @tc.level : Level 0
60 */
fatal_message_0020(void)61 static void fatal_message_0020(void)
62 {
63 const char msg[1024] = {"abcdefghijklmnopqrstuvwxyz1234567890"};
64 fatal_msg_t *fatal_message = NULL;
65
66 int childRet = 0;
67 int pidParent = 0;
68 int pidChild = 0;
69
70 pid_t fpid;
71 fpid = fork();
72 FORK(fpid);
73 if (fpid == 0) {
74 pidChild = getpid();
75 set_fatal_message(msg);
76 fatal_message = get_fatal_message();
77 EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
78 exit(0);
79 }
80 waitpid(fpid, &childRet, 0);
81 EXPECT_TRUE(childRet == 0);
82 }
83
84 /**
85 * @tc.name : set_fatal_message
86 * @tc.desc : Test the multiple processes of set_fatal_message.
87 * @tc.level : Level 0
88 */
fatal_message_0030(void)89 static void fatal_message_0030(void)
90 {
91 fatal_msg_t *fatal_message = NULL;
92
93 const char msgChild[1024] = {"msgChild"};
94 const char msgParent[1024] = {"msgParent"};
95
96 int childRet = 0;
97 int pidChild = 0;
98 int pidParent = 0;
99 int pidCParent = 0;
100 int pidCChild = 0;
101
102 pid_t fpid;
103
104 // start process
105 fpid = fork();
106 FORK(fpid);
107 if (fpid == 0) {
108 pidChild = getpid();
109 } else {
110 pidParent = getpid();
111 pid_t fpidChild;
112
113 // start process again
114 fpidChild = fork();
115 if (fpidChild < 0) {
116 t_printf("error in fork!");
117 } else if (fpidChild == 0) {
118 pidCChild = getpid();
119 set_fatal_message(msgParent);
120 fatal_message = get_fatal_message();
121 EXPECT_TRUE(strcmp(fatal_message->msg, msgParent) == 0);
122 exit(0);
123 } else {
124 pidCParent = getpid();
125 set_fatal_message(msgChild);
126 fatal_message = get_fatal_message();
127 EXPECT_TRUE(strcmp(fatal_message->msg, msgChild) == 0);
128 waitpid(fpidChild, &childRet, 0);
129 EXPECT_TRUE(childRet == 0);
130 }
131 }
132 }
133
134 /**
135 * @tc.name : set_fatal_message
136 * @tc.desc : Test the multiple processes of set_fatal_message,
137 * One of the threads crashed.
138 * @tc.level : Level 0
139 */
fatal_message_0040(void)140 static void fatal_message_0040(void)
141 {
142 fatal_msg_t *fatal_message = NULL;
143
144 const char msgChild[1024] = {"msgChild004"};
145 const char msgParent[1024] = {"msgParent004"};
146
147 int childRet = 0;
148 int pidChild = 0;
149 int pidParent = 0;
150 int pidCParent = 0;
151 int pidCChild = 0;
152
153 pid_t fpid;
154
155 // start process
156 fpid = fork();
157 FORK(fpid);
158 if (fpid == 0) {
159 pidChild = getpid();
160 } else {
161 pidParent = getpid();
162 pid_t fpidChild;
163
164 // start process again
165 fpidChild = fork();
166 if (fpidChild < 0) {
167 t_printf("error in fork!");
168 } else if (fpidChild == 0) {
169 pidCChild = getpid();
170 char *str = NULL;
171 str[0] = 0;
172 // Process crash. Unable to continue calling the set_fatal_message interface
173 } else {
174 pidCParent = getpid();
175 set_fatal_message(msgParent);
176 fatal_message = get_fatal_message();
177 EXPECT_TRUE(strcmp(fatal_message->msg, msgParent) == 0);
178 waitpid(fpidChild, &childRet, 0);
179 EXPECT_TRUE(childRet != 0);
180 }
181 }
182 }
183
ThreadFun1(void * arg)184 void *ThreadFun1(void *arg)
185 {
186 if (arg == NULL) {
187 t_printf("ThreadFun1 arg is NULL");
188 }
189 fatal_msg_t *fatal_message = get_fatal_message();
190 EXPECT_TRUE(strcmp(fatal_message->msg, (char *)arg) == 0);
191 pthread_exit("ThreadFun1 Exit");
192 }
193
ThreadFun2(void * arg)194 void *ThreadFun2(void *arg)
195 {
196 if (arg == NULL) {
197 t_printf("ThreadFun2 arg is NULL");
198 }
199 fatal_msg_t *fatal_message = get_fatal_message();
200 EXPECT_TRUE(strcmp(fatal_message->msg, (char *)arg) == 0);
201 pthread_exit("ThreadFun2 Exit");
202 }
203
204 /**
205 * @tc.name : set_fatal_message
206 * @tc.desc : Test the multithreading of set_fatal_message.
207 * @tc.level : Level 0
208 */
fatal_message_0050(void)209 static void fatal_message_0050(void)
210 {
211 const char msgThread[1024] = {"msgThread"};
212 int res;
213 pthread_t fatalMessageThread1, fatalMessageThread2;
214
215 set_fatal_message(msgThread);
216 res = pthread_create(&fatalMessageThread1, NULL, ThreadFun1, (void *)msgThread);
217 if (res != 0) {
218 t_printf("pthread_create1 error.");
219 }
220 sleep(WAIT_TIME);
221
222 res = pthread_create(&fatalMessageThread2, NULL, ThreadFun2, (void *)msgThread);
223 if (res != 0) {
224 t_printf("pthread_create2 error.");
225 }
226 pthread_join(fatalMessageThread1, NULL);
227 pthread_join(fatalMessageThread2, NULL);
228 }
229
230 /**
231 * @tc.name : set_fatal_message
232 * @tc.desc : Test the function of null message.
233 * @tc.level : Level 0
234 */
fatal_message_0060(void)235 static void fatal_message_0060(void)
236 {
237 const char* msg = NULL;
238 fatal_msg_t *fatal_message = NULL;
239
240 int pidChild = 0;
241
242 pid_t fpid;
243 fpid = fork();
244 FORK(fpid);
245 if (fpid == 0) {
246 pidChild = getpid();
247 set_fatal_message(msg);
248 fatal_message = get_fatal_message();
249 EXPECT_TRUE(fatal_message == NULL);
250 exit(pidChild);
251 }
252 }
253
254 /**
255 * @tc.name : set_fatal_message
256 * @tc.desc : Test the function of multi call set_fatal_message.
257 * @tc.level : Level 0
258 */
fatal_message_0070(void)259 static void fatal_message_0070(void)
260 {
261 const char msg[1024] = {"abcdefghijklmnopqrstuvwxyz1234567890"};
262 const char msg1[1024] = {"abcdefghijklmnopqr"};
263 fatal_msg_t *fatal_message = NULL;
264
265 int pidParent = 0;
266 int pidChild = 0;
267
268 pid_t fpid;
269 fpid = fork();
270 if (fpid < 0) {
271 t_printf("error in fork!");
272 } else if (fpid == 0) {
273 pidChild = getpid();
274 set_fatal_message(msg);
275 fatal_message = get_fatal_message();
276 EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
277
278 set_fatal_message(msg1);
279 fatal_message = get_fatal_message();
280 EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
281
282 exit(pidChild);
283 }
284 }
285
286
287 TEST_FUN G_Fun_Array[] = {
288 fatal_message_0010,
289 fatal_message_0020,
290 fatal_message_0030,
291 fatal_message_0040,
292 fatal_message_0050,
293 fatal_message_0060,
294 fatal_message_0070
295 };
296
main(void)297 int main(void)
298 {
299 int childPid, childRet;
300 int num = sizeof(G_Fun_Array) / sizeof(TEST_FUN);
301 for (int pos = 0; pos < num; ++pos) {
302 // Run each function in a new process to
303 // keep the initial state of fatal_message.
304 if ((childPid = fork()) == 0) {
305 G_Fun_Array[pos]();
306 exit(0);
307 }
308 waitpid(childPid, &childRet, 0);
309 EXPECT_TRUE(childRet == 0);
310 }
311
312 return t_status;
313 }
314