184 lines
7.0 KiB
C#
184 lines
7.0 KiB
C#
using System;
|
|
using Google.Protobuf;
|
|
using MxGateway.Contracts.Proto;
|
|
using MxGateway.Worker.Bootstrap;
|
|
using MxGateway.Worker.Conversion;
|
|
using ProtobufTimestamp = Google.Protobuf.WellKnownTypes.Timestamp;
|
|
|
|
namespace MxGateway.Worker.Tests.Conversion;
|
|
|
|
public sealed class VariantConverterTests
|
|
{
|
|
private readonly VariantConverter _converter = new();
|
|
|
|
[Theory]
|
|
[InlineData(true, MxDataType.Boolean, MxValue.KindOneofCase.BoolValue)]
|
|
[InlineData(42, MxDataType.Integer, MxValue.KindOneofCase.Int32Value)]
|
|
[InlineData(42L, MxDataType.Integer, MxValue.KindOneofCase.Int64Value)]
|
|
[InlineData(1.25f, MxDataType.Float, MxValue.KindOneofCase.FloatValue)]
|
|
[InlineData(2.5d, MxDataType.Double, MxValue.KindOneofCase.DoubleValue)]
|
|
[InlineData("value", MxDataType.String, MxValue.KindOneofCase.StringValue)]
|
|
public void Convert_WithSupportedScalar_ProjectsTypedValue(
|
|
object value,
|
|
MxDataType expectedDataType,
|
|
MxValue.KindOneofCase expectedKind)
|
|
{
|
|
MxValue converted = _converter.Convert(value);
|
|
|
|
Assert.Equal(expectedDataType, converted.DataType);
|
|
Assert.Equal(expectedKind, converted.KindCase);
|
|
Assert.False(string.IsNullOrWhiteSpace(converted.VariantType));
|
|
}
|
|
|
|
[Fact]
|
|
public void Convert_WithDateTime_ProjectsTimestamp()
|
|
{
|
|
DateTime dateTime = new(2026, 4, 26, 17, 45, 0, DateTimeKind.Utc);
|
|
|
|
MxValue converted = _converter.Convert(dateTime);
|
|
|
|
Assert.Equal(MxDataType.Time, converted.DataType);
|
|
Assert.Equal(ProtobufTimestamp.FromDateTime(dateTime), converted.TimestampValue);
|
|
Assert.Equal("VT_DATE", converted.VariantType);
|
|
}
|
|
|
|
[Fact]
|
|
public void Convert_WithFileTimeAndExpectedTime_ProjectsTimestamp()
|
|
{
|
|
DateTime dateTime = new(2026, 4, 26, 17, 45, 0, DateTimeKind.Utc);
|
|
|
|
MxValue converted = _converter.Convert(dateTime.ToFileTimeUtc(), MxDataType.Time);
|
|
|
|
Assert.Equal(MxDataType.Time, converted.DataType);
|
|
Assert.Equal(ProtobufTimestamp.FromDateTime(dateTime), converted.TimestampValue);
|
|
Assert.Equal("VT_I8", converted.VariantType);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(null, "VT_EMPTY")]
|
|
[InlineData(typeof(DBNull), "VT_NULL")]
|
|
public void Convert_WithNullLikeValue_PreservesNull(
|
|
object? value,
|
|
string expectedVariantType)
|
|
{
|
|
object? actualValue = value is System.Type ? DBNull.Value : value;
|
|
|
|
MxValue converted = _converter.Convert(actualValue);
|
|
|
|
Assert.True(converted.IsNull);
|
|
Assert.Equal(MxDataType.NoData, converted.DataType);
|
|
Assert.Equal(expectedVariantType, converted.VariantType);
|
|
Assert.Equal(MxValue.KindOneofCase.None, converted.KindCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConvertArray_WithSupportedArrays_ProjectsTypedValuesAndDimensions()
|
|
{
|
|
MxValue bools = _converter.Convert(new[] { true, false });
|
|
MxValue ints = _converter.Convert(new[] { 1, 2, 3 });
|
|
MxValue floats = _converter.Convert(new[] { 1.25f, 2.5f });
|
|
MxValue doubles = _converter.Convert(new[] { 1.25d, 2.5d });
|
|
MxValue strings = _converter.Convert(new[] { "one", "two" });
|
|
MxValue times = _converter.Convert(new[]
|
|
{
|
|
new DateTime(2026, 4, 26, 17, 45, 0, DateTimeKind.Utc),
|
|
new DateTime(2026, 4, 26, 17, 46, 0, DateTimeKind.Utc),
|
|
});
|
|
|
|
Assert.Equal(new[] { true, false }, bools.ArrayValue.BoolValues.Values);
|
|
Assert.Equal(new[] { 1, 2, 3 }, ints.ArrayValue.Int32Values.Values);
|
|
Assert.Equal(new[] { 1.25f, 2.5f }, floats.ArrayValue.FloatValues.Values);
|
|
Assert.Equal(new[] { 1.25d, 2.5d }, doubles.ArrayValue.DoubleValues.Values);
|
|
Assert.Equal(new[] { "one", "two" }, strings.ArrayValue.StringValues.Values);
|
|
Assert.Equal(2, times.ArrayValue.TimestampValues.Values.Count);
|
|
Assert.Equal(new uint[] { 2 }, bools.ArrayValue.Dimensions);
|
|
Assert.Equal(MxDataType.Boolean, bools.ArrayValue.ElementDataType);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConvertArray_WithMultidimensionalArray_PreservesRankAndDimensions()
|
|
{
|
|
int[,] values =
|
|
{
|
|
{ 1, 2, 3 },
|
|
{ 4, 5, 6 },
|
|
};
|
|
|
|
MxValue converted = _converter.Convert(values);
|
|
|
|
Assert.Equal(new uint[] { 2, 3 }, converted.ArrayValue.Dimensions);
|
|
Assert.Equal(new[] { 1, 2, 3, 4, 5, 6 }, converted.ArrayValue.Int32Values.Values);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConvertArray_WithExpectedTimeAndFileTimeValues_ProjectsTimestampArray()
|
|
{
|
|
DateTime first = new(2026, 4, 26, 17, 45, 0, DateTimeKind.Utc);
|
|
DateTime second = new(2026, 4, 26, 17, 46, 0, DateTimeKind.Utc);
|
|
|
|
MxValue converted = _converter.Convert(
|
|
new[] { first.ToFileTimeUtc(), second.ToFileTimeUtc() },
|
|
MxDataType.Time);
|
|
|
|
Assert.Equal(MxDataType.Time, converted.ArrayValue.ElementDataType);
|
|
Assert.Equal(
|
|
new[] { ProtobufTimestamp.FromDateTime(first), ProtobufTimestamp.FromDateTime(second) },
|
|
converted.ArrayValue.TimestampValues.Values);
|
|
}
|
|
|
|
[Fact]
|
|
public void Convert_WithUnknownScalar_PreservesRawMetadata()
|
|
{
|
|
UnsupportedVariant value = new("opaque");
|
|
|
|
MxValue converted = _converter.Convert(value);
|
|
|
|
Assert.Equal(MxDataType.Unknown, converted.DataType);
|
|
Assert.Equal(MxValue.KindOneofCase.RawValue, converted.KindCase);
|
|
Assert.Contains(typeof(UnsupportedVariant).FullName!, converted.VariantType);
|
|
Assert.Contains(typeof(UnsupportedVariant).FullName!, converted.RawDiagnostic);
|
|
Assert.Equal(ByteString.CopyFromUtf8("opaque"), converted.RawValue);
|
|
}
|
|
|
|
[Fact]
|
|
public void ConvertArray_WithUnknownArray_PreservesRawMetadata()
|
|
{
|
|
UnsupportedVariant[] values =
|
|
[
|
|
new("first"),
|
|
new("second"),
|
|
];
|
|
|
|
MxValue converted = _converter.Convert(values);
|
|
|
|
Assert.Equal(MxDataType.Unknown, converted.ArrayValue.ElementDataType);
|
|
Assert.Equal(MxArray.ValuesOneofCase.RawValues, converted.ArrayValue.ValuesCase);
|
|
Assert.Equal(new uint[] { 2 }, converted.ArrayValue.Dimensions);
|
|
Assert.Equal("first", converted.ArrayValue.RawValues.Values[0].ToStringUtf8());
|
|
Assert.Contains(typeof(UnsupportedVariant).FullName!, converted.ArrayValue.RawDiagnostic);
|
|
}
|
|
|
|
[Fact]
|
|
public void Redactor_WithCredentialBearingValueFields_RedactsBeforeLogging()
|
|
{
|
|
Assert.Equal(WorkerLogRedactor.RedactedValue, WorkerLogRedactor.RedactValue("credential_value", "secret"));
|
|
Assert.Equal(WorkerLogRedactor.RedactedValue, WorkerLogRedactor.RedactValue("password_value", "secret"));
|
|
Assert.Equal(WorkerLogRedactor.RedactedValue, WorkerLogRedactor.RedactValue("secured_write_token", "secret"));
|
|
}
|
|
|
|
private sealed class UnsupportedVariant
|
|
{
|
|
private readonly string _value;
|
|
|
|
public UnsupportedVariant(string value)
|
|
{
|
|
_value = value;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return _value;
|
|
}
|
|
}
|
|
}
|