1 /*
2 * Copyright (c) 2023 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 <thread>
17 #include <chrono>
18 #include <gtest/gtest.h>
19 #include <sys/eventfd.h>
20 #include <sys/epoll.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <cstdint>
24 #include "c/executor_task.h"
25 #include "ffrt_inner.h"
26 #include "eu/cpu_worker.h"
27 #include "eu/co_routine.h"
28 #include "sched/scheduler.h"
29 #include "../common.h"
30 #include "tm/scpu_task.h"
31
32 using namespace std;
33 using namespace ffrt;
34 using namespace testing;
35 #ifdef HWTEST_TESTING_EXT_ENABLE
36 using namespace testing::ext;
37 #endif
38 #ifdef APP_USE_ARM
39 #define SIZEOF_BYTES sizeof(uint32_t)
40 #else
41 #define SIZEOF_BYTES sizeof(uint64_t)
42 #endif
43 class CoroutineTest : public testing::Test {
44 protected:
SetUpTestCase()45 static void SetUpTestCase()
46 {
47 }
48
TearDownTestCase()49 static void TearDownTestCase()
50 {
51 }
52
SetUp()53 void SetUp() override
54 {
55 }
56
TearDown()57 void TearDown() override
58 {
59 }
60 };
61 constexpr int BLOCKED_COUNT = 3;
62
63 typedef struct {
64 std::atomic<int> count;
65 std::mutex lock;
66 } StacklessCoroutine1;
67
stackless_coroutine(void * co)68 ffrt_coroutine_ret_t stackless_coroutine(void* co)
69 {
70 StacklessCoroutine1* stacklesscoroutine = reinterpret_cast<StacklessCoroutine1*>(co);
71 std::lock_guard lg(stacklesscoroutine->lock);
72 printf("stacklesscoroutine %d\n", stacklesscoroutine->count.load());
73 stacklesscoroutine->count++;
74 if (stacklesscoroutine->count < BLOCKED_COUNT) {
75 ffrt_wake_coroutine(ffrt_get_current_task());
76 return ffrt_coroutine_pending;
77 } else if (stacklesscoroutine->count == BLOCKED_COUNT) {
78 ffrt_wake_coroutine(ffrt_get_current_task());
79 return ffrt_coroutine_pending;
80 } else {
81 return ffrt_coroutine_ready;
82 }
83 return ffrt_coroutine_pending;
84 }
85
exec_stackless_coroutine(void * co)86 ffrt_coroutine_ret_t exec_stackless_coroutine(void *co)
87 {
88 return stackless_coroutine(co);
89 }
90
destroy_stackless_coroutine(void * co)91 void destroy_stackless_coroutine(void *co)
92 {
93 }
94
95 HWTEST_F(CoroutineTest, coroutine_submit_succ, TestSize.Level0)
96 {
97 // coroutine_submit_004
98 StacklessCoroutine1 co1 = {0};
99 StacklessCoroutine1 co2 = {0};
100 ffrt_task_attr_t attr;
101 ffrt_task_attr_init(&attr);
102 ffrt_submit_coroutine((void *)&co1, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
103 ffrt_submit_coroutine((void *)&co2, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
104 // ffrt_poller_wakeup_001
105 ffrt_poller_wakeup(ffrt_qos_default);
106 usleep(100000);
107 EXPECT_EQ(co1.count, 4);
108 EXPECT_EQ(co2.count, 4);
109
110 ffrt_wake_coroutine(nullptr);
111 }
112
113 HWTEST_F(CoroutineTest, coroutine_submit_fail, TestSize.Level0)
114 {
115 // get_task_001
116 EXPECT_EQ(ffrt_get_current_task(), nullptr);
117
118 ffrt_task_attr_t attr;
119 ffrt_task_attr_init(&attr);
120
121 // coroutine_submit_001
122 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
123 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
124 }
125
126 struct TestData {
127 int fd;
128 uint64_t expected;
129 };
130
testCallBack(void * token,uint32_t event)131 static void testCallBack(void* token, uint32_t event)
132 {
133 struct TestData* testData = reinterpret_cast<TestData*>(token);
134 uint64_t value = 0;
135 ssize_t n = read(testData->fd, &value, sizeof(uint64_t));
136 EXPECT_EQ(n, sizeof(value));
137 EXPECT_EQ(value, testData->expected);
138 printf("cb done\n");
139 }
140
141 /*
142 * 测试用例名称:ffrt_get_current_coroutine_stack_success
143 * 测试用例描述:ffrt_get_current_coroutine_stack获取当前协程栈成功
144 * 预置条件 :提交ffrt任务
145 * 操作步骤 :在ffrt任务中调用ffrt_get_current_coroutine_stack接口
146 * 预期结果 :获取协程栈地址和大小成功
147 */
148 HWTEST_F(CoroutineTest, ffrt_get_current_coroutine_stack_success, TestSize.Level0)
149 {
150 ffrt_queue_attr_t queue_attr;
151 (void)ffrt_queue_attr_init(&queue_attr);
152 ffrt_queue_t queue_handle = ffrt_queue_create(ffrt_queue_serial, "test_queue", &queue_attr);
153
__anon043cf0790202() 154 std::function<void()>&& OnePlusFunc = [&]() {
155 void* stackAddr = nullptr;
156 size_t size = 0;
157 bool ret = ffrt_get_current_coroutine_stack(&stackAddr, &size);
158 if (ffrt::USE_COROUTINE) {
159 EXPECT_EQ(ret, true);
160 EXPECT_NE(stackAddr, nullptr);
161 EXPECT_NE(size, 0);
162 } else {
163 EXPECT_EQ(ret, false);
164 EXPECT_EQ(stackAddr, nullptr);
165 EXPECT_EQ(size, 0);
166 }
167 };
168 ffrt_task_handle_t task = ffrt_queue_submit_h(queue_handle,
169 ffrt::create_function_wrapper(OnePlusFunc, ffrt_function_kind_queue), nullptr);
170 const std::vector<ffrt_dependence_t> wait_deps = {{ffrt_dependence_task, task}};
171 ffrt_deps_t wait{static_cast<uint32_t>(wait_deps.size()), wait_deps.data()};
172 ffrt_wait_deps(&wait);
173 ffrt_task_handle_destroy(task);
174 ffrt_queue_attr_destroy(&queue_attr);
175 ffrt_queue_destroy(queue_handle);
176 }
177