Refactor code structure and optimize performance across multiple modules

This commit is contained in:
StellaOps Bot
2025-12-26 20:03:22 +02:00
parent c786faae84
commit f10d83c444
1385 changed files with 69732 additions and 10280 deletions

View File

@@ -20,20 +20,23 @@ public class CecilMethodFingerprinterTests
NullLogger<CecilMethodFingerprinter>.Instance);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Ecosystem_ReturnsNuget()
{
Assert.Equal("nuget", _fingerprinter.Ecosystem);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_WithNullRequest_ThrowsArgumentNullException()
{
await Assert.ThrowsAsync<ArgumentNullException>(
() => _fingerprinter.FingerprintAsync(null!));
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_WithNonExistentPath_ReturnsEmptyResult()
{
// Arrange
@@ -53,7 +56,8 @@ public class CecilMethodFingerprinterTests
Assert.Empty(result.Methods);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_WithOwnAssembly_FindsMethods()
{
// Arrange - use the test assembly itself
@@ -80,7 +84,8 @@ public class CecilMethodFingerprinterTests
Assert.True(result.Methods.Count > 0, "Should find at least some methods");
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_ComputesDeterministicHashes()
{
// Arrange - fingerprint twice
@@ -109,11 +114,13 @@ public class CecilMethodFingerprinterTests
}
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_WithCancellation_RespectsCancellation()
{
// Arrange
using var cts = new CancellationTokenSource();
using StellaOps.TestKit;
cts.Cancel();
var testAssemblyPath = typeof(CecilMethodFingerprinterTests).Assembly.Location;
@@ -142,7 +149,8 @@ public class CecilMethodFingerprinterTests
}
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_MethodKeyFormat_IsValid()
{
// Arrange
@@ -172,7 +180,8 @@ public class CecilMethodFingerprinterTests
}
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task FingerprintAsync_IncludesSignature()
{
// Arrange

View File

@@ -8,11 +8,13 @@ using StellaOps.Scanner.VulnSurfaces.CallGraph;
using StellaOps.Scanner.VulnSurfaces.Models;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Scanner.VulnSurfaces.Tests;
public class InternalCallGraphTests
{
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void AddMethod_StoresMethod()
{
// Arrange
@@ -38,7 +40,8 @@ public class InternalCallGraphTests
Assert.Equal(1, graph.MethodCount);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void AddEdge_CreatesForwardAndReverseMapping()
{
// Arrange
@@ -63,7 +66,8 @@ public class InternalCallGraphTests
Assert.Equal(1, graph.EdgeCount);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void GetPublicMethods_ReturnsOnlyPublic()
{
// Arrange
@@ -97,7 +101,8 @@ public class InternalCallGraphTests
Assert.Equal("A::Public()", publicMethods[0].MethodKey);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void GetCallees_EmptyForUnknownMethod()
{
// Arrange
@@ -114,7 +119,8 @@ public class InternalCallGraphTests
Assert.Empty(callees);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void GetMethod_ReturnsNullForUnknown()
{
// Arrange

View File

@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Scanner.VulnSurfaces.Fingerprint;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Scanner.VulnSurfaces.Tests;
public class MethodDiffEngineTests
@@ -20,14 +21,16 @@ public class MethodDiffEngineTests
NullLogger<MethodDiffEngine>.Instance);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithNullRequest_ThrowsArgumentNullException()
{
await Assert.ThrowsAsync<ArgumentNullException>(
() => _diffEngine.DiffAsync(null!));
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithIdenticalFingerprints_ReturnsNoChanges()
{
// Arrange
@@ -68,7 +71,8 @@ public class MethodDiffEngineTests
Assert.Equal(0, diff.TotalChanges);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithModifiedMethod_ReturnsModified()
{
// Arrange
@@ -112,7 +116,8 @@ public class MethodDiffEngineTests
Assert.Empty(diff.Removed);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithAddedMethod_ReturnsAdded()
{
// Arrange
@@ -155,7 +160,8 @@ public class MethodDiffEngineTests
Assert.Empty(diff.Removed);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithRemovedMethod_ReturnsRemoved()
{
// Arrange
@@ -198,7 +204,8 @@ public class MethodDiffEngineTests
Assert.Equal("Test.Class::RemovedMethod", diff.Removed[0].MethodKey);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithMultipleChanges_ReturnsAllChanges()
{
// Arrange - simulate a fix that modifies one method, adds one, removes one
@@ -247,7 +254,8 @@ public class MethodDiffEngineTests
Assert.Equal(3, diff.TotalChanges);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_TriggerMethods_AreModifiedOrRemoved()
{
// This test validates the key insight:
@@ -298,7 +306,8 @@ public class MethodDiffEngineTests
Assert.Empty(diff.Removed);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DiffAsync_WithEmptyFingerprints_ReturnsNoChanges()
{
// Arrange

View File

@@ -35,7 +35,8 @@ public class NuGetPackageDownloaderTests : IDisposable
}
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public void Ecosystem_ReturnsNuget()
{
// Arrange
@@ -45,7 +46,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.Equal("nuget", downloader.Ecosystem);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithNullRequest_ThrowsArgumentNullException()
{
// Arrange
@@ -56,7 +58,8 @@ public class NuGetPackageDownloaderTests : IDisposable
() => downloader.DownloadAsync(null!));
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithHttpError_ReturnsFailResult()
{
// Arrange
@@ -93,7 +96,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.Null(result.ExtractedPath);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithValidNupkg_ReturnsSuccessResult()
{
// Arrange - create a mock .nupkg (which is just a zip file)
@@ -135,7 +139,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.False(result.FromCache);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithCachedPackage_ReturnsCachedResult()
{
// Arrange - pre-create the cached directory
@@ -162,7 +167,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.Equal(packageDir, result.ExtractedPath);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithCacheFalse_BypassesCache()
{
// Arrange - pre-create the cached directory
@@ -210,7 +216,8 @@ public class NuGetPackageDownloaderTests : IDisposable
ItExpr.IsAny<CancellationToken>());
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_UsesCorrectUrl()
{
// Arrange
@@ -250,7 +257,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.EndsWith(".nupkg", capturedRequest.RequestUri!.ToString());
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithCustomRegistry_UsesCustomUrl()
{
// Arrange
@@ -289,7 +297,8 @@ public class NuGetPackageDownloaderTests : IDisposable
Assert.StartsWith("https://custom.nuget.feed.example.com/v3", capturedRequest.RequestUri!.ToString());
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task DownloadAsync_WithCancellation_HonorsCancellation()
{
// Arrange
@@ -344,6 +353,7 @@ public class NuGetPackageDownloaderTests : IDisposable
// Add a minimal .nuspec file
var nuspecEntry = archive.CreateEntry("test.nuspec");
using var writer = new StreamWriter(nuspecEntry.Open());
using StellaOps.TestKit;
writer.Write("""
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">

View File

@@ -10,6 +10,7 @@ using StellaOps.Scanner.VulnSurfaces.Models;
using StellaOps.Scanner.VulnSurfaces.Triggers;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Scanner.VulnSurfaces.Tests;
public class TriggerMethodExtractorTests
@@ -21,7 +22,8 @@ public class TriggerMethodExtractorTests
_extractor = new TriggerMethodExtractor(NullLogger<TriggerMethodExtractor>.Instance);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_DirectPath_FindsTrigger()
{
// Arrange
@@ -85,7 +87,8 @@ public class TriggerMethodExtractorTests
Assert.False(trigger.IsInterfaceExpansion);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_NoPath_ReturnsEmpty()
{
// Arrange
@@ -124,7 +127,8 @@ public class TriggerMethodExtractorTests
Assert.Empty(result.Triggers);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_MultiplePublicMethods_FindsAllTriggers()
{
// Arrange
@@ -174,7 +178,8 @@ public class TriggerMethodExtractorTests
Assert.Contains(result.Triggers, t => t.TriggerMethodKey == "Class::Api2()");
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_MaxDepthExceeded_DoesNotFindTrigger()
{
// Arrange
@@ -231,7 +236,8 @@ public class TriggerMethodExtractorTests
Assert.Empty(result.Triggers);
}
[Fact]
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task ExtractAsync_VirtualMethod_ReducesConfidence()
{
// Arrange

View File

@@ -4,10 +4,12 @@ using StellaOps.Scanner.VulnSurfaces.Services;
using StellaOps.Scanner.VulnSurfaces.Storage;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Scanner.VulnSurfaces.Tests;
public sealed class VulnSurfaceServiceTests
{
[Trait("Category", TestCategories.Unit)]
[Fact(DisplayName = "GetAffectedSymbolsAsync returns sinks when surface exists")]
public async Task GetAffectedSymbolsAsync_ReturnsSurfaceSinks()
{
@@ -50,6 +52,7 @@ public sealed class VulnSurfaceServiceTests
Assert.Equal(surfaceGuid, repository.LastSurfaceId);
}
[Trait("Category", TestCategories.Unit)]
[Fact(DisplayName = "GetAffectedSymbolsAsync falls back to package symbol provider")]
public async Task GetAffectedSymbolsAsync_FallsBackToPackageSymbols()
{
@@ -64,6 +67,7 @@ public sealed class VulnSurfaceServiceTests
Assert.Single(result.Symbols);
}
[Trait("Category", TestCategories.Unit)]
[Fact(DisplayName = "GetAffectedSymbolsAsync returns heuristic when no data")]
public async Task GetAffectedSymbolsAsync_ReturnsHeuristicWhenEmpty()
{