Files
Omika/tests/Omika.Tests/Observability/Outbox/DiagnosticBatchValidatorTests.cs
T
2026-10-23 18:46:50 +02:00

147 lines
4.5 KiB
C#

using Omika.Core.Observability.Outbox;
namespace Omika.Tests.Observability.Outbox;
/// <summary>Tests de la validation stricte serveur (§32, §28, §29, §60).</summary>
public class DiagnosticBatchValidatorTests
{
private static readonly RemoteDiagnosticOptions Limits = new();
private static DiagnosticBatchDto NewBatch(int eventCount = 1) =>
new()
{
SchemaVersion = 1,
Events = Enumerable.Range(0, eventCount)
.Select(i => new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
TimestampUtc = DateTimeOffset.UtcNow,
Level = "Info",
Priority = "P3"
})
.ToList()
};
[Fact]
public void ValidBatch_Passes()
{
DiagnosticValidationResult result = DiagnosticBatchValidator.Validate(NewBatch(), Limits);
Assert.True(result.IsValid);
}
[Fact]
public void NullBatch_Rejected()
{
Assert.False(DiagnosticBatchValidator.Validate(null, Limits).IsValid);
}
[Fact]
public void WrongSchemaVersion_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
batch = new DiagnosticBatchDto { SchemaVersion = 999, Events = batch.Events };
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void EmptyBatch_Rejected()
{
Assert.False(DiagnosticBatchValidator.Validate(new DiagnosticBatchDto(), Limits).IsValid);
}
[Fact]
public void TooManyEvents_Rejected()
{
DiagnosticBatchDto batch = NewBatch(Limits.MaxEventsPerBatch + 1);
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void EmptyEventId_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
batch.Events[0] = new DiagnosticEventDto { EventCode = "OMK-MOB-APP-001" };
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void ForbiddenMetadataKey_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
batch.Events[0] = new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
Metadata = new Dictionary<string, object?> { ["password"] = "secret" }
};
DiagnosticValidationResult result = DiagnosticBatchValidator.Validate(batch, Limits);
Assert.False(result.IsValid);
Assert.Equal(DiagnosticValidationReason.ForbiddenMetadata, result.Reason);
}
[Fact]
public void ForbiddenMetadataValue_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
batch.Events[0] = new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
Metadata = new Dictionary<string, object?> { ["error"] = "ConnectionString=secret" }
};
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void TooManyMetadata_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
var metadata = new Dictionary<string, object?>();
for (int i = 0; i <= Limits.MaxMetadataCount; i++)
{
metadata[$"k{i}"] = i;
}
batch.Events[0] = new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
Metadata = metadata
};
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void OverlongString_Rejected()
{
DiagnosticBatchDto batch = NewBatch();
batch.Events[0] = new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
Component = new string('x', Limits.MaxStringLength + 1)
};
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
[Fact]
public void ComplexMetadataValue_Rejected()
{
// Une valeur de métadonnée objet/tableau (non simple) est refusée.
DiagnosticBatchDto batch = NewBatch();
batch.Events[0] = new DiagnosticEventDto
{
EventId = Guid.NewGuid(),
EventCode = "OMK-MOB-APP-001",
Metadata = new Dictionary<string, object?> { ["nested"] = new { a = 1 } }
};
Assert.False(DiagnosticBatchValidator.Validate(batch, Limits).IsValid);
}
}