#include #include #include #include #include #include // ==================== 模拟数据结构 ==================== 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 ports; }; struct RackResponse { std::string rack_id; std::string rack_name; std::string location; std::vector 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 list_racks() = 0; virtual std::optional 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 create_unit(const std::string& rack_id, const UnitCreate& body) = 0; virtual bool delete_unit(const std::string& unit_id) = 0; virtual std::vector get_free_ports(const std::optional& rack_id) = 0; virtual std::optional get_port_detail(const std::string& port_id) = 0; virtual std::vector list_connections() = 0; virtual std::optional create_connection(const ConnectionCreate& body) = 0; virtual bool delete_connection(const std::string& connection_id) = 0; virtual std::optional get_port_path(const std::string& port_id) = 0; virtual std::string health_check() = 0; }; // 模拟实现(用于测试基类) class MockODFService : public ODFService { public: MOCK_METHOD(std::vector, list_racks, (), (override)); MOCK_METHOD(std::optional, 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, 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, get_free_ports, (const std::optional& rack_id), (override)); MOCK_METHOD(std::optional, get_port_detail, (const std::string& port_id), (override)); MOCK_METHOD(std::vector, list_connections, (), (override)); MOCK_METHOD(std::optional, create_connection, (const ConnectionCreate& body), (override)); MOCK_METHOD(bool, delete_connection, (const std::string& connection_id), (override)); MOCK_METHOD(std::optional, 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(); } void TearDown() override { mock_service.reset(); } std::shared_ptr mock_service; }; // ==================== 机架 API 测试 ==================== TEST_F(ODFServiceTest, testListRacksNormal) { std::vector 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{})); 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(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(12); EXPECT_CALL(*mock_service, create_unit("rack1", body)) .WillOnce(::testing::Return(std::optional(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 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 ports = { {"port3", "rack2", 2, 1, PortType::LC} }; EXPECT_CALL(*mock_service, get_free_ports(std::optional("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("ghost"))) .WillOnce(::testing::Return(std::vector{})); 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(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 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{})); 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(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(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); }