1 /*
2 * Copyright (c) 2025 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 <gtest/gtest.h>
17 #include "curl/curl.h"
18 #include "http_handover_handler.h"
19 #include "request_context.h"
20
21 namespace OHOS::NetStack::HttpOverCurl {
22 namespace {
23 using namespace testing::ext;
24 static constexpr const char *REQUEST_URL = "https://127.0.0.1";
25 static constexpr const long TIMEOUT_MS = 6000;
26 static constexpr const long TIMEOUT_IMMEDIATE = 0;
27 static constexpr const long TIMEOUT_STOP = -1;
28 static constexpr const FileDescriptor FILE_DESCRIPTOR = 222;
29
GetCurlHandle()30 CURL *GetCurlHandle()
31 {
32 CURL *handle = curl_easy_init();
33 curl_easy_setopt(handle, CURLOPT_URL, REQUEST_URL);
34 curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
35 return handle;
36 }
37
GetRequestInfo()38 RequestInfo *GetRequestInfo()
39 {
40 CURL *handle = GetCurlHandle();
41 RequestInfo *requestInfo = new RequestInfo();
42 requestInfo->easyHandle = handle;
43 static auto startCallback = +[](CURL *easyHandle, void *opaqueData) {};
44 static auto responseCallback = +[](CURLMsg *curlMessage, void *opaqueData) {};
45 static auto handoverInfoCallback = +[](void *opaqueData) {
46 HttpHandoverStackInfo httpHandoverStackInfo;
47 return httpHandoverStackInfo;
48 };
49 static auto setHandoverInfoCallback = +[](HttpHandoverInfo httpHandoverInfo, void *opaqueData) {};
50 HttpOverCurl::TransferCallbacks callbacks = {
51 .startedCallback = startCallback,
52 .doneCallback = responseCallback,
53 .handoverInfoCallback = handoverInfoCallback,
54 .setHandoverInfoCallback = setHandoverInfoCallback,
55 };
56 requestInfo->callbacks = callbacks;
57 requestInfo->opaqueData = static_cast<void *>(malloc(sizeof(Http::RequestContext)));
58 return requestInfo;
59 }
60
DeleteRequestInfo(RequestInfo * requestInfo)61 void DeleteRequestInfo(RequestInfo *requestInfo)
62 {
63 free(requestInfo->opaqueData);
64 delete requestInfo;
65 }
66 }
67
68 class HttpHandoverHandlerTest : public testing::Test {
69 public:
SetUpTestCase()70 static void SetUpTestCase() {}
71
TearDownTestCase()72 static void TearDownTestCase() {}
73
SetUp()74 virtual void SetUp() {}
75
TearDown()76 virtual void TearDown() {}
77 };
78
79 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestSocketTime, TestSize.Level2)
80 {
81 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
82 curl_socket_t fd = 0;
83 EXPECT_TRUE(CheckSocketTime(netHandoverHandler.get(), fd));
84 EXPECT_TRUE(CheckSocketTime(nullptr, fd));
85 }
86
87 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestOpenSocket, TestSize.Level2)
88 {
89 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
90 curl_sockaddr addr = {AF_INET, SOCK_STREAM, 0};
91 curlsocktype purpose = CURLSOCKTYPE_IPCXN;
92 curl_socket_t sockfd = OpenSocket(netHandoverHandler.get(), purpose, &addr);
93 EXPECT_GE(sockfd, 0);
94 }
95
96 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestCloseSocketCallback, TestSize.Level2)
97 {
98 auto netHandoverHandler = std::make_shared<HttpHandoverHandler>();
99 curl_socket_t fd = 0;
100 int ret = CloseSocketCallback(netHandoverHandler.get(), fd);
101 EXPECT_EQ(ret, 0);
102 }
103
104 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestEvent, TestSize.Level2)
105 {
106 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
107 netHandoverHandler->Initialize();
108 netHandoverHandler->IsInitSuccess();
109
110 Epoller poller;
111 netHandoverHandler->RegisterForPolling(poller);
112 netHandoverHandler->SetHandoverEvent();
113 netHandoverHandler->SetHandoverTimeoutEvent(TIMEOUT_MS);
114 netHandoverHandler->SetHandoverTimeoutEvent(TIMEOUT_IMMEDIATE);
115 netHandoverHandler->SetHandoverTimeoutEvent(TIMEOUT_STOP);
116
117 FileDescriptor descriptor = FILE_DESCRIPTOR;
118 EXPECT_TRUE(!netHandoverHandler->IsItHandoverEvent(descriptor));
119 EXPECT_TRUE(!netHandoverHandler->IsItHandoverTimeoutEvent(descriptor));
120 }
121
122 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestCallbackEvent, TestSize.Level2)
123 {
124 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
125 HandoverCallback(static_cast<void*>(netHandoverHandler.get()));
126 HandoverTimerCallback(static_cast<void*>(netHandoverHandler.get()), TIMEOUT_MS);
127 HandoverCallback(nullptr);
128 HandoverTimerCallback(nullptr, TIMEOUT_MS);
129 netHandoverHandler->HandoverTimeoutCallback();
130
131 RequestInfo *requestInfo = GetRequestInfo();
132 netHandoverHandler->SetCallback(requestInfo);
133 std::map<CURL *, RequestInfo *> ongoingRequests;
134 CURLM *multi = curl_multi_init();
135 netHandoverHandler->SetHandoverEvent();
136 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
137 DeleteRequestInfo(requestInfo);
138
139 CURL *handle = GetCurlHandle();
140 EXPECT_EQ(netHandoverHandler->IsRequestRead(handle), 0);
141 }
142
143 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestHandoverQuery, TestSize.Level2)
144 {
145 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
146 netHandoverHandler->HandoverQuery();
147 EXPECT_EQ(netHandoverHandler->GetStatus(), HttpHandoverHandler::INIT);
148 EXPECT_EQ(netHandoverHandler->GetNetId(), 0);
149 int32_t netId = 100;
150 netHandoverHandler->SetNetId(netId);
151 EXPECT_EQ(netHandoverHandler->GetNetId(), netId);
152 }
153
154 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestCheckSocket, TestSize.Level2)
155 {
156 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
157 curl_socket_t fd = 0;
158 netHandoverHandler->SetSocketOpenTime(fd);
159 netHandoverHandler->EraseFd(fd);
160 EXPECT_EQ(netHandoverHandler->CheckSocketOpentimeLessThanEndTime(fd), 0);
161 }
162
163 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestTryFlowControl, TestSize.Level2)
164 {
165 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
166 RequestInfo *requestInfo = GetRequestInfo();
167 netHandoverHandler->SetStatus(HttpHandoverHandler::INIT);
168 EXPECT_FALSE(netHandoverHandler->TryFlowControl(requestInfo, HandoverRequestType::INCOMING));
169 netHandoverHandler->SetStatus(HttpHandoverHandler::START);
170 EXPECT_TRUE(netHandoverHandler->TryFlowControl(requestInfo, HandoverRequestType::INCOMING));
171 EXPECT_TRUE(netHandoverHandler->TryFlowControl(requestInfo, HandoverRequestType::NETWORKERROR));
172 EXPECT_TRUE(netHandoverHandler->TryFlowControl(requestInfo, HandoverRequestType::UNDONE));
173 netHandoverHandler->SetStatus(HttpHandoverHandler::FATAL);
174 EXPECT_FALSE(netHandoverHandler->TryFlowControl(requestInfo, HandoverRequestType::INCOMING));
175 DeleteRequestInfo(requestInfo);
176 }
177
178 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestHandoverRequestCallback, TestSize.Level2)
179 {
180 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
181 RequestInfo *requestInfo = GetRequestInfo();
182 std::map<CURL *, RequestInfo *> ongoingRequests;
183 ongoingRequests[requestInfo->easyHandle] = requestInfo;
184 CURLM *multi = curl_multi_init();
185
186 netHandoverHandler->SetHandoverEvent();
187 netHandoverHandler->SetStatus(HttpHandoverHandler::START);
188 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
189 netHandoverHandler->SetHandoverEvent();
190 netHandoverHandler->SetStatus(HttpHandoverHandler::END);
191 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
192 netHandoverHandler->SetHandoverEvent();
193 netHandoverHandler->SetStatus(HttpHandoverHandler::TIMEOUT);
194 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
195 netHandoverHandler->SetHandoverEvent();
196 netHandoverHandler->SetStatus(HttpHandoverHandler::FATAL);
197 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
198 EXPECT_EQ(netHandoverHandler->GetStatus(), HttpHandoverHandler::FATAL);
199 DeleteRequestInfo(requestInfo);
200 }
201
202 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestRetransRequest, TestSize.Level2)
203 {
204 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
205 std::map<CURL *, RequestInfo *> ongoingRequests;
206 CURLM *multi = curl_multi_init();
207 RequestInfo *requestInfo = GetRequestInfo();
208 EXPECT_TRUE(netHandoverHandler->RetransRequest(ongoingRequests, multi, requestInfo));
209 DeleteRequestInfo(requestInfo);
210 }
211
212 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestIsNetworkErrorTypeCorrect, TestSize.Level2)
213 {
214 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
215 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_SEND_ERROR));
216 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_RECV_ERROR));
217
218 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_COULDNT_RESOLVE_HOST));
219 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_COULDNT_CONNECT));
220 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_SSL_CONNECT_ERROR));
221 EXPECT_TRUE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_QUIC_CONNECT_ERROR));
222
223 EXPECT_FALSE(netHandoverHandler->IsNetworkErrorTypeCorrect(CURLE_OK));
224 }
225
226 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestCheckRequestCanRetrans, TestSize.Level2)
227 {
228 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
229 RequestInfo *requestInfo = GetRequestInfo();
230
231 EXPECT_TRUE(netHandoverHandler->CheckRequestCanRetrans(
232 requestInfo, HandoverRequestType::INCOMING, CURLE_SEND_ERROR));
233 EXPECT_TRUE(netHandoverHandler->CheckRequestCanRetrans(
234 requestInfo, HandoverRequestType::NETWORKERROR, CURLE_RECV_ERROR));
235 EXPECT_TRUE(netHandoverHandler->CheckRequestCanRetrans(
236 requestInfo, HandoverRequestType::OLD, CURLE_COULDNT_RESOLVE_HOST));
237 EXPECT_TRUE(netHandoverHandler->CheckRequestCanRetrans(
238 requestInfo, HandoverRequestType::UNDONE, CURLE_COULDNT_CONNECT));
239 DeleteRequestInfo(requestInfo);
240 }
241
242 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestUndoneRequestHandle, TestSize.Level2)
243 {
244 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
245 RequestInfo *requestInfo = GetRequestInfo();
246 std::map<CURL *, RequestInfo *> ongoingRequests;
247 ongoingRequests[requestInfo->easyHandle] = requestInfo;
248 CURLM *multi = curl_multi_init();
249 netHandoverHandler->UndoneRequestHandle(ongoingRequests, multi);
250 DeleteRequestInfo(requestInfo);
251 }
252
253 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestProcessRequestErr, TestSize.Level2)
254 {
255 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
256 std::map<CURL *, RequestInfo *> ongoingRequests;
257 CURLM *multi = curl_multi_init();
258 RequestInfo *requestInfo = GetRequestInfo();
259 CURLMsg message;
260 message.msg = CURLMSG_DONE;
261 message.data.result = CURLE_SEND_ERROR;
262 EXPECT_EQ(netHandoverHandler->ProcessRequestErr(ongoingRequests, multi, requestInfo, &message), 0);
263 DeleteRequestInfo(requestInfo);
264 }
265
266 HWTEST_F(HttpHandoverHandlerTest, HttpHandoverHandlerTestProcessRequestNetErrorErrorType, TestSize.Level2)
267 {
268 std::shared_ptr<HttpHandoverHandler> netHandoverHandler = std::make_shared<HttpHandoverHandler>();
269 std::map<CURL *, RequestInfo *> ongoingRequests;
270 CURLM *multi = curl_multi_init();
271 RequestInfo *requestInfo = GetRequestInfo();
272 CURLMsg message;
273
274 netHandoverHandler->SetHandoverEvent();
275 netHandoverHandler->HandoverRequestCallback(ongoingRequests, multi);
276 message.msg = CURLMSG_DONE;
277 message.data.result = CURLE_SEND_ERROR;
278 EXPECT_FALSE(netHandoverHandler->ProcessRequestNetError(ongoingRequests, multi, requestInfo, &message));
279 DeleteRequestInfo(requestInfo);
280 }
281 }