Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
78 lines
2.9 KiB
C#
78 lines
2.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.Json.Nodes;
|
|
|
|
namespace StellaOps.Notify.Models.Tests;
|
|
|
|
public sealed class NotifyCanonicalJsonSerializerTests
|
|
{
|
|
[Fact]
|
|
public void SerializeRuleIsDeterministic()
|
|
{
|
|
var ruleA = NotifyRule.Create(
|
|
ruleId: "rule-1",
|
|
tenantId: "tenant-a",
|
|
name: "critical",
|
|
match: NotifyRuleMatch.Create(eventKinds: new[] { NotifyEventKinds.ScannerReportReady }),
|
|
actions: new[]
|
|
{
|
|
NotifyRuleAction.Create(actionId: "b", channel: "slack:sec"),
|
|
NotifyRuleAction.Create(actionId: "a", channel: "email:soc")
|
|
},
|
|
metadata: new Dictionary<string, string>
|
|
{
|
|
["beta"] = "2",
|
|
["alpha"] = "1"
|
|
},
|
|
createdAt: DateTimeOffset.Parse("2025-10-18T00:00:00Z"),
|
|
updatedAt: DateTimeOffset.Parse("2025-10-18T00:00:00Z"));
|
|
|
|
var ruleB = NotifyRule.Create(
|
|
ruleId: "rule-1",
|
|
tenantId: "tenant-a",
|
|
name: "critical",
|
|
match: NotifyRuleMatch.Create(eventKinds: new[] { NotifyEventKinds.ScannerReportReady }),
|
|
actions: new[]
|
|
{
|
|
NotifyRuleAction.Create(actionId: "a", channel: "email:soc"),
|
|
NotifyRuleAction.Create(actionId: "b", channel: "slack:sec")
|
|
},
|
|
metadata: new Dictionary<string, string>
|
|
{
|
|
["alpha"] = "1",
|
|
["beta"] = "2"
|
|
},
|
|
createdAt: DateTimeOffset.Parse("2025-10-18T00:00:00Z"),
|
|
updatedAt: DateTimeOffset.Parse("2025-10-18T00:00:00Z"));
|
|
|
|
var jsonA = NotifyCanonicalJsonSerializer.Serialize(ruleA);
|
|
var jsonB = NotifyCanonicalJsonSerializer.Serialize(ruleB);
|
|
|
|
Assert.Equal(jsonA, jsonB);
|
|
Assert.Contains("\"schemaVersion\":\"notify.rule@1\"", jsonA, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public void SerializeEventOrdersPayloadKeys()
|
|
{
|
|
var payload = JsonNode.Parse("{\"b\":2,\"a\":1}");
|
|
var @event = NotifyEvent.Create(
|
|
eventId: Guid.NewGuid(),
|
|
kind: NotifyEventKinds.ScannerReportReady,
|
|
tenant: "tenant-a",
|
|
ts: DateTimeOffset.Parse("2025-10-18T05:41:22Z"),
|
|
payload: payload,
|
|
scope: NotifyEventScope.Create(repo: "ghcr.io/acme/api", digest: "sha256:123"));
|
|
|
|
var json = NotifyCanonicalJsonSerializer.Serialize(@event);
|
|
|
|
var payloadIndex = json.IndexOf("\"payload\":{", StringComparison.Ordinal);
|
|
Assert.NotEqual(-1, payloadIndex);
|
|
|
|
var aIndex = json.IndexOf("\"a\":1", payloadIndex, StringComparison.Ordinal);
|
|
var bIndex = json.IndexOf("\"b\":2", payloadIndex, StringComparison.Ordinal);
|
|
|
|
Assert.True(aIndex is >= 0 && bIndex is >= 0 && aIndex < bIndex, "Payload keys should be ordered alphabetically.");
|
|
}
|
|
}
|