1f92157deSopenharmony_ci/*
2f92157deSopenharmony_ci* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
3f92157deSopenharmony_ci* Description:多线程测试框架(GTEST-MULTITHREAD)库接口声明
4f92157deSopenharmony_ci* Author:
5f92157deSopenharmony_ci* Create:2023/2/24
6f92157deSopenharmony_ci*/
7f92157deSopenharmony_ci
8f92157deSopenharmony_ci#ifndef __MULTI_THREAD_TEST_H__
9f92157deSopenharmony_ci#define __MULTI_THREAD_TEST_H__
10f92157deSopenharmony_ci
11f92157deSopenharmony_ci#include <vector>
12f92157deSopenharmony_ci#include <string>
13f92157deSopenharmony_ci#include <map>
14f92157deSopenharmony_ci#include <thread>
15f92157deSopenharmony_ci#include "gtest/gtest.h"
16f92157deSopenharmony_ci
17f92157deSopenharmony_ciusing ::testing::TestPartResult;
18f92157deSopenharmony_ci
19f92157deSopenharmony_cinamespace testing{
20f92157deSopenharmony_ci    namespace mt {
21f92157deSopenharmony_ci        using PF = void(*)();
22f92157deSopenharmony_ci        using uint = unsigned int;
23f92157deSopenharmony_ci        const uint RANDOM_THREAD_ID = 0x3f3f3f3f; //线程ID常量
24f92157deSopenharmony_ci        static uint g_thread_count = 10 ; //全局变量,默认线程数是10
25f92157deSopenharmony_ci        inline void setThreadNum(uint num)
26f92157deSopenharmony_ci        {
27f92157deSopenharmony_ci            g_thread_count = num;
28f92157deSopenharmony_ci        }
29f92157deSopenharmony_ci        class TestTask {
30f92157deSopenharmony_ci        public:
31f92157deSopenharmony_ci            TestTask() = default;
32f92157deSopenharmony_ci            TestTask(std::string ts, std::string tc, PF func) : m_testsuite(ts), m_testcase(tc), m_func(func){}
33f92157deSopenharmony_ci            std::string m_testsuite;
34f92157deSopenharmony_ci            std::string m_testcase;
35f92157deSopenharmony_ci            PF m_func;
36f92157deSopenharmony_ci        };
37f92157deSopenharmony_ci        class ThreadTaskEntry {
38f92157deSopenharmony_ci        public:
39f92157deSopenharmony_ci            ThreadTaskEntry(std::vector<TestTask> v_task) : funcList(v_task) {}
40f92157deSopenharmony_ci            std::thread *thread;
41f92157deSopenharmony_ci            std::vector<TestTask> funcList;
42f92157deSopenharmony_ci        };
43f92157deSopenharmony_ci        class MultiThreadTest {
44f92157deSopenharmony_ci        private:
45f92157deSopenharmony_ci            std::vector<std::vector<TestTask>> threadTasks;
46f92157deSopenharmony_ci            std::vector<ThreadTaskEntry> threadTestEntryList;
47f92157deSopenharmony_ci            std::map<std::string, std::vector<TestTask>> randomTasks;
48f92157deSopenharmony_ci
49f92157deSopenharmony_ci        public:
50f92157deSopenharmony_ci            void doTest();
51f92157deSopenharmony_ci            void run();
52f92157deSopenharmony_ci            MultiThreadTest() {}
53f92157deSopenharmony_ci            unsigned m_threadNum;
54f92157deSopenharmony_ci            MultiThreadTest(unsigned int t_cnt) : m_threadNum(t_cnt) {}
55f92157deSopenharmony_ci            uint runTask(unsigned thread_num, PF func, std::string testsuite, std::string testcase);
56f92157deSopenharmony_ci            void appendTaskToList(unsigned thread_id, PF func, std::string testsuite, std::string testcase);
57f92157deSopenharmony_ci        };
58f92157deSopenharmony_ci
59f92157deSopenharmony_ci        static MultiThreadTest testInstance;
60f92157deSopenharmony_ci        static MultiThreadTest *getMTestSingleton()
61f92157deSopenharmony_ci        {
62f92157deSopenharmony_ci            return &testInstance;
63f92157deSopenharmony_ci        }
64f92157deSopenharmony_ci
65f92157deSopenharmony_ci        inline void getMTest()
66f92157deSopenharmony_ci        {
67f92157deSopenharmony_ci            auto ret = getMTestSingleton();
68f92157deSopenharmony_ci            if (ret == nullptr) {
69f92157deSopenharmony_ci                return;
70f92157deSopenharmony_ci            }
71f92157deSopenharmony_ci        }
72f92157deSopenharmony_ci
73f92157deSopenharmony_ci        class MultiThreadFailCaseListener : public EmptyTestEventListener {
74f92157deSopenharmony_ci        private:
75f92157deSopenharmony_ci            MultiThreadTest *testInstance;
76f92157deSopenharmony_ci        public:
77f92157deSopenharmony_ci            MultiThreadFailCaseListener(MultiThreadTest *ins)
78f92157deSopenharmony_ci            {
79f92157deSopenharmony_ci                this->testInstance = ins;
80f92157deSopenharmony_ci            }
81f92157deSopenharmony_ci        };
82f92157deSopenharmony_ci
83f92157deSopenharmony_ci        inline void addPostTest(unsigned thread_id, PF func, std::string testsuite = "NA", std::string testcase = "NA")
84f92157deSopenharmony_ci        {
85f92157deSopenharmony_ci            for (unsigned int i = 0; i < g_thread_count; i++) {
86f92157deSopenharmony_ci                testInstance.appendTaskToList(thread_id, func, testsuite, testcase);
87f92157deSopenharmony_ci            }
88f92157deSopenharmony_ci        }
89f92157deSopenharmony_ci
90f92157deSopenharmony_ci        #define MTEST_ADD_TASK(thread_id, func) addPostTest(thread_id, func)
91f92157deSopenharmony_ci
92f92157deSopenharmony_ci        #define MTEST_POST_RUN()            \
93f92157deSopenharmony_ci            do {                            \
94f92157deSopenharmony_ci                getMTestSingleton()->run(); \
95f92157deSopenharmony_ci            } while (0)
96f92157deSopenharmony_ci
97f92157deSopenharmony_ci        #define SET_THREAD_NUM(n) setThreadNum(n)
98f92157deSopenharmony_ci        #define MTEST_FUNC_NAME(x, y) TC_##x_##y
99f92157deSopenharmony_ci        #define GTEST_RUN_TASK(hook) \
100f92157deSopenharmony_ci        do { \
101f92157deSopenharmony_ci            MultiThreadTest _test(g_thread_count);        \
102f92157deSopenharmony_ci            _test.runTask(_test.m_threadNum, hook, this->test_info_->test_case_name(), this->test_info_->name()); \
103f92157deSopenharmony_ci        } while (0)
104f92157deSopenharmony_ci
105f92157deSopenharmony_ci        #define MTEST_TYPE(x, y, z, n)                      \
106f92157deSopenharmony_ci            void MTEST_FUNC_NAME(x, y)();                   \
107f92157deSopenharmony_ci            z(x, y)                                         \
108f92157deSopenharmony_ci            {                                               \
109f92157deSopenharmony_ci                 SET_THREAD_NUM(n);                         \
110f92157deSopenharmony_ci                 GTEST_RUN_TASK(MTEST_FUNC_NAME(x, y));     \
111f92157deSopenharmony_ci            }                                               \
112f92157deSopenharmony_ci            void MTEST_FUNC_NAME(x, y)()
113f92157deSopenharmony_ci        #define HWMTEST(x, y, w, n) MTEST_TYPE(x, y, TEST, n)
114f92157deSopenharmony_ci        #define HWMTEST_F(x, y, w, n) MTEST_TYPE(x, y, TEST_F, n)
115f92157deSopenharmony_ci    }
116f92157deSopenharmony_ci}
117f92157deSopenharmony_ci#endif /* __MULTI_THREAD_TEST_H__ */