1570af302Sopenharmony_ci/*
2570af302Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4570af302Sopenharmony_ci * you may not use this file except in compliance with the License.
5570af302Sopenharmony_ci * You may obtain a copy of the License at
6570af302Sopenharmony_ci *
7570af302Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8570af302Sopenharmony_ci *
9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12570af302Sopenharmony_ci * See the License for the specific language governing permissions and
13570af302Sopenharmony_ci * limitations under the License.
14570af302Sopenharmony_ci */
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci#include <info/fatal_message.h>
17570af302Sopenharmony_ci
18570af302Sopenharmony_ci#include <errno.h>
19570af302Sopenharmony_ci#include <stdio.h>
20570af302Sopenharmony_ci#include <stdlib.h>
21570af302Sopenharmony_ci#include <string.h>
22570af302Sopenharmony_ci#include <test.h>
23570af302Sopenharmony_ci#include <pthread.h>
24570af302Sopenharmony_ci#include <unistd.h>
25570af302Sopenharmony_ci#include <sys/wait.h>
26570af302Sopenharmony_ci
27570af302Sopenharmony_ci#define EXPECT_TRUE(c)                \
28570af302Sopenharmony_ci    do                                \
29570af302Sopenharmony_ci    {                                 \
30570af302Sopenharmony_ci        if (!(c))                     \
31570af302Sopenharmony_ci            t_error("[%s] failed\n"); \
32570af302Sopenharmony_ci    } while (0)
33570af302Sopenharmony_ci
34570af302Sopenharmony_ci#define FORK(fpid)                    \
35570af302Sopenharmony_ci    do                                \
36570af302Sopenharmony_ci    {                                 \
37570af302Sopenharmony_ci        if (fpid < 0) {               \
38570af302Sopenharmony_ci            t_error("error in fork!");\
39570af302Sopenharmony_ci        }                             \
40570af302Sopenharmony_ci    } while (0)
41570af302Sopenharmony_ci
42570af302Sopenharmony_citypedef void (*TEST_FUN)(void);
43570af302Sopenharmony_cistatic const int WAIT_TIME = 1;
44570af302Sopenharmony_ci
45570af302Sopenharmony_ci/**
46570af302Sopenharmony_ci * @tc.name      : get_fatal_message
47570af302Sopenharmony_ci * @tc.desc      : Test the function of get_fatal_message.
48570af302Sopenharmony_ci * @tc.level     : Level 0
49570af302Sopenharmony_ci */
50570af302Sopenharmony_cistatic void fatal_message_0010(void)
51570af302Sopenharmony_ci{
52570af302Sopenharmony_ci    fatal_msg_t *fatal_message = get_fatal_message();
53570af302Sopenharmony_ci    EXPECT_TRUE(fatal_message == NULL);
54570af302Sopenharmony_ci}
55570af302Sopenharmony_ci
56570af302Sopenharmony_ci/**
57570af302Sopenharmony_ci * @tc.name      : set_fatal_message
58570af302Sopenharmony_ci * @tc.desc      : Test the function of set_fatal_message.
59570af302Sopenharmony_ci * @tc.level     : Level 0
60570af302Sopenharmony_ci */
61570af302Sopenharmony_cistatic void fatal_message_0020(void)
62570af302Sopenharmony_ci{
63570af302Sopenharmony_ci    const char msg[1024] = {"abcdefghijklmnopqrstuvwxyz1234567890"};
64570af302Sopenharmony_ci    fatal_msg_t *fatal_message = NULL;
65570af302Sopenharmony_ci
66570af302Sopenharmony_ci    int childRet = 0;
67570af302Sopenharmony_ci    int pidParent = 0;
68570af302Sopenharmony_ci    int pidChild = 0;
69570af302Sopenharmony_ci
70570af302Sopenharmony_ci    pid_t fpid;
71570af302Sopenharmony_ci    fpid = fork();
72570af302Sopenharmony_ci    FORK(fpid);
73570af302Sopenharmony_ci    if (fpid == 0) {
74570af302Sopenharmony_ci        pidChild = getpid();
75570af302Sopenharmony_ci        set_fatal_message(msg);
76570af302Sopenharmony_ci        fatal_message = get_fatal_message();
77570af302Sopenharmony_ci        EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
78570af302Sopenharmony_ci        exit(0);
79570af302Sopenharmony_ci    }
80570af302Sopenharmony_ci    waitpid(fpid, &childRet, 0);
81570af302Sopenharmony_ci    EXPECT_TRUE(childRet == 0);
82570af302Sopenharmony_ci}
83570af302Sopenharmony_ci
84570af302Sopenharmony_ci/**
85570af302Sopenharmony_ci * @tc.name      : set_fatal_message
86570af302Sopenharmony_ci * @tc.desc      : Test the multiple processes of set_fatal_message.
87570af302Sopenharmony_ci * @tc.level     : Level 0
88570af302Sopenharmony_ci */
89570af302Sopenharmony_cistatic void fatal_message_0030(void)
90570af302Sopenharmony_ci{
91570af302Sopenharmony_ci    fatal_msg_t *fatal_message = NULL;
92570af302Sopenharmony_ci
93570af302Sopenharmony_ci    const char msgChild[1024] = {"msgChild"};
94570af302Sopenharmony_ci    const char msgParent[1024] = {"msgParent"};
95570af302Sopenharmony_ci
96570af302Sopenharmony_ci    int childRet = 0;
97570af302Sopenharmony_ci    int pidChild = 0;
98570af302Sopenharmony_ci    int pidParent = 0;
99570af302Sopenharmony_ci    int pidCParent = 0;
100570af302Sopenharmony_ci    int pidCChild = 0;
101570af302Sopenharmony_ci
102570af302Sopenharmony_ci    pid_t fpid;
103570af302Sopenharmony_ci
104570af302Sopenharmony_ci    // start process
105570af302Sopenharmony_ci    fpid = fork();
106570af302Sopenharmony_ci    FORK(fpid);
107570af302Sopenharmony_ci    if (fpid == 0) {
108570af302Sopenharmony_ci        pidChild = getpid();
109570af302Sopenharmony_ci    } else {
110570af302Sopenharmony_ci        pidParent = getpid();
111570af302Sopenharmony_ci        pid_t fpidChild;
112570af302Sopenharmony_ci
113570af302Sopenharmony_ci        // start process again
114570af302Sopenharmony_ci        fpidChild = fork();
115570af302Sopenharmony_ci        if (fpidChild < 0) {
116570af302Sopenharmony_ci            t_printf("error in fork!");
117570af302Sopenharmony_ci        } else if (fpidChild == 0) {
118570af302Sopenharmony_ci            pidCChild = getpid();
119570af302Sopenharmony_ci            set_fatal_message(msgParent);
120570af302Sopenharmony_ci            fatal_message = get_fatal_message();
121570af302Sopenharmony_ci            EXPECT_TRUE(strcmp(fatal_message->msg, msgParent) == 0);
122570af302Sopenharmony_ci            exit(0);
123570af302Sopenharmony_ci        } else {
124570af302Sopenharmony_ci            pidCParent = getpid();
125570af302Sopenharmony_ci            set_fatal_message(msgChild);
126570af302Sopenharmony_ci            fatal_message = get_fatal_message();
127570af302Sopenharmony_ci            EXPECT_TRUE(strcmp(fatal_message->msg, msgChild) == 0);
128570af302Sopenharmony_ci            waitpid(fpidChild, &childRet, 0);
129570af302Sopenharmony_ci            EXPECT_TRUE(childRet == 0);
130570af302Sopenharmony_ci        }
131570af302Sopenharmony_ci    }
132570af302Sopenharmony_ci}
133570af302Sopenharmony_ci
134570af302Sopenharmony_ci/**
135570af302Sopenharmony_ci * @tc.name      : set_fatal_message
136570af302Sopenharmony_ci * @tc.desc      : Test the multiple processes of set_fatal_message,
137570af302Sopenharmony_ci*                  One of the threads crashed.
138570af302Sopenharmony_ci * @tc.level     : Level 0
139570af302Sopenharmony_ci */
140570af302Sopenharmony_cistatic void fatal_message_0040(void)
141570af302Sopenharmony_ci{
142570af302Sopenharmony_ci    fatal_msg_t *fatal_message = NULL;
143570af302Sopenharmony_ci
144570af302Sopenharmony_ci    const char msgChild[1024] = {"msgChild004"};
145570af302Sopenharmony_ci    const char msgParent[1024] = {"msgParent004"};
146570af302Sopenharmony_ci
147570af302Sopenharmony_ci    int childRet = 0;
148570af302Sopenharmony_ci    int pidChild = 0;
149570af302Sopenharmony_ci    int pidParent = 0;
150570af302Sopenharmony_ci    int pidCParent = 0;
151570af302Sopenharmony_ci    int pidCChild = 0;
152570af302Sopenharmony_ci
153570af302Sopenharmony_ci    pid_t fpid;
154570af302Sopenharmony_ci
155570af302Sopenharmony_ci    // start process
156570af302Sopenharmony_ci    fpid = fork();
157570af302Sopenharmony_ci    FORK(fpid);
158570af302Sopenharmony_ci    if (fpid == 0) {
159570af302Sopenharmony_ci        pidChild = getpid();
160570af302Sopenharmony_ci    } else {
161570af302Sopenharmony_ci        pidParent = getpid();
162570af302Sopenharmony_ci        pid_t fpidChild;
163570af302Sopenharmony_ci
164570af302Sopenharmony_ci        // start process again
165570af302Sopenharmony_ci        fpidChild = fork();
166570af302Sopenharmony_ci        if (fpidChild < 0) {
167570af302Sopenharmony_ci            t_printf("error in fork!");
168570af302Sopenharmony_ci        } else if (fpidChild == 0) {
169570af302Sopenharmony_ci            pidCChild = getpid();
170570af302Sopenharmony_ci            char *str = NULL;
171570af302Sopenharmony_ci            str[0] = 0;
172570af302Sopenharmony_ci            // Process crash. Unable to continue calling the set_fatal_message interface
173570af302Sopenharmony_ci        } else {
174570af302Sopenharmony_ci            pidCParent = getpid();
175570af302Sopenharmony_ci            set_fatal_message(msgParent);
176570af302Sopenharmony_ci            fatal_message = get_fatal_message();
177570af302Sopenharmony_ci            EXPECT_TRUE(strcmp(fatal_message->msg, msgParent) == 0);
178570af302Sopenharmony_ci            waitpid(fpidChild, &childRet, 0);
179570af302Sopenharmony_ci            EXPECT_TRUE(childRet != 0);
180570af302Sopenharmony_ci        }
181570af302Sopenharmony_ci    }
182570af302Sopenharmony_ci}
183570af302Sopenharmony_ci
184570af302Sopenharmony_civoid *ThreadFun1(void *arg)
185570af302Sopenharmony_ci{
186570af302Sopenharmony_ci    if (arg == NULL) {
187570af302Sopenharmony_ci        t_printf("ThreadFun1 arg is NULL");
188570af302Sopenharmony_ci    }
189570af302Sopenharmony_ci    fatal_msg_t *fatal_message = get_fatal_message();
190570af302Sopenharmony_ci    EXPECT_TRUE(strcmp(fatal_message->msg, (char *)arg) == 0);
191570af302Sopenharmony_ci    pthread_exit("ThreadFun1 Exit");
192570af302Sopenharmony_ci}
193570af302Sopenharmony_ci
194570af302Sopenharmony_civoid *ThreadFun2(void *arg)
195570af302Sopenharmony_ci{
196570af302Sopenharmony_ci    if (arg == NULL) {
197570af302Sopenharmony_ci        t_printf("ThreadFun2 arg is NULL");
198570af302Sopenharmony_ci    }
199570af302Sopenharmony_ci    fatal_msg_t *fatal_message = get_fatal_message();
200570af302Sopenharmony_ci    EXPECT_TRUE(strcmp(fatal_message->msg, (char *)arg) == 0);
201570af302Sopenharmony_ci    pthread_exit("ThreadFun2 Exit");
202570af302Sopenharmony_ci}
203570af302Sopenharmony_ci
204570af302Sopenharmony_ci/**
205570af302Sopenharmony_ci * @tc.name      : set_fatal_message
206570af302Sopenharmony_ci * @tc.desc      : Test the multithreading of set_fatal_message.
207570af302Sopenharmony_ci * @tc.level     : Level 0
208570af302Sopenharmony_ci */
209570af302Sopenharmony_cistatic void fatal_message_0050(void)
210570af302Sopenharmony_ci{
211570af302Sopenharmony_ci    const char msgThread[1024] = {"msgThread"};
212570af302Sopenharmony_ci    int res;
213570af302Sopenharmony_ci    pthread_t fatalMessageThread1, fatalMessageThread2;
214570af302Sopenharmony_ci
215570af302Sopenharmony_ci    set_fatal_message(msgThread);
216570af302Sopenharmony_ci    res = pthread_create(&fatalMessageThread1, NULL, ThreadFun1, (void *)msgThread);
217570af302Sopenharmony_ci    if (res != 0) {
218570af302Sopenharmony_ci        t_printf("pthread_create1 error.");
219570af302Sopenharmony_ci    }
220570af302Sopenharmony_ci    sleep(WAIT_TIME);
221570af302Sopenharmony_ci
222570af302Sopenharmony_ci    res = pthread_create(&fatalMessageThread2, NULL, ThreadFun2, (void *)msgThread);
223570af302Sopenharmony_ci    if (res != 0) {
224570af302Sopenharmony_ci        t_printf("pthread_create2 error.");
225570af302Sopenharmony_ci    }
226570af302Sopenharmony_ci    pthread_join(fatalMessageThread1, NULL);
227570af302Sopenharmony_ci    pthread_join(fatalMessageThread2, NULL);
228570af302Sopenharmony_ci}
229570af302Sopenharmony_ci
230570af302Sopenharmony_ci/**
231570af302Sopenharmony_ci * @tc.name      : set_fatal_message
232570af302Sopenharmony_ci * @tc.desc      : Test the function of null message.
233570af302Sopenharmony_ci * @tc.level     : Level 0
234570af302Sopenharmony_ci */
235570af302Sopenharmony_cistatic void fatal_message_0060(void)
236570af302Sopenharmony_ci{
237570af302Sopenharmony_ci    const char* msg = NULL;
238570af302Sopenharmony_ci    fatal_msg_t *fatal_message = NULL;
239570af302Sopenharmony_ci
240570af302Sopenharmony_ci    int pidChild = 0;
241570af302Sopenharmony_ci
242570af302Sopenharmony_ci    pid_t fpid;
243570af302Sopenharmony_ci    fpid = fork();
244570af302Sopenharmony_ci    FORK(fpid);
245570af302Sopenharmony_ci    if (fpid == 0) {
246570af302Sopenharmony_ci        pidChild = getpid();
247570af302Sopenharmony_ci        set_fatal_message(msg);
248570af302Sopenharmony_ci        fatal_message = get_fatal_message();
249570af302Sopenharmony_ci        EXPECT_TRUE(fatal_message == NULL);
250570af302Sopenharmony_ci        exit(pidChild);
251570af302Sopenharmony_ci    }
252570af302Sopenharmony_ci}
253570af302Sopenharmony_ci
254570af302Sopenharmony_ci/**
255570af302Sopenharmony_ci * @tc.name      : set_fatal_message
256570af302Sopenharmony_ci * @tc.desc      : Test the function of multi call set_fatal_message.
257570af302Sopenharmony_ci * @tc.level     : Level 0
258570af302Sopenharmony_ci */
259570af302Sopenharmony_cistatic void fatal_message_0070(void)
260570af302Sopenharmony_ci{
261570af302Sopenharmony_ci    const char msg[1024] = {"abcdefghijklmnopqrstuvwxyz1234567890"};
262570af302Sopenharmony_ci    const char msg1[1024] = {"abcdefghijklmnopqr"};
263570af302Sopenharmony_ci    fatal_msg_t *fatal_message = NULL;
264570af302Sopenharmony_ci
265570af302Sopenharmony_ci    int pidParent = 0;
266570af302Sopenharmony_ci    int pidChild = 0;
267570af302Sopenharmony_ci
268570af302Sopenharmony_ci    pid_t fpid;
269570af302Sopenharmony_ci    fpid = fork();
270570af302Sopenharmony_ci    if (fpid < 0) {
271570af302Sopenharmony_ci        t_printf("error in fork!");
272570af302Sopenharmony_ci    } else if (fpid == 0) {
273570af302Sopenharmony_ci        pidChild = getpid();
274570af302Sopenharmony_ci        set_fatal_message(msg);
275570af302Sopenharmony_ci        fatal_message = get_fatal_message();
276570af302Sopenharmony_ci        EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
277570af302Sopenharmony_ci
278570af302Sopenharmony_ci        set_fatal_message(msg1);
279570af302Sopenharmony_ci        fatal_message = get_fatal_message();
280570af302Sopenharmony_ci        EXPECT_TRUE(strcmp(fatal_message->msg, msg) == 0);
281570af302Sopenharmony_ci
282570af302Sopenharmony_ci        exit(pidChild);
283570af302Sopenharmony_ci    }
284570af302Sopenharmony_ci}
285570af302Sopenharmony_ci
286570af302Sopenharmony_ci
287570af302Sopenharmony_ciTEST_FUN G_Fun_Array[] = {
288570af302Sopenharmony_ci    fatal_message_0010,
289570af302Sopenharmony_ci    fatal_message_0020,
290570af302Sopenharmony_ci    fatal_message_0030,
291570af302Sopenharmony_ci    fatal_message_0040,
292570af302Sopenharmony_ci    fatal_message_0050,
293570af302Sopenharmony_ci    fatal_message_0060,
294570af302Sopenharmony_ci    fatal_message_0070
295570af302Sopenharmony_ci};
296570af302Sopenharmony_ci
297570af302Sopenharmony_ciint main(void)
298570af302Sopenharmony_ci{
299570af302Sopenharmony_ci    int childPid, childRet;
300570af302Sopenharmony_ci    int num = sizeof(G_Fun_Array) / sizeof(TEST_FUN);
301570af302Sopenharmony_ci    for (int pos = 0; pos < num; ++pos) {
302570af302Sopenharmony_ci        // Run each function in a new process to
303570af302Sopenharmony_ci        // keep the initial state of fatal_message.
304570af302Sopenharmony_ci        if ((childPid = fork()) == 0) {
305570af302Sopenharmony_ci            G_Fun_Array[pos]();
306570af302Sopenharmony_ci            exit(0);
307570af302Sopenharmony_ci        }
308570af302Sopenharmony_ci        waitpid(childPid, &childRet, 0);
309570af302Sopenharmony_ci        EXPECT_TRUE(childRet == 0);
310570af302Sopenharmony_ci    }
311570af302Sopenharmony_ci
312570af302Sopenharmony_ci    return t_status;
313570af302Sopenharmony_ci}
314