Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using Omika.Core.Observability;
|
||||
using Omika.Core.Observability.Outbox;
|
||||
|
||||
namespace Omika.Tests.Observability.Outbox;
|
||||
|
||||
/// <summary>Tests du DiagnosticOutbox : filtrage P0..P3, saturation, éviction, rétention, fail-open.</summary>
|
||||
public class DiagnosticOutboxTests
|
||||
{
|
||||
private static (DiagnosticOutbox Outbox, InMemoryDiagnosticOutboxStore Store, DiagnosticCounters Counters) Create(
|
||||
DiagnosticOutboxOptions? options = null)
|
||||
{
|
||||
var store = new InMemoryDiagnosticOutboxStore();
|
||||
var counters = new DiagnosticCounters();
|
||||
var outbox = new DiagnosticOutbox(store, options ?? new DiagnosticOutboxOptions(), counters);
|
||||
return (outbox, store, counters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_StoresP0ThroughP3_ByDefault()
|
||||
{
|
||||
(DiagnosticOutbox outbox, _, DiagnosticCounters counters) = Create();
|
||||
|
||||
int stored = await outbox.StoreAsync(
|
||||
[
|
||||
OutboxTestHarness.NewEvent(TelemetryPriority.P0),
|
||||
OutboxTestHarness.NewEvent(TelemetryPriority.P1),
|
||||
OutboxTestHarness.NewEvent(TelemetryPriority.P2),
|
||||
OutboxTestHarness.NewEvent(TelemetryPriority.P3)
|
||||
]);
|
||||
|
||||
Assert.Equal(4, stored);
|
||||
Assert.Equal(4, counters.OutboxStored);
|
||||
Assert.Equal(0, counters.OutboxDropped);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_DropsP4_ByDefault()
|
||||
{
|
||||
(DiagnosticOutbox outbox, _, DiagnosticCounters counters) = Create();
|
||||
|
||||
int stored = await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P4)]);
|
||||
|
||||
Assert.Equal(0, stored);
|
||||
Assert.Equal(1, counters.OutboxDropped);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_IncludeP4Option_StoresP4()
|
||||
{
|
||||
var options = new DiagnosticOutboxOptions { IncludeP4 = true };
|
||||
(DiagnosticOutbox outbox, _, DiagnosticCounters counters) = Create(options);
|
||||
|
||||
int stored = await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P4)]);
|
||||
|
||||
Assert.Equal(1, stored);
|
||||
Assert.Equal(1, counters.OutboxStored);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_EvictsP3_BeforeP0_WhenSaturated()
|
||||
{
|
||||
var options = new DiagnosticOutboxOptions { MaxRows = 10 };
|
||||
(DiagnosticOutbox outbox, InMemoryDiagnosticOutboxStore store, DiagnosticCounters counters) = Create(options);
|
||||
|
||||
// Remplit l'outbox avec 10 P3.
|
||||
List<OmikaEvent> p3s = Enumerable.Range(0, 10)
|
||||
.Select(_ => (OmikaEvent)OutboxTestHarness.NewEvent(TelemetryPriority.P3))
|
||||
.ToList();
|
||||
await outbox.StoreAsync(p3s);
|
||||
Assert.Equal(10, await store.CountAsync());
|
||||
|
||||
// Un nouveau P0 doit évincer un P3 (pas un P0).
|
||||
await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P0)]);
|
||||
|
||||
Assert.Equal(10, await store.CountAsync());
|
||||
Assert.Contains(store.Snapshot(), r => r.Priority == TelemetryPriority.P0);
|
||||
Assert.Equal(1, counters.OutboxEvictedP3);
|
||||
Assert.Equal(0, counters.OutboxEvictedP0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_FullOfP0_DropsNewP0_WithCounter()
|
||||
{
|
||||
var options = new DiagnosticOutboxOptions { MaxRows = 5 };
|
||||
(DiagnosticOutbox outbox, InMemoryDiagnosticOutboxStore store, DiagnosticCounters counters) = Create(options);
|
||||
|
||||
await outbox.StoreAsync(Enumerable.Range(0, 5)
|
||||
.Select(_ => OutboxTestHarness.NewEvent(TelemetryPriority.P0))
|
||||
.ToList());
|
||||
Assert.Equal(5, await store.CountAsync());
|
||||
|
||||
int stored = await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P0)]);
|
||||
|
||||
Assert.Equal(0, stored);
|
||||
Assert.Equal(5, await store.CountAsync());
|
||||
Assert.Equal(1, counters.OutboxDroppedFull);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_Disabled_StoresNothing()
|
||||
{
|
||||
var options = new DiagnosticOutboxOptions { Enabled = false };
|
||||
(DiagnosticOutbox outbox, InMemoryDiagnosticOutboxStore store, _) = Create(options);
|
||||
|
||||
int stored = await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P0)]);
|
||||
|
||||
Assert.Equal(0, stored);
|
||||
Assert.Equal(0, await store.CountAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CleanupExpired_RemovesExpiredOnly()
|
||||
{
|
||||
(DiagnosticOutbox outbox, InMemoryDiagnosticOutboxStore store, DiagnosticCounters counters) = Create();
|
||||
|
||||
// Utilise une rétention courte pour forcer l'expiration.
|
||||
var options = new DiagnosticOutboxOptions { Retention = TimeSpan.FromMilliseconds(1) };
|
||||
(outbox, store, counters) = Create(options);
|
||||
await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P3)]);
|
||||
|
||||
await Task.Delay(20);
|
||||
int removed = await outbox.CleanupExpiredAsync();
|
||||
|
||||
Assert.Equal(1, removed);
|
||||
Assert.Equal(1, counters.OutboxExpired);
|
||||
Assert.Equal(0, await store.CountAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Store_ThrowingStore_FailOpen_DegradesAndCounts()
|
||||
{
|
||||
var store = new InMemoryDiagnosticOutboxStore { ThrowOnStore = true };
|
||||
var counters = new DiagnosticCounters();
|
||||
var outbox = new DiagnosticOutbox(store, new DiagnosticOutboxOptions(), counters);
|
||||
|
||||
int stored = await outbox.StoreAsync([OutboxTestHarness.NewEvent(TelemetryPriority.P0)]);
|
||||
|
||||
Assert.Equal(0, stored);
|
||||
Assert.Equal(1, counters.OutboxDegraded);
|
||||
Assert.True(outbox.IsDegraded);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user