# 单元测试(设计 §12)。M1 spike 阶段先放一个 gtest 冒烟用例, # 验证 gtest 经 vcpkg 接入、ctest 可跑;随 core/data/algo 实现补充真实用例。 find_package(GTest CONFIG REQUIRED) add_executable(geopro_tests smoke_test.cpp) target_link_libraries(geopro_tests PRIVATE GTest::gtest GTest::gtest_main) include(GoogleTest) # PROJ 运行时需要数据目录(proj.db 等)。vcpkg 把数据装在 share/proj 下。 # 通过测试环境变量 PROJ_DATA 注入,使 `ctest -R CrsTransform` 无需调用方手动 set。 file(GLOB _proj_data_dirs "${CMAKE_BINARY_DIR}/vcpkg_installed/*/share/proj" ) # DISCOVERY_MODE PRE_TEST:把用例枚举推迟到 ctest 运行时执行,而非构建后立即跑 # exe。因 geopro_data 链 Qt6::Core,构建期发现会因 Qt6Core.dll 尚未拷贝到 exe 旁而 # 失败(0xc0000135);推迟到运行期时 POST_BUILD 已把运行时 DLL 拷到位。 if(_proj_data_dirs) list(GET _proj_data_dirs 0 GEOPRO_PROJ_DATA) gtest_discover_tests(geopro_tests DISCOVERY_MODE PRE_TEST PROPERTIES ENVIRONMENT "PROJ_DATA=${GEOPRO_PROJ_DATA}") else() gtest_discover_tests(geopro_tests DISCOVERY_MODE PRE_TEST) endif() target_sources(geopro_tests PRIVATE core/test_local_frame.cpp) target_sources(geopro_tests PRIVATE core/test_model.cpp) target_sources(geopro_tests PRIVATE core/test_color_scale.cpp) target_sources(geopro_tests PRIVATE core/test_idw.cpp) # buildVolume:凸包足迹裁剪 + maxDist=0 自动覆盖测区(对齐客户 Surfer Blanking)。 target_sources(geopro_tests PRIVATE core/test_volume_builder.cpp) target_sources(geopro_tests PRIVATE core/test_crs_transform.cpp) target_sources(geopro_tests PRIVATE core/test_model_data.cpp) target_sources(geopro_tests PRIVATE core/test_geo_frame.cpp) target_sources(geopro_tests PRIVATE core/test_scalar_volume_i16.cpp) # GprVolumeBuilder:结构化建体(X/Z 落格 + 仅 Y 向 1D 线性插值 → int16 量化体)。 target_sources(geopro_tests PRIVATE core/test_gpr_volume_builder.cpp) target_link_libraries(geopro_tests PRIVATE geopro_core) target_sources(geopro_tests PRIVATE data/test_parsers.cpp) target_sources(geopro_tests PRIVATE data/test_local_repo.cpp) # I3dSceneRepository/LocalSample3dRepository:dimensionOf 映射 + loadVolume/loadTerrainPaths 异步回调(需 PROJ_DATA)。 target_sources(geopro_tests PRIVATE data/test_3d_repo.cpp) target_sources(geopro_tests PRIVATE data/test_nav_dto.cpp) target_sources(geopro_tests PRIVATE data/test_vtk3d_requests.cpp) target_sources(geopro_tests PRIVATE data/test_dataset_field_dictionary.cpp) target_sources(geopro_tests PRIVATE data/test_dataset_chart_dto.cpp) target_sources(geopro_tests PRIVATE data/test_measurement_dto.cpp) target_sources(geopro_tests PRIVATE data/test_gr_dto.cpp) target_sources(geopro_tests PRIVATE data/test_trajectory_dto.cpp) target_sources(geopro_tests PRIVATE data/test_grid_dto.cpp) target_sources(geopro_tests PRIVATE data/test_dataset_load_handles.cpp) # 通用仓储分派离线单测(loadAsync 分派 + QVariant payload round-trip)。 target_sources(geopro_tests PRIVATE data/test_async_repo_dispatch.cpp) # NavRequest 离线单测(QVariant payload: done/failed/abort 闸门)。 target_sources(geopro_tests PRIVATE data/test_nav_request.cpp) # GprVolumeRepository:逐线 GPR int16 量化体(BuiltI16)→ app 渲染链 float 体(VolumeGrid)。 # 纯适配器逐值反量化 + 全链(合成多通道 .iprb 走真 P1/P2)产出有效 VolumeGrid。 target_sources(geopro_tests PRIVATE data/test_gpr_volume_repository.cpp) target_link_libraries(geopro_tests PRIVATE geopro_data) # store 层:ChunkedVolumeStore(GPR 三维体分块压缩落盘 round-trip + 边缘块 + 压缩生效)。 target_sources(geopro_tests PRIVATE data/store/test_chunked_volume_store.cpp) # store 层:金字塔(多分辨率 LOD + 每块 min/max;不破坏 level0 与老 store 兼容)。 target_sources(geopro_tests PRIVATE data/store/test_pyramid.cpp) # store 层:StreamingVolumeWriter(逐块增量写 level0;与非流式 write 逐块+meta 对拍一致)。 target_sources(geopro_tests PRIVATE data/store/test_streaming_write.cpp) # data 层:StreamingVolumeBuilder(流式建体 B4;与非流式 buildGprVolume+write 逐 brick+meta 对拍)。 target_sources(geopro_tests PRIVATE data/test_streaming_builder.cpp) # core/algo:GeoVolumeBuilder(G1 build-geo:PCA 路向旋转 + 多线统一网格重叠均值; # 编排 io_gpr+core+store,符号编在 geopro_store,故归此节)。 target_sources(geopro_tests PRIVATE core/test_geo_volume_builder.cpp) target_link_libraries(geopro_tests PRIVATE geopro_store) # net 层:RSA 加密器。测试需直接用 OpenSSL 生成/解密密钥,故显式 find_package # 并链接 OpenSSL(geopro_net 的 PUBLIC 链接通常已传递,这里显式以防头文件找不到)。 find_package(OpenSSL REQUIRED) find_package(Qt6 COMPONENTS Core Network Test REQUIRED) target_sources(geopro_tests PRIVATE net/test_rsa.cpp) # 端到端登录连通测试(ApiClient + AuthService),需 Qt6::Core/Network 与事件循环。 target_sources(geopro_tests PRIVATE net/test_auth.cpp) # ApiBatch 离线单测(QSignalSpy 需 Qt6::Test)。 target_sources(geopro_tests PRIVATE net/test_api_batch.cpp) # ApiChain 离线单测(顺序依赖链:顺序/失败短路/abort闸门/工厂抛异常)。 target_sources(geopro_tests PRIVATE net/test_api_chain.cpp) # AuthLoads 离线单测(CaptchaLoad/LoginLoad 句柄:done/failed/abort 闸门)。 target_sources(geopro_tests PRIVATE net/test_auth_loads.cpp) target_link_libraries(geopro_tests PRIVATE geopro_net OpenSSL::SSL OpenSSL::Crypto Qt6::Core Qt6::Network Qt6::Test) # geopro_data 链 Qt6::Core,测试 exe 运行(含 gtest 发现)需要 Qt6Core.dll 等运行时 # DLL 在旁。复用 app 同样的 TARGET_RUNTIME_DLLS POST_BUILD 拷贝。 if(WIN32) add_custom_command(TARGET geopro_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ COMMAND_EXPAND_LISTS) endif() # render 层:ColorLutBuilder(core ColorScale -> vtkLookupTable)。 # 需 vtkLookupTable(VTK::CommonCore);geopro_render 已 PUBLIC 传递其余 VTK 组件。 find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel RenderingCore RenderingAnnotation FiltersSources) # Scene:addActor/addViewProp 计数 + clear 清空(vtkVolume 经 addViewProp 进场)。 target_sources(geopro_tests PRIVATE render/test_scene.cpp) target_sources(geopro_tests PRIVATE render/test_color_lut.cpp) target_sources(geopro_tests PRIVATE render/test_contour_bands.cpp) # dd_voxel:buildVoxel(ScalarVolume->vtkImageData->GPU 体绘制) 构建不崩 + dims 正确。 target_sources(geopro_tests PRIVATE render/test_voxel_build.cpp) # dd_voxel int16:buildVoxelI16(ScalarVolumeI16->vtkImageData(vtkShortArray)) 类型/dims/值/blank。 target_sources(geopro_tests PRIVATE render/test_voxel_i16_smoke.cpp) # dd_voxel 回归:buildVoxelFromScatters(散点 projX/Y -EPSG:4547-> 世界系 + IDW) 配准+充填(需 PROJ_DATA)。 target_sources(geopro_tests PRIVATE render/test_voxel_register.cpp) # Curtain:buildCurtain(Grid+GeoLocalFrame->vtkStructuredGrid 帘面) 非空 actor + 点数=nx*ny。 target_sources(geopro_tests PRIVATE render/test_curtain.cpp) # Scatter(#17):buildScatter(ScatterField+ColorScale->vtkPolyData 彩色散点) 点数/verts/上色/y取负。 target_sources(geopro_tests PRIVATE render/test_scatter.cpp) # Anomaly:buildAnomalies(markType 点/线/面 -> vtkActor) 几何/闭合/颜色/y取负/空跳过。 target_sources(geopro_tests PRIVATE render/test_anomaly.cpp) # Electrode:buildElectrodes(剖面顶边朝下三角 ▼) 三角数/顶点位置/空安全。 target_sources(geopro_tests PRIVATE render/test_electrode.cpp) # Terrain:buildTerrain(GDAL 读 dem/image + 重投影 → warp 面+纹理) 非空/缺文件安全(需 PROJ_DATA)。 target_sources(geopro_tests PRIVATE render/test_terrain.cpp) # CameraPreset(P2):6 向快捷视图 position/focalPoint/viewUp 方向 + zoomBy 距离/parallelScale。 target_sources(geopro_tests PRIVATE render/test_camera_preset.cpp) # AxesActor(P2):buildAxes(bounds+unit/mode→vtkCubeAxesActor) 单位换算(英尺/经纬度)/不显示返回空。 target_sources(geopro_tests PRIVATE render/test_axes.cpp) # TileMath(P5):天地图底图 Web Mercator 瓦片坐标数学(经纬↔z/x/y、瓦片地理边界)——纯函数。 target_sources(geopro_tests PRIVATE render/test_tile_math.cpp) # SlicePlaneMath(P3):切面法向/滚轮平移+夹限/双击正视相机(含竖直兜底)/滚轮步长/最近切片——纯几何。 target_sources(geopro_tests PRIVATE render/test_slice_plane_math.cpp) # WholeVolumeSource(B):读分块存储→重组整卷 VTK_SHORT image,校验 dims/类型/边缘块重组位置。 target_sources(geopro_tests PRIVATE render/test_whole_volume_source.cpp) # BrickPager(C):内存恒定的 brick LRU 分页器,驻留 ≤ budget 个解压块,证明超大体浏览内存不爆。 target_sources(geopro_tests PRIVATE render/test_brick_pager.cpp) target_sources(geopro_tests PRIVATE render/test_outofcore_source.cpp) # ViewAdaptiveLodPolicy(C1):视野自适应 LOD 选层(纯逻辑,零 VTK/Qt)——视锥裁剪求可见 brick 区间 + 视距/分辨率选层。 target_sources(geopro_tests PRIVATE render/test_view_adaptive_lod.cpp) # ViewAdaptiveVolumeSource(C2):用 C1 selectLod 选层选区→从分块存储重组当前视野区域为单张 VTK_SHORT image(各轴≤16384/世界 origin/spacing 按 level+exagg/体素位置与 store 一致)。headless 不需 GPU。 target_sources(geopro_tests PRIVATE render/test_view_adaptive_source.cpp) # AsyncRegionBuilder(C3-1):后台 worker 调公共重组核 reorganizeRegion 重组视野区域→单图,主线程非阻塞 takeLatest 取最新就绪(supersede/析构干净 join/并发不崩/非阻塞)。真线程不需 GPU。 target_sources(geopro_tests PRIVATE render/test_async_region_builder.cpp) target_link_libraries(geopro_tests PRIVATE geopro_render ${VTK_LIBRARIES}) vtk_module_autoinit(TARGETS geopro_tests MODULES ${VTK_LIBRARIES}) # Qwt 集成冒烟(仅当 qwt 目标存在,即 external/qwt-src 已拉取)。 if(TARGET qwt) target_sources(geopro_tests PRIVATE render/test_qwt_smoke.cpp) target_link_libraries(geopro_tests PRIVATE qwt) endif() target_include_directories(geopro_tests PRIVATE ${CMAKE_SOURCE_DIR}/src/app) # tests/ 在 include 路径:net/test_api_batch.cpp 用 #include "net/FakeApiCall.hpp"。 target_include_directories(geopro_tests PRIVATE ${CMAKE_SOURCE_DIR}/tests) target_sources(geopro_tests PRIVATE app/test_chart_strategy_registry.cpp) # ColorMapService 测试(geopro_desktop 是可执行文件,直接把源加入测试目标) target_sources(geopro_tests PRIVATE app/test_colormap_service.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/chart/ColorMapService.cpp ) # 散点 hover 文本格式(inline 纯函数,无需链 qwt/实例化 ScatterHoverTip)。 target_sources(geopro_tests PRIVATE app/test_scatter_hover.cpp) # 层级分层算法(normal/log/equalArea 纯函数,无 Qt/VTK 依赖)。 target_sources(geopro_tests PRIVATE app/test_contour_levels.cpp ${CMAKE_SOURCE_DIR}/src/app/ContourLevels.cpp ) # 色阶文件 IO(.lvl/.clr 解析/生成,纯函数,无 Qt/VTK 依赖)。 target_sources(geopro_tests PRIVATE app/test_color_scale_io.cpp ${CMAKE_SOURCE_DIR}/src/app/ColorScaleIO.cpp ) # 维度过滤纯函数(splitByDimension: ddCode -> 三维/二维/分析三栏,无 Qt/VTK 依赖)。 target_sources(geopro_tests PRIVATE app/test_dataset_dimension.cpp ${CMAKE_SOURCE_DIR}/src/app/DatasetDimension.cpp ) # 大类分类纯函数(splitByCategory: dsTypeCode/ddCode -> 5 个数据类型大类段,无 Qt/VTK 依赖)。 target_sources(geopro_tests PRIVATE app/test_dataset_category.cpp ${CMAKE_SOURCE_DIR}/src/app/DatasetCategory.cpp ) # 对象树勾选纯逻辑(GS 三态聚合 aggregateGsState + 勾选源去重 dedupeSources,header-only)。 target_sources(geopro_tests PRIVATE app/test_object_tree_selection.cpp) # measurement 散点纯逻辑(值类型变换 / 显隐 id 收集 / 过滤体 / 另存体,Qt6::Core JSON + core model)。 target_sources(geopro_tests PRIVATE app/test_scatter_data_ops.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/chart/ScatterDataOps.cpp ) # 图上交互纯几何(M14 框选命中 pointsInRect / I9 绘形归一化,QtCore QPointF/QRectF + core model)。 target_sources(geopro_tests PRIVATE app/test_chart_pick_geometry.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/chart/ChartPickGeometry.cpp ) # 反演处理类纯逻辑(网格化/白化/滤波 请求体组装 + code 映射,仅 Qt6::Core JSON)。 target_sources(geopro_tests PRIVATE app/test_inversion_process_ops.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/chart/InversionProcessOps.cpp ) # 等值线 Douglas-Peucker 抽稀(I8 简化容差,纯几何,无 Qt/VTK 依赖)。 target_sources(geopro_tests PRIVATE app/test_contour_simplify.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/chart/ContourSimplify.cpp ) # Quill Delta ↔ QTextDocument 互转(I14 描述富文本,纯函数,Qt6::Core/Gui)。 find_package(Qt6 COMPONENTS Gui REQUIRED) target_sources(geopro_tests PRIVATE app/test_quill_delta.cpp ${CMAKE_SOURCE_DIR}/src/app/panels/QuillDelta.cpp ) target_link_libraries(geopro_tests PRIVATE Qt6::Gui) # controller 层:DatasetDetailController 编排集成测试(QSignalSpy 验证 datasetOpened/tabReady/loadFailed)。 find_package(Qt6 COMPONENTS Test REQUIRED) target_sources(geopro_tests PRIVATE controller/test_dataset_detail_controller.cpp) target_sources(geopro_tests PRIVATE controller/test_workbench_nav_controller.cpp) # VtkSceneController 编排:注入 fake repo + fake view,断言 视图模式×图层 组合下 add 的图元类型/数量;取消勾选清空。 target_sources(geopro_tests PRIVATE controller/test_vtk_scene_controller.cpp) target_link_libraries(geopro_tests PRIVATE geopro_controller Qt6::Test) # io/gpr 层:.iprh 头解析 + .iprb B-scan 读取(纯 C++17,零 Qt/VTK)。 target_sources(geopro_tests PRIVATE io/gpr/test_ipr_header.cpp) target_sources(geopro_tests PRIVATE io/gpr/test_iprb_reader.cpp) target_sources(geopro_tests PRIVATE io/gpr/test_gpr_geometry.cpp) # GprSurveyAssembler:若干通道 .iprb + .ord -> GprSurvey(samples 校验/traces 对齐/Y 升序重排)。 target_sources(geopro_tests PRIVATE io/gpr/test_gpr_survey_assembler.cpp) # GpsTrack:.gps 解析 + 经纬→局部米 + 沿轨迹里程插值/航向(G1 build-geo 基础,纯 C++17)。 target_sources(geopro_tests PRIVATE io/gpr/test_gps_track.cpp) # NormalizedRadarReader:规范化 .head(KEY:VALUE) 解析(维度/字节序/通道偏移/波速/深度间距,纯 C++17)。 target_sources(geopro_tests PRIVATE io/gpr/test_normalized_radar_reader.cpp) target_link_libraries(geopro_tests PRIVATE geopro_io_gpr) # Gpr3dvVolumeBridge(P2):gpr3dv 处理后立方体 → geopro 量化体(轴 X=道/Y=通道/Z=样本)。 # 链 geopro_gpr3dv_bridge(含 vendored gpr3dv + Qt)。 target_sources(geopro_tests PRIVATE io/gpr/test_gpr3dv_volume_bridge.cpp) # RadarVolumeAssembler:格式无关共享建体(扫值域→Quant→通道插值→逐体素填→spacing)。 target_sources(geopro_tests PRIVATE io/gpr/test_radar_volume_assembler.cpp) target_link_libraries(geopro_tests PRIVATE geopro_gpr3dv_bridge) add_subdirectory(spike) # spike S3: banded contour 渲染验证