Files
git.stella-ops.org/src/Concelier/__Tests/StellaOps.Concelier.WebService.Tests/Aoc/AocVerifyRegressionTests.cs

356 lines
12 KiB
C#

using System.Text.Json;
using Microsoft.Extensions.Options;
using StellaOps.Aoc;
using StellaOps.Concelier.Core.Aoc;
namespace StellaOps.Concelier.WebService.Tests.Aoc;
/// <summary>
/// Regression tests ensuring AOC verify consistently emits ERR_AOC_001 and maintains
/// mapper/guard parity across all violation scenarios.
/// Per CONCELIER-WEB-AOC-19-007.
/// </summary>
public sealed class AocVerifyRegressionTests
{
private static readonly AocGuardOptions GuardOptions = AocGuardOptions.Default;
[Fact]
public void Verify_ForbiddenField_EmitsErrAoc001()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithForbiddenField("severity", "high");
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
var violation = Assert.Single(result.Violations.Where(v => v.Path == "/severity"));
Assert.Equal("ERR_AOC_001", violation.ErrorCode);
Assert.Equal(AocViolationCode.ForbiddenField, violation.Code);
}
[Theory]
[InlineData("severity")]
[InlineData("cvss")]
[InlineData("cvss_vector")]
[InlineData("merged_from")]
[InlineData("consensus_provider")]
[InlineData("reachability")]
[InlineData("asset_criticality")]
[InlineData("risk_score")]
public void Verify_AllForbiddenFields_EmitErrAoc001(string forbiddenField)
{
var guard = new AocWriteGuard();
var json = CreateJsonWithForbiddenField(forbiddenField, "forbidden_value");
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
var violation = result.Violations.FirstOrDefault(v => v.Path == $"/{forbiddenField}");
Assert.NotNull(violation);
Assert.Equal("ERR_AOC_001", violation.ErrorCode);
Assert.Equal(AocViolationCode.ForbiddenField, violation.Code);
}
[Fact]
public void Verify_DerivedField_EmitsErrAoc006()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithDerivedField("effective_status", "affected");
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
var violation = result.Violations.FirstOrDefault(v =>
v.Path == "/effective_status" && v.ErrorCode == "ERR_AOC_006");
Assert.NotNull(violation);
Assert.Equal(AocViolationCode.DerivedFindingDetected, violation.Code);
}
[Theory]
[InlineData("effective_status")]
[InlineData("effective_range")]
[InlineData("effective_severity")]
[InlineData("effective_cvss")]
public void Verify_AllDerivedFields_EmitErrAoc006(string derivedField)
{
var guard = new AocWriteGuard();
var json = CreateJsonWithDerivedField(derivedField, "derived_value");
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
var violation = result.Violations.FirstOrDefault(v =>
v.Path == $"/{derivedField}" && v.ErrorCode == "ERR_AOC_006");
Assert.NotNull(violation);
Assert.Equal(AocViolationCode.DerivedFindingDetected, violation.Code);
}
[Fact]
public void Verify_UnknownField_EmitsErrAoc007()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithUnknownField("completely_unknown_field", "some_value");
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
var violation = Assert.Single(result.Violations.Where(v =>
v.Path == "/completely_unknown_field" && v.ErrorCode == "ERR_AOC_007"));
Assert.Equal(AocViolationCode.UnknownField, violation.Code);
}
[Fact]
public void Verify_MergeAttempt_EmitsErrAoc002()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithMergedFrom(["obs-1", "obs-2"]);
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
// merged_from triggers ERR_AOC_001 (forbidden field)
var violation = result.Violations.FirstOrDefault(v => v.Path == "/merged_from");
Assert.NotNull(violation);
Assert.Equal("ERR_AOC_001", violation.ErrorCode);
}
[Fact]
public void Verify_MultipleViolations_EmitsAllErrorCodes()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithMultipleViolations();
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.False(result.IsValid);
// Should have ERR_AOC_001 for forbidden field
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_001");
// Should have ERR_AOC_006 for derived field
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_006");
// Should have ERR_AOC_007 for unknown field
Assert.Contains(result.Violations, v => v.ErrorCode == "ERR_AOC_007");
}
[Fact]
public void Verify_ValidDocument_NoViolations()
{
var guard = new AocWriteGuard();
var json = CreateValidJson();
var result = guard.Validate(json.RootElement, GuardOptions);
Assert.True(result.IsValid);
Assert.Empty(result.Violations);
}
[Fact]
public void Verify_ErrorCodeConsistency_AcrossMultipleRuns()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithForbiddenField("severity", "critical");
// Run validation multiple times
var results = Enumerable.Range(0, 10)
.Select(_ => guard.Validate(json.RootElement, GuardOptions))
.ToList();
// All should produce same error code
var allErrorCodes = results
.SelectMany(r => r.Violations)
.Select(v => v.ErrorCode)
.Distinct()
.ToList();
Assert.Single(allErrorCodes);
Assert.Equal("ERR_AOC_001", allErrorCodes[0]);
}
[Fact]
public void Verify_PathConsistency_AcrossMultipleRuns()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithForbiddenField("cvss", "9.8");
// Run validation multiple times
var results = Enumerable.Range(0, 10)
.Select(_ => guard.Validate(json.RootElement, GuardOptions))
.ToList();
// All should produce same path
var allPaths = results
.SelectMany(r => r.Violations)
.Select(v => v.Path)
.Distinct()
.ToList();
Assert.Single(allPaths);
Assert.Equal("/cvss", allPaths[0]);
}
[Fact]
public void Verify_MapperGuardParity_ValidationResultsMatch()
{
var guard = new AocWriteGuard();
var validator = new AdvisorySchemaValidator(guard, Options.Create(GuardOptions));
// Create document with forbidden field
var json = CreateJsonWithForbiddenField("severity", "high");
// Validate with guard directly
var guardResult = guard.Validate(json.RootElement, GuardOptions);
// Both should detect the violation
Assert.False(guardResult.IsValid);
Assert.Contains(guardResult.Violations, v =>
v.ErrorCode == "ERR_AOC_001" && v.Path == "/severity");
}
[Fact]
public void Verify_ViolationMessage_ContainsMeaningfulDetails()
{
var guard = new AocWriteGuard();
var json = CreateJsonWithForbiddenField("severity", "high");
var result = guard.Validate(json.RootElement, GuardOptions);
var violation = result.Violations.First(v => v.ErrorCode == "ERR_AOC_001");
// Message should not be empty
Assert.False(string.IsNullOrWhiteSpace(violation.Message));
// Path should be correct
Assert.Equal("/severity", violation.Path);
}
private static JsonDocument CreateJsonWithForbiddenField(string field, string value)
{
return JsonDocument.Parse($$"""
{
"tenant": "test",
"{{field}}": "{{value}}",
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
private static JsonDocument CreateJsonWithDerivedField(string field, string value)
{
return JsonDocument.Parse($$"""
{
"tenant": "test",
"{{field}}": "{{value}}",
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
private static JsonDocument CreateJsonWithUnknownField(string field, string value)
{
return JsonDocument.Parse($$"""
{
"tenant": "test",
"{{field}}": "{{value}}",
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
private static JsonDocument CreateJsonWithMergedFrom(string[] mergedFrom)
{
var mergedArray = string.Join(", ", mergedFrom.Select(m => $"\"{m}\""));
return JsonDocument.Parse($$"""
{
"tenant": "test",
"merged_from": [{{mergedArray}}],
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
private static JsonDocument CreateJsonWithMultipleViolations()
{
return JsonDocument.Parse("""
{
"tenant": "test",
"severity": "high",
"effective_status": "affected",
"unknown_custom_field": "value",
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
private static JsonDocument CreateValidJson()
{
return JsonDocument.Parse("""
{
"tenant": "test",
"source": {"vendor": "test", "connector": "test", "version": "1.0"},
"upstream": {
"upstream_id": "CVE-2024-0001",
"content_hash": "sha256:abc",
"retrieved_at": "2024-01-01T00:00:00Z",
"signature": {"present": false},
"provenance": {}
},
"content": {"format": "OSV", "raw": {}},
"identifiers": {"aliases": [], "primary": "CVE-2024-0001"},
"linkset": {}
}
""");
}
}