生成代码工程

This commit is contained in:
root 2026-07-09 10:02:27 +08:00
parent e92b4bdc96
commit 868fd74ca2
8 changed files with 6505 additions and 2 deletions

37
CMakeLists.txt Normal file
View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.14)
project(dataflow_system VERSION 1.0.0 LANGUAGES CXX)
# C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# MSVC UTF-8
if(MSVC)
add_compile_options(/utf-8)
endif()
#
set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
# ============================
#
# ============================
add_executable(dataflow_main
src/main.cpp
src/app.cpp
)
target_include_directories(dataflow_main PRIVATE ${INCLUDE_DIR})
# ============================
#
# ============================
add_executable(basic_test
tests/basic_test.cpp
src/app.cpp
)
target_include_directories(basic_test PRIVATE ${INCLUDE_DIR})
# ctest
enable_testing()
add_test(NAME basic_test COMMAND basic_test)

View File

@ -1,3 +1,73 @@
# 测试
# 数据处理与交互平台(测试系统)
暂无描述
## 概述
本工程是一个模拟的数据处理与交互平台(测试系统),采用管道流式处理架构。
核心功能包括:
- **CSU-01 (DataReceiver)**:模拟 TCP 服务端,按自定义协议(消息头 + 消息体)接收外部数据源的数据。
- **CSU-02 (DataProcessor)**:从队列获取原始数据,进行校验(非空、长度、字符合法性)和格式转换。
- **CSU-03 (DataStorage)**:将处理后的数据持久化存储(当前版本使用内存向量模拟数据库写入)。
三个模块通过线程安全队列(`ThreadSafeQueue`)解耦,形成数据流水线。
## 工程结构
```
.
├── CMakeLists.txt # CMake 构建配置
├── README.md # 本文件
├── include/
│ └── app.hpp # 公共头文件(类声明、数据结构)
├── src/
│ ├── main.cpp # 命令行入口(完整流水线演示)
│ └── app.cpp # 模块实现
└── tests/
└── basic_test.cpp # 单元测试与集成测试
```
## 编译与运行
### 前置条件
- CMake >= 3.14
- 支持 C++17 的编译器GCC 8+, Clang 7+, MSVC 2019+
### 编译步骤
```bash
cd codegen-runs/codegen_fa54ba0e8c734a7683962ff923b15d4b
mkdir -p build && cd build
cmake ..
cmake --build .
```
### 运行主程序
```bash
./dataflow_main
```
### 运行测试
```bash
./basic_test
# 或
ctest
```
## 模块映射
| 文档中的软件单元 | 本工程类名 | 职责 |
|:---|:---|:---|
| CSU-01 | `DataReceiver` | 数据接收(模拟 TCP 服务端、协议拆包) |
| CSU-02 | `DataProcessor` | 数据处理(校验、格式转换) |
| CSU-03 | `DataStorage` | 数据存储(持久化到内存数据库) |
| 内部接口 IF_CSU01_02 | `ThreadSafeQueue<std::string>` | 原始数据传递队列 |
| 内部接口 CSU-02→CSU-03 | `ThreadSafeQueue<std::string>` | 处理后数据传递队列 |
## 需求追踪
| 需求标识 | 需求名称 | 对应函数 |
|:---|:---|:---|
| SRS-测试_F-001 | 数据接收功能 | `DataReceiver::start()`, `DataReceiver::receiveLoop()`, `DataReceiver::parsePacket()`, `DataProcessor::start()`, `DataProcessor::processLoop()`, `DataProcessor::validateAndTransform()`, `DataStorage::start()`, `DataStorage::storageLoop()`, `DataStorage::storeToDatabase()`, `main()` |

5354
events.ndjson Normal file

File diff suppressed because one or more lines are too long

30
generation.json Normal file

File diff suppressed because one or more lines are too long

341
include/app.hpp Normal file
View File

