You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/tests/CncCollector.Tests/DataParserTests.cs

312 lines
12 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using Xunit;
using CncModels.Entity;
using CncCollector.Core;
namespace CncCollector.Tests
{
/// <summary>
/// DataParser 单元测试
/// 覆盖正常解析、空JSON、缺失字段、非法数值、多品牌映射
/// </summary>
public class DataParserTests
{
/// <summary>创建标准 FANUC 品牌配置</summary>
private static Brand CreateFanucBrand()
{
return new Brand { DeviceField = "device", TagsPath = "tags" };
}
/// <summary>创建16条标准 FANUC 字段映射</summary>
private static List<BrandFieldMapping> CreateFanucMappings()
{
return new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "program_name", FieldName = "Tag5", DataType = "string" },
new BrandFieldMapping { StandardField = "part_count", FieldName = "Tag8", DataType = "number" },
new BrandFieldMapping { StandardField = "runtime", FieldName = "Tag9", DataType = "number" },
new BrandFieldMapping { StandardField = "start_value", FieldName = "Tag11", DataType = "number" },
new BrandFieldMapping { StandardField = "angle", FieldName = "Tag14", DataType = "number" },
new BrandFieldMapping { StandardField = "feed", FieldName = "Tag17", DataType = "number" },
new BrandFieldMapping { StandardField = "rpm", FieldName = "Tag18", DataType = "number" },
new BrandFieldMapping { StandardField = "spindle", FieldName = "Tag19", DataType = "number" },
new BrandFieldMapping { StandardField = "speed", FieldName = "Tag20", DataType = "number" },
new BrandFieldMapping { StandardField = "temperature", FieldName = "Tag21", DataType = "number" },
new BrandFieldMapping { StandardField = "mass", FieldName = "Tag22", DataType = "number" },
new BrandFieldMapping { StandardField = "height", FieldName = "Tag23", DataType = "number" },
new BrandFieldMapping { StandardField = "width", FieldName = "Tag24", DataType = "number" },
new BrandFieldMapping { StandardField = "length", FieldName = "Tag25", DataType = "number" },
new BrandFieldMapping { StandardField = "custom_code", FieldName = "Tag26", DataType = "string" },
new BrandFieldMapping { StandardField = "io_status", FieldName = "_io_status", DataType = "number" }
};
}
/// <summary>构造标准 FANUC 设备 JSON 对象</summary>
private static JObject BuildFanucDeviceJson()
{
var json = @"[
{
""device"": ""CNC-A001"",
""desc"": ""测试机床"",
""tags"": [
{ ""id"": ""_io_status"", ""value"": ""1.00000"" },
{ ""id"": ""Tag5"", ""value"": ""O0001"" },
{ ""id"": ""Tag8"", ""value"": ""1219.00000"" },
{ ""id"": ""Tag9"", ""value"": ""3.00000"" },
{ ""id"": ""Tag11"", ""value"": ""1.00000"" },
{ ""id"": ""Tag14"", ""value"": ""100.00000"" },
{ ""id"": ""Tag17"", ""value"": ""300.00000"" },
{ ""id"": ""Tag18"", ""value"": ""60.00000"" },
{ ""id"": ""Tag19"", ""value"": ""450.00000"" },
{ ""id"": ""Tag20"", ""value"": ""60.00000"" },
{ ""id"": ""Tag21"", ""value"": ""25.00000"" },
{ ""id"": ""Tag22"", ""value"": ""23558160.00000"" },
{ ""id"": ""Tag23"", ""value"": ""18224.00000"" },
{ ""id"": ""Tag24"", ""value"": ""6848959.00000"" },
{ ""id"": ""Tag25"", ""value"": ""699.00000"" },
{ ""id"": ""Tag26"", ""value"": ""G01"" }
]
}
]";
var arr = JArray.Parse(json);
return arr[0] as JObject;
}
// ===== 正常解析测试 =====
[Fact]
public void ParseDevice_FANUC_()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var mappings = CreateFanucMappings();
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.NotNull(result);
Assert.Equal(16, result.Count);
// 验证字符串字段
Assert.Equal("O0001", result["program_name"].StringValue);
Assert.Equal("G01", result["custom_code"].StringValue);
// 验证数值字段
Assert.True(result["part_count"].NumericValue.HasValue);
Assert.Equal(1219m, result["part_count"].NumericValue.Value);
Assert.True(result["runtime"].NumericValue.HasValue);
Assert.Equal(3m, result["runtime"].NumericValue.Value);
// 验证所有映射字段都存在
foreach (var key in mappings.Select(m => m.StandardField))
{
Assert.True(result.ContainsKey(key), $"字段 {key} 未在结果中找到");
}
}
[Fact]
public void ParseDevice__decimal()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "part_count", FieldName = "Tag8", DataType = "number" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.True(result["part_count"].NumericValue.HasValue);
Assert.Equal(1219m, result["part_count"].NumericValue.Value);
Assert.Equal("1219.00000", result["part_count"].StringValue);
}
[Fact]
public void ParseDevice__()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "program_name", FieldName = "Tag5", DataType = "string" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.Equal("O0001", result["program_name"].StringValue);
}
// ===== 空值和null 测试 =====
[Fact]
public void ParseDevice_deviceObjnull_()
{
var brand = CreateFanucBrand();
var mappings = CreateFanucMappings();
var result = DataParser.ParseDevice(null, brand, mappings);
Assert.NotNull(result);
Assert.Empty(result);
}
[Fact]
public void ParseDevice_mappingsnull_()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var result = DataParser.ParseDevice(deviceObj, brand, null);
Assert.NotNull(result);
Assert.Empty(result);
}
[Fact]
public void ParseDevice_mappings_()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var result = DataParser.ParseDevice(deviceObj, brand, new List<BrandFieldMapping>());
Assert.NotNull(result);
Assert.Empty(result);
}
// ===== 缺失字段测试 =====
[Fact]
public void ParseDevice_tags_()
{
var deviceObj = BuildFanucDeviceJson();
var brand = new Brand { DeviceField = "device", TagsPath = "nonexistent_path" };
var mappings = CreateFanucMappings();
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.Empty(result);
}
[Fact]
public void ParseDevice_tags_()
{
var deviceObj = BuildFanucDeviceJson();
var brand = CreateFanucBrand();
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "program_name", FieldName = "Tag5", DataType = "string" },
new BrandFieldMapping { StandardField = "missing_field", FieldName = "Tag999", DataType = "string" },
new BrandFieldMapping { StandardField = "part_count", FieldName = "Tag8", DataType = "number" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.Equal(2, result.Count);
Assert.True(result.ContainsKey("program_name"));
Assert.True(result.ContainsKey("part_count"));
Assert.False(result.ContainsKey("missing_field"));
}
// ===== 非法数值测试 =====
[Fact]
public void ParseDevice__NumericValuenull()
{
var json = @"[{ ""device"": ""D1"", ""tags"": [{ ""id"": ""Tag8"", ""value"": ""not_a_number"" }] }]";
var deviceObj = JArray.Parse(json)[0] as JObject;
var brand = new Brand { DeviceField = "device", TagsPath = "tags" };
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "part_count", FieldName = "Tag8", DataType = "number" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.True(result.ContainsKey("part_count"));
Assert.Null(result["part_count"].NumericValue);
Assert.Equal("not_a_number", result["part_count"].StringValue);
}
[Fact]
public void ParseDevice__NumericValuenull()
{
var json = @"[{ ""device"": ""D1"", ""tags"": [{ ""id"": ""Tag8"", ""value"": """" }] }]";
var deviceObj = JArray.Parse(json)[0] as JObject;
var brand = new Brand { DeviceField = "device", TagsPath = "tags" };
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "part_count", FieldName = "Tag8", DataType = "number" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.True(result.ContainsKey("part_count"));
Assert.Null(result["part_count"].NumericValue);
}
// ===== ExtractDeviceCode 测试 =====
[Fact]
public void ExtractDeviceCode_JSON_device()
{
var json = @"{ ""device"": ""fanake_1.8"" }";
var obj = JObject.Parse(json);
var code = DataParser.ExtractDeviceCode(obj);
Assert.Equal("fanake_1.8", code);
}
[Fact]
public void ExtractDeviceCode__()
{
var json = @"{ ""name"": ""myDevice"" }";
var obj = JObject.Parse(json);
var code = DataParser.ExtractDeviceCode(obj, "name");
Assert.Equal("myDevice", code);
}
[Fact]
public void ExtractDeviceCode_null_null()
{
var code = DataParser.ExtractDeviceCode(null);
Assert.Null(code);
}
[Fact]
public void ExtractDeviceCode_device_null()
{
var json = @"{ ""other"": ""x"" }";
var obj = JObject.Parse(json);
var code = DataParser.ExtractDeviceCode(obj);
Assert.Null(code);
}
// ===== 多品牌/不同结构测试 =====
[Fact]
public void ParseDevice_TagsPath_()
{
var json = @"[{ ""device"": ""M1"", ""data"": [{ ""id"": ""prog"", ""value"": ""P001"" }] }]";
var deviceObj = JArray.Parse(json)[0] as JObject;
var brand = new Brand { DeviceField = "device", TagsPath = "data" };
var mappings = new List<BrandFieldMapping>
{
new BrandFieldMapping { StandardField = "program_name", FieldName = "prog", DataType = "string" }
};
var result = DataParser.ParseDevice(deviceObj, brand, mappings);
Assert.Single(result);
Assert.Equal("P001", result["program_name"].StringValue);
}
}
}