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 }