Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (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
Docs CI / lint-and-preview (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
79 lines
3.3 KiB
C#
79 lines
3.3 KiB
C#
using System.Linq;
|
|
using System.Text.Json;
|
|
using StellaOps.Scanner.Analyzers.Lang.Rust;
|
|
using StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
|
|
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
|
|
|
namespace StellaOps.Scanner.Analyzers.Lang.Tests.Rust;
|
|
|
|
public sealed class RustHeuristicCoverageComparisonTests
|
|
{
|
|
[Fact]
|
|
public async Task HeuristicCoverageExceedsCompetitorBaselineAsync()
|
|
{
|
|
var cancellationToken = TestContext.Current.CancellationToken;
|
|
var fixturePath = TestPaths.ResolveFixture("lang", "rust", "heuristics");
|
|
var baselinePath = Path.Combine(fixturePath, "competitor-baseline.json");
|
|
RustFixtureBinaries.EnsureHeuristicBinary(fixturePath);
|
|
|
|
var analyzers = new ILanguageAnalyzer[]
|
|
{
|
|
new RustLanguageAnalyzer()
|
|
};
|
|
|
|
var output = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
|
fixturePath,
|
|
analyzers,
|
|
cancellationToken);
|
|
|
|
using var ours = JsonDocument.Parse(output);
|
|
var heuristicNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
foreach (var element in ours.RootElement.EnumerateArray())
|
|
{
|
|
if (!element.TryGetProperty("metadata", out var metadata) || metadata.ValueKind != JsonValueKind.Object)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var provenance = metadata.EnumerateObject()
|
|
.FirstOrDefault(p => string.Equals(p.Name, "provenance", StringComparison.OrdinalIgnoreCase));
|
|
|
|
if (provenance.Value.ValueKind == JsonValueKind.String &&
|
|
string.Equals(provenance.Value.GetString(), "heuristic", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
if (element.TryGetProperty("name", out var nameProperty) && nameProperty.ValueKind == JsonValueKind.String)
|
|
{
|
|
var value = nameProperty.GetString();
|
|
if (!string.IsNullOrWhiteSpace(value))
|
|
{
|
|
heuristicNames.Add(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
using var competitor = JsonDocument.Parse(await File.ReadAllTextAsync(baselinePath, cancellationToken));
|
|
var competitorNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
if (competitor.RootElement.TryGetProperty("detectedCrates", out var detectedCrates) && detectedCrates.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var entry in detectedCrates.EnumerateArray())
|
|
{
|
|
if (entry.ValueKind == JsonValueKind.Object && entry.TryGetProperty("name", out var nameProperty) && nameProperty.ValueKind == JsonValueKind.String)
|
|
{
|
|
var name = nameProperty.GetString();
|
|
if (!string.IsNullOrWhiteSpace(name))
|
|
{
|
|
competitorNames.Add(name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Assert.NotEmpty(competitorNames);
|
|
Assert.True(heuristicNames.IsSupersetOf(competitorNames));
|
|
|
|
var improvement = (double)heuristicNames.Count / competitorNames.Count;
|
|
Assert.True(improvement >= 1.15, $"Expected at least 15% improvement; got {improvement:P2} ({heuristicNames.Count} vs {competitorNames.Count}).");
|
|
}
|
|
}
|