fix(audit): ScadaBridge C3 review — safe enum-parse (fallback) in SqliteAuditWriter.MapRow + AuditEventDtoMapper.FromDto (Task 2.5)
This commit is contained in:
@@ -457,4 +457,47 @@ public class SqliteAuditWriterWriteTests
|
||||
var row = Assert.Single(rows);
|
||||
Assert.Null(row.SourceNode);
|
||||
}
|
||||
|
||||
// ----- C3 hardening: safe enum-parse in MapRow ----- //
|
||||
|
||||
/// <summary>
|
||||
/// C3 hardening (Task 2.5): a row whose Channel/Kind/Status columns hold
|
||||
/// an unknown/renamed enum string must NOT fault the read path; it degrades
|
||||
/// gracefully to the same fallbacks used by <c>AuditRowProjection.Decompose</c>
|
||||
/// (ApiInbound / InboundRequest / Submitted). The read is exercised via the
|
||||
/// public <see cref="SqliteAuditWriter.ReadPendingAsync"/> surface which calls
|
||||
/// the private <c>MapRow</c>.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ReadPendingAsync_UnknownEnumStrings_DoNotThrow_YieldFallbackValues()
|
||||
{
|
||||
var (writer, dataSource) = CreateWriter(
|
||||
nameof(ReadPendingAsync_UnknownEnumStrings_DoNotThrow_YieldFallbackValues));
|
||||
await using var _ = writer;
|
||||
|
||||
var evt = NewEvent();
|
||||
await writer.WriteAsync(evt);
|
||||
|
||||
// Tamper: overwrite the three enum columns with unknown strings that are
|
||||
// not declared AuditChannel/AuditKind/AuditStatus member names.
|
||||
using (var conn = OpenVerifierConnection(dataSource))
|
||||
using (var cmd = conn.CreateCommand())
|
||||
{
|
||||
cmd.CommandText =
|
||||
"UPDATE AuditLog SET Channel = 'ObsoleteChannelV0', " +
|
||||
"Kind = 'LegacyKindName', Status = 'RenamedStatus99' " +
|
||||
"WHERE EventId = $id;";
|
||||
cmd.Parameters.AddWithValue("$id", evt.EventId.ToString());
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// Must not throw (previously would throw ArgumentException from Enum.Parse).
|
||||
var rows = await writer.ReadPendingAsync(limit: 10);
|
||||
|
||||
var row = Assert.Single(rows);
|
||||
var typedRow = row.AsRow();
|
||||
Assert.Equal(AuditChannel.ApiInbound, typedRow.Channel);
|
||||
Assert.Equal(AuditKind.InboundRequest, typedRow.Kind);
|
||||
Assert.Equal(AuditStatus.Submitted, typedRow.Status);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user