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 "download/downloader.h"
17 #include "monitor/download_monitor.h"
18 #include "utils/media_cached_buffer.h"
19 #include "download/network_client/http_curl_client.h"
20 #include "gtest/gtest.h"
21
22 using namespace std;
23 using namespace testing::ext;
24
25 namespace OHOS {
26 namespace Media {
27 namespace Plugins {
28 namespace HttpPlugin {
29 class DownloaderUnitTest : public testing::Test {
30 public:
31 static void SetUpTestCase(void);
32 static void TearDownTestCase(void);
33 void SetUp(void);
34 void TearDown(void);
35 protected:
36 std::shared_ptr<Downloader> downloader;
37 };
38
39 constexpr int START_POS = 10;
40 constexpr int ONE_KILO = 1024;
41 constexpr int FIR_BUFFER = 128;
42
SetUpTestCase(void)43 void DownloaderUnitTest::SetUpTestCase(void)
44 {
45 }
46
TearDownTestCase(void)47 void DownloaderUnitTest::TearDownTestCase(void)
48 {
49 }
50
SetUp(void)51 void DownloaderUnitTest::SetUp(void)
52 {
53 downloader = std::make_shared<Downloader>("test");
54 }
55
TearDown(void)56 void DownloaderUnitTest::TearDown(void)
57 {
58 downloader.reset();
59 }
60
61 HWTEST_F(DownloaderUnitTest, ClearMiddleReadFragment, TestSize.Level1)
62 {
63 CacheMediaChunkBuffer cachedMediaBuffer;
64 ASSERT_EQ(true, cachedMediaBuffer.Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE));
65 EXPECT_FALSE(cachedMediaBuffer.ClearMiddleReadFragment(10, 1000));
66 cachedMediaBuffer.IsReadSplit(100);
67 }
68
69 HWTEST_F(DownloaderUnitTest, Downloader_Construct_nullptr, TestSize.Level1)
70 {
71 EXPECT_NE(downloader->client_, nullptr);
72 }
73
74 HWTEST_F(DownloaderUnitTest, Retry_1, TestSize.Level1)
75 {
76 std::map<std::string, std::string> httpHeader;
77 RequestInfo requestInfo;
78 requestInfo.url = "http";
79 requestInfo.httpHeader = httpHeader;
80 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860102(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 81 std::shared_ptr<DownloadRequest>& request) {
82 };
__anonaa7631860202(uint8_t*&& data, uint32_t&& len, bool notblock) 83 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
84 return len;
85 };
86 std::shared_ptr<DownloadRequest> Request_ =
87 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
88 EXPECT_FALSE(downloader->Retry(Request_));
89 }
90
91 HWTEST_F(DownloaderUnitTest, Retry_2, TestSize.Level1)
92 {
93 std::map<std::string, std::string> httpHeader;
94 RequestInfo requestInfo;
95 requestInfo.url = "http";
96 requestInfo.httpHeader = httpHeader;
97 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860302(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 98 std::shared_ptr<DownloadRequest>& request) {
99 };
__anonaa7631860402(uint8_t*&& data, uint32_t&& len, bool notblock) 100 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
101 return len;
102 };
103 std::shared_ptr<DownloadRequest> Request_ =
104 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
105 downloader->isAppBackground_ = true;
106 EXPECT_TRUE(downloader->Retry(Request_));
107 }
108
109 HWTEST_F(DownloaderUnitTest, Retry_3, TestSize.Level1)
110 {
111 std::map<std::string, std::string> httpHeader;
112 RequestInfo requestInfo;
113 requestInfo.url = "http";
114 requestInfo.httpHeader = httpHeader;
115 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860502(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 116 std::shared_ptr<DownloadRequest>& request) {
117 };
__anonaa7631860602(uint8_t*&& data, uint32_t&& len, bool notblock) 118 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
119 return len;
120 };
121 std::shared_ptr<DownloadRequest> Request_ =
122 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
123 downloader->isDestructor_ = true;
124 EXPECT_FALSE(downloader->Retry(Request_));
125 }
126
127 HWTEST_F(DownloaderUnitTest, Retry_4, TestSize.Level1)
128 {
129 std::map<std::string, std::string> httpHeader;
130 RequestInfo requestInfo;
131 requestInfo.url = "http";
132 requestInfo.httpHeader = httpHeader;
133 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860702(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 134 std::shared_ptr<DownloadRequest>& request) {
135 };
__anonaa7631860802(uint8_t*&& data, uint32_t&& len, bool notblock) 136 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
137 return len;
138 };
139 std::shared_ptr<DownloadRequest> Request_ =
140 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
141 downloader->isDestructor_ = false;
142 EXPECT_FALSE(downloader->Retry(Request_));
143 }
144
145 HWTEST_F(DownloaderUnitTest, Retry_5, TestSize.Level1)
146 {
147 std::map<std::string, std::string> httpHeader;
148 RequestInfo requestInfo;
149 requestInfo.url = "http";
150 requestInfo.httpHeader = httpHeader;
151 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860902(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 152 std::shared_ptr<DownloadRequest>& request) {
153 };
__anonaa7631860a02(uint8_t*&& data, uint32_t&& len, bool notblock) 154 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
155 return len;
156 };
157 std::shared_ptr<DownloadRequest> Request_ =
158 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
159 downloader->isDestructor_ = false;
160 downloader->shouldStartNextRequest = false;
161 EXPECT_TRUE(downloader->Retry(Request_));
162 }
163
164 HWTEST_F(DownloaderUnitTest, Retry_6, TestSize.Level1)
165 {
166 std::map<std::string, std::string> httpHeader;
167 RequestInfo requestInfo;
168 requestInfo.url = "http";
169 requestInfo.httpHeader = httpHeader;
170 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860b02(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 171 std::shared_ptr<DownloadRequest>& request) {
172 };
__anonaa7631860c02(uint8_t*&& data, uint32_t&& len, bool notblock) 173 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
174 return len;
175 };
176 std::shared_ptr<DownloadRequest> Request_ =
177 std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
178 downloader->isDestructor_ = false;
179 downloader->shouldStartNextRequest = false;
180 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
181 EXPECT_TRUE(downloader->Retry(Request_));
182 }
183
TestLastCheck(CacheMediaChunkBuffer & cachedMediaBuffer)184 bool TestLastCheck(CacheMediaChunkBuffer& cachedMediaBuffer)
185 {
186 auto& fragmentCacheBuffer = cachedMediaBuffer.impl_->fragmentCacheBuffer_;
187 auto pos = fragmentCacheBuffer.begin();
188 while (pos != fragmentCacheBuffer.end()) {
189 cachedMediaBuffer.impl_->lruCache_.Delete(pos->offsetBegin);
190 cachedMediaBuffer.impl_->totalReadSize_ -= pos->totalReadSize;
191 cachedMediaBuffer.impl_->freeChunks_.splice(cachedMediaBuffer.impl_->freeChunks_.end(), pos->chunks);
192 pos = fragmentCacheBuffer.erase(pos);
193 }
194
195 auto success = cachedMediaBuffer.impl_->Check();
196 if (!success) {
197 cachedMediaBuffer.Dump(0);
198 }
199 return success;
200 }
201
TestCheck(CacheMediaChunkBuffer & cachedMediaBuffer)202 bool TestCheck(CacheMediaChunkBuffer& cachedMediaBuffer)
203 {
204 auto success = cachedMediaBuffer.impl_->Check();
205 if (!success) {
206 cachedMediaBuffer.Dump(0);
207 }
208 return success;
209 }
210
211 HWTEST_F(DownloaderUnitTest, cachedMediaBuffer, TestSize.Level1)
212 {
213 CacheMediaChunkBuffer cachedMediaBuffer;
214 ASSERT_EQ(true, cachedMediaBuffer.Init(MAX_CACHE_BUFFER_SIZE, CHUNK_SIZE));
215 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
216 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
217
218 constexpr int64_t mediaSize = ONE_KILO * ONE_KILO * 3;
219 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
220 size_t writeLen = ONE_KILO;
221 size_t* data = (size_t*)mp4Data.get();
222 for (size_t i = 0; i < mediaSize / sizeof(size_t); i++) {
223 data[i] = i;
224 }
225
226 int64_t offset1 = 0;
227 ASSERT_EQ(writeLen, cachedMediaBuffer.Write(mp4Data.get(), offset1, writeLen));
228 EXPECT_EQ(writeLen, cachedMediaBuffer.GetBufferSize(offset1));
229 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
230
231 int64_t offset2 = (int64_t)writeLen * 3;
232 ASSERT_EQ(writeLen, cachedMediaBuffer.Write(mp4Data.get(), offset2, writeLen));
233 EXPECT_EQ(writeLen, cachedMediaBuffer.GetBufferSize(offset1));
234 EXPECT_EQ((size_t)offset2, cachedMediaBuffer.GetNextBufferOffset(offset1));
235 EXPECT_EQ((size_t)offset2, cachedMediaBuffer.GetNextBufferOffset(offset1 + writeLen - 3));
236
237 cachedMediaBuffer.Dump(0);
238 EXPECT_EQ((size_t)offset2, cachedMediaBuffer.GetNextBufferOffset(offset1 + writeLen));
239 EXPECT_EQ((size_t)offset2, cachedMediaBuffer.GetNextBufferOffset(offset1 + writeLen + 1));
240 EXPECT_EQ((size_t)offset2, cachedMediaBuffer.GetNextBufferOffset(offset2 - 2));
241
242 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset2));
243 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset2 + writeLen));
244 }
245
246 HWTEST_F(DownloaderUnitTest, DeleteOtherHasReadFragmentCache, TestSize.Level1)
247 {
248 CacheMediaChunkBuffer cachedMediaBuffer;
249 uint64_t totalSize = FIR_BUFFER * ONE_KILO;
250 uint32_t chunkSize = FIR_BUFFER;
251 EXPECT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
252
253 int64_t mediaSize = ONE_KILO * 8;
254 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
255 size_t* data = (size_t*)mp4Data.get();
256 for (size_t i = 0; i < mediaSize / sizeof(size_t); i++) {
257 data[i] = i;
258 }
259
260 size_t writeLen = FIR_BUFFER * 2;
261 int64_t offset1 = 0;
262 ASSERT_EQ(writeLen, cachedMediaBuffer.Write(mp4Data.get(), offset1, writeLen));
263 EXPECT_EQ(true, cachedMediaBuffer.Check());
264
265 int64_t offset2 = FIR_BUFFER * 10;
266 size_t writeLen2 = FIR_BUFFER * 2;
267 ASSERT_EQ(writeLen2, cachedMediaBuffer.Write(mp4Data.get() + offset2, offset2, writeLen2));
268 EXPECT_EQ(true, cachedMediaBuffer.Check());
269
270 int64_t offset3 = FIR_BUFFER * 15;
271 size_t writeLen3 = FIR_BUFFER * 2;
272 ASSERT_EQ(writeLen3, cachedMediaBuffer.Write(mp4Data.get() + offset3, offset3, writeLen3));
273 EXPECT_EQ(true, cachedMediaBuffer.Check());
274
275 uint32_t buffer[ONE_KILO * 2] = {0};
276 size_t readSize = 128u;
277 ASSERT_EQ(readSize, cachedMediaBuffer.Read(buffer, offset2, readSize));
278 ASSERT_EQ(writeLen, cachedMediaBuffer.Read(buffer, offset1, writeLen));
279 EXPECT_EQ(true, cachedMediaBuffer.Check());
280
281 int64_t offset5 = writeLen;
282 size_t writeLen5 = FIR_BUFFER * 3;
283 ASSERT_EQ(writeLen5, cachedMediaBuffer.Write(mp4Data.get() + offset5, offset5, writeLen5));
284 EXPECT_EQ(true, cachedMediaBuffer.Check());
285
286 ASSERT_EQ(writeLen, cachedMediaBuffer.Read(buffer, offset1 + writeLen, writeLen));
287 EXPECT_EQ(true, cachedMediaBuffer.Check());
288
289 int64_t offset7 = writeLen5 + offset5;
290 size_t writeLen7 = FIR_BUFFER;
291 ASSERT_EQ(writeLen7, cachedMediaBuffer.Write(mp4Data.get() + offset7, offset7, writeLen7));
292 EXPECT_EQ(true, cachedMediaBuffer.Check());
293 }
294
295 HWTEST_F(DownloaderUnitTest, ReadSplitChunk_0, TestSize.Level1)
296 {
297 CacheMediaChunkBuffer cachedMediaBuffer;
298 constexpr uint32_t chunkNum = 2 * 15 * 100;
299 constexpr uint32_t chunKSizePer = 512;
300 uint64_t totalSize = chunKSizePer * chunkNum;
301 uint32_t chunkSize = chunKSizePer;
302 ASSERT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
303 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
304 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
305 constexpr int64_t mediaSize = ONE_KILO * (chunkNum + 1);
306 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
307 size_t writeLen1 = chunKSizePer * 20 + 8;
308 int64_t offset1 = 0;
309 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get(), offset1, writeLen1));
310 EXPECT_EQ(writeLen1, cachedMediaBuffer.GetBufferSize(offset1));
311 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
312 auto fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
313 EXPECT_EQ(0, fragmentInfo.chunks.front()->offset);
314 size_t readLen2 = chunkSize - 8;
315 char buffer[chunKSizePer * chunkNum] = {0};
316 EXPECT_EQ(readLen2, cachedMediaBuffer.Read(buffer, offset1, readLen2));
317 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, readLen2));
318 cachedMediaBuffer.Dump(0);
319 int64_t chunkOffsetReadBegin = 16;
320 size_t readLen3 = 512 + 8;
321 int64_t offset3 = chunKSizePer * 2 * 6 + chunkOffsetReadBegin;
322 EXPECT_EQ(true, cachedMediaBuffer.Seek(offset3));
323 EXPECT_EQ(readLen3, cachedMediaBuffer.Read(buffer, offset3, readLen3));
324 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, readLen3));
325
326 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
327 EXPECT_EQ(offset1 + (int64_t)readLen2, fragmentInfo.accessLength);
328 EXPECT_EQ((int64_t)readLen2, fragmentInfo.accessLength);
329 EXPECT_EQ(0, fragmentInfo.offsetBegin);
330 EXPECT_EQ(offset3, fragmentInfo.dataLength); // changed
331 EXPECT_EQ(*fragmentInfo.chunks.begin(), *fragmentInfo.accessPos);
332
333 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.back();
334 EXPECT_EQ((int64_t)readLen3, fragmentInfo.accessLength);
335 EXPECT_EQ(offset3, fragmentInfo.offsetBegin);
336 EXPECT_EQ((int64_t)writeLen1 - offset3, fragmentInfo.dataLength); // changed
337 EXPECT_EQ(*std::next(fragmentInfo.chunks.begin()), *fragmentInfo.accessPos);
338 cachedMediaBuffer.Dump(0);
339 ASSERT_EQ(true, TestCheck(cachedMediaBuffer));
340
341 EXPECT_EQ((size_t)offset3, cachedMediaBuffer.Read(buffer, offset1, (size_t)offset3));
342 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, (size_t)offset3));
343
344 EXPECT_EQ(writeLen1 - (size_t)offset3, cachedMediaBuffer.Read(buffer, offset3, writeLen1 - (size_t)offset3));
345 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, writeLen1 - (size_t)offset3));
346 ASSERT_EQ(true, TestLastCheck(cachedMediaBuffer));
347 }
348
349 HWTEST_F(DownloaderUnitTest, ReadSplitChunk_1, TestSize.Level1)
350 {
351 CacheMediaChunkBuffer cachedMediaBuffer;
352 constexpr uint32_t chunkNum = 2 * 15 * 100;
353 constexpr uint32_t chunKSizePer = 512;
354 uint64_t totalSize = chunKSizePer * chunkNum;
355 uint32_t chunkSize = chunKSizePer;
356 ASSERT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
357 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
358 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
359
360 constexpr int64_t mediaSize = ONE_KILO * (chunkNum + 1);
361 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
362 size_t writeLen1 = chunKSizePer * 20 + 8;
363 int64_t offset1 = 0;
364 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get(), offset1, writeLen1));
365 EXPECT_EQ(writeLen1, cachedMediaBuffer.GetBufferSize(offset1));
366 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
367 auto fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
368 EXPECT_EQ(0, fragmentInfo.chunks.front()->offset);
369
370 size_t readLen2 = chunkSize - 8;
371 char buffer[chunKSizePer * chunkNum] = {0};
372 EXPECT_EQ(readLen2, cachedMediaBuffer.Read(buffer, offset1, readLen2));
373
374 cachedMediaBuffer.Dump(0);
375
376 int64_t chunkOffsetReadBegin = 0;
377 size_t readLen3 = 512 + 8;
378 int64_t offset3 = chunKSizePer * 2 * 6 + chunkOffsetReadBegin;
379 EXPECT_EQ(true, cachedMediaBuffer.Seek(offset3));
380 EXPECT_EQ(readLen3, cachedMediaBuffer.Read(buffer, offset3, readLen3));
381 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, readLen3));
382
383 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
384 EXPECT_EQ(offset1 + (int64_t)readLen2, fragmentInfo.accessLength);
385 EXPECT_EQ((int64_t)readLen2, fragmentInfo.accessLength);
386 EXPECT_EQ(0, fragmentInfo.offsetBegin);
387 EXPECT_EQ(offset3, fragmentInfo.dataLength);
388 EXPECT_EQ(*fragmentInfo.chunks.begin(), *fragmentInfo.accessPos);
389
390 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.back();
391 EXPECT_EQ((int64_t)readLen3, fragmentInfo.accessLength);
392 EXPECT_EQ(offset3, fragmentInfo.offsetBegin);
393 EXPECT_EQ((int64_t)writeLen1 - offset3, fragmentInfo.dataLength);
394 EXPECT_EQ(*std::next(fragmentInfo.chunks.begin()), *fragmentInfo.accessPos);
395 cachedMediaBuffer.Dump(0);
396 ASSERT_EQ(true, TestCheck(cachedMediaBuffer));
397
398 EXPECT_EQ((size_t)offset3, cachedMediaBuffer.Read(buffer, offset1, (size_t)offset3));
399 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, (size_t)offset3));
400
401 EXPECT_EQ(writeLen1 - (size_t)offset3, cachedMediaBuffer.Read(buffer, offset3, writeLen1 - (size_t)offset3));
402 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, writeLen1 - (size_t)offset3));
403 ASSERT_EQ(true, TestLastCheck(cachedMediaBuffer));
404 }
405
406 HWTEST_F(DownloaderUnitTest, ReadSplitChunk_2, TestSize.Level1)
407 {
408 CacheMediaChunkBuffer cachedMediaBuffer;
409 constexpr uint32_t chunkNum = 2 * 15 * 100;
410 constexpr uint32_t chunKSizePer = 512;
411 uint64_t totalSize = chunKSizePer * chunkNum;
412 uint32_t chunkSize = chunKSizePer;
413 ASSERT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
414 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
415 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
416
417 constexpr int64_t mediaSize = ONE_KILO * (chunkNum + 1);
418 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
419
420 size_t writeLen1 = chunKSizePer * 20 + 8;
421 int64_t offset1 = 0;
422 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get(), offset1, writeLen1));
423 EXPECT_EQ(writeLen1, cachedMediaBuffer.GetBufferSize(offset1));
424 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
425 auto fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
426 EXPECT_EQ(0, fragmentInfo.chunks.front()->offset);
427
428
429 size_t writeLen2 = 10;
430 int64_t wrOffset2 = chunKSizePer * 25 + 8;
431 ASSERT_EQ(writeLen2, cachedMediaBuffer.Write(mp4Data.get(), wrOffset2, writeLen2));
432
433 size_t readLen2 = chunkSize - 8;
434 char buffer[chunKSizePer * chunkNum] = {0};
435 EXPECT_EQ(readLen2, cachedMediaBuffer.Read(buffer, offset1, readLen2));
436 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, readLen2));
437
438 cachedMediaBuffer.Dump(0);
439
440 int64_t chunkOffsetReadBegin = 0;
441 size_t readLen3 = 512 + 8;
442 int64_t offset3 = chunKSizePer * 2 * 6 + chunkOffsetReadBegin;
443 EXPECT_EQ(true, cachedMediaBuffer.Seek(offset3));
444 EXPECT_EQ(readLen3, cachedMediaBuffer.Read(buffer, offset3, readLen3));
445 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, readLen3));
446
447 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
448 EXPECT_EQ(offset1 + (int64_t)readLen2, fragmentInfo.accessLength);
449 EXPECT_EQ((int64_t)readLen2, fragmentInfo.accessLength);
450 EXPECT_EQ(0, fragmentInfo.offsetBegin);
451 EXPECT_EQ(offset3, fragmentInfo.dataLength);
452 EXPECT_EQ(*fragmentInfo.chunks.begin(), *fragmentInfo.accessPos);
453
454 fragmentInfo = *std::next(cachedMediaBuffer.impl_->fragmentCacheBuffer_.begin()) ;
455 EXPECT_EQ((int64_t)readLen3, fragmentInfo.accessLength);
456 EXPECT_EQ(offset3, fragmentInfo.offsetBegin);
457 EXPECT_EQ((int64_t)writeLen1 - offset3, fragmentInfo.dataLength);
458 EXPECT_EQ(*std::next(fragmentInfo.chunks.begin()), *fragmentInfo.accessPos);
459 cachedMediaBuffer.Dump(0);
460 ASSERT_EQ(true, TestCheck(cachedMediaBuffer));
461
462 EXPECT_EQ((size_t)offset3, cachedMediaBuffer.Read(buffer, offset1, (size_t)offset3));
463 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, (size_t)offset3));
464
465 EXPECT_EQ(writeLen1 - (size_t)offset3, cachedMediaBuffer.Read(buffer, offset3, writeLen1 - (size_t)offset3));
466 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, writeLen1 - (size_t)offset3));
467 }
468
469 HWTEST_F(DownloaderUnitTest, ReadSplitChunk_3, TestSize.Level1)
470 {
471 CacheMediaChunkBuffer cachedMediaBuffer;
472 constexpr uint32_t chunkNum = 2 * 15 * 100;
473 constexpr uint32_t chunKSizePer = 512;
474 uint64_t totalSize = chunKSizePer * chunkNum;
475 uint32_t chunkSize = chunKSizePer;
476 ASSERT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
477 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
478 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
479
480 constexpr int64_t mediaSize = ONE_KILO * (chunkNum + 1);
481 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
482
483 size_t writeLen1 = chunKSizePer * 20 + 8;
484 int64_t offset1 = chunKSizePer + 8;
485 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get() + offset1, offset1, writeLen1));
486 EXPECT_EQ(writeLen1, cachedMediaBuffer.GetBufferSize(offset1));
487 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
488 auto fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.front();
489 EXPECT_EQ(offset1, fragmentInfo.chunks.front()->offset);
490
491 size_t writeLen2 = 10;
492 int64_t wrOffset2 = 0;
493 ASSERT_EQ(writeLen2, cachedMediaBuffer.Write(mp4Data.get(), wrOffset2, writeLen2));
494
495 size_t readLen2 = chunkSize - 8;
496 char buffer[chunKSizePer * chunkNum] = {0};
497 EXPECT_EQ(readLen2, cachedMediaBuffer.Read(buffer, offset1, readLen2));
498 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, readLen2));
499
500 cachedMediaBuffer.Dump(0);
501
502 int64_t chunkOffsetReadBegin = 0;
503 size_t readLen3 = 512 + 8;
504 int64_t offset3 = chunKSizePer * 2 * 6 + chunkOffsetReadBegin;
505 EXPECT_EQ(true, cachedMediaBuffer.Seek(offset3));
506 EXPECT_EQ(readLen3, cachedMediaBuffer.Read(buffer, offset3, readLen3));
507 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, readLen3));
508 cachedMediaBuffer.Dump(0);
509 EXPECT_EQ(writeLen1, cachedMediaBuffer.GetBufferSize(offset1));
510 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(offset1));
511
512 fragmentInfo = cachedMediaBuffer.impl_->fragmentCacheBuffer_.back();
513 EXPECT_EQ((int64_t)readLen3, fragmentInfo.accessLength);
514 EXPECT_EQ(offset3, fragmentInfo.offsetBegin);
515 int64_t splitFirstLeftLenght = offset3 - offset1;
516 EXPECT_EQ((int64_t)writeLen1 - splitFirstLeftLenght, fragmentInfo.dataLength);
517 cachedMediaBuffer.Dump(0);
518
519 ASSERT_EQ(true, TestCheck(cachedMediaBuffer));
520
521 EXPECT_EQ((size_t)splitFirstLeftLenght, cachedMediaBuffer.Read(buffer, offset1, (size_t)splitFirstLeftLenght));
522 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, (size_t)splitFirstLeftLenght));
523
524 EXPECT_GT(writeLen1, (size_t)splitFirstLeftLenght);
525 EXPECT_EQ(writeLen1, cachedMediaBuffer.Read(buffer, offset1, writeLen1));
526 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset1, writeLen1));
527
528 EXPECT_EQ(writeLen1 - (size_t)offset3, cachedMediaBuffer.Read(buffer, offset3, writeLen1 - (size_t)offset3));
529 EXPECT_EQ(0, memcmp(buffer, mp4Data.get() + offset3, writeLen1 - (size_t)offset3));
530 }
531
532 HWTEST_F(DownloaderUnitTest, ReadSplitChunk_4, TestSize.Level1)
533 {
534 CacheMediaChunkBuffer cachedMediaBuffer;
535 constexpr uint32_t chunkNum = 2 * 15 * 100;
536 constexpr uint32_t chunKSizePer = 512;
537 uint64_t totalSize = chunKSizePer * chunkNum;
538 uint32_t chunkSize = chunKSizePer;
539 ASSERT_EQ(true, cachedMediaBuffer.Init(totalSize, chunkSize));
540 EXPECT_EQ(0u, cachedMediaBuffer.GetBufferSize(0));
541 EXPECT_EQ(0u, cachedMediaBuffer.GetNextBufferOffset(0));
542
543 constexpr int64_t mediaSize = ONE_KILO * (chunkNum + 1);
544 std::unique_ptr<uint8_t[]> mp4Data = std::make_unique<uint8_t[]>(mediaSize);
545 size_t* data = (size_t*) mp4Data.get();
546 for (size_t i = 0; i < mediaSize / sizeof(size_t); ++i) {
547 data[i] = i;
548 }
549
550 for (uint32_t i = 0; i < 20; ++i) {
551 size_t writeLen1 = chunKSizePer - 16;
552 int64_t offset1 = chunKSizePer * i + 8 ;
553 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get() + offset1, offset1, writeLen1));
554 }
555
556 for (uint32_t i = 0; i < 30; ++i) {
557 size_t writeLen1 = chunKSizePer - 8;
558 int64_t offset1 = chunKSizePer * i + 8 ;
559 ASSERT_EQ(writeLen1, cachedMediaBuffer.Write(mp4Data.get() + offset1, offset1, writeLen1));
560 }
561 cachedMediaBuffer.Clear();
562 ASSERT_EQ(true, TestLastCheck(cachedMediaBuffer));
563 }
564
565 HWTEST_F(DownloaderUnitTest, StopBufferring_1, TestSize.Level1)
566 {
567 downloader->StopBufferring();
568 EXPECT_NE(downloader->client_, nullptr);
569 }
570
571 HWTEST_F(DownloaderUnitTest, StopBufferring_2, TestSize.Level1)
572 {
573 downloader->task_ = std::make_shared<Task>(std::string("OS_Downloader"));
574 std::map<std::string, std::string> httpHeader;
575 RequestInfo requestInfo;
576 requestInfo.url = "http";
577 requestInfo.httpHeader = httpHeader;
578 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860d02(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 579 std::shared_ptr<DownloadRequest>& request) {
580 };
__anonaa7631860e02(uint8_t*&& data, uint32_t&& len, bool notblock) 581 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
582 return len;
583 };
584 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
585 downloader->isAppBackground_ = true;
586 downloader->StopBufferring();
587 EXPECT_NE(downloader->client_, nullptr);
588 }
589
590 HWTEST_F(DownloaderUnitTest, StopBufferring_3, TestSize.Level1)
591 {
592 downloader->task_ = std::make_shared<Task>(std::string("OS_Downloader"));
593 std::map<std::string, std::string> httpHeader;
594 RequestInfo requestInfo;
595 requestInfo.url = "http";
596 requestInfo.httpHeader = httpHeader;
597 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631860f02(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 598 std::shared_ptr<DownloadRequest>& request) {
599 };
__anonaa7631861002(uint8_t*&& data, uint32_t&& len, bool notblock) 600 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
601 return len;
602 };
603 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
604 downloader->isAppBackground_ = false;
605 downloader->StopBufferring();
606 EXPECT_NE(downloader->client_, nullptr);
607 }
608
609 HWTEST_F(DownloaderUnitTest, StopBufferring_4, TestSize.Level1)
610 {
611 std::map<std::string, std::string> httpHeader;
612 RequestInfo requestInfo;
613 requestInfo.url = "http";
614 requestInfo.httpHeader = httpHeader;
615 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631861102(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 616 std::shared_ptr<DownloadRequest>& request) {
617 };
__anonaa7631861202(uint8_t*&& data, uint32_t&& len, bool notblock) 618 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
619 return len;
620 };
621 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
622 downloader->isAppBackground_ = false;
623 downloader->StopBufferring();
624 EXPECT_NE(downloader->client_, nullptr);
625 }
626
627 HWTEST_F(DownloaderUnitTest, StopBufferring_5, TestSize.Level1)
628 {
629 downloader->task_ = std::make_shared<Task>(std::string("OS_Downloader"));
630 std::map<std::string, std::string> httpHeader;
631 RequestInfo requestInfo;
632 requestInfo.url = "http";
633 requestInfo.httpHeader = httpHeader;
634 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631861302(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 635 std::shared_ptr<DownloadRequest>& request) {
636 };
__anonaa7631861402(uint8_t*&& data, uint32_t&& len, bool notblock) 637 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
638 return len;
639 };
640 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
641 downloader->currentRequest_->startPos_ = START_POS;
642 downloader->isAppBackground_ = false;
643 downloader->shouldStartNextRequest = false;
644 downloader->StopBufferring();
645 EXPECT_NE(downloader->client_, nullptr);
646 }
647
648 HWTEST_F(DownloaderUnitTest, StopBufferring_6, TestSize.Level1)
649 {
650 downloader->task_ = std::make_shared<Task>(std::string("OS_Downloader"));
651 std::map<std::string, std::string> httpHeader;
652 RequestInfo requestInfo;
653 requestInfo.url = "http";
654 requestInfo.httpHeader = httpHeader;
655 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631861502(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 656 std::shared_ptr<DownloadRequest>& request) {
657 };
__anonaa7631861602(uint8_t*&& data, uint32_t&& len, bool notblock) 658 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
659 return len;
660 };
661 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
662 downloader->isAppBackground_ = false;
663 downloader->shouldStartNextRequest = false;
664 downloader->StopBufferring();
665 EXPECT_NE(downloader->client_, nullptr);
666 }
667
668 HWTEST_F(DownloaderUnitTest, ToString_EmptyList, TestSize.Level1)
669 {
670 list<string> lists;
671 string result = ToString(lists);
672 EXPECT_EQ(result, "");
673 }
674
675 HWTEST_F(DownloaderUnitTest, ToString_NoEmptyList, TestSize.Level1)
676 {
677 list<string> lists = {"Hello", "World"};
678 string result = ToString(lists);
679 EXPECT_EQ(result, "Hello,World");
680 }
681
682 HWTEST_F(DownloaderUnitTest, InsertCharBefore_Test1, TestSize.Level1)
683 {
684 string input = "hello world";
685 char from = 'x';
686 char preChar = 'y';
687 char nextChar = 'z';
688 string expected = "hello world";
689 string actual = InsertCharBefore(input, from, preChar, nextChar);
690 EXPECT_EQ(expected, actual);
691 }
692
693 HWTEST_F(DownloaderUnitTest, InsertCharBefore_Test2, TestSize.Level1)
694 {
695 string input = "hello world";
696 char from = 'l';
697 char preChar = 'y';
698 char nextChar = 'o';
699 string expected = "heyllo woryld";
700 string actual = InsertCharBefore(input, from, preChar, nextChar);
701 EXPECT_EQ(expected, actual);
702 }
703
704 HWTEST_F(DownloaderUnitTest, InsertCharBefore_Test3, TestSize.Level1)
705 {
706 string input = "hello world";
707 char from = 'l';
708 char preChar = 'y';
709 char nextChar = 'l';
710 string expected = "hello woryld";
711 string actual = InsertCharBefore(input, from, preChar, nextChar);
712 EXPECT_EQ(expected, actual);
713 }
714
715 HWTEST_F(DownloaderUnitTest, Trim_EmptyString, TestSize.Level1)
716 {
717 string input = "";
718 string expected = "";
719 EXPECT_EQ(Trim(input), expected);
720 }
721
722 HWTEST_F(DownloaderUnitTest, Trim_LeadingSpaces, TestSize.Level1)
723 {
724 string input = " Hello";
725 string expected = "Hello";
726 EXPECT_EQ(Trim(input), expected);
727 }
728
729 HWTEST_F(DownloaderUnitTest, Trim_TrailingSpaces, TestSize.Level1)
730 {
731 string input = "Hello ";
732 string expected = "Hello";
733 EXPECT_EQ(Trim(input), expected);
734 }
735
736 HWTEST_F(DownloaderUnitTest, Trim_LeadingAndTrailingSpaces, TestSize.Level1)
737 {
738 string input = " Hello ";
739 string expected = "Hello";
740 EXPECT_EQ(Trim(input), expected);
741 }
742
743 HWTEST_F(DownloaderUnitTest, Trim_NoSpaces, TestSize.Level1)
744 {
745 string input = "Hello";
746 string expected = "Hello";
747 EXPECT_EQ(Trim(input), expected);
748 }
749
750 HWTEST_F(DownloaderUnitTest, IsRegexValid_Test1, TestSize.Level1)
751 {
752 string regex = "";
753 bool result = IsRegexValid(regex);
754 EXPECT_EQ(result, false);
755 }
756
757 HWTEST_F(DownloaderUnitTest, IsRegexValid_Test2, TestSize.Level1)
758 {
759 string regex = "!@#$%^&*()";
760 bool result = IsRegexValid(regex);
761 EXPECT_EQ(result, false);
762 }
763
764 HWTEST_F(DownloaderUnitTest, IsRegexValid_Test3, TestSize.Level1)
765 {
766 string regex = "abc123";
767 bool result = IsRegexValid(regex);
768 EXPECT_EQ(result, true);
769 }
770
771 HWTEST_F(DownloaderUnitTest, ReplaceCharacters_01, TestSize.Level1)
772 {
773 string input = "";
774 string output = ReplaceCharacters(input);
775 EXPECT_EQ(output, "");
776 }
777
778 HWTEST_F(DownloaderUnitTest, ReplaceCharacters_02, TestSize.Level1)
779 {
780 string input = "abc";
781 string output = ReplaceCharacters(input);
782 EXPECT_EQ(output, "abc");
783 }
784
785 HWTEST_F(DownloaderUnitTest, ReplaceCharacters_03, TestSize.Level1)
786 {
787 string input = "a.b.c";
788 string output = ReplaceCharacters(input);
789 EXPECT_EQ(output, "a\\.b\\.c");
790 }
791
792 HWTEST_F(DownloaderUnitTest, ReplaceCharacters_04, TestSize.Level1)
793 {
794 string input = "a\\b\\c";
795 string output = ReplaceCharacters(input);
796 EXPECT_EQ(output, "a\\b\\c");
797 }
798
799 HWTEST_F(DownloaderUnitTest, ReplaceCharacters_05, TestSize.Level1)
800 {
801 string input = "a\\b.c";
802 string output = ReplaceCharacters(input);
803 EXPECT_EQ(output, "a\\b\\.c");
804 }
805
806 HWTEST_F(DownloaderUnitTest, IsMatch_01, TestSize.Level1)
807 {
808 string str = "test";
809 string patternStr = "";
810 bool result = IsMatch(str, patternStr);
811 EXPECT_FALSE(result);
812 }
813
814 HWTEST_F(DownloaderUnitTest, IsMatch_02, TestSize.Level1)
815 {
816 string str = "test";
817 string patternStr = "*";
818 bool result = IsMatch(str, patternStr);
819 EXPECT_TRUE(result);
820 }
821
822 HWTEST_F(DownloaderUnitTest, IsMatch_03, TestSize.Level1)
823 {
824 string str = "test";
825 string patternStr = "test";
826 bool result = IsMatch(str, patternStr);
827 EXPECT_TRUE(result);
828 }
829
830 HWTEST_F(DownloaderUnitTest, IsMatch_04, TestSize.Level1)
831 {
832 string str = "test";
833 string patternStr = "t.*";
834 bool result = IsMatch(str, patternStr);
835 EXPECT_FALSE(result);
836 }
837
838 HWTEST_F(DownloaderUnitTest, IsMatch_05, TestSize.Level1)
839 {
840 string str = "test";
841 string patternStr = "e.*";
842 bool result = IsMatch(str, patternStr);
843 EXPECT_FALSE(result);
844 }
845
846 HWTEST_F(DownloaderUnitTest, IsExcluded_01, TestSize.Level1)
847 {
848 string str = "test";
849 string exclusions = "";
850 string split = ",";
851 EXPECT_FALSE(IsExcluded(str, exclusions, split));
852 }
853
854 HWTEST_F(DownloaderUnitTest, IsExcluded_02, TestSize.Level1)
855 {
856 string str = "test";
857 string exclusions = "test,example";
858 string split = ",";
859 EXPECT_TRUE(IsExcluded(str, exclusions, split));
860 }
861
862 HWTEST_F(DownloaderUnitTest, IsExcluded_03, TestSize.Level1)
863 {
864 string str = "test";
865 string exclusions = "example,sample";
866 string split = ",";
867 EXPECT_FALSE(IsExcluded(str, exclusions, split));
868 }
869
870 HWTEST_F(DownloaderUnitTest, IsExcluded_04, TestSize.Level1)
871 {
872 string str = "test";
873 string exclusions = "example";
874 string split = ",";
875 EXPECT_FALSE(IsExcluded(str, exclusions, split));
876 }
877
878 HWTEST_F(DownloaderUnitTest, HandleRetErrorCode001, TestSize.Level1)
879 {
880 downloader->task_ = std::make_shared<Task>(std::string("OS_Downloader"));
881 std::map<std::string, std::string> httpHeader;
882 RequestInfo requestInfo;
883 requestInfo.url = "http";
884 requestInfo.httpHeader = httpHeader;
885 auto realStatusCallback = [this] (DownloadStatus&& status, std::shared_ptr<Downloader>& downloader,
__anonaa7631861702(DownloadStatus&& status, std::shared_ptr<Downloader>& downloader, std::shared_ptr<DownloadRequest>& request) 886 std::shared_ptr<DownloadRequest>& request) {
887 };
__anonaa7631861802(uint8_t*&& data, uint32_t&& len, bool notblock) 888 auto saveData = [this] (uint8_t*&& data, uint32_t&& len, bool notblock) {
889 return len;
890 };
891 downloader->currentRequest_ = std::make_shared<DownloadRequest>(saveData, realStatusCallback, requestInfo);
892 downloader->currentRequest_->serverError_ = 500;
893 downloader->HandleRetErrorCode();
894 EXPECT_NE(downloader->client_, nullptr);
895 }
896 }
897 }
898 }
899 }