using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
namespace NavisworksTransport.UnitTests.Integration
{
///
/// 路径导出→导入回环集成测试(覆盖计划 T12)。
///
/// 验证路径导出(XML/JSON)与导入的完整回环:
/// - 导出路径文件成功(文件存在、格式正确)
/// - 重新导入后属性一致:名称、路径类型、点数、总长度(米)
///
[TestClass]
[TestCategory("NavisworksIntegration")]
public class ExportImportRoundTripAutomationTests
{
private const string RouteName = "导出回环_测试";
[TestMethod]
[Timeout(240000)]
public async Task ExportImportRoundTrip_Xml_PropertiesConsistent()
{
await RunRoundTripAsync("xml").ConfigureAwait(false);
}
[TestMethod]
[Timeout(240000)]
public async Task ExportImportRoundTrip_Json_PropertiesConsistent()
{
await RunRoundTripAsync("json").ConfigureAwait(false);
}
private static async Task RunRoundTripAsync(string format)
{
using (var client = new NavisworksTestAutomationClient())
{
await client.EnsureServiceReadyAsync(TimeSpan.FromSeconds(90)).ConfigureAwait(false);
string tempDir = Path.Combine(Path.GetTempPath(), "NavisworksTransportIntegrationTests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempDir);
try
{
// 1. 准备一条临时路径(2 点 Ground,坐标取自测试基准区域)
string sourceFile = Path.Combine(tempDir, "source-route.json");
File.WriteAllText(sourceFile, BuildSourceRouteJson(), new UTF8Encoding(false));
JObject importSource = await client.ImportRouteFileAsync(sourceFile, overwrite: true).ConfigureAwait(false);
Assert.IsTrue(importSource.Value("ok"), "准备源路径失败: " + (string)importSource["error"]);
double metersToModelUnits = importSource["data"].Value("metersToModelUnits");
// 2. 导出
string exportPath = Path.Combine(tempDir, "exported-route." + format);
JObject exportResponse = await client.ExportRouteFileAsync(RouteName, format, exportPath).ConfigureAwait(false);
Assert.IsTrue(exportResponse.Value("ok"), "导出失败: " + (string)exportResponse["error"]);
Assert.IsTrue(File.Exists(exportPath), "导出文件不存在: " + exportPath);
Assert.IsTrue(new FileInfo(exportPath).Length > 0, "导出文件为空");
int sourcePointCount = (int)exportResponse["data"]["pointCount"];
double sourceLengthMeters = (double)exportResponse["data"]["totalLengthInMeters"];
// 3. 重新导入(overwrite 同名路径)
JObject reimportResponse = await client.ImportRouteFileAsync(exportPath, overwrite: true).ConfigureAwait(false);
Assert.IsTrue(reimportResponse.Value("ok"), "重新导入失败: " + (string)reimportResponse["error"]);
JObject reimported = (JObject)((JArray)reimportResponse["data"]["routes"])[0];
// 4. 回环一致性断言
Assert.AreEqual(RouteName, (string)reimported["name"], "回环后路径名不一致");
Assert.AreEqual("Ground", (string)reimported["pathType"], "回环后路径类型不一致");
Assert.AreEqual(sourcePointCount, (int)reimported["pointCount"], "回环后点数不一致");
Assert.AreEqual(
sourceLengthMeters,
(double)reimported["totalLengthInMeters"],
1e-2,
"回环后总长度不一致(源 " + sourceLengthMeters.ToString("F3") + "m)");
// 长度应等于模型单位直线距离换算(验证单位链完整;YUp 水平面为 XZ)
double expectedStraightMeters = Math.Sqrt(
(EndX - StartX) * (EndX - StartX) +
(EndZ - StartZ) * (EndZ - StartZ)) / metersToModelUnits;
Assert.AreEqual(
expectedStraightMeters,
(double)reimported["totalLengthInMeters"],
1e-2,
"回环后长度与起终点直线距离不一致(单位换算)");
}
finally
{
SafeDelete(tempDir);
}
}
}
// 源路径起终点(模型单位,测试基准区域附近)
private const double StartX = -204.608;
private const double StartY = 14.833;
private const double StartZ = 19.250;
private const double EndX = -208.608;
private const double EndY = 14.833;
private const double EndZ = 18.250;
private static string BuildSourceRouteJson()
{
return string.Format(
System.Globalization.CultureInfo.InvariantCulture,
@"{{""PathPlanningData"":{{""version"":""1.0"",""generator"":""integration-test"",""timestamp"":""2026-08-04T21:30:00"",""ProjectInfo"":{{""name"":""test"",""description"":""test"",""units"":""meters"",""coordinateSystem"":""Global""}},""Routes"":[{{""id"":""roundtrip-{0}"",""name"":""{1}"",""description"":"""",""pathType"":""Ground"",""totalLength"":10.0,""objectLimits"":{{""maxLength"":0,""maxWidth"":0,""maxHeight"":0,""safetyMargin"":0}},""gridSize"":1.0,""liftHeight"":0.0,""created"":""2026-08-04T21:30:00"",""points"":[{{""id"":""rt-p1"",""name"":""start"",""type"":""StartPoint"",""index"":0,""x"":{2},""y"":{3},""z"":{4},""created"":""2026-08-04T21:30:00""}},{{""id"":""rt-p2"",""name"":""end"",""type"":""EndPoint"",""index"":1,""x"":{5},""y"":{6},""z"":{7},""created"":""2026-08-04T21:30:00""}}]}}]}}}}",
Guid.NewGuid().ToString("N"),
RouteName,
StartX, StartY, StartZ,
EndX, EndY, EndZ);
}
private static void SafeDelete(string directory)
{
if (!Directory.Exists(directory))
{
return;
}
try
{
Directory.Delete(directory, true);
}
catch
{
}
}
}
}