1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "osTest.h"
33#include <sys/syscall.h>
34#include <unistd.h>
35
36UINT32 g_shellTestQueueID;
37INT32 g_iCunitErrCode = 0;
38INT32 g_iCunitErrLineNo = 0;
39
40UINT32 g_testTskHandle;
41UINT32 g_testCount;
42UINT32 g_flowcheck = 0;
43UINT32 g_failResult = 0;
44UINT32 g_passResult = 0;
45
46#ifdef TEST1980
47UINT32 g_testhwiFlag;
48UINT32 g_testCpuMask;
49#endif
50
51UINT32 g_testCount1;
52UINT32 g_testCount2;
53UINT32 g_testCount3;
54UINT32 g_testTaskID01;
55UINT32 g_testTaskID02;
56UINT32 g_testTaskID03;
57UINT32 g_testTaskID04;
58UINT32 g_hwiNum1;
59UINT32 g_hwiNum2;
60UINT32 g_semID;
61UINT32 g_semID2;
62UINT32 g_mutexTest;
63UINT32 g_cpupTestCount;
64UINT32 g_waitTestCount;
65UINT32 g_testPeriod;
66
67UINT16 g_swTmrID;
68UINT32 g_testQueueID01;
69UINT32 g_testQueueID02;
70UINT32 g_testQueueID03;
71UINT32 g_leavingTaskNum;
72UINT32 g_mAuwTestTaskID[32] = {0};
73UINT32 g_getTickConsume = 0;
74CHAR g_libcPathname[50] = "/usr/jffs0";
75UINT32 g_testCircleCount = 0;
76
77UINT32 g_fatFilesystem;
78UINT8 g_mUsIndex;
79
80#if TEST_MODULE_CHECK == 1
81
82extern UINT32 g_FailModelResult[];
83extern UINT32 g_PassModelResult[];
84extern UINT32 g_ExecutModelNum[];
85#endif
86extern char *StrLayer[];
87extern char *StrLevel[];
88extern char *StrType[];
89
90extern char *StrModule[];
91extern UINT32 g_ModelNum;
92
93#ifdef LOSCFG_USER_TEST_FS_FAT
94#define TEST_FAT32 0x02
95#define TEST_EXFAT 0x04
96#endif
97
98BOOL g_isSpinorInit = FALSE;
99BOOL g_isSdInit = FALSE;
100BOOL g_isUartDevInit = FALSE;
101BOOL g_isTcpipInit = FALSE;
102BOOL g_isInitSerial = FALSE;
103UINT32 g_vfsCyclesCount = 0;
104INT32 g_serialInitFlag = -1;
105BOOL g_isAddArray = TRUE;
106BOOL g_isUsbInit = FALSE;
107BOOL g_isIpcGmacInit = FALSE;
108
109BOOL g_isDriversRandomInit = FALSE;
110
111BOOL g_isHisiEthSetPhyModeInit = FALSE;
112
113BOOL g_isVfsInit = FALSE;
114BOOL g_isProcInit = FALSE;
115
116INT32 g_libFilesystem = -1;
117enum {
118    LIB_USE_FAT = 1,
119    LIB_USE_JFFS2,
120};
121#ifdef LOSCFG_DRIVERS_USB
122VOID test_init_usb(controller_type ctype, device_type dtype);
123#endif
124VOID test_init_ipc_gmac(VOID);
125VOID test_init_proc(VOID);
126VOID test_init_sd(VOID);
127VOID TestInitVfs(VOID);
128VOID test_init_spinor(VOID);
129VOID test_deinit_jffs(VOID);
130VOID test_mtd_jffs(VOID);
131
132UINT32 PrepareFileEnv(CHAR *pathList[], CHAR *streamList[], INT32 streamLen[], INT32 listCnt)
133{
134    CHAR nameBuf[256] = {0};
135    for (UINT32 i = 0; i < listCnt; i++) {
136        UINT32 ret = access(pathList[i], 0);
137        if (ret == 0) {
138            ret = memcpy_s(nameBuf, sizeof(nameBuf), pathList[i], strlen(pathList[i]) + 1);
139            if (ret != 0) {
140                return -1;
141            }
142            ret = strcat_s(nameBuf, sizeof(nameBuf), "_bak_for_test");
143            if (ret != 0) {
144                return -1;
145            }
146            ret = rename(pathList[i], nameBuf);
147            if (ret != 0) {
148                return -1;
149            }
150        }
151        FILE *fp = fopen(pathList[i], "w");
152        if (fp == NULL) {
153            return -1;
154        }
155        ret = fwrite(streamList[i], 1, streamLen[i], fp);
156        if (ret != streamLen[i]) {
157            (VOID)fclose(fp);
158            return -1;
159        }
160        ret = fclose(fp);
161        if (ret != 0) {
162            printf("%d\n", errno);
163        }
164    }
165    return 0;
166}
167
168UINT32 RecoveryFileEnv(CHAR *pathList[], INT32 listCnt)
169{
170    UINT32 ret;
171    CHAR nameBuf[256] = {0};
172    for (UINT32 i = 0; i < listCnt; i++) {
173        ret = remove(pathList[i]);
174        if (ret != 0) {
175            printf("ret = %d, err = %d\n", ret, errno);
176        }
177        ret = memcpy_s(nameBuf, sizeof(nameBuf), pathList[i], strlen(pathList[i]) + 1);
178        if (ret != 0) {
179            return -1;
180        }
181        ret = strcat_s(nameBuf, sizeof(nameBuf), "_bak_for_test");
182        if (ret != 0) {
183            return -1;
184        }
185        ret = access(nameBuf, 0);
186        if (ret == 0) {
187            ret = rename(nameBuf, pathList[i]);
188            if (ret != 0) {
189                return -1;
190            }
191        }
192    }
193    return 0;
194}
195
196VOID Wfi(VOID)
197{
198    __asm__ __volatile__("wfi" : : : "memory");
199}
200
201VOID Dmb(VOID)
202{
203    __asm__ __volatile__("dmb" : : : "memory");
204}
205
206VOID Dsb(VOID)
207{
208    __asm__ __volatile__("dsb" : : : "memory");
209}
210
211__attribute__((weak)) int Gettid()
212{
213    return syscall(SYS_gettid);
214}
215
216UINT32 LosCurTaskIDGet()
217{
218    return Gettid();
219}
220
221
222UINT32 LosTaskDelay(UINT32 tick)
223{
224    return usleep(10 * tick * 1000);
225}
226
227VOID TestExtraTaskDelay(UINT32 uwTick)
228{
229#ifdef LOSCFG_KERNEL_SMP
230    // trigger task schedule may occor on another core
231    // needs adding delay and checking status later
232    LosTaskDelay(uwTick);
233#else
234    // do nothing
235#endif
236}
237
238extern volatile UINT64 g_tickCount[];
239UINT64 TestTickCountGet(VOID)
240{
241    /* not use LOS_TickCountGet for now,
242       cause every timer is not match with others.
243       use cpu0 timer instead. */
244    return clock();
245}
246
247UINT64 TestTickCountByCurrCpuid(VOID)
248{
249    return clock();
250}
251
252/*
253 * different from calling LOS_TaskDelay,
254 * this func will not yield this task to another one.
255 */
256VOID TestBusyTaskDelay(UINT32 tick)
257{
258    UINT64 runtime = 0;
259
260    runtime = TestTickCountByCurrCpuid() + tick;
261    while (1) {
262        if (runtime <= TestTickCountByCurrCpuid()) {
263            break;
264        }
265        Wfi();
266    }
267}
268
269VOID TestAssertBusyTaskDelay(UINT32 timeout, UINT32 flag)
270{
271    UINT64 runtime = 0;
272
273    runtime = TestTickCountGet() + timeout;
274    while (1) {
275        if ((runtime <= TestTickCountGet()) || (g_testCount == flag)) {
276            break;
277        }
278        Wfi();
279    }
280}
281
282VOID TestAssertWaitDelay(UINT32 *testCount, UINT32 flag)
283{
284    while (*testCount != flag) {
285    usleep(1);
286    }
287}
288
289UINT32 PosixPthreadInit(pthread_attr_t *attr, int pri)
290{
291    UINT32 uwRet = 0;
292    struct sched_param sp;
293
294    uwRet = pthread_attr_init(attr);
295    ICUNIT_GOTO_EQUAL(uwRet, 0, uwRet, NOK);
296
297    uwRet = pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
298    ICUNIT_GOTO_EQUAL(uwRet, 0, uwRet, NOK);
299
300    sp.sched_priority = pri;
301    uwRet = pthread_attr_setschedparam(attr, &sp);
302    ICUNIT_GOTO_EQUAL(uwRet, 0, uwRet, NOK);
303
304    return LOS_OK;
305NOK:
306    return LOS_NOK;
307}
308
309UINT32 PosixPthreadDestroy(pthread_attr_t *attr, pthread_t thread)
310{
311    UINT32 uwRet = 0;
312
313    uwRet = pthread_join(thread, NULL);
314    ICUNIT_GOTO_EQUAL(uwRet, 0, uwRet, NOK);
315
316    uwRet = pthread_attr_destroy(attr);
317    ICUNIT_GOTO_EQUAL(uwRet, 0, uwRet, NOK);
318
319    return LOS_OK;
320NOK:
321    return LOS_NOK;
322}
323
324VOID TestInitVfs(VOID)
325{
326#if defined(LOSCFG_FS_VFS)
327    if (g_isVfsInit) {
328        return;
329    }
330
331    extern VOID los_vfs_init(VOID);
332    los_vfs_init();
333    g_isVfsInit = TRUE;
334
335#endif
336}
337
338VOID TestInitDriversRandom(VOID)
339{
340    if (g_isDriversRandomInit) {
341        return;
342    }
343
344#if defined(LOSCFG_DRIVERS_RANDOM)
345
346    printf("random init ...\n");
347    extern int ran_dev_register(VOID);
348    ran_dev_register();
349
350#endif
351
352#if defined(LOSCFG_HW_RANDOM_ENABLE)
353
354    extern int random_hw_dev_register(VOID);
355    printf("random_hw init ...\n");
356    if (random_hw_dev_register() != 0) {
357        printf("Failed!\n");
358    }
359
360#endif
361
362    g_isDriversRandomInit = TRUE;
363}
364
365VOID TestInitUartDev(VOID) {}
366
367/* ****************************************
368Function:Test_PartInit
369Description: create a partition for testing,partition num is 0,mount point is jffs0
370Input:
371 [1]type: "spinor"
372 [2]start_addr: the partition start address
373 [3]length: the partition length
374Output: None
375Return: None
376***************************************** */
377VOID TestPartInit(char *type, UINT32 start_addr, UINT32 length)
378{
379#if defined(LOSCFG_FS_JFFS)
380    int uwRet = 0;
381
382    if ((uwRet = add_mtd_partition(type, start_addr, length, 0)) != 0)
383        PRINT_ERR("add %s partition failed, return %d\n", type, uwRet);
384    else {
385        printf("[OK] add %s partition successful\n", type);
386        if (strcmp(type, "spinor") == 0) {
387            if ((uwRet = mount("/dev/spinorblk0", "/jffs0", "jffs", 0, NULL)) != 0)
388                PRINT_ERR("mount jffs0 failed,err %d\n", uwRet);
389            else
390                printf("[OK] mount jffs0 successful\n");
391        }
392    }
393#endif
394    return;
395}
396
397/* ****************************************
398Function:Test_PartDelete
399Description: delete the partition for test
400Input:
401 [1]type: "spinor"
402Output: None
403Return: None
404***************************************** */
405VOID TestPartDelete(char *type)
406{
407#if defined(LOSCFG_FS_JFFS)
408
409    int uwRet = 0;
410    char *point = "";
411
412    if (strcmp(type, "spinor") == 0) {
413        point = "/jffs0";
414    }
415
416    if ((uwRet = umount(point)) != 0) {
417        PRINT_ERR("umount %s failed,err %d.\n", point, uwRet);
418    } else {
419        printf("[OK] umount %s OK.\n", point);
420        if ((uwRet = delete_mtd_partition(0, type)) != 0)
421            PRINT_ERR("delete %s partition failed, return %d\n", type, uwRet);
422        else
423            printf("[OK] delete %s partition OK.\n", type);
424    }
425#endif
426    return;
427}
428
429/* *
430 * dir: what you want to delete force
431 */
432int RemoveDir(const char *dir)
433{
434    char cur_dir[] = ".";
435    char up_dir[] = "..";
436    char dir_name[128] = { 0 };
437    DIR *dirp = NULL;
438    struct dirent *dp = NULL;
439    struct stat dir_stat;
440    int ret;
441
442    if (access(dir, F_OK) != 0) {
443        return 0;
444    }
445
446    if (stat(dir, &dir_stat) < 0) {
447        perror("get directory stat error");
448        return -1;
449    }
450
451    if (S_ISREG(dir_stat.st_mode)) {
452        remove(dir);
453    } else if (S_ISDIR(dir_stat.st_mode)) {
454        dirp = opendir(dir);
455        while ((dp = readdir(dirp)) != NULL) {
456            if ((strcmp(cur_dir, dp->d_name) == 0) || (strcmp(up_dir, dp->d_name) == 0)) {
457                continue;
458            }
459
460            ret = sprintf_s(dir_name, sizeof(dir_name), "%s/%s", dir, dp->d_name);
461            if (ret < 0) {
462                perror("sprintf dir_name error");
463                closedir(dirp);
464                return -1;
465            }
466            RemoveDir(dir_name);
467        }
468        closedir(dirp);
469
470        rmdir(dir); /* now dir is empty */
471    } else {
472        perror("unknown file type!");
473    }
474    return 0;
475}
476