consolidate the tests locations
This commit is contained in:
@@ -0,0 +1,453 @@
|
||||
// =============================================================================
|
||||
// StellaOps.Integration.Performance - Performance Baseline Tests
|
||||
// Sprint 3500.0004.0003 - T7: Performance Baseline Tests
|
||||
// =============================================================================
|
||||
|
||||
using FluentAssertions;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Integration.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Performance baseline tests to establish and validate performance characteristics.
|
||||
/// Uses timing measurements against known baselines with 20% regression threshold.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// T7-AC1: Score computation time baseline
|
||||
/// T7-AC2: Proof bundle generation baseline
|
||||
/// T7-AC3: Call graph extraction baseline
|
||||
/// T7-AC4: Reachability computation baseline
|
||||
/// T7-AC5: Regression alerts on >20% degradation
|
||||
/// </remarks>
|
||||
[Trait("Category", "Performance")]
|
||||
[Trait("Category", "Integration")]
|
||||
public class PerformanceBaselineTests : IClassFixture<PerformanceTestFixture>
|
||||
{
|
||||
private readonly PerformanceTestFixture _fixture;
|
||||
private const double RegressionThresholdPercent = 20.0;
|
||||
|
||||
public PerformanceBaselineTests(PerformanceTestFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
#region T7-AC1: Score Computation Baseline
|
||||
|
||||
[Fact(DisplayName = "T7-AC1.1: Score computation completes within baseline")]
|
||||
public async Task ScoreComputation_CompletesWithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("score_computation_ms");
|
||||
var findings = GenerateSampleFindings(100);
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var score = await ComputeScoreAsync(findings);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var actualMs = sw.ElapsedMilliseconds;
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
|
||||
actualMs.Should().BeLessThanOrEqualTo((long)threshold,
|
||||
$"Score computation took {actualMs}ms, exceeding baseline {baseline}ms + {RegressionThresholdPercent}% threshold");
|
||||
|
||||
// Record for baseline updates
|
||||
_fixture.RecordMeasurement("score_computation_ms", actualMs);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC1.2: Score computation scales linearly with findings")]
|
||||
public async Task ScoreComputation_ScalesLinearly()
|
||||
{
|
||||
// Arrange
|
||||
var sizes = new[] { 10, 50, 100, 200 };
|
||||
var times = new List<(int size, long ms)>();
|
||||
|
||||
// Act
|
||||
foreach (var size in sizes)
|
||||
{
|
||||
var findings = GenerateSampleFindings(size);
|
||||
var sw = Stopwatch.StartNew();
|
||||
await ComputeScoreAsync(findings);
|
||||
sw.Stop();
|
||||
times.Add((size, sw.ElapsedMilliseconds));
|
||||
}
|
||||
|
||||
// Assert - verify roughly linear scaling (within 3x of linear)
|
||||
var baseRatio = times[0].ms / (double)times[0].size;
|
||||
foreach (var (size, ms) in times.Skip(1))
|
||||
{
|
||||
var actualRatio = ms / (double)size;
|
||||
var scaleFactor = actualRatio / baseRatio;
|
||||
scaleFactor.Should().BeLessThan(3.0,
|
||||
$"Score computation at size {size} shows non-linear scaling (factor: {scaleFactor:F2}x)");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC1.3: Score computation handles large finding sets")]
|
||||
public async Task ScoreComputation_HandlesLargeSets()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("score_computation_large_ms");
|
||||
var findings = GenerateSampleFindings(1000);
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var score = await ComputeScoreAsync(findings);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold);
|
||||
|
||||
_fixture.RecordMeasurement("score_computation_large_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T7-AC2: Proof Bundle Generation Baseline
|
||||
|
||||
[Fact(DisplayName = "T7-AC2.1: Proof bundle generation completes within baseline")]
|
||||
public async Task ProofBundleGeneration_CompletesWithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("proof_bundle_generation_ms");
|
||||
var manifest = GenerateSampleManifest();
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var bundle = await GenerateProofBundleAsync(manifest);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold,
|
||||
$"Proof bundle generation took {sw.ElapsedMilliseconds}ms, exceeding baseline {baseline}ms");
|
||||
|
||||
_fixture.RecordMeasurement("proof_bundle_generation_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC2.2: Proof signing performance within baseline")]
|
||||
public async Task ProofSigning_WithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("proof_signing_ms");
|
||||
var payload = GenerateSamplePayload(10 * 1024); // 10KB payload
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var signature = await SignPayloadAsync(payload);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold);
|
||||
|
||||
_fixture.RecordMeasurement("proof_signing_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T7-AC3: Call Graph Extraction Baseline
|
||||
|
||||
[Fact(DisplayName = "T7-AC3.1: .NET call graph extraction within baseline")]
|
||||
public async Task DotNetCallGraphExtraction_WithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("dotnet_callgraph_extraction_ms");
|
||||
var assemblyPath = _fixture.GetTestAssemblyPath("DotNetSample");
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var graph = await ExtractDotNetCallGraphAsync(assemblyPath);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold,
|
||||
$"Call graph extraction took {sw.ElapsedMilliseconds}ms, exceeding baseline {baseline}ms");
|
||||
|
||||
_fixture.RecordMeasurement("dotnet_callgraph_extraction_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC3.2: Call graph scales with assembly size")]
|
||||
public async Task CallGraphExtraction_ScalesWithSize()
|
||||
{
|
||||
// Arrange
|
||||
var assemblies = _fixture.GetTestAssemblies();
|
||||
var results = new List<(string name, int nodes, long ms)>();
|
||||
|
||||
// Act
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var graph = await ExtractDotNetCallGraphAsync(assembly.Path);
|
||||
sw.Stop();
|
||||
results.Add((assembly.Name, graph.NodeCount, sw.ElapsedMilliseconds));
|
||||
}
|
||||
|
||||
// Assert - log results for baseline establishment
|
||||
foreach (var (name, nodes, ms) in results)
|
||||
{
|
||||
_fixture.RecordMeasurement($"callgraph_{name}_ms", ms);
|
||||
}
|
||||
|
||||
// Verify no catastrophic performance (>10s for any assembly)
|
||||
results.Should().AllSatisfy(r => r.ms.Should().BeLessThan(10000));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T7-AC4: Reachability Computation Baseline
|
||||
|
||||
[Fact(DisplayName = "T7-AC4.1: Reachability computation within baseline")]
|
||||
public async Task ReachabilityComputation_WithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("reachability_computation_ms");
|
||||
var callGraph = GenerateSampleCallGraph(500, 1000); // 500 nodes, 1000 edges
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await ComputeReachabilityAsync(callGraph);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold,
|
||||
$"Reachability computation took {sw.ElapsedMilliseconds}ms, exceeding baseline {baseline}ms");
|
||||
|
||||
_fixture.RecordMeasurement("reachability_computation_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC4.2: Large graph reachability within baseline")]
|
||||
public async Task LargeGraphReachability_WithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("reachability_large_graph_ms");
|
||||
var callGraph = GenerateSampleCallGraph(2000, 5000); // 2000 nodes, 5000 edges
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await ComputeReachabilityAsync(callGraph);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold,
|
||||
$"Large graph reachability took {sw.ElapsedMilliseconds}ms, exceeding baseline {baseline}ms");
|
||||
|
||||
_fixture.RecordMeasurement("reachability_large_graph_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC4.3: Reachability with deep paths within baseline")]
|
||||
public async Task DeepPathReachability_WithinBaseline()
|
||||
{
|
||||
// Arrange
|
||||
var baseline = _fixture.GetBaseline("reachability_deep_path_ms");
|
||||
var callGraph = GenerateDeepCallGraph(100); // 100 levels deep
|
||||
|
||||
// Act
|
||||
var sw = Stopwatch.StartNew();
|
||||
var result = await ComputeReachabilityAsync(callGraph);
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
sw.ElapsedMilliseconds.Should().BeLessThanOrEqualTo((long)threshold);
|
||||
|
||||
_fixture.RecordMeasurement("reachability_deep_path_ms", sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region T7-AC5: Regression Alerts
|
||||
|
||||
[Fact(DisplayName = "T7-AC5.1: All baselines within threshold")]
|
||||
public void AllBaselines_WithinThreshold()
|
||||
{
|
||||
// Arrange
|
||||
var measurements = _fixture.GetAllMeasurements();
|
||||
var regressions = new List<string>();
|
||||
|
||||
// Act & Assert
|
||||
foreach (var (metric, measured) in measurements)
|
||||
{
|
||||
var baseline = _fixture.GetBaseline(metric);
|
||||
var threshold = baseline * (1 + RegressionThresholdPercent / 100);
|
||||
|
||||
if (measured > threshold)
|
||||
{
|
||||
var regression = (measured - baseline) / baseline * 100;
|
||||
regressions.Add($"{metric}: {measured}ms vs baseline {baseline}ms (+{regression:F1}%)");
|
||||
}
|
||||
}
|
||||
|
||||
regressions.Should().BeEmpty(
|
||||
$"Performance regressions detected (>{RegressionThresholdPercent}%):\n" +
|
||||
string.Join("\n", regressions));
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "T7-AC5.2: Generate regression report")]
|
||||
public void GenerateRegressionReport()
|
||||
{
|
||||
// Arrange
|
||||
var measurements = _fixture.GetAllMeasurements();
|
||||
|
||||
// Act
|
||||
var report = new PerformanceReport
|
||||
{
|
||||
GeneratedAt = DateTime.UtcNow,
|
||||
ThresholdPercent = RegressionThresholdPercent,
|
||||
Metrics = measurements.Select(m => new MetricReport
|
||||
{
|
||||
Name = m.metric,
|
||||
Baseline = _fixture.GetBaseline(m.metric),
|
||||
Measured = m.value,
|
||||
DeltaPercent = (m.value - _fixture.GetBaseline(m.metric)) / _fixture.GetBaseline(m.metric) * 100
|
||||
}).ToList()
|
||||
};
|
||||
|
||||
// Assert - report should be valid
|
||||
report.Metrics.Should().NotBeEmpty();
|
||||
|
||||
// Write report for CI consumption
|
||||
var json = JsonSerializer.Serialize(report, new JsonSerializerOptions { WriteIndented = true });
|
||||
_fixture.SaveReport("performance-report.json", json);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private static List<SampleFinding> GenerateSampleFindings(int count)
|
||||
{
|
||||
return Enumerable.Range(1, count)
|
||||
.Select(i => new SampleFinding
|
||||
{
|
||||
Id = $"finding-{i:D4}",
|
||||
CveId = $"CVE-2024-{i:D5}",
|
||||
Severity = (i % 4) switch
|
||||
{
|
||||
0 => "CRITICAL",
|
||||
1 => "HIGH",
|
||||
2 => "MEDIUM",
|
||||
_ => "LOW"
|
||||
},
|
||||
CvssScore = 10.0 - (i % 10)
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static async Task<double> ComputeScoreAsync(List<SampleFinding> findings)
|
||||
{
|
||||
// Simulated score computation
|
||||
await Task.Delay(findings.Count / 10); // ~10 findings per ms
|
||||
return findings.Sum(f => f.CvssScore) / findings.Count;
|
||||
}
|
||||
|
||||
private static SampleManifest GenerateSampleManifest()
|
||||
{
|
||||
return new SampleManifest
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
Findings = GenerateSampleFindings(50)
|
||||
};
|
||||
}
|
||||
|
||||
private static async Task<byte[]> GenerateProofBundleAsync(SampleManifest manifest)
|
||||
{
|
||||
await Task.Delay(50); // Simulated bundle generation
|
||||
return JsonSerializer.SerializeToUtf8Bytes(manifest);
|
||||
}
|
||||
|
||||
private static byte[] GenerateSamplePayload(int sizeBytes)
|
||||
{
|
||||
var random = new Random(42);
|
||||
var buffer = new byte[sizeBytes];
|
||||
random.NextBytes(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static async Task<byte[]> SignPayloadAsync(byte[] payload)
|
||||
{
|
||||
await Task.Delay(10); // Simulated signing
|
||||
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
||||
return sha256.ComputeHash(payload);
|
||||
}
|
||||
|
||||
private static async Task<SampleCallGraph> ExtractDotNetCallGraphAsync(string assemblyPath)
|
||||
{
|
||||
await Task.Delay(100); // Simulated extraction
|
||||
return new SampleCallGraph { NodeCount = 100, EdgeCount = 250 };
|
||||
}
|
||||
|
||||
private static SampleCallGraph GenerateSampleCallGraph(int nodes, int edges)
|
||||
{
|
||||
return new SampleCallGraph { NodeCount = nodes, EdgeCount = edges };
|
||||
}
|
||||
|
||||
private static SampleCallGraph GenerateDeepCallGraph(int depth)
|
||||
{
|
||||
return new SampleCallGraph { NodeCount = depth, EdgeCount = depth - 1, Depth = depth };
|
||||
}
|
||||
|
||||
private static async Task<ReachabilityResult> ComputeReachabilityAsync(SampleCallGraph graph)
|
||||
{
|
||||
// Simulated reachability - O(V + E) complexity
|
||||
var delay = (graph.NodeCount + graph.EdgeCount) / 100;
|
||||
await Task.Delay(Math.Max(1, delay));
|
||||
return new ReachabilityResult { ReachableNodes = graph.NodeCount / 2 };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sample Types
|
||||
|
||||
private record SampleFinding
|
||||
{
|
||||
public string Id { get; init; } = "";
|
||||
public string CveId { get; init; } = "";
|
||||
public string Severity { get; init; } = "";
|
||||
public double CvssScore { get; init; }
|
||||
}
|
||||
|
||||
private record SampleManifest
|
||||
{
|
||||
public string Id { get; init; } = "";
|
||||
public DateTime CreatedAt { get; init; }
|
||||
public List<SampleFinding> Findings { get; init; } = new();
|
||||
}
|
||||
|
||||
private record SampleCallGraph
|
||||
{
|
||||
public int NodeCount { get; init; }
|
||||
public int EdgeCount { get; init; }
|
||||
public int Depth { get; init; }
|
||||
}
|
||||
|
||||
private record ReachabilityResult
|
||||
{
|
||||
public int ReachableNodes { get; init; }
|
||||
}
|
||||
|
||||
private record PerformanceReport
|
||||
{
|
||||
public DateTime GeneratedAt { get; init; }
|
||||
public double ThresholdPercent { get; init; }
|
||||
public List<MetricReport> Metrics { get; init; } = new();
|
||||
}
|
||||
|
||||
private record MetricReport
|
||||
{
|
||||
public string Name { get; init; } = "";
|
||||
public double Baseline { get; init; }
|
||||
public double Measured { get; init; }
|
||||
public double DeltaPercent { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// =============================================================================
|
||||
// StellaOps.Integration.Performance - Performance Test Fixture
|
||||
// Sprint 3500.0004.0003 - T7: Performance Baseline Tests
|
||||
// =============================================================================
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace StellaOps.Integration.Performance;
|
||||
|
||||
/// <summary>
|
||||
/// Test fixture for performance baseline tests.
|
||||
/// Manages baseline data and measurement recording.
|
||||
/// </summary>
|
||||
public sealed class PerformanceTestFixture : IDisposable
|
||||
{
|
||||
private readonly string _baselinesPath;
|
||||
private readonly string _outputPath;
|
||||
private readonly Dictionary<string, double> _baselines;
|
||||
private readonly Dictionary<string, double> _measurements = new();
|
||||
|
||||
public PerformanceTestFixture()
|
||||
{
|
||||
_baselinesPath = Path.Combine(AppContext.BaseDirectory, "baselines");
|
||||
_outputPath = Path.Combine(AppContext.BaseDirectory, "output");
|
||||
|
||||
Directory.CreateDirectory(_outputPath);
|
||||
|
||||
_baselines = LoadBaselines();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the baseline value for a metric.
|
||||
/// Returns default if baseline not found.
|
||||
/// </summary>
|
||||
public double GetBaseline(string metric)
|
||||
{
|
||||
return _baselines.TryGetValue(metric, out var baseline) ? baseline : GetDefaultBaseline(metric);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records a measurement for a metric.
|
||||
/// </summary>
|
||||
public void RecordMeasurement(string metric, double value)
|
||||
{
|
||||
_measurements[metric] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all recorded measurements.
|
||||
/// </summary>
|
||||
public IEnumerable<(string metric, double value)> GetAllMeasurements()
|
||||
{
|
||||
return _measurements.Select(kv => (kv.Key, kv.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to a test assembly.
|
||||
/// </summary>
|
||||
public string GetTestAssemblyPath(string name)
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "test-assemblies", $"{name}.dll");
|
||||
return File.Exists(path) ? path : Path.Combine(AppContext.BaseDirectory, "StellaOps.Integration.Performance.dll");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets available test assemblies.
|
||||
/// </summary>
|
||||
public IEnumerable<(string Name, string Path)> GetTestAssemblies()
|
||||
{
|
||||
var testAssembliesDir = Path.Combine(AppContext.BaseDirectory, "test-assemblies");
|
||||
|
||||
if (Directory.Exists(testAssembliesDir))
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(testAssembliesDir, "*.dll"))
|
||||
{
|
||||
yield return (Path.GetFileNameWithoutExtension(file), file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use self as test assembly
|
||||
var selfPath = Path.Combine(AppContext.BaseDirectory, "StellaOps.Integration.Performance.dll");
|
||||
if (File.Exists(selfPath))
|
||||
{
|
||||
yield return ("Self", selfPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves a report file.
|
||||
/// </summary>
|
||||
public void SaveReport(string filename, string content)
|
||||
{
|
||||
var path = Path.Combine(_outputPath, filename);
|
||||
File.WriteAllText(path, content);
|
||||
}
|
||||
|
||||
private Dictionary<string, double> LoadBaselines()
|
||||
{
|
||||
var baselinesFile = Path.Combine(_baselinesPath, "performance-baselines.json");
|
||||
|
||||
if (File.Exists(baselinesFile))
|
||||
{
|
||||
var json = File.ReadAllText(baselinesFile);
|
||||
return JsonSerializer.Deserialize<Dictionary<string, double>>(json) ?? GetDefaultBaselines();
|
||||
}
|
||||
|
||||
return GetDefaultBaselines();
|
||||
}
|
||||
|
||||
private static Dictionary<string, double> GetDefaultBaselines()
|
||||
{
|
||||
return new Dictionary<string, double>
|
||||
{
|
||||
// Score computation
|
||||
["score_computation_ms"] = 100,
|
||||
["score_computation_large_ms"] = 500,
|
||||
|
||||
// Proof bundle
|
||||
["proof_bundle_generation_ms"] = 200,
|
||||
["proof_signing_ms"] = 50,
|
||||
|
||||
// Call graph
|
||||
["dotnet_callgraph_extraction_ms"] = 500,
|
||||
|
||||
// Reachability
|
||||
["reachability_computation_ms"] = 100,
|
||||
["reachability_large_graph_ms"] = 500,
|
||||
["reachability_deep_path_ms"] = 200
|
||||
};
|
||||
}
|
||||
|
||||
private static double GetDefaultBaseline(string metric)
|
||||
{
|
||||
// Default to 1 second for unknown metrics
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Save measurements for potential baseline updates
|
||||
var measurementsFile = Path.Combine(_outputPath, "measurements.json");
|
||||
var json = JsonSerializer.Serialize(_measurements, new JsonSerializerOptions { WriteIndented = true });
|
||||
File.WriteAllText(measurementsFile, json);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Scanner\StellaOps.Scanner.WebService\StellaOps.Scanner.WebService.csproj" />
|
||||
<ProjectReference Include="..\Attestor\StellaOps.Attestor.ProofChain\StellaOps.Attestor.ProofChain.csproj" />
|
||||
<ProjectReference Include="..\Concelier\__Libraries\StellaOps.Concelier.CallGraph\StellaOps.Concelier.CallGraph.csproj" />
|
||||
<ProjectReference Include="..\Policy\__Libraries\StellaOps.Policy.Scoring\StellaOps.Policy.Scoring.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\__Benchmarks\baselines\**\*" LinkBase="baselines" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user