// 本文件测试上位机/主站侧封装。验证 HostClient 是否能构造文档要求的请求, // 并且只接受从站地址、寄存器数量、地址和 Modbus CRC 都符合预期的响应。 #include "line_laser_modbus/host.hpp" #include "test_support.hpp" #include using namespace line_laser_modbus; namespace { void test_status_response_parse() { const HostClient host; const ByteVector response = build_read_response(kDefaultSlaveId, RegisterVector{static_cast( WorkMode::OnlineTracking), static_cast( DeviceState::OnlineTrackingNormal)}); const auto status = host.parse_status_response(response); test_support::require_true(status.has_value(), "host must parse valid mode/state response"); test_support::require_true(status->mode == WorkMode::OnlineTracking, "host must parse work mode"); test_support::require_true(status->state == DeviceState::OnlineTrackingNormal, "host must parse device state"); } void test_status_response_rejects_invalid_state() { const HostClient host; const ByteVector response = build_read_response(kDefaultSlaveId, RegisterVector{0U, 99U}); test_support::require_true(!host.parse_status_response(response).has_value(), "host must reject invalid state value"); } void test_pose_response_parse() { const HostClient host; const Pose6D source{55U, -1.5F, 2.25F, 3.5F, 4.0F, 5.0F, 6.0F}; const ByteVector response = build_read_response(kDefaultSlaveId, pose_to_register_vector(source)); const auto pose = host.parse_current_pose_response(response); test_support::require_true(pose.has_value(), "host must parse current pose"); test_support::require_equal(pose->timestamp_ms, 55U, "host must parse pose timestamp"); test_support::require_float_close(pose->x, -1.5F, "host must parse pose x"); test_support::require_float_close(pose->y, 2.25F, "host must parse pose y"); test_support::require_float_close(pose->z, 3.5F, "host must parse pose z"); } void test_write_ack_parse() { const HostClient host; const ByteVector ack = build_write_response(kDefaultSlaveId, kTargetPoseAddress, kPoseRegisterCount); test_support::require_true( host.parse_write_ack(ack, kTargetPoseAddress, kPoseRegisterCount), "host must accept matching write ack"); test_support::require_true( !host.parse_write_ack(ack, kCorrectionAddress, kPoseRegisterCount), "host must reject ack for unexpected address"); } } // 匿名命名空间 int main() { test_status_response_parse(); test_status_response_rejects_invalid_state(); test_pose_response_parse(); test_write_ack_parse(); std::cout << "host_tests passed\n"; return 0; }