生成代码工程
This commit is contained in:
parent
a4f57febbb
commit
15baeafc77
|
|
@ -0,0 +1,23 @@
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
project(odf_manager LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
add_compile_options(/utf-8)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# 主程序
|
||||||
|
add_executable(odf_manager
|
||||||
|
src/main.cpp
|
||||||
|
src/app.cpp
|
||||||
|
)
|
||||||
|
target_include_directories(odf_manager PRIVATE include)
|
||||||
|
|
||||||
|
# 基础测试可执行文件
|
||||||
|
add_executable(odf_basic_test
|
||||||
|
tests/basic_test.cpp
|
||||||
|
src/app.cpp
|
||||||
|
)
|
||||||
|
target_include_directories(odf_basic_test PRIVATE include)
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,193 @@
|
||||||
|
#ifndef ODF_MANAGER_APP_HPP
|
||||||
|
#define ODF_MANAGER_APP_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
#include <chrono>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace odf {
|
||||||
|
|
||||||
|
// 端口状态枚举
|
||||||
|
enum class PortStatus {
|
||||||
|
ACTIVE,
|
||||||
|
INACTIVE,
|
||||||
|
ERROR_STATE
|
||||||
|
};
|
||||||
|
|
||||||
|
// 端口映射数据结构
|
||||||
|
struct PortMapping {
|
||||||
|
int mapping_id;
|
||||||
|
std::string port_code;
|
||||||
|
std::string fiber_core;
|
||||||
|
std::string splice_tray;
|
||||||
|
std::string cable_core;
|
||||||
|
std::string route_info;
|
||||||
|
std::chrono::system_clock::time_point create_time;
|
||||||
|
std::chrono::system_clock::time_point update_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设备健康状态
|
||||||
|
struct DeviceHealth {
|
||||||
|
std::string node_id;
|
||||||
|
double temperature_celsius;
|
||||||
|
double humidity_percent;
|
||||||
|
bool is_online;
|
||||||
|
PortStatus port_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用户角色枚举
|
||||||
|
enum class UserRole {
|
||||||
|
ADMIN,
|
||||||
|
OPERATOR,
|
||||||
|
VIEWER
|
||||||
|
};
|
||||||
|
|
||||||
|
// 用户信息
|
||||||
|
struct UserInfo {
|
||||||
|
std::string username;
|
||||||
|
UserRole role;
|
||||||
|
bool is_session_valid;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 端口映射管理器,负责端口唯一性校验、映射关系的增删改查及冲突检测。
|
||||||
|
*/
|
||||||
|
class PortMappingManager {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 添加新的端口映射记录。
|
||||||
|
*
|
||||||
|
* @requirement(name="端口唯一编号系统", id="SRS-F-05-001")
|
||||||
|
* @requirement(name="产品型号编码结构", id="SRS-F-05-002")
|
||||||
|
* @requirement(name="内部组件编号与溯源", id="SRS-F-05-003")
|
||||||
|
* @requirement(name="端口映射记录表支持", id="SRS-F-05-004")
|
||||||
|
* @param port_code 端口唯一编号
|
||||||
|
* @param fiber_core 纤芯编号
|
||||||
|
* @param splice_tray 熔接盘号
|
||||||
|
* @param cable_core 光缆芯号
|
||||||
|
* @param route_info 路由信息
|
||||||
|
* @return 映射ID,如果失败(如重复或格式错误)返回 -1
|
||||||
|
*/
|
||||||
|
int addMapping(const std::string& port_code, const std::string& fiber_core,
|
||||||
|
const std::string& splice_tray = "", const std::string& cable_core = "",
|
||||||
|
const std::string& route_info = "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定端口的映射记录。
|
||||||
|
*
|
||||||
|
* @requirement(name="端口映射记录表支持", id="SRS-F-05-004")
|
||||||
|
* @param port_code 要解除绑定的端口编号
|
||||||
|
* @return 是否删除成功
|
||||||
|
*/
|
||||||
|
bool deleteMapping(const std::string& port_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定端口的完整映射详情。
|
||||||
|
*
|
||||||
|
* @requirement(name="端口唯一编号系统", id="SRS-F-05-001")
|
||||||
|
* @param port_code 端口编号
|
||||||
|
* @return 映射对象,若未找到则返回 std::nullopt
|
||||||
|
*/
|
||||||
|
std::optional<PortMapping> getMapping(const std::string& port_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新指定端口的纤芯绑定及其他信息。
|
||||||
|
*
|
||||||
|
* @requirement(name="内部组件编号与溯源", id="SRS-F-05-003")
|
||||||
|
* @requirement(name="端口映射记录表支持", id="SRS-F-05-004")
|
||||||
|
* @param port_code 端口编号
|
||||||
|
* @param new_fiber_core 新的纤芯编号
|
||||||
|
* @param splice_tray 新的熔接盘号
|
||||||
|
* @param cable_core 新的光缆芯号
|
||||||
|
* @param route_info 新的路由信息
|
||||||
|
* @return 是否更新成功
|
||||||
|
*/
|
||||||
|
bool updateMapping(const std::string& port_code, const std::string& new_fiber_core,
|
||||||
|
const std::string& splice_tray = "", const std::string& cable_core = "",
|
||||||
|
const std::string& route_info = "");
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 模拟数据库存储
|
||||||
|
std::map<std::string, PortMapping> mappings_;
|
||||||
|
int next_id_ = 1;
|
||||||
|
std::mutex mutex_;
|
||||||
|
|
||||||
|
// 辅助:验证端口编码格式 (SRS-F-05-002)
|
||||||
|
bool validatePortCodeFormat(const std::string& code) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备监控器,负责硬件节点健康度轮询、离线/故障告警生成及环境参数采集。
|
||||||
|
*/
|
||||||
|
class DeviceMonitor {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 检查并上报设备节点的健康状态。
|
||||||
|
*
|
||||||
|
* @requirement(name="CSCI运行适应性需求", id="SRS-NFR-SRS-010")
|
||||||
|
* @param node_id 设备节点ID
|
||||||
|
* @param temperature 当前温度
|
||||||
|
* @param humidity 当前湿度
|
||||||
|
* @param is_connected 物理连接状态
|
||||||
|
* @return 设备健康快照
|
||||||
|
*/
|
||||||
|
DeviceHealth checkStatus(const std::string& node_id, double temperature,
|
||||||
|
double humidity, bool is_connected);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据阈值判断是否产生告警。
|
||||||
|
*
|
||||||
|
* @requirement(name="CSCI运行适应性需求", id="SRS-NFR-SRS-010")
|
||||||
|
* @param health 设备健康状态
|
||||||
|
* @param temp_threshold 温度告警阈值
|
||||||
|
* @param humidity_threshold 湿度告警阈值
|
||||||
|
* @return 告警消息,若无异常返回空字符串
|
||||||
|
*/
|
||||||
|
std::string generateAlert(const DeviceHealth& health, double temp_threshold = 40.0,
|
||||||
|
double humidity_threshold = 80.0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户认证服务,负责账号登录验证、RBAC角色权限控制及会话管理。
|
||||||
|
*/
|
||||||
|
class UserService {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 验证用户登录凭证并签发会话令牌。
|
||||||
|
*
|
||||||
|
* @requirement(name="安全性需求", id="SRS-NFR-SRS-011")
|
||||||
|
* @param username 用户名
|
||||||
|
* @param password 密码
|
||||||
|
* @return 用户信息,若验证失败返回 nullopt
|
||||||
|
*/
|
||||||
|
std::optional<UserInfo> authenticate(const std::string& username, const std::string& password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查用户是否具有执行特定操作所需的角色权限。
|
||||||
|
*
|
||||||
|
* @requirement(name="安全性需求", id="SRS-NFR-SRS-011")
|
||||||
|
* @param user 当前用户
|
||||||
|
* @param required_role 所需最低角色
|
||||||
|
* @return 是否拥有权限
|
||||||
|
*/
|
||||||
|
bool hasPermission(const UserInfo& user, UserRole required_role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销用户会话,使其失效。
|
||||||
|
*
|
||||||
|
* @requirement(name="安全性需求", id="SRS-NFR-SRS-011")
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
|
void logout(const std::string& username);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, UserInfo> users_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace odf
|
||||||
|
|
||||||
|
#endif // ODF_MANAGER_APP_HPP
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
#include "app.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <regex>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace odf {
|
||||||
|
|
||||||
|
// ==================== PortMappingManager 实现 ====================
|
||||||
|
|
||||||
|
bool PortMappingManager::validatePortCodeFormat(const std::string& code) const {
|
||||||
|
// SRS-F-05-002: 产品型号编码结构校验
|
||||||
|
// 简化正则:允许字母、数字、连字符,长度 1-10
|
||||||
|
static const std::regex port_regex("^[A-Za-z0-9\\-]{1,10}$");
|
||||||
|
return std::regex_match(code, port_regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PortMappingManager::addMapping(const std::string& port_code, const std::string& fiber_core,
|
||||||
|
const std::string& splice_tray, const std::string& cable_core,
|
||||||
|
const std::string& route_info) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
|
// SRS-F-05-001: 端口唯一编号系统 - 校验格式与唯一性
|
||||||
|
if (!validatePortCodeFormat(port_code)) {
|
||||||
|
std::cerr << "Invalid port code format: " << port_code << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mappings_.find(port_code) != mappings_.end()) {
|
||||||
|
std::cerr << "Port code already exists: " << port_code << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortMapping pm;
|
||||||
|
pm.mapping_id = next_id_++;
|
||||||
|
pm.port_code = port_code;
|
||||||
|
pm.fiber_core = fiber_core;
|
||||||
|
pm.splice_tray = splice_tray;
|
||||||
|
pm.cable_core = cable_core;
|
||||||
|
pm.route_info = route_info;
|
||||||
|
pm.create_time = std::chrono::system_clock::now();
|
||||||
|
pm.update_time = pm.create_time;
|
||||||
|
|
||||||
|
mappings_[port_code] = pm;
|
||||||
|
return pm.mapping_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PortMappingManager::deleteMapping(const std::string& port_code) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto it = mappings_.find(port_code);
|
||||||
|
if (it != mappings_.end()) {
|
||||||
|
mappings_.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<PortMapping> PortMappingManager::getMapping(const std::string& port_code) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto it = mappings_.find(port_code);
|
||||||
|
if (it != mappings_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PortMappingManager::updateMapping(const std::string& port_code, const std::string& new_fiber_core,
|
||||||
|
const std::string& splice_tray, const std::string& cable_core,
|
||||||
|
const std::string& route_info) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto it = mappings_.find(port_code);
|
||||||
|
if (it == mappings_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SRS-F-05-003: 内部组件编号与溯源 - 更新组件信息并记录时间戳
|
||||||
|
it->second.fiber_core = new_fiber_core;
|
||||||
|
if (!splice_tray.empty()) it->second.splice_tray = splice_tray;
|
||||||
|
if (!cable_core.empty()) it->second.cable_core = cable_core;
|
||||||
|
if (!route_info.empty()) it->second.route_info = route_info;
|
||||||
|
it->second.update_time = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== DeviceMonitor 实现 ====================
|
||||||
|
|
||||||
|
DeviceHealth DeviceMonitor::checkStatus(const std::string& node_id, double temperature,
|
||||||
|
double humidity, bool is_connected) {
|
||||||
|
// SRS-NFR-SRS-010: CSCI运行适应性需求 - 采集环境参数
|
||||||
|
DeviceHealth health;
|
||||||
|
health.node_id = node_id;
|
||||||
|
health.temperature_celsius = temperature;
|
||||||
|
health.humidity_percent = humidity;
|
||||||
|
health.is_online = is_connected;
|
||||||
|
|
||||||
|
if (!is_connected) {
|
||||||
|
health.port_status = PortStatus::ERROR_STATE;
|
||||||
|
} else if (temperature > 40.0 || humidity > 80.0) {
|
||||||
|
health.port_status = PortStatus::ERROR_STATE;
|
||||||
|
} else {
|
||||||
|
health.port_status = PortStatus::ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return health;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DeviceMonitor::generateAlert(const DeviceHealth& health, double temp_threshold,
|
||||||
|
double humidity_threshold) {
|
||||||
|
// SRS-NFR-SRS-010: CSCI运行适应性需求 - 异常告警生成
|
||||||
|
std::ostringstream oss;
|
||||||
|
if (!health.is_online) {
|
||||||
|
oss << "ALERT: Node " << health.node_id << " is offline.";
|
||||||
|
} else {
|
||||||
|
if (health.temperature_celsius > temp_threshold) {
|
||||||
|
oss << "ALERT: High temperature on " << health.node_id
|
||||||
|
<< ": " << health.temperature_celsius << "°C";
|
||||||
|
}
|
||||||
|
if (health.humidity_percent > humidity_threshold) {
|
||||||
|
oss << "ALERT: High humidity on " << health.node_id
|
||||||
|
<< ": " << health.humidity_percent << "%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== UserService 实现 ====================
|
||||||
|
|
||||||
|
std::optional<UserInfo> UserService::authenticate(const std::string& username, const std::string& password) {
|
||||||
|
// SRS-NFR-SRS-011: 安全性需求 - 身份认证与会话管理
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
|
// 模拟简单的用户验证逻辑
|
||||||
|
// 实际场景中应查询数据库并比对哈希密码
|
||||||
|
if (username.empty() || password.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserInfo user;
|
||||||
|
user.username = username;
|
||||||
|
// 默认分配角色,实际应根据数据库中的 Roles/Permissions 表确定
|
||||||
|
if (username == "admin") {
|
||||||
|
user.role = UserRole::ADMIN;
|
||||||
|
} else if (username == "operator") {
|
||||||
|
user.role = UserRole::OPERATOR;
|
||||||
|
} else {
|
||||||
|
user.role = UserRole::VIEWER;
|
||||||
|
}
|
||||||
|
user.is_session_valid = true;
|
||||||
|
|
||||||
|
users_[username] = user;
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserService::hasPermission(const UserInfo& user, UserRole required_role) {
|
||||||
|
// SRS-NFR-SRS-011: 安全性需求 - RBAC权限控制
|
||||||
|
if (!user.is_session_valid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 简单层级比较:ADMIN > OPERATOR > VIEWER
|
||||||
|
int user_level = static_cast<int>(user.role);
|
||||||
|
int required_level = static_cast<int>(required_role);
|
||||||
|
|
||||||
|
return user_level >= required_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserService::logout(const std::string& username) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
auto it = users_.find(username);
|
||||||
|
if (it != users_.end()) {
|
||||||
|
it->second.is_session_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace odf
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include "app.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
using namespace odf;
|
||||||
|
|
||||||
|
std::cout << "=== ODF Fiber Distribution Management System ===" << std::endl;
|
||||||
|
|
||||||
|
// 1. 端口映射管理测试 (SRS-F-05-001, SRS-F-05-002, SRS-F-05-003, SRS-F-05-004)
|
||||||
|
PortMappingManager pm_manager;
|
||||||
|
|
||||||
|
std::cout << "\n--- Testing Port Mapping ---" << std::endl;
|
||||||
|
|
||||||
|
// 添加有效映射
|
||||||
|
int id1 = pm_manager.addMapping("PORT-001", "FIBER-A1", "TRAY-01", "CABLE-X1", "Route A->B");
|
||||||
|
std::cout << "Added mapping ID: " << id1 << std::endl;
|
||||||
|
|
||||||
|
// 添加重复端口(应失败)
|
||||||
|
int id2 = pm_manager.addMapping("PORT-001", "FIBER-B2");
|
||||||
|
std::cout << "Duplicate add result: " << id2 << " (expected -1)" << std::endl;
|
||||||
|
|
||||||
|
// 添加无效格式端口(应失败,SRS-F-05-002)
|
||||||
|
int id3 = pm_manager.addMapping("INVALID PORT!", "FIBER-C3");
|
||||||
|
std::cout << "Invalid format add result: " << id3 << " (expected -1)" << std::endl;
|
||||||
|
|
||||||
|
// 查询映射
|
||||||
|
auto map_opt = pm_manager.getMapping("PORT-001");
|
||||||
|
if (map_opt) {
|
||||||
|
std::cout << "Found mapping: Port=" << map_opt->port_code
|
||||||
|
<< ", Fiber=" << map_opt->fiber_core
|
||||||
|
<< ", Tray=" << map_opt->splice_tray << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Mapping not found." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新映射 (SRS-F-05-003)
|
||||||
|
bool updated = pm_manager.updateMapping("PORT-001", "FIBER-A1-UPDATED", "TRAY-02");
|
||||||
|
std::cout << "Update result: " << (updated ? "Success" : "Failed") << std::endl;
|
||||||
|
|
||||||
|
// 删除映射
|
||||||
|
bool deleted = pm_manager.deleteMapping("PORT-001");
|
||||||
|
std::cout << "Delete result: " << (deleted ? "Success" : "Failed") << std::endl;
|
||||||
|
|
||||||
|
// 2. 设备状态监控测试 (SRS-NFR-SRS-010)
|
||||||
|
DeviceMonitor monitor;
|
||||||
|
|
||||||
|
std::cout << "\n--- Testing Device Monitor ---" << std::endl;
|
||||||
|
|
||||||
|
DeviceHealth healthy = monitor.checkStatus("NODE-1", 25.0, 50.0, true);
|
||||||
|
std::string alert1 = monitor.generateAlert(healthy);
|
||||||
|
std::cout << "Healthy node alert: '" << alert1 << "' (expected empty)" << std::endl;
|
||||||
|
|
||||||
|
DeviceHealth overheated = monitor.checkStatus("NODE-2", 45.0, 60.0, true);
|
||||||
|
std::string alert2 = monitor.generateAlert(overheated);
|
||||||
|
std::cout << "Overheated node alert: '" << alert2 << "'" << std::endl;
|
||||||
|
|
||||||
|
DeviceHealth offline = monitor.checkStatus("NODE-3", 20.0, 40.0, false);
|
||||||
|
std::string alert3 = monitor.generateAlert(offline);
|
||||||
|
std::cout << "Offline node alert: '" << alert3 << "'" << std::endl;
|
||||||
|
|
||||||
|
// 3. 用户认证与授权测试 (SRS-NFR-SRS-011)
|
||||||
|
UserService user_service;
|
||||||
|
|
||||||
|
std::cout << "\n--- Testing User Service ---" << std::endl;
|
||||||
|
|
||||||
|
auto admin_user = user_service.authenticate("admin", "password123");
|
||||||
|
if (admin_user) {
|
||||||
|
std::cout << "Admin login success. Role: " << static_cast<int>(admin_user->role) << std::endl;
|
||||||
|
|
||||||
|
bool can_manage = user_service.hasPermission(*admin_user, UserRole::OPERATOR);
|
||||||
|
std::cout << "Admin has OPERATOR permission: " << (can_manage ? "Yes" : "No") << std::endl;
|
||||||
|
|
||||||
|
bool can_view = user_service.hasPermission(*admin_user, UserRole::VIEWER);
|
||||||
|
std::cout << "Admin has VIEWER permission: " << (can_view ? "Yes" : "No") << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Admin login failed." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto viewer_user = user_service.authenticate("viewer", "pass456");
|
||||||
|
if (viewer_user) {
|
||||||
|
bool can_operate = user_service.hasPermission(*viewer_user, UserRole::OPERATOR);
|
||||||
|
std::cout << "Viewer has OPERATOR permission: " << (can_operate ? "Yes" : "No") << std::endl;
|
||||||
|
|
||||||
|
user_service.logout("viewer");
|
||||||
|
bool still_valid = user_service.hasPermission(*viewer_user, UserRole::VIEWER);
|
||||||
|
std::cout << "Viewer session valid after logout: " << (still_valid ? "Yes" : "No") << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n=== All Tests Completed ===" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include "app.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void test_port_mapping_unique_id() {
|
||||||
|
// SRS-F-05-001: 端口唯一编号系统
|
||||||
|
odf::PortMappingManager pm;
|
||||||
|
|
||||||
|
int id1 = pm.addMapping("P-001", "F-001");
|
||||||
|
assert(id1 > 0);
|
||||||
|
|
||||||
|
int id2 = pm.addMapping("P-002", "F-002");
|
||||||
|
assert(id2 > 0);
|
||||||
|
assert(id2 != id1);
|
||||||
|
|
||||||
|
// 重复端口应返回 -1
|
||||||
|
int id_dup = pm.addMapping("P-001", "F-003");
|
||||||
|
assert(id_dup == -1);
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_port_mapping_unique_id" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_port_mapping_format_validation() {
|
||||||
|
// SRS-F-05-002: 产品型号编码结构
|
||||||
|
odf::PortMappingManager pm;
|
||||||
|
|
||||||
|
// 有效格式
|
||||||
|
int id_valid = pm.addMapping("ODF-1U-24", "F-001");
|
||||||
|
assert(id_valid > 0);
|
||||||
|
|
||||||
|
// 无效格式(包含空格或过长)
|
||||||
|
int id_invalid = pm.addMapping("INVALID PORT!", "F-002");
|
||||||
|
assert(id_invalid == -1);
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_port_mapping_format_validation" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_port_mapping_update_traceability() {
|
||||||
|
// SRS-F-05-003: 内部组件编号与溯源
|
||||||
|
odf::PortMappingManager pm;
|
||||||
|
|
||||||
|
pm.addMapping("P-001", "F-OLD", "TRAY-1", "CABLE-A", "Route 1");
|
||||||
|
|
||||||
|
bool updated = pm.updateMapping("P-001", "F-NEW", "TRAY-2", "CABLE-B", "Route 2");
|
||||||
|
assert(updated);
|
||||||
|
|
||||||
|
auto mapping = pm.getMapping("P-001");
|
||||||
|
assert(mapping.has_value());
|
||||||
|
assert(mapping->fiber_core == "F-NEW");
|
||||||
|
assert(mapping->splice_tray == "TRAY-2");
|
||||||
|
assert(mapping->cable_core == "CABLE-B");
|
||||||
|
assert(mapping->route_info == "Route 2");
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_port_mapping_update_traceability" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_port_mapping_crud() {
|
||||||
|
// SRS-F-05-004: 端口映射记录表支持
|
||||||
|
odf::PortMappingManager pm;
|
||||||
|
|
||||||
|
// Create
|
||||||
|
int id = pm.addMapping("P-CRUD", "F-CRUD");
|
||||||
|
assert(id > 0);
|
||||||
|
|
||||||
|
// Read
|
||||||
|
auto opt = pm.getMapping("P-CRUD");
|
||||||
|
assert(opt.has_value());
|
||||||
|
assert(opt->port_code == "P-CRUD");
|
||||||
|
|
||||||
|
// Update
|
||||||
|
bool upd = pm.updateMapping("P-CRUD", "F-CRUD-V2");
|
||||||
|
assert(upd);
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
bool del = pm.deleteMapping("P-CRUD");
|
||||||
|
assert(del);
|
||||||
|
|
||||||
|
// Verify deleted
|
||||||
|
auto opt_after_del = pm.getMapping("P-CRUD");
|
||||||
|
assert(!opt_after_del.has_value());
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_port_mapping_crud" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_device_monitor_status() {
|
||||||
|
// SRS-NFR-SRS-010: CSCI运行适应性需求
|
||||||
|
odf::DeviceMonitor monitor;
|
||||||
|
|
||||||
|
// 正常状态
|
||||||
|
auto healthy = monitor.checkStatus("N1", 25.0, 50.0, true);
|
||||||
|
assert(healthy.port_status == odf::PortStatus::ACTIVE);
|
||||||
|
assert(monitor.generateAlert(healthy).empty());
|
||||||
|
|
||||||
|
// 高温告警
|
||||||
|
auto hot = monitor.checkStatus("N2", 45.0, 50.0, true);
|
||||||
|
assert(hot.port_status == odf::PortStatus::ERROR_STATE);
|
||||||
|
assert(!monitor.generateAlert(hot).empty());
|
||||||
|
|
||||||
|
// 离线告警
|
||||||
|
auto offline = monitor.checkStatus("N3", 20.0, 40.0, false);
|
||||||
|
assert(offline.port_status == odf::PortStatus::ERROR_STATE);
|
||||||
|
assert(!monitor.generateAlert(offline).empty());
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_device_monitor_status" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_user_authentication() {
|
||||||
|
// SRS-NFR-SRS-011: 安全性需求
|
||||||
|
odf::UserService service;
|
||||||
|
|
||||||
|
// 登录成功
|
||||||
|
auto user = service.authenticate("admin", "pass");
|
||||||
|
assert(user.has_value());
|
||||||
|
assert(user->is_session_valid);
|
||||||
|
|
||||||
|
// 权限检查
|
||||||
|
assert(service.hasPermission(*user, odf::UserRole::ADMIN));
|
||||||
|
assert(service.hasPermission(*user, odf::UserRole::OPERATOR));
|
||||||
|
assert(service.hasPermission(*user, odf::UserRole::VIEWER));
|
||||||
|
|
||||||
|
// 登出后权限失效
|
||||||
|
service.logout("admin");
|
||||||
|
assert(!service.hasPermission(*user, odf::UserRole::VIEWER));
|
||||||
|
|
||||||
|
std::cout << "[PASS] test_user_authentication" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "Running ODF Manager Basic Tests..." << std::endl;
|
||||||
|
|
||||||
|
test_port_mapping_unique_id();
|
||||||
|
test_port_mapping_format_validation();
|
||||||
|
test_port_mapping_update_traceability();
|
||||||
|
test_port_mapping_crud();
|
||||||
|
test_device_monitor_status();
|
||||||
|
test_user_authentication();
|
||||||
|
|
||||||
|
std::cout << "All basic tests passed!" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue