e1b203fd创建于 11 天前历史提交
/*
 * Copyright (c) 2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include <hdf_log.h>
#include <condition_variable>
#include <mutex>
#include "v1_0/iserials.h"
#include "v1_0/iserial_device_callback.h"

using namespace OHOS::HDI::Serial::V1_0;
using namespace testing::ext;

constexpr int32_t TEST_WAIT_DATA_TIMEOUT_MS = 1000;
constexpr int32_t TEST_WAIT_OFFLINE_TIMEOUT_MS = 5000;
constexpr int32_t TEST_WRITE_TIMEOUT_MS = 1000;
constexpr int32_t TEST_LARGE_DATA_SIZE = 5000;
constexpr int32_t TEST_MIN_DEVICES_COUNT = 2;
constexpr int32_t DEFAULT_BAUD_RATE = 115200;
constexpr int32_t TEST_BAUD_RATE_9600 = 9600;
constexpr int32_t DATA_BIT_8 = 8;
constexpr int32_t STOP_BIT_1 = 1;
class SerialDeviceCallbackImpl : public ISerialDeviceCallback {
public:
    SerialDeviceCallbackImpl() : deviceOffline_(false), dataReceived_(false) {}
    ~SerialDeviceCallbackImpl() override = default;

    int32_t OnDeviceOffline() override
    {
        deviceOffline_ = true;
        offlineCond_.notify_all();
        HDF_LOGI("Device offline notified");
        return HDF_SUCCESS;
    }

    int32_t OnReadData(const std::vector<int8_t>& data, uint32_t dataLen) override
    {
        std::lock_guard<std::mutex> lock(dataMutex_);
        receivedData_ = data;
        receivedLen_ = dataLen;
        dataReceived_ = true;
        dataCond_.notify_one();
        return HDF_SUCCESS;
    }

    bool WaitForData(std::vector<int8_t>& data, uint32_t& dataLen, int timeoutMs = TEST_WAIT_DATA_TIMEOUT_MS)
    {
        std::unique_lock<std::mutex> lock(dataMutex_);
        return dataCond_.wait_for(lock, std::chrono::milliseconds(timeoutMs),
            [this] { return dataReceived_.load(); }) && dataReceived_.load();
    }

    bool WaitForOffline(int timeoutMs = TEST_WAIT_OFFLINE_TIMEOUT_MS)
    {
        std::unique_lock<std::mutex> lock(offlineMutex_);
        return offlineCond_.wait_for(lock, std::chrono::milliseconds(timeoutMs),
            [this] { return deviceOffline_.load(); }) && deviceOffline_.load();
    }

    bool IsDeviceOffline() const { return deviceOffline_; }
    void Reset() { deviceOffline_ = false; dataReceived_ = false; }

private:
    std::atomic<bool> deviceOffline_;
    std::atomic<bool> dataReceived_;
    std::mutex dataMutex_;
    std::mutex offlineMutex_;
    std::condition_variable dataCond_;
    std::condition_variable offlineCond_;
    std::vector<int8_t> receivedData_;
    uint32_t receivedLen_ = 0;
};

class HdfSerialsTest : public testing::Test {
public:
    static void SetUpTestCase();
    static void TearDownTestCase();
    void SetUp();
    void TearDown();

    static sptr<ISerials> serials_;
    static SerialConfig defaultConfig_;
};

sptr<ISerials> HdfSerialsTest::serials_ = nullptr;
SerialConfig HdfSerialsTest::defaultConfig_ = {};

void HdfSerialsTest::SetUpTestCase()
{
    HDF_LOGI("HdfSerialsTest::SetUpTestCase");
    serials_ = ISerials::Get(true);
    ASSERT_NE(serials_, nullptr);

    defaultConfig_.baudRate = DEFAULT_BAUD_RATE;
    defaultConfig_.dataBits = DATA_BIT_8;
    defaultConfig_.stopBits = STOP_BIT_1;
    defaultConfig_.parity = 0;
    defaultConfig_.rtscts = false;
    defaultConfig_.xon = false;
    defaultConfig_.xoff = false;
    defaultConfig_.xany = false;
}

void HdfSerialsTest::TearDownTestCase()
{
    HDF_LOGI("HdfSerialsTest::TearDownTestCase");
    serials_ = nullptr;
}

void HdfSerialsTest::SetUp()
{
    HDF_LOGI("HdfSerialsTest::SetUp");
}

void HdfSerialsTest::TearDown()
{
    HDF_LOGI("HdfSerialsTest::TearDown");
}

HWTEST_F(HdfSerialsTest, QueryDevices_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);

    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    EXPECT_GE(devices.size(), 0);
}

HWTEST_F(HdfSerialsTest, QueryDevices_002, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);

    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);

    for (const auto& device : devices) {
        EXPECT_FALSE(device.portName.empty());
        HDF_LOGI("Device: portName=%{public}s, manufacturer=%{public}s",
            device.portName.c_str(), device.manufacturer.c_str());
    }
}

HWTEST_F(HdfSerialsTest, OpenDevice_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    EXPECT_EQ(ret, HDF_SUCCESS);
    EXPECT_NE(device, nullptr);

    if (device != nullptr) {
        device->Close();
    }
}

HWTEST_F(HdfSerialsTest, OpenDevice_002, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    SerialConfig config;
    config.baudRate = TEST_BAUD_RATE_9600;
    config.dataBits = DATA_BIT_8;
    config.stopBits = STOP_BIT_1;
    config.parity = 0;
    config.rtscts = false;
    config.xon = false;
    config.xoff = false;
    config.xany = false;

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, config, callback, device);
    EXPECT_EQ(ret, HDF_SUCCESS);
    EXPECT_NE(device, nullptr);

    if (device != nullptr) {
        device->Close();
    }
}

HWTEST_F(HdfSerialsTest, OpenDevice_003, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device1;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device1);
    EXPECT_EQ(ret, HDF_SUCCESS);

    sptr<ISerialDevice> device2;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device2);
    EXPECT_EQ(ret, HDF_ERR_DEVICE_BUSY);

    if (device1 != nullptr) {
        device1->Close();
    }
}

HWTEST_F(HdfSerialsTest, OpenDevice_004, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    int32_t ret = serials_->OpenDevice("/dev/nonexistent", defaultConfig_, callback, device);
    EXPECT_NE(ret, HDF_SUCCESS);
}

HWTEST_F(HdfSerialsTest, OpenDevice_005, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, nullptr, device);
    EXPECT_EQ(ret, HDF_SUCCESS);
    EXPECT_NE(device, nullptr);

    if (device != nullptr) {
        device->Close();
    }
}

HWTEST_F(HdfSerialsTest, Write_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    std::vector<uint8_t> data = {0x01, 0x02, 0x03, 0x04};
    int32_t bytesWritten = 0;
    ret = device->Write(data, TEST_WRITE_TIMEOUT_MS, bytesWritten);
    EXPECT_EQ(ret, HDF_SUCCESS);
    EXPECT_EQ(bytesWritten, static_cast<int32_t>(data.size()));

    device->Close();
}

HWTEST_F(HdfSerialsTest, Write_002, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    std::vector<uint8_t> emptyData;
    int32_t bytesWritten = 0;
    ret = device->Write(emptyData, TEST_WRITE_TIMEOUT_MS, bytesWritten);
    EXPECT_NE(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, Write_003, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    std::vector<uint8_t> largeData(TEST_LARGE_DATA_SIZE, 0x55);
    int32_t bytesWritten = 0;
    ret = device->Write(largeData, TEST_WRITE_TIMEOUT_MS, bytesWritten);
    EXPECT_NE(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, StartRead_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->StartRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    ret = device->StopRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, StartRead_002, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->StartRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    ret = device->StartRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    ret = device->StopRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, Close_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->Close();
    EXPECT_EQ(ret, HDF_SUCCESS);
}

HWTEST_F(HdfSerialsTest, Flush_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->Flush();
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, Drain_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->Drain();
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, SendBrkSignal_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->SendBrkSignal();
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, SetRtsSignal_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->SetRtsSignal(true);
    EXPECT_EQ(ret, HDF_SUCCESS);

    ret = device->SetRtsSignal(false);
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, GetCtsSignal_001, TestSize.Level0)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    bool cts = false;
    ret = device->GetCtsSignal(cts);
    EXPECT_EQ(ret, HDF_SUCCESS);

    device->Close();
}

HWTEST_F(HdfSerialsTest, CloseBeforeStopRead_001, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    ret = device->StartRead();
    EXPECT_EQ(ret, HDF_SUCCESS);

    ret = device->Close();
    EXPECT_EQ(ret, HDF_SUCCESS);
}

HWTEST_F(HdfSerialsTest, OperationAfterClose_001, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    device->Close();

    std::vector<uint8_t> data = {0x01, 0x02};
    int32_t bytesWritten = 0;
    ret = device->Write(data, TEST_WRITE_TIMEOUT_MS, bytesWritten);
    EXPECT_NE(ret, HDF_SUCCESS);

    ret = device->StartRead();
    EXPECT_NE(ret, HDF_SUCCESS);
}

HWTEST_F(HdfSerialsTest, DeviceOfflineCallback_001, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.empty()) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback = new SerialDeviceCallbackImpl();
    sptr<ISerialDevice> device;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback, device);
    ASSERT_EQ(ret, HDF_SUCCESS);
    ASSERT_NE(device, nullptr);

    EXPECT_FALSE(callback->IsDeviceOffline());

    device->Close();
}

HWTEST_F(HdfSerialsTest, MultipleDevices_001, TestSize.Level1)
{
    ASSERT_NE(serials_, nullptr);
    std::vector<SerialDeviceInfo> devices;
    int32_t ret = serials_->QueryDevices(devices);
    EXPECT_EQ(ret, HDF_SUCCESS);
    if (devices.size() < TEST_MIN_DEVICES_COUNT) {
        return;
    }

    sptr<SerialDeviceCallbackImpl> callback1 = new SerialDeviceCallbackImpl();
    sptr<SerialDeviceCallbackImpl> callback2 = new SerialDeviceCallbackImpl();

    sptr<ISerialDevice> device1;
    ret = serials_->OpenDevice(devices[0].portName, defaultConfig_, callback1, device1);
    EXPECT_EQ(ret, HDF_SUCCESS);

    sptr<ISerialDevice> device2;
    ret = serials_->OpenDevice(devices[1].portName, defaultConfig_, callback2, device2);
    EXPECT_EQ(ret, HDF_SUCCESS);

    if (device1 != nullptr) {
        device1->Close();
    }
    if (device2 != nullptr) {
        device2->Close();
    }
}