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 42typedef void (*TEST_FUN)(void); 43static 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 */ 50static 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 */ 61static 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 */ 89static 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 */ 140static 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 184void *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 194void *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 */ 209static 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 */ 235static 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 */ 259static 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 287TEST_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 297int 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