ODF/tests/test_odf_manager.cpp

419 lines
14 KiB
C++
Raw Normal View History

2026-05-15 02:12:31 +00:00
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <string>
#include <vector>
#include <optional>
#include <stdexcept>
// ==================== 模拟数据结构 ====================
enum class PortType { SC, LC, FC, ST };
struct RackCreate {
std::string rack_name;
std::string location;
};
struct UnitCreate {
int unit_number;
std::string unit_name;
int position;
int port_count;
PortType port_type;
};
struct ConnectionCreate {
std::string port_a_id;
std::string port_b_id;
double fiber_length;
std::string remark;
};
struct RackListResponse {
std::string rack_id;
std::string rack_name;
int unit_count;
};
struct PortResponse {
std::string port_id;
int port_number;
PortType port_type;
std::string status;
};
struct UnitResponse {
std::string unit_id;
int unit_number;
std::string unit_name;
int position;
std::vector<PortResponse> ports;
};
struct RackResponse {
std::string rack_id;
std::string rack_name;
std::string location;
std::vector<UnitResponse> units;
};
struct FreePortResponse {
std::string port_id;
std::string rack_id;
int unit_number;
int port_number;
PortType port_type;
};
struct PortDetail {
std::string port_id;
int port_number;
PortType port_type;
std::string status;
std::string unit_id;
std::string rack_id;
};
struct ConnectionResponse {
std::string connection_id;
std::string port_a_id;
std::string port_b_id;
double fiber_length;
std::string remark;
};
// ==================== 被测服务类(模拟实现) ====================
class ODFService {
public:
virtual ~ODFService() = default;
virtual std::vector<RackListResponse> list_racks() = 0;
virtual std::optional<RackResponse> get_rack(const std::string& rack_id) = 0;
virtual RackResponse create_rack(const RackCreate& body) = 0;
virtual bool delete_rack(const std::string& rack_id) = 0;
virtual std::optional<UnitResponse> create_unit(const std::string& rack_id, const UnitCreate& body) = 0;
virtual bool delete_unit(const std::string& unit_id) = 0;
virtual std::vector<FreePortResponse> get_free_ports(const std::optional<std::string>& rack_id) = 0;
virtual std::optional<PortDetail> get_port_detail(const std::string& port_id) = 0;
virtual std::vector<ConnectionResponse> list_connections() = 0;
virtual std::optional<ConnectionResponse> create_connection(const ConnectionCreate& body) = 0;
virtual bool delete_connection(const std::string& connection_id) = 0;
virtual std::optional<std::string> get_port_path(const std::string& port_id) = 0;
virtual std::string health_check() = 0;
};
// 模拟实现(用于测试基类)
class MockODFService : public ODFService {
public:
MOCK_METHOD(std::vector<RackListResponse>, list_racks, (), (override));
MOCK_METHOD(std::optional<RackResponse>, get_rack, (const std::string& rack_id), (override));
MOCK_METHOD(RackResponse, create_rack, (const RackCreate& body), (override));
MOCK_METHOD(bool, delete_rack, (const std::string& rack_id), (override));
MOCK_METHOD(std::optional<UnitResponse>, create_unit, (const std::string& rack_id, const UnitCreate& body), (override));
MOCK_METHOD(bool, delete_unit, (const std::string& unit_id), (override));
MOCK_METHOD(std::vector<FreePortResponse>, get_free_ports, (const std::optional<std::string>& rack_id), (override));
MOCK_METHOD(std::optional<PortDetail>, get_port_detail, (const std::string& port_id), (override));
MOCK_METHOD(std::vector<ConnectionResponse>, list_connections, (), (override));
MOCK_METHOD(std::optional<ConnectionResponse>, create_connection, (const ConnectionCreate& body), (override));
MOCK_METHOD(bool, delete_connection, (const std::string& connection_id), (override));
MOCK_METHOD(std::optional<std::string>, get_port_path, (const std::string& port_id), (override));
MOCK_METHOD(std::string, health_check, (), (override));
};
// ==================== 测试夹具 ====================
class ODFServiceTest : public ::testing::Test {
protected:
void SetUp() override {
mock_service = std::make_shared<MockODFService>();
}
void TearDown() override {
mock_service.reset();
}
std::shared_ptr<MockODFService> mock_service;
};
// ==================== 机架 API 测试 ====================
TEST_F(ODFServiceTest, testListRacksNormal) {
std::vector<RackListResponse> expected = {
{"rack1", "Rack A", 3},
{"rack2", "Rack B", 0}
};
EXPECT_CALL(*mock_service, list_racks())
.WillOnce(::testing::Return(expected));
auto result = mock_service->list_racks();
ASSERT_EQ(result.size(), 2);
EXPECT_EQ(result[0].rack_id, "rack1");
EXPECT_EQ(result[1].unit_count, 0);
}
TEST_F(ODFServiceTest, testListRacksEmpty) {
EXPECT_CALL(*mock_service, list_racks())
.WillOnce(::testing::Return(std::vector<RackListResponse>{}));
auto result = mock_service->list_racks();
EXPECT_TRUE(result.empty());
}
TEST_F(ODFServiceTest, testGetRackExists) {
RackResponse rack;
rack.rack_id = "rack1";
rack.rack_name = "Main Rack";
EXPECT_CALL(*mock_service, get_rack("rack1"))
.WillOnce(::testing::Return(std::optional<RackResponse>(rack)));
auto result = mock_service->get_rack("rack1");
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result->rack_id, "rack1");
}
TEST_F(ODFServiceTest, testGetRackNotFound) {
EXPECT_CALL(*mock_service, get_rack("invalid"))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->get_rack("invalid");
EXPECT_FALSE(result.has_value());
}
TEST_F(ODFServiceTest, testCreateRackNormal) {
RackCreate body{"New Rack", "Room 101"};
RackResponse expected;
expected.rack_id = "rack_new";
expected.rack_name = "New Rack";
expected.location = "Room 101";
EXPECT_CALL(*mock_service, create_rack(body))
.WillOnce(::testing::Return(expected));
auto result = mock_service->create_rack(body);
EXPECT_EQ(result.rack_name, "New Rack");
EXPECT_EQ(result.location, "Room 101");
}
TEST_F(ODFServiceTest, testCreateRackEmptyName) {
RackCreate body{"", "Location"};
EXPECT_CALL(*mock_service, create_rack(body))
.WillOnce(::testing::Throw(std::invalid_argument("rack_name cannot be empty")));
EXPECT_THROW(mock_service->create_rack(body), std::invalid_argument);
}
TEST_F(ODFServiceTest, testDeleteRackSuccess) {
EXPECT_CALL(*mock_service, delete_rack("rack1"))
.WillOnce(::testing::Return(true));
EXPECT_TRUE(mock_service->delete_rack("rack1"));
}
TEST_F(ODFServiceTest, testDeleteRackNotFound) {
EXPECT_CALL(*mock_service, delete_rack("ghost"))
.WillOnce(::testing::Return(false));
EXPECT_FALSE(mock_service->delete_rack("ghost"));
}
// ==================== 配线单元 API 测试 ====================
TEST_F(ODFServiceTest, testCreateUnitNormal) {
UnitCreate body{1, "Unit 1", 1, 12, PortType::SC};
UnitResponse unit;
unit.unit_id = "unit1";
unit.unit_number = 1;
unit.unit_name = "Unit 1";
unit.position = 1;
unit.ports = std::vector<PortResponse>(12);
EXPECT_CALL(*mock_service, create_unit("rack1", body))
.WillOnce(::testing::Return(std::optional<UnitResponse>(unit)));
auto result = mock_service->create_unit("rack1", body);
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result->unit_number, 1);
EXPECT_EQ(result->ports.size(), 12);
}
TEST_F(ODFServiceTest, testCreateUnitRackNotFound) {
UnitCreate body{1, "Unit 1", 1, 12, PortType::LC};
EXPECT_CALL(*mock_service, create_unit("bad_rack", body))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->create_unit("bad_rack", body);
EXPECT_FALSE(result.has_value());
}
TEST_F(ODFServiceTest, testCreateUnitInvalidPortCount) {
UnitCreate body{1, "Unit 1", 1, 0, PortType::FC};
EXPECT_CALL(*mock_service, create_unit("rack1", body))
.WillOnce(::testing::Throw(std::invalid_argument("port_count must be positive")));
EXPECT_THROW(mock_service->create_unit("rack1", body), std::invalid_argument);
}
TEST_F(ODFServiceTest, testDeleteUnitSuccess) {
EXPECT_CALL(*mock_service, delete_unit("unit1"))
.WillOnce(::testing::Return(true));
EXPECT_TRUE(mock_service->delete_unit("unit1"));
}
TEST_F(ODFServiceTest, testDeleteUnitNotFound) {
EXPECT_CALL(*mock_service, delete_unit("unknown"))
.WillOnce(::testing::Return(false));
EXPECT_FALSE(mock_service->delete_unit("unknown"));
}
// ==================== 端口 API 测试 ====================
TEST_F(ODFServiceTest, testGetFreePortsAll) {
std::vector<FreePortResponse> ports = {
{"port1", "rack1", 1, 1, PortType::SC},
{"port2", "rack1", 1, 2, PortType::SC}
};
EXPECT_CALL(*mock_service, get_free_ports(std::nullopt))
.WillOnce(::testing::Return(ports));
auto result = mock_service->get_free_ports(std::nullopt);
ASSERT_EQ(result.size(), 2);
EXPECT_EQ(result[0].port_id, "port1");
}
TEST_F(ODFServiceTest, testGetFreePortsFilterByRack) {
std::vector<FreePortResponse> ports = {
{"port3", "rack2", 2, 1, PortType::LC}
};
EXPECT_CALL(*mock_service, get_free_ports(std::optional<std::string>("rack2")))
.WillOnce(::testing::Return(ports));
auto result = mock_service->get_free_ports("rack2");
ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0].rack_id, "rack2");
}
TEST_F(ODFServiceTest, testGetFreePortsRackNotFound) {
EXPECT_CALL(*mock_service, get_free_ports(std::optional<std::string>("ghost")))
.WillOnce(::testing::Return(std::vector<FreePortResponse>{}));
auto result = mock_service->get_free_ports("ghost");
EXPECT_TRUE(result.empty());
}
TEST_F(ODFServiceTest, testGetPortDetailExists) {
PortDetail detail{"port1", 1, PortType::SC, "FREE", "unit1", "rack1"};
EXPECT_CALL(*mock_service, get_port_detail("port1"))
.WillOnce(::testing::Return(std::optional<PortDetail>(detail)));
auto result = mock_service->get_port_detail("port1");
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result->status, "FREE");
EXPECT_EQ(result->rack_id, "rack1");
}
TEST_F(ODFServiceTest, testGetPortDetailNotFound) {
EXPECT_CALL(*mock_service, get_port_detail("bad_port"))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->get_port_detail("bad_port");
EXPECT_FALSE(result.has_value());
}
// ==================== 跳接连接 API 测试 ====================
TEST_F(ODFServiceTest, testListConnectionsNormal) {
std::vector<ConnectionResponse> conns = {
{"conn1", "port1", "port2", 10.5, "test"}
};
EXPECT_CALL(*mock_service, list_connections())
.WillOnce(::testing::Return(conns));
auto result = mock_service->list_connections();
ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0].connection_id, "conn1");
}
TEST_F(ODFServiceTest, testListConnectionsEmpty) {
EXPECT_CALL(*mock_service, list_connections())
.WillOnce(::testing::Return(std::vector<ConnectionResponse>{}));
auto result = mock_service->list_connections();
EXPECT_TRUE(result.empty());
}
TEST_F(ODFServiceTest, testCreateConnectionNormal) {
ConnectionCreate body{"port1", "port2", 5.0, "link"};
ConnectionResponse conn{"conn1", "port1", "port2", 5.0, "link"};
EXPECT_CALL(*mock_service, create_connection(body))
.WillOnce(::testing::Return(std::optional<ConnectionResponse>(conn)));
auto result = mock_service->create_connection(body);
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result->fiber_length, 5.0);
}
TEST_F(ODFServiceTest, testCreateConnectionSamePort) {
ConnectionCreate body{"port1", "port1", 1.0, ""};
EXPECT_CALL(*mock_service, create_connection(body))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->create_connection(body);
EXPECT_FALSE(result.has_value());
}
TEST_F(ODFServiceTest, testCreateConnectionPortNotFree) {
ConnectionCreate body{"port1", "port3", 2.0, ""};
EXPECT_CALL(*mock_service, create_connection(body))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->create_connection(body);
EXPECT_FALSE(result.has_value());
}
TEST_F(ODFServiceTest, testDeleteConnectionSuccess) {
EXPECT_CALL(*mock_service, delete_connection("conn1"))
.WillOnce(::testing::Return(true));
EXPECT_TRUE(mock_service->delete_connection("conn1"));
}
TEST_F(ODFServiceTest, testDeleteConnectionNotFound) {
EXPECT_CALL(*mock_service, delete_connection("bad_conn"))
.WillOnce(::testing::Return(false));
EXPECT_FALSE(mock_service->delete_connection("bad_conn"));
}
// ==================== 路径查询 API 测试 ====================
TEST_F(ODFServiceTest, testGetPortPathExists) {
std::string path_info = "port1 -> conn1 -> port2";
EXPECT_CALL(*mock_service, get_port_path("port1"))
.WillOnce(::testing::Return(std::optional<std::string>(path_info)));
auto result = mock_service->get_port_path("port1");
ASSERT_TRUE(result.has_value());
EXPECT_EQ(*result, path_info);
}
TEST_F(ODFServiceTest, testGetPortPathNotFound) {
EXPECT_CALL(*mock_service, get_port_path("unknown"))
.WillOnce(::testing::Return(std::nullopt));
auto result = mock_service->get_port_path("unknown");
EXPECT_FALSE(result.has_value());
}
// ==================== 健康检查 API 测试 ====================
TEST_F(ODFServiceTest, testHealthCheck) {
EXPECT_CALL(*mock_service, health_check())
.WillOnce(::testing::Return("{\"status\": \"ok\"}"));
auto result = mock_service->health_check();
EXPECT_NE(result.find("ok"), std::string::npos);
}