1/*
2 * Copyright (c) 2021 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 "host_uart_test.h"
17
18#include <chrono>
19#include <random>
20#include <thread>
21
22#include "server.h"
23
24using namespace std::chrono;
25using namespace std::chrono_literals;
26using namespace testing::ext;
27using namespace testing;
28
29namespace Hdc {
30class HdcHostUARTTest : public testing::Test {
31public:
32    static void SetUpTestCase(void);
33    static void TearDownTestCase(void);
34    void SetUp();
35    void TearDown();
36
37    constexpr static int PAIR = 2;
38    constexpr static int SENDER = 0;
39    constexpr static int RECEIVER = 1;
40
41    std::default_random_engine rnd;
42    const std::string nullDevPath = "/dev/null";
43    class MockHdcServer : public HdcServer {
44        MockHdcServer() : HdcServer(true) {};
45        MOCK_METHOD3(AdminDaemonMap, string(uint8_t, const string &, HDaemonInfo &));
46        MOCK_METHOD1(EnumUARTDeviceRegister, void(UartKickoutZombie));
47        MOCK_METHOD4(MallocSession, HSession(bool, const ConnType, void *, uint32_t));
48        MOCK_METHOD1(FreeSession, void(const uint32_t));
49        MOCK_METHOD3(AdminSession, HSession(const uint8_t, const uint32_t, HSession));
50        MOCK_METHOD2(EchoToClientsForSession, void(uint32_t, const string &));
51    } mockServer;
52
53    class MockBaseInterface : public ExternInterface {
54    public:
55        MOCK_METHOD4(StartWorkThread, int(uv_loop_t *, uv_work_cb, uv_after_work_cb, void *));
56        MOCK_METHOD2(TryCloseHandle, void(const uv_handle_t *, uv_close_cb));
57        MOCK_METHOD3(TimerUvTask, bool(uv_loop_t *, void *, uv_timer_cb));
58        MOCK_METHOD3(SendToStream, int(uv_stream_t *, const uint8_t *, const int));
59        MOCK_METHOD3(SendToPollFd, int(int, const uint8_t *, const int));
60        MOCK_METHOD6(DelayDo, bool(uv_loop_t *, const int, const uint8_t, string, void *, DelayCB));
61        MOCK_METHOD4(UvTimerStart, bool(uv_timer_t *, uv_timer_cb, uint64_t, uint64_t));
62    } mockInterface;
63
64    class MockHdcHostUART : public HdcHostUART {
65    public:
66        explicit MockHdcHostUART(HdcServer &daemonIn,
67                        ExternInterface &externInterface = HdcUARTBase::defaultInterface)
68            : HdcHostUART(daemonIn, externInterface)
69        {
70        }
71        MOCK_METHOD0(StartupUARTWork, RetErrCode());
72        MOCK_METHOD0(UartWriteThread, void());
73        MOCK_METHOD1(CloseSerialPort, void(const HUART));
74        MOCK_METHOD1(EnumSerialPort, bool(bool &));
75        MOCK_METHOD0(Stop, void());
76        MOCK_METHOD3(UpdateUARTDaemonInfo, void(const std::string &, HSession, ConnStatus));
77        MOCK_METHOD1(StartUartReadThread, bool(HSession));
78        MOCK_METHOD0(StartUartSendThread, bool());
79        MOCK_METHOD0(WatchUartDevPlugin, void());
80        MOCK_METHOD1(OpenSerialPort, int(const std::string &));
81        MOCK_METHOD1(UartReadThread, void(HSession));
82        MOCK_METHOD3(SendUARTRaw, bool(HSession, uint8_t *, const size_t));
83        MOCK_METHOD3(RequestSendPackage, void(uint8_t *, const size_t, bool));
84        MOCK_METHOD1(UartSendThread, void(HSession));
85        MOCK_METHOD0(SendPkgInUARTOutMap, void());
86        MOCK_METHOD1(IsDeviceOpened, bool(const HdcUART &));
87        MOCK_METHOD3(ReadUartDev, ssize_t(std::vector<uint8_t> &, size_t, HdcUART &));
88        MOCK_METHOD1(NeedStop, bool(const HSession));
89        MOCK_METHOD2(PackageProcess, size_t(vector<uint8_t> &, HSession hSession));
90        MOCK_METHOD1(OnTransferError, void(const HSession));
91        MOCK_METHOD1(ClearUARTOutMap, void(uint32_t));
92    } mockHostUART;
93
94    HdcSession mySession;
95    HdcUART myUART;
96    const int testSerialHandle = 0x1234;
97    const std::string testSerialPortName = "COMX";
98
99    HdcHostUARTTest() : mockHostUART(mockServer, mockInterface)
100    {
101        myUART.serialPort = testSerialPortName;
102        myUART.devUartHandle = testSerialHandle;
103        mySession.hUART = &myUART;
104        mySession.classModule = &mockHostUART;
105        mySession.classInstance = &mockServer;
106    };
107};
108
109void HdcHostUARTTest::SetUpTestCase()
110{
111#ifdef UT_DEBUG
112    Hdc::Base::SetLogLevel(LOG_ALL);
113#else
114    Hdc::Base::SetLogLevel(LOG_OFF);
115#endif
116}
117
118void HdcHostUARTTest::TearDownTestCase() {}
119
120void HdcHostUARTTest::SetUp()
121{
122    // The destructor will call these
123    EXPECT_CALL(mockHostUART, Stop).Times(AnyNumber());
124    EXPECT_CALL(mockInterface, TryCloseHandle).Times(AnyNumber());
125}
126
127void HdcHostUARTTest::TearDown()
128{
129    // session will close mockDaemon.loopMain ,so we dont need close it in UT
130
131    // ~HdcHostUART will call close
132}
133
134/*
135 * @tc.name: HdcHostUART
136 * @tc.desc: Check the behavior of the HdcHostUART function
137 * @tc.type: FUNC
138 */
139HWTEST_F(HdcHostUARTTest, HdcHostUART, TestSize.Level1)
140{
141    HdcHostUART hostUart(mockServer);
142    EXPECT_EQ(hostUart.uartOpened, false);
143    EXPECT_EQ(hostUart.baudRate, 0u);
144    EXPECT_EQ(hostUart.mapIgnoreDevice.empty(), true);
145    EXPECT_EQ(hostUart.serialPortInfo.empty(), true);
146
147    hostUart.devUartWatcher.data = this;
148    uv_timer_start(
149        &hostUart.devUartWatcher,
150        [](uv_timer_s *timer) {
151            EXPECT_NE(timer->data, nullptr);
152            timer->data = nullptr;
153        },
154        100, 0);
155
156    std::this_thread::sleep_for(200ms);
157    uv_run(&mockServer.loopMain, UV_RUN_NOWAIT);
158
159    EXPECT_EQ(hostUart.devUartWatcher.data, nullptr);
160    EXPECT_EQ(hostUart.semUartDevCheck.try_lock(), true);
161
162    EXPECT_NE(uv_has_ref(reinterpret_cast<uv_handle_t *>(&hostUart.devUartWatcher)), 0);
163}
164
165/*
166 * @tc.name: Initial
167 * @tc.desc: Check the behavior of the Initial function
168 * @tc.type: FUNC
169 */
170HWTEST_F(HdcHostUARTTest, Initial, TestSize.Level1)
171{
172    EXPECT_CALL(mockHostUART, StartupUARTWork).Times(1);
173    EXPECT_EQ(mockHostUART.Initial(), 0);
174    EXPECT_EQ(mockHostUART.uartOpened, false);
175    EXPECT_EQ(mockHostUART.stopped, false);
176}
177
178/*
179 * @tc.name: Stop
180 * @tc.desc: Check the behavior of the Stop function
181 * @tc.type: FUNC
182 */
183HWTEST_F(HdcHostUARTTest, Stop, TestSize.Level1)
184{
185    ON_CALL(mockHostUART, Stop).WillByDefault(Invoke([&]() {
186        return mockHostUART.HdcHostUART::Stop();
187    }));
188    EXPECT_CALL(mockHostUART, Stop).Times(1);
189    EXPECT_CALL(
190        mockInterface,
191        TryCloseHandle(reinterpret_cast<uv_handle_t *>(&mockHostUART.devUartWatcher), nullptr))
192        .Times(1);
193    mockHostUART.Stop();
194
195    // unable stop twice
196    EXPECT_CALL(mockHostUART, Stop).Times(1);
197    EXPECT_CALL(mockInterface, TryCloseHandle).Times(0);
198    mockHostUART.Stop();
199}
200
201/*
202 * @tc.name: ConnectDaemonByUart
203 * @tc.desc: Check the behavior of the ConnectDaemonByUart function
204 * @tc.type: FUNC
205 */
206HWTEST_F(HdcHostUARTTest, ConnectDaemonByUart, TestSize.Level1)
207{
208    mockHostUART.uartOpened = true;
209
210    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo(mySession.connectKey, &mySession, STATUS_READY))
211        .Times(1);
212    EXPECT_CALL(mockHostUART, StartUartReadThread(&mySession)).Times(1).WillOnce(Return(true));
213    EXPECT_CALL(mockInterface, StartWorkThread(&mockServer.loopMain, mockServer.SessionWorkThread,
214                                               Base::FinishWorkThread, &mySession))
215        .Times(1);
216    EXPECT_CALL(
217        mockInterface,
218        SendToPollFd(mySession.ctrlFd[STREAM_MAIN], _, _))
219        .Times(1);
220    mySession.childLoop.active_handles = 1;
221    EXPECT_EQ(mockHostUART.ConnectDaemonByUart(&mySession), &mySession);
222
223    // delay case
224    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo(mySession.connectKey, &mySession, STATUS_READY))
225        .Times(1);
226    EXPECT_CALL(mockHostUART, StartUartReadThread(&mySession)).Times(1).WillOnce(Return(true));
227    EXPECT_CALL(mockInterface, StartWorkThread(&mockServer.loopMain, mockServer.SessionWorkThread,
228                                               Base::FinishWorkThread, &mySession))
229        .Times(1);
230    EXPECT_CALL(
231        mockInterface,
232        SendToPollFd(mySession.ctrlFd[STREAM_MAIN], _, _))
233        .Times(1);
234
235    mySession.childLoop.active_handles = 0;
236    std::thread mockActiveHandles([&]() {
237        std::this_thread::sleep_for(1000ms);
238        mySession.childLoop.active_handles = 1;
239    });
240    EXPECT_EQ(mockHostUART.ConnectDaemonByUart(&mySession), &mySession);
241    mockActiveHandles.join();
242}
243
244/*
245 * @tc.name: ConnectDaemonByUart
246 * @tc.desc: Check the behavior of the ConnectDaemonByUart function
247 * @tc.type: FUNC
248 */
249HWTEST_F(HdcHostUARTTest, ConnectDaemonByUartFail, TestSize.Level1)
250{
251    mockHostUART.uartOpened = false;
252    EXPECT_EQ(mockHostUART.ConnectDaemonByUart(&mySession), nullptr);
253
254    mockHostUART.uartOpened = true;
255    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo(mySession.connectKey, &mySession, STATUS_READY))
256        .Times(1);
257    EXPECT_CALL(mockHostUART, StartUartReadThread).Times(1).WillOnce(Return(false));
258    EXPECT_EQ(mockHostUART.ConnectDaemonByUart(&mySession), nullptr);
259}
260
261/*
262 * @tc.name: UvWatchUartDevPlugin
263 * @tc.desc: Check the behavior of the UvWatchUartDevPlugin function
264 * @tc.type: FUNC
265 */
266HWTEST_F(HdcHostUARTTest, UvWatchUartDevPlugin, TestSize.Level1)
267{
268    EXPECT_CALL(mockHostUART, WatchUartDevPlugin).Times(0);
269    HdcHostUART::UvWatchUartDevPlugin(nullptr);
270
271    EXPECT_CALL(mockHostUART, WatchUartDevPlugin()).Times(1);
272    uv_timer_t handle;
273    handle.data = &mockHostUART;
274    HdcHostUART::UvWatchUartDevPlugin(&handle);
275
276    handle.data = nullptr;
277    HdcHostUART::UvWatchUartDevPlugin(&handle);
278}
279
280/*
281 * @tc.name: WatchUartDevPlugin
282 * @tc.desc: Check the behavior of the WatchUartDevPlugin function
283 * @tc.type: FUNC
284 */
285HWTEST_F(HdcHostUARTTest, WatchUartDevPluginHaveSerialDaemon, TestSize.Level1)
286{
287    EXPECT_CALL(mockHostUART, WatchUartDevPlugin).WillRepeatedly([&]() {
288        mockHostUART.HdcHostUART::WatchUartDevPlugin();
289    });
290    // case 1 EnumSerialPort failed
291    EXPECT_CALL(mockHostUART, EnumSerialPort).WillOnce(Return(false));
292    EXPECT_CALL(mockServer, AdminDaemonMap).Times(0);
293    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo).Times(0);
294    mockHostUART.WatchUartDevPlugin();
295
296    // case 2 EnumSerialPort not fail but no port change
297    EXPECT_CALL(mockHostUART, EnumSerialPort)
298        .WillOnce(DoAll(SetArgReferee<0>(false), Return(true)));
299    EXPECT_CALL(mockServer, AdminDaemonMap).Times(0);
300    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo).Times(0);
301    mockHostUART.WatchUartDevPlugin();
302}
303
304/*
305 * @tc.name: WatchUartDevPlugin
306 * @tc.desc: Check the behavior of the WatchUartDevPlugin function
307 * @tc.type: FUNC
308 */
309HWTEST_F(HdcHostUARTTest, WatchUartDevPluginHaveSomePort, TestSize.Level1)
310{
311    EXPECT_CALL(mockHostUART, WatchUartDevPlugin).WillRepeatedly([&]() {
312        mockHostUART.HdcHostUART::WatchUartDevPlugin();
313    });
314
315    // case 3 EnumSerialPort return two port, not port removed
316    // one port is not connected , the other is connected
317    EXPECT_CALL(mockHostUART, EnumSerialPort).WillOnce(DoAll(SetArgReferee<0>(true), Return(true)));
318    mockHostUART.serialPortInfo.clear();
319    mockHostUART.serialPortInfo.emplace_back("COMX");
320    mockHostUART.serialPortInfo.emplace_back("COMY");
321    mockHostUART.connectedPorts.clear();
322    mockHostUART.connectedPorts.emplace("COMY");
323    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, "COMX", _))
324        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
325    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo("COMX", nullptr, STATUS_READY)).Times(1);
326    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, "COMY", _))
327        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
328    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo("COMY", nullptr, STATUS_READY)).Times(0);
329    mockHostUART.WatchUartDevPlugin();
330}
331
332/*
333 * @tc.name: WatchUartDevPlugin
334 * @tc.desc: Check the behavior of the WatchUartDevPlugin function
335 * @tc.type: FUNC
336 */
337HWTEST_F(HdcHostUARTTest, WatchUartDevPluginHaveRemovedPort, TestSize.Level1)
338{
339    EXPECT_CALL(mockHostUART, WatchUartDevPlugin).WillRepeatedly([&]() {
340        mockHostUART.HdcHostUART::WatchUartDevPlugin();
341    });
342
343    // case 4 EnumSerialPort return two port, and one port removed
344    // one port is not connected , the other is connected
345    EXPECT_CALL(mockHostUART, EnumSerialPort).WillOnce(DoAll(SetArgReferee<0>(true), Return(true)));
346    mockHostUART.serialPortInfo.clear();
347    mockHostUART.serialPortInfo.emplace_back("COMX");
348    mockHostUART.serialPortInfo.emplace_back("COMY");
349    mockHostUART.connectedPorts.clear();
350    mockHostUART.connectedPorts.emplace("COMY");
351    mockHostUART.serialPortRemoved.clear();
352    mockHostUART.serialPortRemoved.emplace_back("COMZ");
353
354    HdcDaemonInformation di;
355    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, "COMX", _))
356        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
357    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo("COMX", nullptr, STATUS_READY)).Times(1);
358    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, "COMY", _))
359        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
360    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo("COMY", nullptr, STATUS_READY)).Times(0);
361    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, "COMZ", _))
362        .WillOnce(DoAll(SetArgReferee<2>(&di), Return("")));
363    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo("COMZ", nullptr, STATUS_READY)).Times(0);
364    mockHostUART.WatchUartDevPlugin();
365}
366
367/*
368 * @tc.name: UpdateUARTDaemonInfo
369 * @tc.desc: Check the behavior of the UpdateUARTDaemonInfo function
370 * @tc.type: FUNC
371 */
372HWTEST_F(HdcHostUARTTest, UpdateUARTDaemonInfo, TestSize.Level1)
373{
374    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo)
375        .WillRepeatedly(
376            [&](const std::string &connectKey, HSession hSession, ConnStatus connStatus) {
377                mockHostUART.HdcHostUART::UpdateUARTDaemonInfo(connectKey, hSession, connStatus);
378            });
379
380    // case 1 STATUS_UNKNOW
381    HdcDaemonInformation diNew;
382    EXPECT_CALL(mockServer,
383                AdminDaemonMap(OP_REMOVE, testSerialPortName,
384                               Field(&HdcDaemonInformation::connectKey, testSerialPortName)))
385        .Times(1)
386        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
387
388    mockHostUART.UpdateUARTDaemonInfo(myUART.serialPort, &mySession, STATUS_UNKNOW);
389
390    // case 2 STATUS_CONNECTED
391    HdcDaemonInformation diDummy;
392    EXPECT_CALL(mockServer, AdminDaemonMap(OP_QUERY, testSerialPortName, _))
393        .Times(1)
394        .WillOnce(DoAll(SetArgReferee<2>(&diDummy), Return("")));
395
396    EXPECT_CALL(mockServer,
397                AdminDaemonMap(OP_UPDATE, testSerialPortName,
398                               Field(&HdcDaemonInformation::connectKey, testSerialPortName)))
399        .Times(1)
400        .WillOnce(DoAll(SetArgReferee<2>(nullptr), Return("")));
401
402    mockHostUART.UpdateUARTDaemonInfo(myUART.serialPort, &mySession, STATUS_CONNECTED);
403}
404
405/*
406 * @tc.name: StartUartReadThread
407 * @tc.desc: Check the behavior of the StartUartReadThread function
408 * @tc.type: FUNC
409 */
410HWTEST_F(HdcHostUARTTest, StartUartReadThread, TestSize.Level1)
411{
412    EXPECT_CALL(mockHostUART, StartUartReadThread).WillOnce(Invoke([&](HSession hSession) {
413        return mockHostUART.HdcHostUART::StartUartReadThread(hSession);
414    }));
415
416    EXPECT_CALL(mockHostUART, UartReadThread(&mySession)).Times(1);
417    mockHostUART.StartUartReadThread(&mySession);
418    if (mySession.hUART->readThread.joinable()) {
419        mySession.hUART->readThread.join();
420    }
421}
422
423/*
424 * @tc.name: ConnectMyNeed
425 * @tc.desc: Check the behavior of the ConnectMyNeed function
426 * @tc.type: FUNC
427 */
428HWTEST_F(HdcHostUARTTest, ConnectMyNeed, TestSize.Level1)
429{
430    HdcUART newUART;
431    mySession.hUART = &newUART;
432    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo(myUART.serialPort, nullptr, STATUS_READY))
433        .Times(1);
434    EXPECT_CALL(mockServer, MallocSession(true, CONN_SERIAL, &mockHostUART, 0))
435        .Times(1)
436        .WillOnce(Return(&mySession));
437    EXPECT_CALL(mockInterface, UvTimerStart(Field(&uv_timer_t::data, &mySession),
438                                            &mockServer.UartPreConnect, UV_TIMEOUT, UV_REPEAT))
439        .Times(1)
440        .WillOnce(Return(RET_SUCCESS));
441
442    EXPECT_EQ(mockHostUART.ConnectMyNeed(&myUART, myUART.serialPort), true);
443
444    EXPECT_EQ(newUART.devUartHandle, testSerialHandle);
445    EXPECT_EQ(newUART.serialPort, testSerialPortName);
446}
447
448/*
449 * @tc.name: ConnectMyNeed
450 * @tc.desc: Check the behavior of the ConnectMyNeed function
451 * @tc.type: FUNC
452 */
453HWTEST_F(HdcHostUARTTest, ConnectMyNeedFail, TestSize.Level1)
454{
455    HdcUART newUART;
456    mySession.hUART = &newUART;
457    EXPECT_CALL(mockHostUART, UpdateUARTDaemonInfo(myUART.serialPort, nullptr, STATUS_READY))
458        .Times(1);
459    EXPECT_CALL(mockServer, MallocSession(true, CONN_SERIAL, &mockHostUART, 0))
460        .Times(1)
461        .WillOnce(Return(&mySession));
462    EXPECT_CALL(mockInterface, UvTimerStart(Field(&uv_timer_t::data, &mySession),
463                                            &mockServer.UartPreConnect, UV_TIMEOUT, UV_REPEAT))
464        .Times(1)
465        .WillOnce(Return(-1));
466
467    EXPECT_EQ(mockHostUART.ConnectMyNeed(&myUART), false);
468
469    EXPECT_EQ(newUART.devUartHandle, testSerialHandle);
470    EXPECT_EQ(newUART.serialPort, testSerialPortName);
471}
472
473/*
474 * @tc.name: StartupUARTWork
475 * @tc.desc: Check the behavior of the StartupUARTWork function
476 * @tc.type: FUNC
477 */
478HWTEST_F(HdcHostUARTTest, StartupUARTWork, TestSize.Level1)
479{
480    EXPECT_CALL(mockHostUART, StartupUARTWork).WillRepeatedly([&]() {
481        return mockHostUART.HdcHostUART::StartupUARTWork();
482    });
483    EXPECT_CALL(mockInterface, UvTimerStart(Field(&uv_timer_t::data, &mockHostUART),
484                                            mockHostUART.UvWatchUartDevPlugin, _, _))
485        .Times(1)
486        .WillOnce(Return(0));
487
488    EXPECT_CALL(mockHostUART, StartUartSendThread()).Times(1).WillOnce(Return(false));
489
490    EXPECT_EQ(mockHostUART.StartupUARTWork(), ERR_GENERIC);
491
492    EXPECT_CALL(mockInterface, UvTimerStart(Field(&uv_timer_t::data, &mockHostUART),
493                                            mockHostUART.UvWatchUartDevPlugin, _, _))
494        .Times(1)
495        .WillOnce(Return(-1));
496    EXPECT_EQ(mockHostUART.StartupUARTWork(), ERR_GENERIC);
497}
498
499MATCHER_P(EqUartHead, otherUartHead, "Equality matcher for type UartHead")
500{
501    UartHead *argUartHead = reinterpret_cast<UartHead *>(arg);
502    return *argUartHead == *otherUartHead;
503}
504
505/*
506 * @tc.name: SendUartSoftReset
507 * @tc.desc: Check the behavior of the SendUartSoftReset function
508 * @tc.type: FUNC
509 */
510HWTEST_F(HdcHostUARTTest, SendUartSoftReset, TestSize.Level1)
511{
512    UartHead resetPackage;
513    constexpr uint32_t sessionId = 1234;
514    resetPackage.option = PKG_OPTION_RESET;
515    resetPackage.dataSize = sizeof(UartHead);
516    resetPackage.sessionId = sessionId;
517
518    EXPECT_CALL(mockHostUART,
519                RequestSendPackage(EqUartHead(&resetPackage), sizeof(UartHead), false))
520        .Times(1);
521    mockHostUART.SendUartSoftReset(&mySession, sessionId);
522}
523
524/*
525 * @tc.name: KickoutZombie
526 * @tc.desc: Check the behavior of the KickoutZombie function
527 * @tc.type: FUNC
528 */
529HWTEST_F(HdcHostUARTTest, KickoutZombie, TestSize.Level1)
530{
531    mockHostUART.KickoutZombie(nullptr);
532
533    mySession.isDead = true;
534    mockHostUART.KickoutZombie(&mySession);
535    mySession.isDead = false;
536
537    myUART.devUartHandle = -1;
538    mockHostUART.KickoutZombie(&mySession);
539    myUART.devUartHandle = 0;
540
541    EXPECT_CALL(mockServer, FreeSession(mySession.sessionId)).Times(1);
542    mockHostUART.KickoutZombie(&mySession);
543}
544
545/*
546 * @tc.name: StartUartSendThread
547 * @tc.desc: Check the behavior of the StartUartSendThread function
548 * @tc.type: FUNC
549 */
550HWTEST_F(HdcHostUARTTest, StartUartSendThread, TestSize.Level1)
551{
552    EXPECT_CALL(mockHostUART, StartUartSendThread).WillRepeatedly([&]() {
553        return mockHostUART.HdcHostUART::StartUartSendThread();
554    });
555    EXPECT_CALL(mockHostUART, UartWriteThread).Times(1);
556    EXPECT_TRUE(mockHostUART.StartUartSendThread());
557    std::this_thread::sleep_for(500ms);
558}
559
560/*
561 * @tc.name: NeedStop
562 * @tc.desc: Check the behavior of the NeedStop function
563 * @tc.type: FUNC
564 */
565HWTEST_F(HdcHostUARTTest, NeedStop, TestSize.Level1)
566{
567    EXPECT_CALL(mockHostUART, NeedStop).WillRepeatedly([&](const HSession hSession) {
568        return mockHostUART.HdcHostUART::NeedStop(hSession);
569    });
570    mockHostUART.uartOpened = true;
571    mySession.isDead = false;
572    mySession.ref = 1;
573    EXPECT_EQ(mockHostUART.NeedStop(&mySession), false);
574
575    mockHostUART.uartOpened = true;
576    mySession.isDead = false;
577    mySession.ref = 0;
578    EXPECT_EQ(mockHostUART.NeedStop(&mySession), false);
579
580    mockHostUART.uartOpened = true;
581    mySession.isDead = true;
582    mySession.ref = 1;
583    EXPECT_EQ(mockHostUART.NeedStop(&mySession), false);
584
585    mockHostUART.uartOpened = true;
586    mySession.isDead = true;
587    mySession.ref = 0;
588    EXPECT_EQ(mockHostUART.NeedStop(&mySession), true);
589
590    mockHostUART.uartOpened = false;
591    mySession.isDead = false;
592    mySession.ref = 1;
593    EXPECT_EQ(mockHostUART.NeedStop(&mySession), true);
594}
595
596/*
597 * @tc.name: IsDeviceOpened
598 * @tc.desc: Check the behavior of the IsDeviceOpened function
599 * @tc.type: FUNC
600 */
601HWTEST_F(HdcHostUARTTest, IsDeviceOpened, TestSize.Level1)
602{
603    EXPECT_CALL(mockHostUART, IsDeviceOpened).WillRepeatedly([&](const HdcUART &uart) {
604        return mockHostUART.HdcHostUART::IsDeviceOpened(uart);
605    });
606    myUART.devUartHandle = -1;
607    EXPECT_EQ(mockHostUART.IsDeviceOpened(myUART), false);
608
609    myUART.devUartHandle = -2;
610    EXPECT_EQ(mockHostUART.IsDeviceOpened(myUART), false);
611
612    myUART.devUartHandle = 0;
613    EXPECT_EQ(mockHostUART.IsDeviceOpened(myUART), true);
614
615    myUART.devUartHandle = 1;
616    EXPECT_EQ(mockHostUART.IsDeviceOpened(myUART), true);
617}
618
619/*
620 * @tc.name: UartWriteThread
621 * @tc.desc: Check the behavior of the UartWriteThread function
622 * @tc.type: FUNC
623 */
624HWTEST_F(HdcHostUARTTest, UartWriteThread, TestSize.Level1)
625{
626    EXPECT_CALL(mockHostUART, UartWriteThread).WillOnce(Invoke([&]() {
627        return mockHostUART.HdcHostUART::UartWriteThread();
628    }));
629
630    EXPECT_CALL(mockHostUART, SendPkgInUARTOutMap).Times(0);
631    auto sendThread = std::thread(&HdcHostUART::UartWriteThread, &mockHostUART);
632    std::this_thread::sleep_for(1000ms);
633    EXPECT_CALL(mockHostUART, SendPkgInUARTOutMap).Times(1);
634    mockHostUART.transfer.Request();
635    std::this_thread::sleep_for(200ms);
636    mockHostUART.stopped = true;
637    mockHostUART.transfer.Request();
638    sendThread.join();
639}
640
641/*
642 * @tc.name: UartReadThread
643 * @tc.desc: Check the behavior of the UartReadThread function
644 * @tc.type: FUNC
645 */
646HWTEST_F(HdcHostUARTTest, UartReadThread, TestSize.Level1)
647{
648    EXPECT_CALL(mockHostUART, UartReadThread).WillRepeatedly(Invoke([&](HSession hSession) {
649        return mockHostUART.HdcHostUART::UartReadThread(hSession);
650    }));
651
652    // case 1 need stop
653    EXPECT_CALL(mockHostUART, NeedStop).WillOnce(Return(true));
654    auto readThread = std::thread(&HdcHostUART::UartReadThread, &mockHostUART, &mySession);
655    readThread.join();
656
657    // case 2 ReadUartDev return -1 will cause OnTransferError
658    EXPECT_CALL(mockHostUART, NeedStop).WillOnce(Return(false)).WillOnce(Return(true));
659    EXPECT_CALL(mockHostUART, ReadUartDev).WillOnce(Return(-1));
660    EXPECT_CALL(mockHostUART, OnTransferError).Times(1);
661    EXPECT_CALL(mockHostUART, PackageProcess).Times(0);
662    auto readThread2 = std::thread(&HdcHostUART::UartReadThread, &mockHostUART, &mySession);
663    readThread2.join();
664
665    // case 3 ReadUartDev retturn 0 will timeout, try again
666    EXPECT_CALL(mockHostUART, NeedStop).WillOnce(Return(false)).WillOnce(Return(true));
667    EXPECT_CALL(mockHostUART, ReadUartDev).WillOnce(Return(0));
668    EXPECT_CALL(mockHostUART, OnTransferError).Times(0);
669    EXPECT_CALL(mockHostUART, PackageProcess).Times(0);
670    auto readThread3 = std::thread(&HdcHostUART::UartReadThread, &mockHostUART, &mySession);
671    readThread3.join();
672
673    // case 4 ReadUartDev return sizeof(UartHead)
674    EXPECT_CALL(mockHostUART, NeedStop).WillOnce(Return(false)).WillOnce(Return(true));
675    EXPECT_CALL(mockHostUART, ReadUartDev)
676        .WillOnce(Invoke([&](std::vector<uint8_t> &readBuf, size_t expectedSize, HdcUART &uart) {
677            readBuf.resize(sizeof(UartHead));
678            return readBuf.size();
679        }));
680    EXPECT_CALL(mockHostUART, OnTransferError).Times(0);
681    EXPECT_CALL(mockHostUART, PackageProcess).WillOnce(Return(0));
682    auto readThread4 = std::thread(&HdcHostUART::UartReadThread, &mockHostUART, &mySession);
683    readThread4.join();
684
685    // case 5 ReadUartDev return more than sizeof(UartHead)
686    EXPECT_CALL(mockHostUART, NeedStop).WillOnce(Return(false)).WillOnce(Return(true));
687    const size_t testDataSize = sizeof(UartHead) * 2;
688
689    EXPECT_CALL(mockHostUART, ReadUartDev)
690        .WillOnce(Invoke([&](std::vector<uint8_t> &readBuf, size_t expectedSize, HdcUART &uart) {
691            readBuf.resize(testDataSize);
692            return readBuf.size();
693        }));
694    EXPECT_CALL(mockHostUART, OnTransferError).Times(0);
695    EXPECT_CALL(mockHostUART, PackageProcess).WillOnce(Return(0));
696    auto readThread5 = std::thread(&HdcHostUART::UartReadThread, &mockHostUART, &mySession);
697    readThread5.join();
698}
699
700/*
701 * @tc.name: WaitUartIdle
702 * @tc.desc: Check the behavior of the WaitUartIdle function
703 * @tc.type: FUNC
704 */
705HWTEST_F(HdcHostUARTTest, WaitUartIdle, TestSize.Level1)
706{
707    EXPECT_CALL(mockHostUART, ReadUartDev(_, 1, Ref(myUART))).WillOnce(Return(0));
708    EXPECT_EQ(mockHostUART.WaitUartIdle(myUART), true);
709
710    EXPECT_CALL(mockHostUART, ReadUartDev(_, 1, Ref(myUART)))
711        .WillOnce(Return(1))
712        .WillOnce(Return(0));
713    EXPECT_EQ(mockHostUART.WaitUartIdle(myUART), true);
714
715    EXPECT_CALL(mockHostUART, ReadUartDev(_, 1, Ref(myUART)))
716        .WillOnce(Return(1))
717        .WillOnce(Return(1));
718    EXPECT_EQ(mockHostUART.WaitUartIdle(myUART), false);
719}
720
721/*
722 * @tc.name: ConnectDaemon
723 * @tc.desc: Check the behavior of the ConnectDaemon function
724 * @tc.type: FUNC
725 */
726HWTEST_F(HdcHostUARTTest, ConnectDaemon, TestSize.Level1)
727{
728    std::string connectKey = "dummykey";
729    EXPECT_CALL(mockHostUART, OpenSerialPort(connectKey)).WillOnce(Return(0));
730    EXPECT_EQ(mockHostUART.ConnectDaemon(connectKey), nullptr);
731}
732
733/*
734 * @tc.name: GetSession
735 * @tc.desc: Check the behavior of the GetSession function
736 * @tc.type: FUNC
737 */
738HWTEST_F(HdcHostUARTTest, GetSession, TestSize.Level1)
739{
740    constexpr uint32_t sessionId = 1234;
741    HdcSession mySession;
742    HdcUART myUART;
743    mySession.hUART = &myUART;
744    EXPECT_CALL(mockServer, AdminSession(OP_QUERY, sessionId, nullptr))
745        .Times(1)
746        .WillOnce(Return(&mySession));
747    mockHostUART.GetSession(sessionId, false);
748}
749
750/*
751 * @tc.name: CloseSerialPort
752 * @tc.desc: Check the behavior of the CloseSerialPort function
753 * @tc.type: FUNC
754 */
755HWTEST_F(HdcHostUARTTest, CloseSerialPort, TestSize.Level1)
756{
757    myUART.devUartHandle = -1;
758    mockHostUART.CloseSerialPort(&myUART);
759    EXPECT_EQ(myUART.devUartHandle, -1);
760}
761
762/*
763 * @tc.name: GetPortFromKey
764 * @tc.desc: Check the behavior of the GetPortFromKey function
765 * @tc.type: FUNC
766 */
767HWTEST_F(HdcHostUARTTest, GetPortFromKey, TestSize.Level1)
768{
769    std::string portName;
770    uint32_t baudRate;
771    const uint32_t baudRateTest = 111u;
772    EXPECT_EQ(mockHostUART.GetPortFromKey("COM1", portName, baudRate), true);
773    EXPECT_STREQ(portName.c_str(), "COM1");
774    EXPECT_EQ(baudRate, mockHostUART.DEFAULT_BAUD_RATE_VALUE);
775
776    EXPECT_EQ(mockHostUART.GetPortFromKey("COM1,aaa", portName, baudRate), false);
777
778    EXPECT_EQ(mockHostUART.GetPortFromKey("COM1,111", portName, baudRate), true);
779    EXPECT_STREQ(portName.c_str(), "COM1");
780    EXPECT_EQ(baudRate, baudRateTest);
781}
782
783/*
784 * @tc.name: Restartession
785 * @tc.desc: Check the behavior of the Restartession function
786 * successed
787 * @tc.type: FUNC
788 */
789HWTEST_F(HdcHostUARTTest, Restartession, TestSize.Level1)
790{
791    const uint32_t sessionId = 12345;
792    mySession.sessionId = sessionId;
793    EXPECT_CALL(mockHostUART, CloseSerialPort(mySession.hUART)).WillOnce(Return());
794    EXPECT_CALL(mockServer, EchoToClientsForSession(sessionId, _)).WillOnce(Return());
795    mockHostUART.Restartession(&mySession);
796}
797
798/*
799 * @tc.name: StopSession
800 * @tc.desc: Check the behavior of the StopSession function
801 * successed
802 * @tc.type: FUNC
803 */
804HWTEST_F(HdcHostUARTTest, StopSession, TestSize.Level1)
805{
806    EXPECT_EQ(mySession.hUART->ioCancel, false);
807    mockHostUART.StopSession(nullptr);
808    EXPECT_EQ(mySession.hUART->ioCancel, false);
809    mockHostUART.StopSession(&mySession);
810    EXPECT_EQ(mySession.hUART->ioCancel, true);
811}
812
813/*
814 * @tc.name: OnTransferError
815 * @tc.desc: Check the behavior of the OnTransferError function
816 * @tc.type: FUNC
817 */
818HWTEST_F(HdcHostUARTTest, OnTransferError, TestSize.Level1)
819{
820    EXPECT_CALL(mockHostUART, OnTransferError).WillRepeatedly(Invoke([&](const HSession session) {
821        return mockHostUART.HdcHostUART::OnTransferError(session);
822    }));
823    mockHostUART.OnTransferError(nullptr);
824    const uint32_t sessionId = mySession.sessionId;
825
826    EXPECT_CALL(mockHostUART, IsDeviceOpened(Ref(*mySession.hUART))).WillOnce(Return(true));
827    EXPECT_CALL(mockServer, EchoToClientsForSession(sessionId, _)).WillOnce(Return());
828    EXPECT_CALL(mockHostUART, CloseSerialPort(mySession.hUART)).WillOnce(Return());
829    EXPECT_CALL(mockHostUART,
830                UpdateUARTDaemonInfo(mySession.connectKey, &mySession, STATUS_OFFLINE))
831        .WillOnce(Return());
832    EXPECT_CALL(mockServer, FreeSession(sessionId)).WillOnce(Return());
833    EXPECT_CALL(mockHostUART, ClearUARTOutMap(sessionId)).WillOnce(Return());
834    mockHostUART.OnTransferError(&mySession);
835}
836} // namespace Hdc
837