SectionBoxExporter: - TraverseAndCollect 对非几何节点(组节点)先查聚合包围盒, 与剖面盒不相交 → 整棵子树跳过(NW BoundingBox 为文档级缓存 O(1), 已用 Architecture.nwd 2 万节点 + 全厂模型 403MB 验证) - GetObjectsAndHiddenItems 增加 prune 参数(默认 true,false 供性能对比) 验证(全厂设备模型 403MB,100x100x40 测试盒): - 剪枝 72.9s vs 无剪枝 129.9s(~1.8 倍) - 盒内对象/隐藏节点完全一致(3521/80043,正确性无变化) - Architecture.nwd(2 万节点):273ms vs 580ms(~2.1 倍) - 集成测试 25/25 测试基础设施: - export-section-box 端点加 prune 参数 + traversalMs 计时 - bbox-profiling 端点加 enum=false 模式(根盒查询,避免大模型全枚举 10+ 分钟) - BatchQueueF1ProcessAutomationTests 末尾等待后台批处理完全退出 (修复 F1 后台任务残留导致后续 BatchQueue_AddItems isExecuting 断言失败) - batch-queue-status 端点加 isExecuting 字段
95 lines
4.2 KiB
C#
95 lines
4.2 KiB
C#
using System;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||
using Newtonsoft.Json.Linq;
|
||
|
||
namespace NavisworksTransport.UnitTests.Integration
|
||
{
|
||
/// <summary>
|
||
/// 批处理队列 F1 端到端测试(剖面盒自动检测,副实例多进程)。
|
||
///
|
||
/// 独立 TestCategory(NavisworksIntegrationF1),不进默认全量
|
||
/// (TestCategory=NavisworksIntegration),因为完整 F1 流程
|
||
/// (副实例启动 + 剖面盒导出 + 局部模型检测)耗时较长(分钟级)。
|
||
///
|
||
/// 单独运行:
|
||
/// run-integration-tests.bat "TestCategory=NavisworksIntegrationF1"
|
||
///
|
||
/// 覆盖链路:add(虚拟物体,DetectAllObjects=true)→ process(触发 F1)
|
||
/// → 轮询 batch-queue-status 至 Completed → 断言碰撞报告已生成。
|
||
/// </summary>
|
||
[TestClass]
|
||
[TestCategory("NavisworksIntegrationF1")]
|
||
public class BatchQueueF1ProcessAutomationTests
|
||
{
|
||
private const int TestFrameRate = 15;
|
||
private const double TestDurationSeconds = 5.0;
|
||
|
||
[TestMethod]
|
||
[Timeout(360000)]
|
||
public async Task BatchQueueF1_ProcessQueue_CompletesWithCollisionReport()
|
||
{
|
||
using (var client = new NavisworksTestAutomationClient())
|
||
{
|
||
await client.EnsureServiceReadyAsync(TimeSpan.FromSeconds(90)).ConfigureAwait(false);
|
||
|
||
// 1. 添加虚拟物体队列项(F1 剖面盒自动检测:DetectAllObjects=true 走副实例)
|
||
JObject add = await client.BatchQueueAddAsync(
|
||
"自动测试_Ground", TestFrameRate, TestDurationSeconds).ConfigureAwait(false);
|
||
Assert.IsTrue(add.Value<bool>("ok"), "添加队列项失败: " + (string)add["error"]);
|
||
|
||
int itemId = (int)((JObject)add["data"])["itemId"];
|
||
Assert.IsTrue(itemId > 0, "队列项 ID 无效");
|
||
|
||
// 2. 触发后台处理(F1)
|
||
JObject process = await client.BatchQueueProcessAsync().ConfigureAwait(false);
|
||
Assert.IsTrue(process.Value<bool>("ok"), "触发批处理失败: " + (string)process["error"]);
|
||
|
||
// 3. 轮询队列状态直到该 itemId 进入终态(Completed/Failed)
|
||
DateTime deadline = DateTime.UtcNow.AddMinutes(3);
|
||
string status = null;
|
||
string errorMessage = null;
|
||
while (DateTime.UtcNow < deadline)
|
||
{
|
||
await Task.Delay(5000).ConfigureAwait(false);
|
||
|
||
JObject statusResp = await client.BatchQueueStatusAsync(10).ConfigureAwait(false);
|
||
Assert.IsTrue(statusResp.Value<bool>("ok"), "查询队列状态失败");
|
||
|
||
var items = (JArray)statusResp["data"]["items"];
|
||
var mine = items?.FirstOrDefault(i => (int)i["itemId"] == itemId);
|
||
if (mine != null)
|
||
{
|
||
status = (string)mine["status"];
|
||
errorMessage = (string)mine["errorMessage"];
|
||
if (status == "Completed" || status == "Failed")
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
Assert.AreEqual(
|
||
"Completed",
|
||
status,
|
||
"F1 批处理未在时限内完成。itemId=" + itemId +
|
||
(string.IsNullOrEmpty(errorMessage) ? "" : ",错误: " + errorMessage));
|
||
|
||
// 等待后台批处理完全退出(避免后台任务残留影响后续测试的 isExecuting 断言)
|
||
DateTime exitDeadline = DateTime.UtcNow.AddSeconds(90);
|
||
while (DateTime.UtcNow < exitDeadline)
|
||
{
|
||
JObject statusResp = await client.BatchQueueStatusAsync(1).ConfigureAwait(false);
|
||
bool isExecuting = (bool?)statusResp["data"]?["isExecuting"] ?? false;
|
||
if (!isExecuting)
|
||
{
|
||
break;
|
||
}
|
||
await Task.Delay(2000).ConfigureAwait(false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|