task_auto_plan1/tests/basic_test.cpp

215 lines
6.4 KiB
C++
Raw Normal View History

2026-04-25 04:26:31 +00:00
/**
* @file basic_test.cpp
* @brief - 使 assert
*/
#include "app.hpp"
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
/// 测试枚举转换函数
static void testEnumToString() {
std::cout << "[TEST] 枚举转换函数..." << std::endl;
assert(checkinMethodToString(CheckinMethod::FACE) == "人脸识别");
assert(checkinMethodToString(CheckinMethod::GPS) == "GPS定位");
assert(checkinMethodToString(CheckinMethod::CARD) == "工牌刷卡");
assert(attendanceStatusToString(AttendanceStatus::NORMAL) == "正常");
assert(attendanceStatusToString(AttendanceStatus::LATE) == "迟到");
assert(attendanceStatusToString(AttendanceStatus::EARLY) == "早退");
assert(attendanceStatusToString(AttendanceStatus::ABSENT) == "缺勤");
assert(attendanceStatusToString(AttendanceStatus::OVERTIME) == "加班");
assert(alertTypeToString(AlertType::UNCHECKED) == "未打卡");
assert(alertTypeToString(AlertType::EARLY) == "早退预警");
assert(alertTypeToString(AlertType::LATE) == "迟到预警");
assert(alertTypeToString(AlertType::MISSING) == "连续缺勤");
std::cout << " PASS" << std::endl;
}
/// 测试记录ID生成
static void testGenerateRecordId() {
std::cout << "[TEST] recordId生成..." << std::endl;
std::string id1 = generateRecordId();
std::string id2 = generateRecordId();
assert(!id1.empty());
assert(!id2.empty());
assert(id1 != id2); // 两次生成的ID应该不同
assert(id1.substr(0, 2) == "CK");
std::cout << " PASS: id1=" << id1 << ", id2=" << id2 << std::endl;
}
/// 测试打卡处理
static void testProcessCheckin() {
std::cout << "[TEST] 打卡处理..." << std::endl;
GeoLocation loc = {39.9042, 116.4074};
std::vector<uint8_t> face = {0x01, 0x02, 0x03};
int64_t ts = 1700000000000LL; // 固定时间戳
// 人脸打卡
CheckinRecord rec1 = processCheckin("EMP001", CheckinMethod::FACE, ts, loc, face);
assert(rec1.employeeId == "EMP001");
assert(rec1.status == CheckinStatus::SUCCESS);
assert(!rec1.recordId.empty());
// GPS打卡
CheckinRecord rec2 = processCheckin("EMP002", CheckinMethod::GPS, ts, loc, {});
assert(rec2.employeeId == "EMP002");
assert(rec2.status == CheckinStatus::SUCCESS);
// 工牌刷卡
CheckinRecord rec3 = processCheckin("EMP003", CheckinMethod::CARD, ts, loc, {});
assert(rec3.employeeId == "EMP003");
assert(rec3.status == CheckinStatus::SUCCESS);
std::cout << " PASS: 三种打卡方式均成功" << std::endl;
}
/// 测试考勤计算
static void testCalculateAttendance() {
std::cout << "[TEST] 考勤计算..." << std::endl;
ShiftRule shift;
shift.shiftName = "早班";
shift.startHour = 9;
shift.startMinute = 0;
shift.endHour = 18;
shift.endMinute = 0;
shift.breakDuration = 60;
shift.overtimeThreshold = 30;
// 场景1: 准时打卡 (9:00)
{
struct tm tm_in = {};
tm_in.tm_year = 2025 - 1900;
tm_in.tm_mon = 0;
tm_in.tm_mday = 15;
tm_in.tm_hour = 9;
tm_in.tm_min = 0;
time_t sec = mktime(&tm_in);
CheckinRecord rec;
rec.employeeId = "EMP001";
rec.timestamp = static_cast<int64_t>(sec) * 1000;
AttendanceResult res = calculateAttendance(rec, shift);
assert(res.lateMinutes == 0);
assert(res.status == AttendanceStatus::NORMAL || res.status == AttendanceStatus::NORMAL);
}
// 场景2: 迟到 (9:45)
{
struct tm tm_in = {};
tm_in.tm_year = 2025 - 1900;
tm_in.tm_mon = 0;
tm_in.tm_mday = 15;
tm_in.tm_hour = 9;
tm_in.tm_min = 45;
time_t sec = mktime(&tm_in);
CheckinRecord rec;
rec.employeeId = "EMP002";
rec.timestamp = static_cast<int64_t>(sec) * 1000;
AttendanceResult res = calculateAttendance(rec, shift);
assert(res.lateMinutes > 0);
assert(res.status == AttendanceStatus::LATE);
}
std::cout << " PASS: 正常与迟到判定正确" << std::endl;
}
/// 测试异常检测
static void testDetectAnomaly() {
std::cout << "[TEST] 异常检测..." << std::endl;
// 正常情况 - 不应生成预警
{
AttendanceResult normal;
normal.employeeId = "EMP001";
normal.date = "2025-01-15";
normal.lateMinutes = 0;
normal.absent = false;
AlertNotification alert = detectAnomaly(normal);
assert(alert.alertType == AlertType::UNCHECKED);
assert(alert.reason == "正常");
}
// 迟到超过30分钟 - 应生成迟到预警
{
AttendanceResult late;
late.employeeId = "EMP002";
late.date = "2025-01-15";
late.lateMinutes = 45;
late.absent = false;
AlertNotification alert = detectAnomaly(late);
assert(alert.alertType == AlertType::LATE);
assert(!alert.notifiedChannels.empty());
}
std::cout << " PASS" << std::endl;
}
/// 测试报表生成
static void testGenerateReport() {
std::cout << "[TEST] 报表生成..." << std::endl;
ReportRequest req;
req.dimension = ReportDimension::MONTH;
req.startDate = "2025-01-01";
req.endDate = "2025-01-31";
req.format = ExportFormat::EXCEL;
ReportResponse resp = generateReport(req);
assert(resp.success);
assert(!resp.reportUrl.empty());
assert(resp.fileSize > 0);
std::cout << " PASS: URL=" << resp.reportUrl << std::endl;
}
/// 测试加密模块
static void testEncryption() {
std::cout << "[TEST] 人脸特征加密..." << std::endl;
std::vector<uint8_t> original = {0x10, 0x20, 0x30, 0x40, 0x50};
std::vector<uint8_t> encrypted = encryptFaceFeature(original);
assert(encrypted.size() == original.size());
// 加密后应该与原文不同
bool different = false;
for (size_t i = 0; i < original.size(); i++) {
if (encrypted[i] != original[i]) {
different = true;
break;
}
}
assert(different);
std::cout << " PASS: 加密后数据已变更" << std::endl;
}
/// 主测试入口
int main() {
std::cout << "========== 考勤系统单元测试 ==========" << std::endl;
testEnumToString();
testGenerateRecordId();
testProcessCheckin();
testCalculateAttendance();
testDetectAnomaly();
testGenerateReport();
testEncryption();
std::cout << "\n========== 所有测试通过! ==========" << std::endl;
return 0;
}