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_monitor.h"
27 #include "sched/scheduler.h"
28 #include "../common.h"
29
30 using namespace std;
31 using namespace ffrt;
32 using namespace testing;
33 #ifdef HWTEST_TESTING_EXT_ENABLE
34 using namespace testing::ext;
35 #endif
36
37 class CoroutineTest : public testing::Test {
38 protected:
SetUpTestCase()39 static void SetUpTestCase()
40 {
41 }
42
TearDownTestCase()43 static void TearDownTestCase()
44 {
45 }
46
SetUp()47 virtual void SetUp()
48 {
49 }
50
TearDown()51 virtual void TearDown()
52 {
53 }
54 };
55 constexpr int BLOCKED_COUNT = 3;
56
57 typedef struct {
58 int count;
59 std::mutex lock;
60 } StacklessCoroutine1;
61
stackless_coroutine(void * co)62 ffrt_coroutine_ret_t stackless_coroutine(void* co)
63 {
64 StacklessCoroutine1* stacklesscoroutine = reinterpret_cast<StacklessCoroutine1*>(co);
65 std::lock_guard lg(stacklesscoroutine->lock);
66 printf("stacklesscoroutine %d\n", stacklesscoroutine->count);
67 stacklesscoroutine->count++;
68 if (stacklesscoroutine->count < BLOCKED_COUNT) {
69 ffrt_wake_coroutine(ffrt_get_current_task());
70 return ffrt_coroutine_pending;
71 } else if (stacklesscoroutine->count == BLOCKED_COUNT) {
72 ffrt_wake_coroutine(ffrt_get_current_task());
73 return ffrt_coroutine_pending;
74 } else {
75 return ffrt_coroutine_ready;
76 }
77 return ffrt_coroutine_pending;
78 }
79
exec_stackless_coroutine(void * co)80 ffrt_coroutine_ret_t exec_stackless_coroutine(void *co)
81 {
82 return stackless_coroutine(co);
83 }
84
destroy_stackless_coroutine(void * co)85 void destroy_stackless_coroutine(void *co)
86 {
87 }
88
89 HWTEST_F(CoroutineTest, coroutine_submit_succ, TestSize.Level1)
90 {
91 StacklessCoroutine1 co1 = {0};
92 StacklessCoroutine1 co2 = {0};
93 ffrt_task_attr_t attr;
94 ffrt_task_attr_init(&attr);
95 ffrt_submit_coroutine((void *)&co1, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
96 ffrt_submit_coroutine((void *)&co2, exec_stackless_coroutine, destroy_stackless_coroutine, NULL, NULL, &attr);
97 ffrt_poller_wakeup(ffrt_qos_default);
98 usleep(100000);
99 EXPECT_EQ(co1.count, 4);
100 EXPECT_EQ(co2.count, 4);
101 }
102
103 HWTEST_F(CoroutineTest, coroutine_submit_fail, TestSize.Level1)
104 {
105 EXPECT_EQ(ffrt_get_current_task(), nullptr);
106
107 ffrt_task_attr_t attr;
108 ffrt_task_attr_init(&attr);
109
110 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
111 ffrt_submit_coroutine(nullptr, nullptr, nullptr, NULL, NULL, &attr);
112 }
113
114 struct TestData {
115 int fd;
116 uint64_t expected;
117 };
118
testCallBack(void * token,uint32_t event)119 static void testCallBack(void* token, uint32_t event)
120 {
121 struct TestData* testData = reinterpret_cast<TestData*>(token);
122 uint64_t value = 0;
123 ssize_t n = read(testData->fd, &value, sizeof(uint64_t));
124 EXPECT_EQ(n, sizeof(value));
125 EXPECT_EQ(value, testData->expected);
126 }
127
128 HWTEST_F(CoroutineTest, ffrt_epoll_ctl_add_del, TestSize.Level1)
129 {
130 uint64_t expected = 0xabacadae;
131 int testFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
132
__anon9765910f0202() 133 ffrt::submit([&]() {
134 ssize_t n = write(testFd, &expected, sizeof(uint64_t));
135 EXPECT_EQ(sizeof(n), sizeof(uint32_t));
136 }, {}, {});
137
138 struct TestData testData {.fd = testFd, .expected = expected};
139 ffrt_epoll_ctl(ffrt_qos_default, EPOLL_CTL_ADD, testFd, EPOLLIN, reinterpret_cast<void*>(&testData), testCallBack);
140 usleep(100);
141 ffrt_epoll_ctl(ffrt_qos_default, EPOLL_CTL_DEL, testFd, 0, nullptr, nullptr);
142 close(testFd);
143 }