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