@ -0,0 +1,341 @@
#ifndef DATAFLOW_APP_HPP
#define DATAFLOW_APP_HPP
#include <string>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
#include <chrono>
#include <cstdint>
#include <stdexcept>
namespace dataflow {
/**
* @brief 线
*
* 线
*/
template<typename T>
class ThreadSafeQueue {
public:
ThreadSafeQueue() = default;
~ThreadSafeQueue() = default;
ThreadSafeQueue(const ThreadSafeQueue&) = delete;
ThreadSafeQueue& operator=(const ThreadSafeQueue&) = delete;
void push(T item) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(std::move(item));
cond_.notify_one();
}
bool tryPop(T& item) {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) {
return false;
}
item = std::move(queue_.front());
queue_.pop();
return true;
}
void waitAndPop(T& item) {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return !queue_.empty(); });
item = std::move(queue_.front());
queue_.pop();
}
bool empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
size_t size() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
void clear() {
std::lock_guard<std::mutex> lock(mutex_);
while (!queue_.empty()) {
queue_.pop();
}
}
private:
mutable std::mutex mutex_;
std::queue<T> queue_;
std::condition_variable cond_;
};
/**
* @brief
*
* TCP
* 4 + UTF-8
*/
struct RawDataPacket {
uint32_t length; ///< 消息体长度(字节数)
std::string body; ///< 消息体内容UTF-8 编码,最大 1024 字符)
};
/**
* @brief CSU-01
*
* TCP
* +
*
*/
class DataReceiver {
public:
/**
* @brief
* @param outputQueue
*/
explicit DataReceiver(ThreadSafeQueue<std::string>& outputQueue);
~DataReceiver();
/**
* @brief
*
* 线
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
* TCP
*/
void start();
/**
* @brief
*/
void stop();
/**
* @brief
* @param data
*
* 4 +
*/
void setMockDataSource(const std::vector<std::string>& data);
/** @brief 获取已成功接收并解析的数据包数量。 */
size_t getReceivedCount() const;
/** @brief 获取解析失败的数据包数量。 */
size_t getErrorCount() const;
/** @brief 获取最近一次错误信息。 */
std::string getLastError() const;
private:
/**
* @brief 线
*
* parsePacket
*
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void receiveLoop();
/**
* @brief
* @param buffer +
* @param offset /
* @param outData [out]
* @return true false
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
* +
*/
bool parsePacket(const std::vector<char>& buffer, size_t& offset, std::string& outData);
ThreadSafeQueue<std::string>& outputQueue_;
std::vector<std::string> mockData_;
std::atomic<bool> running_{false};
std::thread workerThread_;
std::atomic<size_t> receivedCount_{0};
std::atomic<size_t> errorCount_{0};
std::string lastError_;
mutable std::mutex errorMutex_;
};
/**
* @brief CSU-02
*
*
*
*
*/
class DataProcessor {
public:
/**
* @brief
* @param inputQueue CSU-01
* @param outputQueue CSU-03
*/
DataProcessor(ThreadSafeQueue<std::string>& inputQueue,
ThreadSafeQueue<std::string>& outputQueue);
~DataProcessor();
/**
* @brief
*
* 线
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void start();
/**
* @brief
*/
void stop();
/** @brief 获取成功处理的数据包数量。 */
size_t getProcessedCount() const;
/** @brief 因校验失败被丢弃的数据包数量。 */
size_t getDiscardedCount() const;
/** @brief 处理过程中发生异常的次数。 */
size_t getErrorCount() const;
/** @brief 获取最近一次错误信息。 */
std::string getLastError() const;
private:
/**
* @brief 线
*
* validateAndTransform
*
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void processLoop();
/**
* @brief
* @param rawData
* @param outProcessed [out]
* @return true false
*
*
* -
* - 1024
* - UTF-8 ASCII
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
bool validateAndTransform(const std::string& rawData, std::string& outProcessed);
ThreadSafeQueue<std::string>& inputQueue_;
ThreadSafeQueue<std::string>& outputQueue_;
std::atomic<bool> running_{false};
std::thread workerThread_;
std::atomic<size_t> processedCount_{0};
std::atomic<size_t> discardedCount_{0};
std::atomic<size_t> errorCount_{0};
std::string lastError_;
mutable std::mutex errorMutex_;
};
/**
* @brief CSU-03
*
*
* 使 MySQL t_received_data
*/
class DataStorage {
public:
/**
* @brief
* @param inputQueue CSU-02
*/
explicit DataStorage(ThreadSafeQueue<std::string>& inputQueue);
~DataStorage();
/**
* @brief
*
* 线
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void start();
/**
* @brief
*/
void stop();
/** @brief 成功存储的数据条数。 */
size_t getStoredCount() const;
/** @brief 存储过程中发生的错误次数。 */
size_t getErrorCount() const;
/** @brief 获取最近一次错误信息。 */
std::string getLastError() const;
/**
* @brief
* @return
*/
std::vector<std::string> getAllStoredData() const;
/** @brief 当前存储的数据总条数。 */
size_t getStorageSize() const;
private:
/**
* @brief 线
*
* storeToDatabase
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void storageLoop();
/**
* @brief
* @param data
* @return true false
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
bool storeToDatabase(const std::string& data);
ThreadSafeQueue<std::string>& inputQueue_;
std::atomic<bool> running_{false};
std::thread workerThread_;
std::atomic<size_t> storedCount_{0};
std::atomic<size_t> errorCount_{0};
std::string lastError_;
mutable std::mutex errorMutex_;
/// 内存模拟数据库存储(对应 t_received_data 表的数据内容)
std::vector<std::string> storage_;
mutable std::mutex storageMutex_;
};
} // namespace dataflow
#endif // DATAFLOW_APP_HPP

359
src/app.cpp Normal file
View File

@ -0,0 +1,359 @@
#include "app.hpp"
#include <iostream>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <algorithm>
namespace dataflow {
// ============================================================================
// DataReceiver
// ============================================================================
DataReceiver::DataReceiver(ThreadSafeQueue<std::string>& outputQueue)
: outputQueue_(outputQueue) {
}
DataReceiver::~DataReceiver() {
stop();
}
void DataReceiver::start() {
if (running_.exchange(true)) {
return;
}
workerThread_ = std::thread(&DataReceiver::receiveLoop, this);
}
void DataReceiver::stop() {
running_ = false;
if (workerThread_.joinable()) {
workerThread_.join();
}
}
void DataReceiver::setMockDataSource(const std::vector<std::string>& data) {
mockData_ = data;
}
size_t DataReceiver::getReceivedCount() const {
return receivedCount_.load();
}
size_t DataReceiver::getErrorCount() const {
return errorCount_.load();
}
std::string DataReceiver::getLastError() const {
std::lock_guard<std::mutex> lock(errorMutex_);
return lastError_;
}
/**
* @brief 线
*
* parsePacket
*
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void DataReceiver::receiveLoop() {
for (const auto& msgBody : mockData_) {
if (!running_) {
break;
}
// 构造完整数据包4 字节长度前缀(小端序)+ 消息体
uint32_t bodyLen = static_cast<uint32_t>(msgBody.size());
std::vector<char> packet(4 + bodyLen);
std::memcpy(packet.data(), &bodyLen, sizeof(bodyLen));
if (bodyLen > 0) {
std::memcpy(packet.data() + 4, msgBody.data(), bodyLen);
}
// 解析数据包
size_t offset = 0;
std::string parsedData;
if (parsePacket(packet, offset, parsedData)) {
outputQueue_.push(parsedData);
receivedCount_++;
} else {
errorCount_++;
{
std::lock_guard<std::mutex> lock(errorMutex_);
lastError_ = "DataReceiver: failed to parse packet";
}
}
// 模拟间隔(每秒最多 100 次 => 每次至少 10ms
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
/**
* @brief
* @param buffer +
* @param offset /
* @param outData [out]
* @return true false
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
* +
*/
bool DataReceiver::parsePacket(const std::vector<char>& buffer,
size_t& offset,
std::string& outData) {
// 检查剩余数据是否足够读取消息头
if (offset + 4 > buffer.size()) {
return false;
}
// 读取消息头中的长度字段(小端序)
uint32_t bodyLen = 0;
std::memcpy(&bodyLen, buffer.data() + offset, sizeof(bodyLen));
offset += 4;
// 检查消息体长度合法性
if (bodyLen > 1024) {
return false;
}
// 检查剩余数据是否足够读取完整消息体
if (offset + bodyLen > buffer.size()) {
return false;
}
// 读取消息体
outData.assign(buffer.data() + offset, bodyLen);
offset += bodyLen;
return true;
}
// ============================================================================
// DataProcessor
// ============================================================================
DataProcessor::DataProcessor(ThreadSafeQueue<std::string>& inputQueue,
ThreadSafeQueue<std::string>& outputQueue)
: inputQueue_(inputQueue), outputQueue_(outputQueue) {
}
DataProcessor::~DataProcessor() {
stop();
}
void DataProcessor::start() {
if (running_.exchange(true)) {
return;
}
workerThread_ = std::thread(&DataProcessor::processLoop, this);
}
void DataProcessor::stop() {
running_ = false;
if (workerThread_.joinable()) {
workerThread_.join();
}
}
size_t DataProcessor::getProcessedCount() const {
return processedCount_.load();
}
size_t DataProcessor::getDiscardedCount() const {
return discardedCount_.load();
}
size_t DataProcessor::getErrorCount() const {
return errorCount_.load();
}
std::string DataProcessor::getLastError() const {
std::lock_guard<std::mutex> lock(errorMutex_);
return lastError_;
}
/**
* @brief 线
*
* validateAndTransform
*
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void DataProcessor::processLoop() {
while (running_) {
std::string rawData;
// 尝试非阻塞获取,以便能及时响应停止信号
if (inputQueue_.tryPop(rawData)) {
std::string processedData;
if (validateAndTransform(rawData, processedData)) {
outputQueue_.push(processedData);
processedCount_++;
} else {
discardedCount_++;
{
std::lock_guard<std::mutex> lock(errorMutex_);
lastError_ = "DataProcessor: data validation failed, discarded";
}
}
} else {
// 队列为空时短暂休眠
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
}
/**
* @brief
* @param rawData
* @param outProcessed [out]
* @return true false
*
*
* -
* - 1024
* - UTF-8 ASCII
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
bool DataProcessor::validateAndTransform(const std::string& rawData,
std::string& outProcessed) {
// 规则1非空检查
if (rawData.empty()) {
return false;
}
// 规则2长度不超过 1024 字符
if (rawData.size() > 1024) {
return false;
}
// 规则3仅包含可打印 ASCII 字符的简单检查
// (用于模拟防止注入攻击的验证)
for (unsigned char ch : rawData) {
if (ch < 0x20 || ch > 0x7E) {
// 允许常见的空白字符(水平制表符、换行符等)用于实际业务场景,
// 但此处为简单校验,严格限定为可打印 ASCII。
// 对于中文 UTF-8 多字节字符,每个字节均大于 0x7E
// 此简单校验不通过;实际系统中应使用完整的 UTF-8 验证。
// 本示例中,我们放宽限制以允许 UTF-8 中文数据通过。
// 放宽检查仅拒绝控制字符0x00 - 0x1F, 0x7F
if (ch <= 0x1F || ch == 0x7F) {
return false;
}
}
}
// 转换:添加处理时间戳前缀(模拟格式转换)
auto now = std::chrono::system_clock::now();
auto nowT = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << "[PROCESSED:" << std::put_time(std::localtime(&nowT), "%Y%m%d%H%M%S") << "] " << rawData;
outProcessed = ss.str();
return true;
}
// ============================================================================
// DataStorage
// ============================================================================
DataStorage::DataStorage(ThreadSafeQueue<std::string>& inputQueue)
: inputQueue_(inputQueue) {
}
DataStorage::~DataStorage() {
stop();
}
void DataStorage::start() {
if (running_.exchange(true)) {
return;
}
workerThread_ = std::thread(&DataStorage::storageLoop, this);
}
void DataStorage::stop() {
running_ = false;
if (workerThread_.joinable()) {
workerThread_.join();
}
}
size_t DataStorage::getStoredCount() const {
return storedCount_.load();
}
size_t DataStorage::getErrorCount() const {
return errorCount_.load();
}
std::string DataStorage::getLastError() const {
std::lock_guard<std::mutex> lock(errorMutex_);
return lastError_;
}
std::vector<std::string> DataStorage::getAllStoredData() const {
std::lock_guard<std::mutex> lock(storageMutex_);
return storage_;
}
size_t DataStorage::getStorageSize() const {
std::lock_guard<std::mutex> lock(storageMutex_);
return storage_.size();
}
/**
* @brief 线
*
* storeToDatabase
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void DataStorage::storageLoop() {
while (running_) {
std::string data;
if (inputQueue_.tryPop(data)) {
if (storeToDatabase(data)) {
storedCount_++;
} else {
errorCount_++;
{
std::lock_guard<std::mutex> lock(errorMutex_);
lastError_ = "DataStorage: failed to store data";
}
}
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
}
/**
* @brief
* @param data
* @return true false
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
bool DataStorage::storeToDatabase(const std::string& data) {
try {
std::lock_guard<std::mutex> lock(storageMutex_);
storage_.push_back(data);
return true;
} catch (const std::exception& e) {
std::lock_guard<std::mutex> lock(errorMutex_);
lastError_ = std::string("DataStorage::storeToDatabase exception: ") + e.what();
return false;
}
}
} // namespace dataflow

93
src/main.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "app.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
/**
* @brief
*
*
* CSU-01 CSU-02 CSU-03
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
int main() {
std::cout << "=== 测试系统 - 管道流水线处理演示 ===" << std::endl;
// 创建模块间数据传递队列
dataflow::ThreadSafeQueue<std::string> queue01to02; // CSU-01 → CSU-02
dataflow::ThreadSafeQueue<std::string> queue02to03; // CSU-02 → CSU-03
// 创建三个处理模块
dataflow::DataReceiver receiver(queue01to02);
dataflow::DataProcessor processor(queue01to02, queue02to03);
dataflow::DataStorage storage(queue02to03);
// 设置模拟数据源(模拟外部数据源发送的数据)
std::vector<std::string> mockData = {
"Hello, system test!",
"Sensor reading: temperature=23.5, humidity=65",
"Event: system startup completed",
"", // 空数据,应被丢弃
"Normal data packet #4",
"中文测试数据包",
"Another measurement: pressure=1013.25",
};
receiver.setMockDataSource(mockData);
// 启动所有模块
std::cout << "启动各处理模块..." << std::endl;
receiver.start();
processor.start();
storage.start();
// 等待处理完成(模拟数据源发送完毕后,等待处理线程完成)
// 实际系统中会持续运行,此处等待足够时间让所有数据被处理
std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 停止所有模块
std::cout << "停止各处理模块..." << std::endl;
receiver.stop();
processor.stop();
storage.stop();
// 输出统计信息
std::cout << "\n=== 处理统计 ===" << std::endl;
std::cout << "接收模块 (CSU-01):" << std::endl;
std::cout << " 成功接收: " << receiver.getReceivedCount() << " 个数据包" << std::endl;
std::cout << " 解析错误: " << receiver.getErrorCount() << " 个数据包" << std::endl;
if (receiver.getErrorCount() > 0) {
std::cout << " 最近错误: " << receiver.getLastError() << std::endl;
}
std::cout << "\n处理模块 (CSU-02):" << std::endl;
std::cout << " 成功处理: " << processor.getProcessedCount() << " 个数据包" << std::endl;
std::cout << " 被丢弃: " << processor.getDiscardedCount() << " 个数据包" << std::endl;
if (processor.getDiscardedCount() > 0) {
std::cout << " 最近错误: " << processor.getLastError() << std::endl;
}
std::cout << "\n存储模块 (CSU-03):" << std::endl;
std::cout << " 成功存储: " << storage.getStoredCount() << " 条记录" << std::endl;
std::cout << " 存储错误: " << storage.getErrorCount() << " 条记录" << std::endl;
if (storage.getErrorCount() > 0) {
std::cout << " 最近错误: " << storage.getLastError() << std::endl;
}
// 输出存储的所有数据
std::cout << "\n=== 已存储的数据内容 ===" << std::endl;
auto storedData = storage.getAllStoredData();
for (size_t i = 0; i < storedData.size(); ++i) {
std::cout << " [" << (i + 1) << "] " << storedData[i] << std::endl;
}
std::cout << "\n=== 演示结束 ===" << std::endl;
// 返回 0 表示成功,非 0 表示有错误
bool hasErrors = (receiver.getErrorCount() > 0)
|| (storage.getErrorCount() > 0);
return hasErrors ? 1 : 0;
}

219
tests/basic_test.cpp Normal file
View File

@ -0,0 +1,219 @@
#include "app.hpp"
#include <cassert>
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
/**
* @brief CSU-01 DataReceiver
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void testDataReceiverParsing() {
std::cout << "[单元测试] testDataReceiverParsing ... ";
dataflow::ThreadSafeQueue<std::string> outputQueue;
dataflow::DataReceiver receiver(outputQueue);
std::vector<std::string> mockData = {
"Hello",
"World"
};
receiver.setMockDataSource(mockData);
receiver.start();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
receiver.stop();
assert(receiver.getReceivedCount() == 2);
assert(receiver.getErrorCount() == 0);
std::string data1, data2;
assert(outputQueue.tryPop(data1));
assert(outputQueue.tryPop(data2));
assert(!outputQueue.tryPop(data1)); // 队列应为空
std::cout << "PASS" << std::endl;
}
/**
* @brief CSU-02 DataProcessor
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void testDataProcessorValidation() {
std::cout << "[单元测试] testDataProcessorValidation ... ";
dataflow::ThreadSafeQueue<std::string> inputQueue;
dataflow::ThreadSafeQueue<std::string> outputQueue;
dataflow::DataProcessor processor(inputQueue, outputQueue);
processor.start();
// 推送有效数据
inputQueue.push("Valid data packet");
inputQueue.push("Another valid data");
// 推送空数据(应被丢弃)
inputQueue.push("");
// 推送超长数据(应被丢弃)
std::string longData(1025, 'A');
inputQueue.push(longData);
// 等待处理
std::this_thread::sleep_for(std::chrono::milliseconds(50));
processor.stop();
// 验证统计
assert(processor.getProcessedCount() == 2);
assert(processor.getDiscardedCount() == 2);
assert(processor.getErrorCount() == 0);
// 验证输出队列内容
std::string processed;
assert(outputQueue.tryPop(processed));
assert(processed.find("[PROCESSED:") == 0);
assert(processed.find("Valid data packet") != std::string::npos);
assert(outputQueue.tryPop(processed));
assert(processed.find("Another valid data") != std::string::npos);
std::cout << "PASS" << std::endl;
}
/**
* @brief CSU-03 DataStorage
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
*
*/
void testDataStorage() {
std::cout << "[单元测试] testDataStorage ... ";
dataflow::ThreadSafeQueue<std::string> inputQueue;
dataflow::DataStorage storage(inputQueue);
storage.start();
inputQueue.push("Record 1");
inputQueue.push("Record 2");
inputQueue.push("Record 3");
std::this_thread::sleep_for(std::chrono::milliseconds(50));
storage.stop();
assert(storage.getStoredCount() == 3);
assert(storage.getErrorCount() == 0);
assert(storage.getStorageSize() == 3);
auto allData = storage.getAllStoredData();
assert(allData.size() == 3);
assert(allData[0] == "Record 1");
assert(allData[1] == "Record 2");
assert(allData[2] == "Record 3");
std::cout << "PASS" << std::endl;
}
/**
* @brief ThreadSafeQueue
*/
void testThreadSafeQueue() {
std::cout << "[单元测试] testThreadSafeQueue ... ";
dataflow::ThreadSafeQueue<int> queue;
assert(queue.empty());
assert(queue.size() == 0);
queue.push(10);
queue.push(20);
queue.push(30);
assert(!queue.empty());
assert(queue.size() == 3);
int val;
assert(queue.tryPop(val));
assert(val == 10);
assert(queue.size() == 2);
assert(queue.tryPop(val));
assert(val == 20);
assert(queue.tryPop(val));
assert(val == 30);
assert(!queue.tryPop(val));
assert(queue.empty());
// 测试 clear
queue.push(1);
queue.push(2);
queue.clear();
assert(queue.empty());
std::cout << "PASS" << std::endl;
}
/**
* @brief
*
* @requirement(name="数据接收功能", id="SRS-测试_F-001")
* CSU-01 CSU-03
*/
void testFullPipeline() {
std::cout << "[集成测试] testFullPipeline ... ";
dataflow::ThreadSafeQueue<std::string> queue01to02;
dataflow::ThreadSafeQueue<std::string> queue02to03;
dataflow::DataReceiver receiver(queue01to02);
dataflow::DataProcessor processor(queue01to02, queue02to03);
dataflow::DataStorage storage(queue02to03);
std::vector<std::string> mockData = {
"Pipeline test data 1",
"Pipeline test data 2",
"" // 空数据应被丢弃
};
receiver.setMockDataSource(mockData);
receiver.start();
processor.start();
storage.start();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
receiver.stop();
processor.stop();
storage.stop();
assert(receiver.getReceivedCount() == 3);
assert(processor.getProcessedCount() == 2);
assert(processor.getDiscardedCount() == 1);
assert(storage.getStoredCount() == 2);
auto stored = storage.getAllStoredData();
assert(stored.size() == 2);
assert(stored[0].find("Pipeline test data 1") != std::string::npos);
assert(stored[1].find("Pipeline test data 2") != std::string::npos);
std::cout << "PASS" << std::endl;
}
int main() {
std::cout << "=== 测试套件执行开始 ===" << std::endl;
testThreadSafeQueue();
testDataReceiverParsing();
testDataProcessorValidation();
testDataStorage();
testFullPipeline();
std::cout << "\n=== 所有测试通过 === (0)" << std::endl;
return 0;
}