Refactor code structure and optimize performance across multiple modules
This commit is contained in:
@@ -3,6 +3,8 @@ using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public class CorpusFixtureTests
|
||||
@@ -10,7 +12,8 @@ public class CorpusFixtureTests
|
||||
private static readonly string RepoRoot = ReachbenchFixtureTests.LocateRepoRoot();
|
||||
private static readonly string CorpusRoot = Path.Combine(RepoRoot, "tests", "reachability", "corpus");
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ManifestExistsAndIsDeterministic()
|
||||
{
|
||||
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
|
||||
@@ -21,7 +24,8 @@ public class CorpusFixtureTests
|
||||
doc.RootElement.ValueKind.Should().Be(JsonValueKind.Array);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CorpusEntriesMatchManifestHashes()
|
||||
{
|
||||
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
|
||||
@@ -53,7 +57,8 @@ public class CorpusFixtureTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GroundTruthFilesContainRequiredFields()
|
||||
{
|
||||
var manifestPath = Path.Combine(CorpusRoot, "manifest.json");
|
||||
|
||||
@@ -2,6 +2,8 @@ using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public sealed class FixtureCoverageTests
|
||||
@@ -11,7 +13,8 @@ public sealed class FixtureCoverageTests
|
||||
private static readonly string CorpusRoot = Path.Combine(ReachabilityRoot, "corpus");
|
||||
private static readonly string SamplesPublicRoot = Path.Combine(ReachabilityRoot, "samples-public");
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CorpusAndPublicSamplesCoverExpectedLanguageBuckets()
|
||||
{
|
||||
var corpusLanguages = ReadManifestLanguages(Path.Combine(CorpusRoot, "manifest.json"));
|
||||
@@ -21,7 +24,8 @@ public sealed class FixtureCoverageTests
|
||||
samplesLanguages.Should().Contain(new[] { "csharp", "js", "php" });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CorpusManifestIsSorted()
|
||||
{
|
||||
var keys = ReadManifestKeys(Path.Combine(CorpusRoot, "manifest.json"));
|
||||
|
||||
@@ -7,6 +7,7 @@ using StellaOps.Reachability.FixtureTests.PatchOracle;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
/// <summary>
|
||||
@@ -21,14 +22,16 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Oracle Loading Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Loader_IndexExists()
|
||||
{
|
||||
var loader = new PatchOracleLoader(PatchOracleRoot);
|
||||
loader.IndexExists().Should().BeTrue("patch-oracle INDEX.json should exist");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Loader_IndexLoadsSuccessfully()
|
||||
{
|
||||
var loader = new PatchOracleLoader(PatchOracleRoot);
|
||||
@@ -40,7 +43,8 @@ public class PatchOracleHarnessTests
|
||||
index.Oracles.Should().NotBeEmpty("should have at least one oracle defined");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Loader_AllOraclesLoadSuccessfully()
|
||||
{
|
||||
var loader = new PatchOracleLoader(PatchOracleRoot);
|
||||
@@ -56,7 +60,8 @@ public class PatchOracleHarnessTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Loader_LoadOracleById()
|
||||
{
|
||||
var loader = new PatchOracleLoader(PatchOracleRoot);
|
||||
@@ -72,7 +77,8 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Comparer Tests - Pass Cases
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_PassesWhenAllExpectedElementsPresent()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -112,7 +118,8 @@ public class PatchOracleHarnessTests
|
||||
result.Violations.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_PassesWithWildcardPatterns()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -146,7 +153,8 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Comparer Tests - Fail Cases
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_FailsWhenExpectedFunctionMissing()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -177,7 +185,8 @@ public class PatchOracleHarnessTests
|
||||
result.Summary.MissingFunctions.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_FailsWhenExpectedEdgeMissing()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -211,7 +220,8 @@ public class PatchOracleHarnessTests
|
||||
result.Summary.MissingEdges.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_FailsWhenExpectedRootMissing()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -241,7 +251,8 @@ public class PatchOracleHarnessTests
|
||||
result.Summary.MissingRoots.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_FailsWhenForbiddenFunctionPresent()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -274,7 +285,8 @@ public class PatchOracleHarnessTests
|
||||
result.Summary.ForbiddenFunctionsPresent.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_FailsWhenForbiddenEdgePresent()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -311,7 +323,8 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Confidence Threshold Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_RespectsMinConfidenceThreshold()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -343,7 +356,8 @@ public class PatchOracleHarnessTests
|
||||
result.Summary.MissingEdges.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_EdgeSpecificConfidenceOverridesDefault()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -378,7 +392,8 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Strict Mode Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Comparer_StrictModeRejectsUnexpectedNodes()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -416,7 +431,8 @@ public class PatchOracleHarnessTests
|
||||
|
||||
#region Report Generation Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Result_GeneratesReadableReport()
|
||||
{
|
||||
var oracle = new PatchOracleDefinition
|
||||
@@ -469,7 +485,8 @@ public class PatchOracleHarnessTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(AllOracleData))]
|
||||
public void AllOracles_HaveValidStructure(string oracleId, string caseRef, string variant)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using StellaOps.Scanner.Reachability;
|
||||
using StellaOps.Scanner.Reachability.Lifters;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public sealed class ReachabilityLifterTests : IDisposable
|
||||
@@ -35,7 +36,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task NodeLifter_ExtractsPackageInfo()
|
||||
{
|
||||
// Arrange
|
||||
@@ -74,7 +76,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Edges.Should().Contain(e => e.EdgeType == "import");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task NodeLifter_ExtractsEntrypoints()
|
||||
{
|
||||
// Arrange
|
||||
@@ -110,7 +113,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Edges.Should().Contain(e => e.EdgeType == "spawn");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task NodeLifter_ExtractsImportsFromSource()
|
||||
{
|
||||
// Arrange
|
||||
@@ -147,7 +151,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Edges.Count(e => e.EdgeType == "import").Should().BeGreaterOrEqualTo(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task DotNetLifter_ExtractsProjectInfo()
|
||||
{
|
||||
// Arrange
|
||||
@@ -189,7 +194,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Edges.Count(e => e.EdgeType == "import").Should().BeGreaterOrEqualTo(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task DotNetLifter_ExtractsProjectReferences()
|
||||
{
|
||||
// Arrange
|
||||
@@ -237,7 +243,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Edges.Should().Contain(e => e.EdgeType == "import");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task LifterRegistry_CombinesMultipleLanguages()
|
||||
{
|
||||
// Arrange
|
||||
@@ -279,7 +286,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Nodes.Should().Contain(n => n.Lang == "dotnet");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task LifterRegistry_SelectsSpecificLanguages()
|
||||
{
|
||||
// Arrange
|
||||
@@ -305,7 +313,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
graph.Nodes.Should().OnlyContain(n => n.Lang == "node");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task LifterRegistry_LiftAndWrite_CreatesOutputFiles()
|
||||
{
|
||||
// Arrange
|
||||
@@ -339,7 +348,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
result.Nodes.RecordCount.Should().BeGreaterThan(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GraphBuilder_AddsRichNodes()
|
||||
{
|
||||
// Arrange
|
||||
@@ -373,7 +383,8 @@ public sealed class ReachabilityLifterTests : IDisposable
|
||||
node.Source!.Evidence.Should().Contain("src/main.ts:42");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GraphBuilder_AddsRichEdges()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -6,11 +6,13 @@ using StellaOps.Replay.Core;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public sealed class ReachabilityReplayWriterTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AttachEvidence_AppendsGraphsAndTracesDeterministically()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
@@ -48,7 +50,8 @@ public sealed class ReachabilityReplayWriterTests
|
||||
manifest.Reachability.RuntimeTraces[1].CasUri.Should().Be("cas://trace/2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AttachEvidence_DoesNotCreateSectionWhenEmpty()
|
||||
{
|
||||
var manifest = new ReplayManifest();
|
||||
|
||||
@@ -2,6 +2,8 @@ using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public class ReachbenchEvaluationHarnessTests
|
||||
@@ -22,7 +24,8 @@ public class ReachbenchEvaluationHarnessTests
|
||||
.Select(path => new object[] { Path.GetFileName(path)! });
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(CaseIds))]
|
||||
public void GroundTruthStatusesMatchVariantIntent(string caseId)
|
||||
{
|
||||
@@ -45,7 +48,8 @@ public class ReachbenchEvaluationHarnessTests
|
||||
.Be("not_affected", $"{caseId} unreachable variant should be marked not_affected for evaluation harness");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(CaseIds))]
|
||||
public void TruthGraphsAlignWithExpectedReachability(string caseId)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ using Xunit;
|
||||
using System.Security.Cryptography;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public class ReachbenchFixtureTests
|
||||
@@ -13,7 +15,8 @@ public class ReachbenchFixtureTests
|
||||
RepoRoot, "tests", "reachability", "fixtures", "reachbench-2025-expanded");
|
||||
private static readonly string CasesRoot = Path.Combine(FixtureRoot, "cases");
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void IndexListsAllCases()
|
||||
{
|
||||
Directory.Exists(FixtureRoot).Should().BeTrue("reachbench fixtures should exist under tests/reachability/fixtures");
|
||||
@@ -61,7 +64,8 @@ public class ReachbenchFixtureTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(CaseVariantData))]
|
||||
public void CaseVariantContainsExpectedArtifacts(string caseId, string variantPath)
|
||||
{
|
||||
@@ -94,7 +98,8 @@ public class ReachbenchFixtureTests
|
||||
VerifyManifestHashes(caseId, variantPath, requiredFiles);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(CaseVariantData))]
|
||||
public void CaseGroundTruthMatchesVariants(string caseId, string variantPath)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@ using System.Text.Json;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public class SamplesPublicFixtureTests
|
||||
@@ -19,7 +21,8 @@ public class SamplesPublicFixtureTests
|
||||
"repro.sh"
|
||||
];
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ManifestExistsAndIsSorted()
|
||||
{
|
||||
var manifestPath = Path.Combine(SamplesPublicRoot, "manifest.json");
|
||||
@@ -37,7 +40,8 @@ public class SamplesPublicFixtureTests
|
||||
keys.Should().BeInAscendingOrder(StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void SamplesPublicEntriesMatchManifestHashes()
|
||||
{
|
||||
var manifestPath = Path.Combine(SamplesPublicRoot, "manifest.json");
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="10.0.0-preview.7.24405.7" />
|
||||
<PackageReference Include="System.Text.Json" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\\..\\fixtures\\**\\*">
|
||||
@@ -25,5 +25,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Scanner\__Libraries\StellaOps.Scanner.Reachability\StellaOps.Scanner.Reachability.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Replay.Core\StellaOps.Replay.Core.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -2,11 +2,13 @@ using FluentAssertions;
|
||||
using StellaOps.Scanner.Reachability;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Reachability.FixtureTests;
|
||||
|
||||
public sealed class SymbolIdTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForJava_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForJava("com.example", "MyClass", "doSomething", "(Ljava/lang/String;)V");
|
||||
@@ -15,7 +17,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().HaveLength("sym:java:".Length + 43); // Base64url SHA-256 without padding = 43 chars
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForJava_IsDeterministic()
|
||||
{
|
||||
var id1 = SymbolId.ForJava("com.example", "MyClass", "doSomething", "(Ljava/lang/String;)V");
|
||||
@@ -24,7 +27,8 @@ public sealed class SymbolIdTests
|
||||
id1.Should().Be(id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForJava_IsCaseInsensitive()
|
||||
{
|
||||
var id1 = SymbolId.ForJava("com.example", "MyClass", "doSomething", "()V");
|
||||
@@ -33,7 +37,8 @@ public sealed class SymbolIdTests
|
||||
id1.Should().Be(id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForDotNet_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForDotNet("MyAssembly", "MyNamespace", "MyClass", "MyMethod(System.String)");
|
||||
@@ -41,7 +46,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:dotnet:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForDotNet_DifferentSignaturesProduceDifferentIds()
|
||||
{
|
||||
var id1 = SymbolId.ForDotNet("MyAssembly", "MyNamespace", "MyClass", "Method(String)");
|
||||
@@ -50,7 +56,8 @@ public sealed class SymbolIdTests
|
||||
id1.Should().NotBe(id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForNode_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForNode("express", "lib/router", "function");
|
||||
@@ -58,7 +65,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:node:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForNode_HandlesScopedPackages()
|
||||
{
|
||||
var id1 = SymbolId.ForNode("@angular/core", "src/render", "function");
|
||||
@@ -68,7 +76,8 @@ public sealed class SymbolIdTests
|
||||
id1.Should().StartWith("sym:node:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForGo_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForGo("github.com/example/repo", "pkg/http", "Server", "HandleRequest");
|
||||
@@ -76,7 +85,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:go:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForGo_FunctionWithoutReceiver()
|
||||
{
|
||||
var id = SymbolId.ForGo("github.com/example/repo", "pkg/main", "", "main");
|
||||
@@ -84,7 +94,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:go:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForRust_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForRust("my_crate", "foo::bar", "my_function", "_ZN8my_crate3foo3bar11my_functionE");
|
||||
@@ -92,7 +103,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:rust:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForSwift_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForSwift("MyModule", "MyClass", "myMethod", null);
|
||||
@@ -100,7 +112,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:swift:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForShell_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForShell("scripts/deploy.sh", "run_migration");
|
||||
@@ -108,7 +121,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:shell:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForBinary_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForBinary("7f6e5d4c3b2a1908", ".text", "_start");
|
||||
@@ -116,7 +130,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:binary:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForPython_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForPython("requests", "requests.api", "get");
|
||||
@@ -124,7 +139,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:python:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForRuby_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForRuby("rails", "ActiveRecord::Base", "#save");
|
||||
@@ -132,7 +148,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:ruby:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ForPhp_CreatesCanonicalSymbolId()
|
||||
{
|
||||
var id = SymbolId.ForPhp("laravel/framework", "Illuminate\\Http", "Request::input");
|
||||
@@ -140,7 +157,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:php:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Parse_ValidSymbolId_ReturnsComponents()
|
||||
{
|
||||
var id = SymbolId.ForJava("com.example", "MyClass", "method", "()V");
|
||||
@@ -152,7 +170,8 @@ public sealed class SymbolIdTests
|
||||
result.Value.Fragment.Should().HaveLength(43);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Parse_InvalidSymbolId_ReturnsNull()
|
||||
{
|
||||
SymbolId.Parse("invalid").Should().BeNull();
|
||||
@@ -162,7 +181,8 @@ public sealed class SymbolIdTests
|
||||
SymbolId.Parse(null!).Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void FromTuple_CreatesSymbolIdFromRawTuple()
|
||||
{
|
||||
var tuple = "my\0canonical\0tuple";
|
||||
@@ -171,7 +191,8 @@ public sealed class SymbolIdTests
|
||||
id.Should().StartWith("sym:custom:");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllLanguagesAreDifferent()
|
||||
{
|
||||
// Same tuple data should produce different IDs for different languages
|
||||
|
||||
@@ -3,11 +3,13 @@ using FluentAssertions;
|
||||
using StellaOps.Replay.Core;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
public sealed class CanonicalJsonTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanonicalJson_OrdersPropertiesLexicographically()
|
||||
{
|
||||
var payload = new
|
||||
@@ -22,7 +24,8 @@ public sealed class CanonicalJsonTests
|
||||
canonical.Should().Be("{\"alpha\":{\"m\":7,\"z\":9},\"list\":[{\"x\":1,\"y\":2}],\"zeta\":1}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanonicalJson_PreservesNumbersAndBooleans()
|
||||
{
|
||||
var payload = JsonSerializer.Deserialize<JsonElement>("{\"b\":true,\"a\":1.25}");
|
||||
|
||||
@@ -3,11 +3,13 @@ using FluentAssertions;
|
||||
using StellaOps.Replay.Core;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
public sealed class DeterministicHashTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Sha256Hex_ComputesLowercaseDigest()
|
||||
{
|
||||
var digest = DeterministicHash.Sha256Hex("replay-core");
|
||||
@@ -15,7 +17,8 @@ public sealed class DeterministicHashTests
|
||||
digest.Should().Be("a914f5ac6a57aab0189bb55bcb0ef6bcdbd86f77198c8669eab5ae38a325e41d");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void MerkleRootHex_IsDeterministic()
|
||||
{
|
||||
var leaves = new[] { "alpha", "beta", "gamma" }
|
||||
|
||||
@@ -4,11 +4,13 @@ using FluentAssertions;
|
||||
using StellaOps.Replay.Core;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
public sealed class DsseEnvelopeTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void BuildUnsigned_ProducesCanonicalPayload()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
|
||||
@@ -6,11 +6,14 @@ using StellaOps.Replay.Core;
|
||||
using ZstdSharp;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
public sealed class ReplayBundleWriterTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task WriteTarZstAsync_IsDeterministicAndSorted()
|
||||
{
|
||||
var entries = new[]
|
||||
@@ -55,7 +58,8 @@ public sealed class ReplayBundleWriterTests
|
||||
names.Should().BeEquivalentTo(new[] { "a.txt", "b.txt" }, opts => opts.WithStrictOrdering());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void BuildCasUri_UsesPrefixAndShard()
|
||||
{
|
||||
ReplayBundleWriter.BuildCasUri("abcdef", null).Should().Be("cas://replay/ab/abcdef.tar.zst");
|
||||
|
||||
@@ -3,11 +3,13 @@ using FluentAssertions;
|
||||
using StellaOps.Replay.Core;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
public sealed class ReplayManifestExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AddsReachabilityEvidence()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
|
||||
@@ -17,5 +17,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../__Libraries/StellaOps.Replay.Core/StellaOps.Replay.Core.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -6,6 +6,7 @@ using StellaOps.Scanner.ReachabilityDrift;
|
||||
using StellaOps.Scanner.ReachabilityDrift.Services;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.ScannerSignals.IntegrationTests;
|
||||
|
||||
/// <summary>
|
||||
@@ -23,7 +24,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region Drift Detection Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WhenPathBecomesReachable_ReportsNewlyReachableSink()
|
||||
{
|
||||
// Arrange: unreachable -> reachable (guard removed)
|
||||
@@ -56,7 +58,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
sink.Path.Sink.NodeId.Should().Be("jndi-lookup-sink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WhenPathBecomesUnreachable_ReportsNewlyUnreachableSink()
|
||||
{
|
||||
// Arrange: reachable -> unreachable (guard added)
|
||||
@@ -85,7 +88,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
sink.Cause.Kind.Should().Be(DriftCauseKind.GuardAdded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WhenNoChange_ReportsNoDrift()
|
||||
{
|
||||
// Arrange: same graph, no changes
|
||||
@@ -111,7 +115,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region Determinism Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_IsDeterministic_SameInputsProduceSameOutputs()
|
||||
{
|
||||
// Arrange
|
||||
@@ -139,7 +144,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_ResultDigest_IsStableAcrossRuns()
|
||||
{
|
||||
// Arrange
|
||||
@@ -165,7 +171,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region CodeChangeFact Extraction Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CodeChangeFactExtractor_DetectsAddedEdge()
|
||||
{
|
||||
// Arrange
|
||||
@@ -185,7 +192,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
c.Details.Value.GetRawText().Contains("edge_added", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CodeChangeFactExtractor_DetectsRemovedEdge()
|
||||
{
|
||||
// Arrange
|
||||
@@ -209,7 +217,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region Multi-Sink Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithMultipleSinks_ReportsAllDriftedSinks()
|
||||
{
|
||||
// Arrange: Multiple sinks become reachable
|
||||
@@ -234,7 +243,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
sinkIds.Should().Contain("file-write-sink");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_OrderingSinks_IsStableAndDeterministic()
|
||||
{
|
||||
// Arrange
|
||||
@@ -263,7 +273,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region Path Compression Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithFullPath_IncludesIntermediateNodes()
|
||||
{
|
||||
// Arrange
|
||||
@@ -288,7 +299,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
sink.Path.FullPath!.Value.Length.Should().BeGreaterThan(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithoutFullPath_OmitsIntermediateNodes()
|
||||
{
|
||||
// Arrange
|
||||
@@ -316,7 +328,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
|
||||
#region Error Handling Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithLanguageMismatch_ThrowsArgumentException()
|
||||
{
|
||||
// Arrange
|
||||
@@ -330,7 +343,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
act.Should().Throw<ArgumentException>().WithMessage("*Language mismatch*");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithNullBaseGraph_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
@@ -342,7 +356,8 @@ public sealed class ReachabilityDriftIntegrationTests
|
||||
act.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DetectDrift_WithNullHeadGraph_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -20,6 +20,8 @@ using StellaOps.Signals.Storage;
|
||||
using StellaOps.Signals.Storage.Models;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.ScannerSignals.IntegrationTests;
|
||||
|
||||
public sealed class ScannerToSignalsReachabilityTests
|
||||
@@ -27,7 +29,8 @@ public sealed class ScannerToSignalsReachabilityTests
|
||||
private static readonly string RepoRoot = LocateRepoRoot();
|
||||
private static readonly string FixtureRoot = Path.Combine(RepoRoot, "tests", "reachability", "fixtures", "reachbench-2025-expanded", "cases");
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ScannerBuilderFeedsSignalsScoringPipeline()
|
||||
{
|
||||
var caseId = "java-log4j-CVE-2021-44228-log4shell";
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.Reachability/StellaOps.Scanner.Reachability.csproj" />
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.ReachabilityDrift/StellaOps.Scanner.ReachabilityDrift.csproj" />
|
||||
<ProjectReference Include="../../Scanner/__Libraries/StellaOps.Scanner.CallGraph/StellaOps.Scanner.CallGraph.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\fixtures\**\*">
|
||||
|
||||
@@ -3,6 +3,7 @@ using StellaOps.Signals.Models;
|
||||
using StellaOps.Signals.Parsing;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -13,7 +14,8 @@ public class CallgraphSchemaMigratorTests
|
||||
{
|
||||
#region EnsureV1 - Schema Version Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_SetsSchemaToV1_WhenNotSet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -29,7 +31,8 @@ public class CallgraphSchemaMigratorTests
|
||||
result.Schema.Should().Be(CallgraphSchemaVersions.V1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesV1Schema_WhenAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -45,7 +48,8 @@ public class CallgraphSchemaMigratorTests
|
||||
result.Schema.Should().Be(CallgraphSchemaVersions.V1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_UpdatesLegacySchema_ToV1()
|
||||
{
|
||||
// Arrange
|
||||
@@ -65,7 +69,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Language Parsing Tests
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("dotnet", CallgraphLanguage.DotNet)]
|
||||
[InlineData(".net", CallgraphLanguage.DotNet)]
|
||||
[InlineData("csharp", CallgraphLanguage.DotNet)]
|
||||
@@ -102,7 +107,8 @@ public class CallgraphSchemaMigratorTests
|
||||
result.LanguageType.Should().Be(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesLanguageType_WhenAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -123,7 +129,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Node Visibility Inference Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersPublicVisibility_ForStandardNames()
|
||||
{
|
||||
// Arrange
|
||||
@@ -143,7 +150,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Visibility.Should().Be(SymbolVisibility.Public);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersPrivateVisibility_ForUnderscorePrefixed()
|
||||
{
|
||||
// Arrange
|
||||
@@ -163,7 +171,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Visibility.Should().Be(SymbolVisibility.Private);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersPrivateVisibility_ForAngleBracketNames()
|
||||
{
|
||||
// Arrange
|
||||
@@ -183,7 +192,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Visibility.Should().Be(SymbolVisibility.Private);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersInternalVisibility_ForInternalNamespace()
|
||||
{
|
||||
// Arrange
|
||||
@@ -203,7 +213,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Visibility.Should().Be(SymbolVisibility.Internal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesVisibility_WhenAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -227,7 +238,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Symbol Key Building Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_BuildsSymbolKey_FromNamespaceAndName()
|
||||
{
|
||||
// Arrange
|
||||
@@ -247,7 +259,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.SymbolKey.Should().Be("MyApp.Services.ProcessOrder");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_BuildsSymbolKey_FromNameOnly_WhenNoNamespace()
|
||||
{
|
||||
// Arrange
|
||||
@@ -267,7 +280,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.SymbolKey.Should().Be("GlobalMethod");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesSymbolKey_WhenAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -291,7 +305,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Entrypoint Candidate Detection Tests
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("Main")]
|
||||
[InlineData("main")]
|
||||
[InlineData("MAIN")]
|
||||
@@ -314,7 +329,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.IsEntrypointCandidate.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("OrdersController")]
|
||||
[InlineData("UserController")]
|
||||
public void EnsureV1_DetectsEntrypointCandidate_ForControllerNames(string name)
|
||||
@@ -336,7 +352,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.IsEntrypointCandidate.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("RequestHandler")]
|
||||
[InlineData("EventHandler")]
|
||||
public void EnsureV1_DetectsEntrypointCandidate_ForHandlerNames(string name)
|
||||
@@ -358,7 +375,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.IsEntrypointCandidate.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData(".cctor")]
|
||||
[InlineData("ModuleInitializer")]
|
||||
public void EnsureV1_DetectsEntrypointCandidate_ForModuleInitializers(string name)
|
||||
@@ -384,7 +402,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Edge Reason Inference Tests
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("call", EdgeReason.DirectCall)]
|
||||
[InlineData("direct", EdgeReason.DirectCall)]
|
||||
[InlineData("virtual", EdgeReason.VirtualCall)]
|
||||
@@ -422,7 +441,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Reason.Should().Be(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersRuntimeMinted_ForRuntimeKind()
|
||||
{
|
||||
// Arrange
|
||||
@@ -442,7 +462,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Reason.Should().Be(EdgeReason.RuntimeMinted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersDynamicImport_ForHeuristicKind()
|
||||
{
|
||||
// Arrange
|
||||
@@ -462,7 +483,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Reason.Should().Be(EdgeReason.DynamicImport);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesEdgeReason_WhenAlreadySet()
|
||||
{
|
||||
// Arrange
|
||||
@@ -486,7 +508,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Entrypoint Inference Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersEntrypoints_FromEntrypointCandidateNodes()
|
||||
{
|
||||
// Arrange
|
||||
@@ -509,7 +532,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.NodeId.Should().Be("main");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersEntrypoints_FromExplicitRoots()
|
||||
{
|
||||
// Arrange
|
||||
@@ -535,7 +559,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.NodeId.Should().Be("init");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_PreservesEntrypoints_WhenAlreadyPresent()
|
||||
{
|
||||
// Arrange
|
||||
@@ -567,7 +592,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Ordering Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_SortsNodes_ByIdAlphabetically()
|
||||
{
|
||||
// Arrange
|
||||
@@ -588,7 +614,8 @@ public class CallgraphSchemaMigratorTests
|
||||
result.Nodes.Select(n => n.Id).Should().BeInAscendingOrder();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_SortsEdges_BySourceThenTargetThenTypeThenOffset()
|
||||
{
|
||||
// Arrange
|
||||
@@ -613,7 +640,8 @@ public class CallgraphSchemaMigratorTests
|
||||
sortedEdges[0].Type.Should().Be("call");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_SortsEntrypoints_ByPhaseThenOrder()
|
||||
{
|
||||
// Arrange
|
||||
@@ -641,14 +669,16 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region EnsureV1 - Null Handling Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_ThrowsArgumentNullException_ForNullDocument()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => CallgraphSchemaMigrator.EnsureV1(null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_HandlesEmptyNodes_Gracefully()
|
||||
{
|
||||
// Arrange
|
||||
@@ -664,7 +694,8 @@ public class CallgraphSchemaMigratorTests
|
||||
result.Nodes.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_HandlesEmptyEdges_Gracefully()
|
||||
{
|
||||
// Arrange
|
||||
@@ -684,7 +715,8 @@ public class CallgraphSchemaMigratorTests
|
||||
|
||||
#region Framework Inference Tests
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersAspNetCoreFramework_ForDotNetController()
|
||||
{
|
||||
// Arrange
|
||||
@@ -706,7 +738,8 @@ public class CallgraphSchemaMigratorTests
|
||||
.Which.Framework.Should().Be(EntrypointFramework.AspNetCore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EnsureV1_InfersSpringFramework_ForJavaController()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -9,6 +9,7 @@ using StellaOps.Signals.Models;
|
||||
using StellaOps.Signals.Parsing;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -45,7 +46,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_DeserializesWithoutError(string fixtureName)
|
||||
{
|
||||
@@ -57,7 +59,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document!.Id.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_NodesHaveRequiredFields(string fixtureName)
|
||||
{
|
||||
@@ -71,7 +74,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_EdgesReferenceValidNodes(string fixtureName)
|
||||
{
|
||||
@@ -87,7 +91,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_EntrypointsReferenceValidNodes(string fixtureName)
|
||||
{
|
||||
@@ -102,7 +107,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DotNetFixture_HasCorrectLanguageEnum()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "dotnet-aspnetcore-minimal.json"));
|
||||
@@ -111,7 +117,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.LanguageType.Should().Be(CallgraphLanguage.DotNet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void JavaFixture_HasCorrectLanguageEnum()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "java-spring-boot.json"));
|
||||
@@ -120,7 +127,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.LanguageType.Should().Be(CallgraphLanguage.Java);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void NodeFixture_HasCorrectLanguageEnum()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "node-express-api.json"));
|
||||
@@ -129,7 +137,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.LanguageType.Should().Be(CallgraphLanguage.Node);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GoFixture_HasCorrectLanguageEnum()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "go-gin-api.json"));
|
||||
@@ -138,7 +147,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.LanguageType.Should().Be(CallgraphLanguage.Go);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllEdgeReasonsFixture_ContainsAllEdgeReasons()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "all-edge-reasons.json"));
|
||||
@@ -153,7 +163,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllEdgeReasonsFixture_ContainsAllEdgeKinds()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "all-edge-reasons.json"));
|
||||
@@ -168,7 +179,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllVisibilityFixture_ContainsAllVisibilityLevels()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "all-visibility-levels.json"));
|
||||
@@ -183,7 +195,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void LegacyFixture_HasNoSchemaField()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "legacy-no-schema.json"));
|
||||
@@ -193,7 +206,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.Schema.Should().Be(CallgraphSchemaVersions.V1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void LegacyFixture_MigratesToV1Schema()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "legacy-no-schema.json"));
|
||||
@@ -208,7 +222,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
migrated.Edges.Should().AllSatisfy(e => Enum.IsDefined(e.Reason).Should().BeTrue());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("dotnet-aspnetcore-minimal")]
|
||||
[InlineData("java-spring-boot")]
|
||||
[InlineData("node-express-api")]
|
||||
@@ -227,7 +242,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
migrated2.Entrypoints.Should().HaveCount(migrated1.Entrypoints.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EdgeReason_SerializesAsCamelCaseString()
|
||||
{
|
||||
var edge = new CallgraphEdge
|
||||
@@ -243,7 +259,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
json.Should().Contain("\"reason\": \"directCall\"");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void SymbolVisibility_SerializesAsCamelCaseString()
|
||||
{
|
||||
var node = new CallgraphNode
|
||||
@@ -259,7 +276,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
json.Should().Contain("\"visibility\": \"public\"");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void EntrypointKind_SerializesAsCamelCaseString()
|
||||
{
|
||||
var entrypoint = new CallgraphEntrypoint
|
||||
@@ -275,7 +293,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
json.Should().Contain("\"framework\": \"aspNetCore\"");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_NodesSortedById(string fixtureName)
|
||||
{
|
||||
@@ -288,7 +307,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
nodeIds.Should().Equal(sortedIds, $"Nodes in {fixtureName} should be sorted by Id for determinism");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(GoldenFixtures))]
|
||||
public void GoldenFixture_EntrypointsSortedByOrder(string fixtureName)
|
||||
{
|
||||
@@ -301,7 +321,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
orders.Should().Equal(sortedOrders, $"Entrypoints in {fixtureName} should be sorted by Order for determinism");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void DotNetFixture_HasCorrectAspNetCoreEntrypoints()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "dotnet-aspnetcore-minimal.json"));
|
||||
@@ -311,7 +332,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.Entrypoints.Should().Contain(e => e.Kind == EntrypointKind.Http && e.Route == "/weatherforecast");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void JavaFixture_HasCorrectSpringEntrypoints()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "java-spring-boot.json"));
|
||||
@@ -321,7 +343,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.Entrypoints.Should().Contain(e => e.Kind == EntrypointKind.Http && e.Route == "/owners/{ownerId}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void GoFixture_HasModuleInitEntrypoint()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "go-gin-api.json"));
|
||||
@@ -330,7 +353,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
document.Entrypoints.Should().Contain(e => e.Kind == EntrypointKind.ModuleInit && e.Phase == EntrypointPhase.ModuleInit);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllEdgeReasonsFixture_ReflectionEdgeIsUnresolved()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "all-edge-reasons.json"));
|
||||
@@ -341,7 +365,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
reflectionEdge.Weight.Should().BeLessThan(1.0, "Reflection edges should have lower confidence");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void AllEdgeReasonsFixture_DiBindingHasProvenance()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "all-edge-reasons.json"));
|
||||
@@ -351,7 +376,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
diEdge.Provenance.Should().NotBeNullOrEmpty("DI binding edges should include provenance");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Artifacts_HaveRequiredFields()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "dotnet-aspnetcore-minimal.json"));
|
||||
@@ -366,7 +392,8 @@ public sealed class CallgraphSchemaV1DeterminismTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Metadata_HasRequiredToolInfo()
|
||||
{
|
||||
var json = File.ReadAllText(Path.Combine(FixtureRoot, "dotnet-aspnetcore-minimal.json"));
|
||||
|
||||
@@ -15,6 +15,8 @@ using StellaOps.Signals.Persistence;
|
||||
using StellaOps.Signals.Services;
|
||||
using Xunit;
|
||||
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
public sealed class ReachabilityScoringTests
|
||||
@@ -41,7 +43,8 @@ public sealed class ReachabilityScoringTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[MemberData(nameof(CaseVariants))]
|
||||
public async Task RecomputedFactsMatchTruthFixtures(string caseId, string variant)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using StellaOps.Signals.Persistence;
|
||||
using StellaOps.Signals.Services;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
public sealed class RuntimeFactsIngestionServiceTests
|
||||
@@ -34,7 +35,8 @@ public sealed class RuntimeFactsIngestionServiceTests
|
||||
NullLogger<RuntimeFactsIngestionService>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task IngestAsync_InsertsAggregatedFacts()
|
||||
{
|
||||
var request = new RuntimeFactsIngestRequest
|
||||
@@ -89,7 +91,8 @@ public sealed class RuntimeFactsIngestionServiceTests
|
||||
repository.LastUpsert!.Metadata.Should().ContainKey("source");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task IngestAsync_MergesExistingDocument()
|
||||
{
|
||||
var existing = new ReachabilityFactDocument
|
||||
@@ -128,7 +131,8 @@ public sealed class RuntimeFactsIngestionServiceTests
|
||||
repository.LastUpsert!.RuntimeFacts![1].Metadata.Should().ContainKey("thread").WhoseValue.Should().Be("main");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
public async Task IngestAsync_ValidatesCallgraphId(string? callgraphId)
|
||||
|
||||
@@ -11,7 +11,8 @@ namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
public sealed class RuntimeFactsNdjsonReaderTests
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ReadAsync_ParsesLines()
|
||||
{
|
||||
var ndjson = """
|
||||
@@ -29,7 +30,8 @@ public sealed class RuntimeFactsNdjsonReaderTests
|
||||
events[1].LoaderBase.Should().Be("0x1000");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ReadAsync_HandlesGzip()
|
||||
{
|
||||
var ndjson = """
|
||||
@@ -40,6 +42,7 @@ public sealed class RuntimeFactsNdjsonReaderTests
|
||||
await using (var writer = new StreamWriter(gzip, Encoding.UTF8, leaveOpen: true))
|
||||
{
|
||||
await writer.WriteAsync(ndjson);
|
||||
using StellaOps.TestKit;
|
||||
}
|
||||
|
||||
compressed.Position = 0;
|
||||
|
||||
@@ -7,13 +7,15 @@ using StellaOps.Signals.Hosting;
|
||||
using StellaOps.Signals.Options;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Signals.Reachability.Tests;
|
||||
|
||||
public sealed class SignalsSealedModeMonitorTests : IDisposable
|
||||
{
|
||||
private readonly string tempDir = Path.Combine(Path.GetTempPath(), $"signals-sealed-tests-{Guid.NewGuid():N}");
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void IsCompliant_WhenEnforcementDisabled_ReturnsTrue()
|
||||
{
|
||||
var options = new SignalsOptions();
|
||||
@@ -24,7 +26,8 @@ public sealed class SignalsSealedModeMonitorTests : IDisposable
|
||||
monitor.IsCompliant(out _).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void IsCompliant_WhenEvidenceMissing_ReturnsFalse()
|
||||
{
|
||||
var options = CreateEnforcedOptions();
|
||||
@@ -36,7 +39,8 @@ public sealed class SignalsSealedModeMonitorTests : IDisposable
|
||||
reason.Should().Contain("not found");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void IsCompliant_WhenEvidenceFresh_ReturnsTrue()
|
||||
{
|
||||
var evidencePath = CreateEvidenceFile(TimeSpan.Zero);
|
||||
@@ -48,7 +52,8 @@ public sealed class SignalsSealedModeMonitorTests : IDisposable
|
||||
monitor.IsCompliant(out _).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void IsCompliant_WhenEvidenceStale_ReturnsFalse()
|
||||
{
|
||||
var evidencePath = CreateEvidenceFile(TimeSpan.FromHours(7));
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../Signals/StellaOps.Signals/StellaOps.Signals.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\fixtures\**\*">
|
||||
|
||||
Reference in New Issue
Block a user