Phase 0 WP-0.2–0.9: Implement Commons (types, entities, interfaces, messages, protocol, tests)
- WP-0.2: Namespace/folder skeleton (26 directories) - WP-0.3: Shared data types (6 enums, RetryPolicy, Result<T>) - WP-0.4: 24 domain entity POCOs across 10 domain areas - WP-0.5: 7 repository interfaces with full CRUD signatures - WP-0.6: IAuditService cross-cutting interface - WP-0.7: 26 message contract records across 8 concern areas - WP-0.8: IDataConnection protocol abstraction with batch ops - WP-0.9: 8 architectural constraint enforcement tests All 40 tests pass, zero warnings.
This commit is contained in:
36
tests/ScadaLink.Commons.Tests/Types/EnumTests.cs
Normal file
36
tests/ScadaLink.Commons.Tests/Types/EnumTests.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using ScadaLink.Commons.Types.Enums;
|
||||
|
||||
namespace ScadaLink.Commons.Tests.Types;
|
||||
|
||||
public class EnumTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(typeof(DataType), new[] { "Boolean", "Int32", "Float", "Double", "String", "DateTime", "Binary" })]
|
||||
[InlineData(typeof(InstanceState), new[] { "Enabled", "Disabled" })]
|
||||
[InlineData(typeof(DeploymentStatus), new[] { "Pending", "InProgress", "Success", "Failed" })]
|
||||
[InlineData(typeof(AlarmState), new[] { "Active", "Normal" })]
|
||||
[InlineData(typeof(AlarmTriggerType), new[] { "ValueMatch", "RangeViolation", "RateOfChange" })]
|
||||
[InlineData(typeof(ConnectionHealth), new[] { "Connected", "Disconnected", "Connecting", "Error" })]
|
||||
public void Enum_ShouldHaveExpectedValues(Type enumType, string[] expectedNames)
|
||||
{
|
||||
var actualNames = Enum.GetNames(enumType);
|
||||
Assert.Equal(expectedNames, actualNames);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(DataType))]
|
||||
[InlineData(typeof(InstanceState))]
|
||||
[InlineData(typeof(DeploymentStatus))]
|
||||
[InlineData(typeof(AlarmState))]
|
||||
[InlineData(typeof(AlarmTriggerType))]
|
||||
[InlineData(typeof(ConnectionHealth))]
|
||||
public void Enum_ShouldBeSingularNamed(Type enumType)
|
||||
{
|
||||
// Singular names should not end with 's' (except 'Status' which is singular)
|
||||
var name = enumType.Name;
|
||||
Assert.False(name.EndsWith("es") && !name.EndsWith("Status"),
|
||||
$"Enum {name} appears to be plural (ends with 'es').");
|
||||
Assert.False(name.EndsWith("s") && !name.EndsWith("ss") && !name.EndsWith("us"),
|
||||
$"Enum {name} appears to be plural (ends with 's').");
|
||||
}
|
||||
}
|
||||
75
tests/ScadaLink.Commons.Tests/Types/ResultTests.cs
Normal file
75
tests/ScadaLink.Commons.Tests/Types/ResultTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using ScadaLink.Commons.Types;
|
||||
|
||||
namespace ScadaLink.Commons.Tests.Types;
|
||||
|
||||
public class ResultTests
|
||||
{
|
||||
[Fact]
|
||||
public void Success_ShouldCreateSuccessfulResult()
|
||||
{
|
||||
var result = Result<int>.Success(42);
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.False(result.IsFailure);
|
||||
Assert.Equal(42, result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Failure_ShouldCreateFailedResult()
|
||||
{
|
||||
var result = Result<int>.Failure("something went wrong");
|
||||
|
||||
Assert.True(result.IsFailure);
|
||||
Assert.False(result.IsSuccess);
|
||||
Assert.Equal("something went wrong", result.Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Value_OnFailure_ShouldThrow()
|
||||
{
|
||||
var result = Result<int>.Failure("error");
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => result.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Error_OnSuccess_ShouldThrow()
|
||||
{
|
||||
var result = Result<int>.Success(42);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => result.Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Match_OnSuccess_ShouldCallOnSuccess()
|
||||
{
|
||||
var result = Result<int>.Success(42);
|
||||
|
||||
var output = result.Match(
|
||||
v => $"value={v}",
|
||||
e => $"error={e}");
|
||||
|
||||
Assert.Equal("value=42", output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Match_OnFailure_ShouldCallOnFailure()
|
||||
{
|
||||
var result = Result<int>.Failure("bad");
|
||||
|
||||
var output = result.Match(
|
||||
v => $"value={v}",
|
||||
e => $"error={e}");
|
||||
|
||||
Assert.Equal("error=bad", output);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Success_WithNullableReferenceType_ShouldWork()
|
||||
{
|
||||
var result = Result<string>.Success("hello");
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.Equal("hello", result.Value);
|
||||
}
|
||||
}
|
||||
35
tests/ScadaLink.Commons.Tests/Types/RetryPolicyTests.cs
Normal file
35
tests/ScadaLink.Commons.Tests/Types/RetryPolicyTests.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using ScadaLink.Commons.Types;
|
||||
|
||||
namespace ScadaLink.Commons.Tests.Types;
|
||||
|
||||
public class RetryPolicyTests
|
||||
{
|
||||
[Fact]
|
||||
public void RetryPolicy_ShouldBeImmutableRecord()
|
||||
{
|
||||
var policy = new RetryPolicy(3, TimeSpan.FromSeconds(5));
|
||||
|
||||
Assert.Equal(3, policy.MaxRetries);
|
||||
Assert.Equal(TimeSpan.FromSeconds(5), policy.Delay);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RetryPolicy_WithExpression_ShouldCreateNewInstance()
|
||||
{
|
||||
var original = new RetryPolicy(3, TimeSpan.FromSeconds(5));
|
||||
var modified = original with { MaxRetries = 5 };
|
||||
|
||||
Assert.Equal(3, original.MaxRetries);
|
||||
Assert.Equal(5, modified.MaxRetries);
|
||||
Assert.Equal(original.Delay, modified.Delay);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RetryPolicy_EqualValues_ShouldBeEqual()
|
||||
{
|
||||
var a = new RetryPolicy(3, TimeSpan.FromSeconds(5));
|
||||
var b = new RetryPolicy(3, TimeSpan.FromSeconds(5));
|
||||
|
||||
Assert.Equal(a, b);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user