182 lines
5.0 KiB
C#
182 lines
5.0 KiB
C#
using StellaOps.Signals.Contracts;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.Signals.Contracts.Tests;
|
|
|
|
/// <summary>
|
|
/// Tests for SignalEnvelope model.
|
|
/// </summary>
|
|
public sealed class SignalEnvelopeTests
|
|
{
|
|
[Fact]
|
|
public void SignalEnvelope_RequiredProperties_MustBeSet()
|
|
{
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = "pkg:npm/lodash@4.17.21:reachability",
|
|
SignalType = SignalType.Reachability,
|
|
Value = new { reachable = true, confidence = 0.95 },
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "reachability-analyzer"
|
|
};
|
|
|
|
Assert.Equal("pkg:npm/lodash@4.17.21:reachability", envelope.SignalKey);
|
|
Assert.Equal(SignalType.Reachability, envelope.SignalType);
|
|
Assert.Equal("reachability-analyzer", envelope.SourceService);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(SignalType.Reachability)]
|
|
[InlineData(SignalType.Entropy)]
|
|
[InlineData(SignalType.Exploitability)]
|
|
[InlineData(SignalType.Trust)]
|
|
[InlineData(SignalType.UnknownSymbol)]
|
|
[InlineData(SignalType.Custom)]
|
|
public void SignalEnvelope_SignalType_AllValues_AreValid(SignalType type)
|
|
{
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = $"test:{type.ToString().ToLowerInvariant()}",
|
|
SignalType = type,
|
|
Value = new { test = true },
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "test-service"
|
|
};
|
|
|
|
Assert.Equal(type, envelope.SignalType);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalEnvelope_DefaultSchemaVersion_IsOne()
|
|
{
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = "test:schema",
|
|
SignalType = SignalType.Custom,
|
|
Value = new { },
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "test"
|
|
};
|
|
|
|
Assert.Equal("1.0", envelope.SchemaVersion);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalEnvelope_OptionalProperties_AreNullByDefault()
|
|
{
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = "test:optional",
|
|
SignalType = SignalType.Reachability,
|
|
Value = new { },
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "test"
|
|
};
|
|
|
|
Assert.Null(envelope.TenantId);
|
|
Assert.Null(envelope.CorrelationId);
|
|
Assert.Null(envelope.ProvenanceDigest);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalEnvelope_WithAllOptionalProperties_ContainsValues()
|
|
{
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = "pkg:pypi/django@4.2.0:trust",
|
|
SignalType = SignalType.Trust,
|
|
Value = new { score = 0.85 },
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "trust-engine",
|
|
TenantId = "tenant-001",
|
|
CorrelationId = "corr-abc123",
|
|
ProvenanceDigest = "sha256:xyz789",
|
|
SchemaVersion = "2.0"
|
|
};
|
|
|
|
Assert.Equal("tenant-001", envelope.TenantId);
|
|
Assert.Equal("corr-abc123", envelope.CorrelationId);
|
|
Assert.Equal("sha256:xyz789", envelope.ProvenanceDigest);
|
|
Assert.Equal("2.0", envelope.SchemaVersion);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalEnvelope_Value_CanBeAnyObject()
|
|
{
|
|
var reachabilityValue = new
|
|
{
|
|
reachable = true,
|
|
paths = new[] { "main->helper->vulnerable" },
|
|
confidence = 0.92
|
|
};
|
|
|
|
var envelope = new SignalEnvelope
|
|
{
|
|
SignalKey = "test:value",
|
|
SignalType = SignalType.Reachability,
|
|
Value = reachabilityValue,
|
|
ComputedAt = DateTimeOffset.UtcNow,
|
|
SourceService = "analyzer"
|
|
};
|
|
|
|
Assert.NotNull(envelope.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalEnvelope_RecordEquality_WorksCorrectly()
|
|
{
|
|
var computedAt = DateTimeOffset.UtcNow;
|
|
var value = new { test = 123 };
|
|
|
|
var envelope1 = new SignalEnvelope
|
|
{
|
|
SignalKey = "test:eq",
|
|
SignalType = SignalType.Entropy,
|
|
Value = value,
|
|
ComputedAt = computedAt,
|
|
SourceService = "test"
|
|
};
|
|
|
|
var envelope2 = new SignalEnvelope
|
|
{
|
|
SignalKey = "test:eq",
|
|
SignalType = SignalType.Entropy,
|
|
Value = value,
|
|
ComputedAt = computedAt,
|
|
SourceService = "test"
|
|
};
|
|
|
|
Assert.Equal(envelope1, envelope2);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests for SignalType enum.
|
|
/// </summary>
|
|
public sealed class SignalTypeTests
|
|
{
|
|
[Fact]
|
|
public void SignalType_AllDefinedValues_AreCounted()
|
|
{
|
|
var values = Enum.GetValues<SignalType>();
|
|
|
|
// Ensure we have expected signal types
|
|
Assert.Equal(6, values.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalType_Reachability_HasValue()
|
|
{
|
|
Assert.Equal(0, (int)SignalType.Reachability);
|
|
}
|
|
|
|
[Fact]
|
|
public void SignalType_Custom_IsLast()
|
|
{
|
|
var values = Enum.GetValues<SignalType>();
|
|
var last = values.Max();
|
|
|
|
Assert.Equal(SignalType.Custom, last);
|
|
}
|
|
}
|