up
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
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
This commit is contained in:
@@ -5,7 +5,7 @@ using Xunit;
|
||||
public class ReplayManifestTests
|
||||
{
|
||||
[Fact]
|
||||
public void SerializesWithNamespacesAndAnalysis()
|
||||
public void SerializesWithNamespacesAndAnalysis_V1()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
@@ -20,7 +20,9 @@ public class ReplayManifestTests
|
||||
{
|
||||
Kind = "static",
|
||||
CasUri = "cas://reachability_graphs/aa/aagraph.tar.zst",
|
||||
Sha256 = "aa",
|
||||
Hash = "sha256:aa",
|
||||
HashAlgorithm = "sha256",
|
||||
Sha256 = "aa", // Legacy field for v1 compat
|
||||
Namespace = "reachability_graphs",
|
||||
CallgraphId = "cg-1",
|
||||
Analyzer = "scanner",
|
||||
@@ -31,7 +33,9 @@ public class ReplayManifestTests
|
||||
{
|
||||
Source = "runtime",
|
||||
CasUri = "cas://runtime_traces/bb/bbtrace.tar.zst",
|
||||
Sha256 = "bb",
|
||||
Hash = "sha256:bb",
|
||||
HashAlgorithm = "sha256",
|
||||
Sha256 = "bb", // Legacy field for v1 compat
|
||||
Namespace = "runtime_traces",
|
||||
RecordedAt = System.DateTimeOffset.Parse("2025-11-26T00:00:00Z")
|
||||
});
|
||||
@@ -43,4 +47,36 @@ public class ReplayManifestTests
|
||||
Assert.Contains("\"callgraphId\":\"cg-1\"", json);
|
||||
Assert.Contains("\"namespace\":\"runtime_traces\"", json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerializesWithV2HashFields()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
AnalysisId = "analysis-v2"
|
||||
}
|
||||
};
|
||||
|
||||
manifest.AddReachabilityGraph(new ReplayReachabilityGraphReference
|
||||
{
|
||||
Kind = "static",
|
||||
CasUri = "cas://reachability/graphs/blake3:abc123",
|
||||
Hash = "blake3:abc123def456789012345678901234567890123456789012345678901234",
|
||||
HashAlgorithm = "blake3-256",
|
||||
Namespace = "reachability_graphs",
|
||||
Analyzer = "scanner.java@10.0.0",
|
||||
Version = "10.0.0"
|
||||
});
|
||||
|
||||
var json = JsonSerializer.Serialize(manifest, new JsonSerializerOptions(JsonSerializerDefaults.Web));
|
||||
|
||||
Assert.Contains("\"schemaVersion\":\"2.0\"", json);
|
||||
Assert.Contains("\"hash\":\"blake3:", json);
|
||||
Assert.Contains("\"hashAlg\":\"blake3-256\"", json);
|
||||
// v2 manifests should not emit legacy sha256 field (JsonIgnore when null)
|
||||
Assert.DoesNotContain("\"sha256\":", json);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,483 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Replay.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Replay.Core.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Test vectors from replay-manifest-v2-acceptance.md
|
||||
/// </summary>
|
||||
public class ReplayManifestV2Tests
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
|
||||
{
|
||||
WriteIndented = false
|
||||
};
|
||||
|
||||
#region Section 4.1: Minimal Valid Manifest v2
|
||||
|
||||
[Fact]
|
||||
public void MinimalValidManifestV2_SerializesCorrectly()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Scan = new ReplayScanMetadata
|
||||
{
|
||||
Id = "scan-test-001",
|
||||
Time = DateTimeOffset.Parse("2025-12-13T10:00:00Z")
|
||||
},
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Kind = "static",
|
||||
Analyzer = "scanner.java@10.2.0",
|
||||
Hash = "blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
|
||||
}
|
||||
},
|
||||
RuntimeTraces = new List<ReplayReachabilityTraceReference>(),
|
||||
CodeIdCoverage = new CodeIdCoverage
|
||||
{
|
||||
TotalNodes = 100,
|
||||
NodesWithSymbolId = 100,
|
||||
NodesWithCodeId = 0,
|
||||
CoveragePercent = 100.0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(manifest, JsonOptions);
|
||||
|
||||
Assert.Contains("\"schemaVersion\":\"2.0\"", json);
|
||||
Assert.Contains("\"hash\":\"blake3:", json);
|
||||
Assert.Contains("\"hashAlg\":\"blake3-256\"", json);
|
||||
Assert.Contains("\"code_id_coverage\"", json);
|
||||
Assert.Contains("\"total_nodes\":100", json);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Section 4.2: Manifest with Runtime Traces
|
||||
|
||||
[Fact]
|
||||
public void ManifestWithRuntimeTraces_SerializesCorrectly()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Scan = new ReplayScanMetadata
|
||||
{
|
||||
Id = "scan-test-002",
|
||||
Time = DateTimeOffset.Parse("2025-12-13T11:00:00Z")
|
||||
},
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Kind = "static",
|
||||
Analyzer = "scanner.java@10.2.0",
|
||||
Hash = "blake3:1111111111111111111111111111111111111111111111111111111111111111",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:1111111111111111111111111111111111111111111111111111111111111111"
|
||||
}
|
||||
},
|
||||
RuntimeTraces = new List<ReplayReachabilityTraceReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Source = "eventpipe",
|
||||
Hash = "sha256:2222222222222222222222222222222222222222222222222222222222222222",
|
||||
HashAlgorithm = "sha256",
|
||||
CasUri = "cas://reachability/runtime/sha256:2222222222222222222222222222222222222222222222222222222222222222",
|
||||
RecordedAt = DateTimeOffset.Parse("2025-12-13T10:30:00Z")
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(manifest, JsonOptions);
|
||||
|
||||
Assert.Contains("\"source\":\"eventpipe\"", json);
|
||||
Assert.Contains("\"hash\":\"sha256:", json);
|
||||
Assert.Contains("\"hashAlg\":\"sha256\"", json);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Section 4.3: Sorting Validation
|
||||
|
||||
[Fact]
|
||||
public void SortingValidation_UnsortedGraphs_FailsValidation()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Kind = "framework",
|
||||
Hash = "blake3:zzzz1111111111111111111111111111111111111111111111111111111111",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:zzzz..."
|
||||
},
|
||||
new()
|
||||
{
|
||||
Kind = "static",
|
||||
Hash = "blake3:aaaa1111111111111111111111111111111111111111111111111111111111",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:aaaa..."
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator();
|
||||
var result = validator.ValidateAsync(manifest).GetAwaiter().GetResult();
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.UnsortedEntries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SortingValidation_SortedGraphs_PassesValidation()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Kind = "static",
|
||||
Hash = "blake3:aaaa1111111111111111111111111111111111111111111111111111111111",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:aaaa..."
|
||||
},
|
||||
new()
|
||||
{
|
||||
Kind = "framework",
|
||||
Hash = "blake3:zzzz1111111111111111111111111111111111111111111111111111111111",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:zzzz..."
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator();
|
||||
var result = validator.ValidateAsync(manifest).GetAwaiter().GetResult();
|
||||
|
||||
Assert.True(result.IsValid);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Section 4.4: Invalid Manifest Vectors
|
||||
|
||||
[Fact]
|
||||
public void InvalidManifest_MissingSchemaVersion_FailsValidation()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = null!
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator();
|
||||
var result = validator.ValidateAsync(manifest).GetAwaiter().GetResult();
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.MissingVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidManifest_VersionMismatch_WhenV2Required_FailsValidation()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V1
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator(requireV2: true);
|
||||
var result = validator.ValidateAsync(manifest).GetAwaiter().GetResult();
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.VersionMismatch);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidManifest_MissingHashAlg_InV2_FailsValidation()
|
||||
{
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Hash = "blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||
HashAlgorithm = null!, // Missing
|
||||
CasUri = "cas://reachability/graphs/blake3:..."
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator();
|
||||
var result = validator.ValidateAsync(manifest).GetAwaiter().GetResult();
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.MissingHashAlg);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvalidManifest_MissingCasReference_FailsValidation()
|
||||
{
|
||||
var casValidator = new InMemoryCasValidator();
|
||||
// Don't register any objects
|
||||
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Hash = "blake3:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:missing"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator(casValidator);
|
||||
var result = await validator.ValidateAsync(manifest);
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.CasNotFound);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvalidManifest_HashMismatch_FailsValidation()
|
||||
{
|
||||
var casValidator = new InMemoryCasValidator();
|
||||
casValidator.Register(
|
||||
"cas://reachability/graphs/blake3:actual",
|
||||
"blake3:differenthash");
|
||||
casValidator.Register(
|
||||
"cas://reachability/graphs/blake3:actual.dsse",
|
||||
"blake3:differenthash.dsse");
|
||||
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Hash = "blake3:expected",
|
||||
HashAlgorithm = "blake3-256",
|
||||
CasUri = "cas://reachability/graphs/blake3:actual"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var validator = new ReplayManifestValidator(casValidator);
|
||||
var result = await validator.ValidateAsync(manifest);
|
||||
|
||||
Assert.False(result.IsValid);
|
||||
Assert.Contains(result.Errors, e => e.ErrorCode == ReplayManifestErrorCodes.HashMismatch);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Section 5: Migration Path
|
||||
|
||||
[Fact]
|
||||
public void UpgradeToV2_ConvertsV1ManifestCorrectly()
|
||||
{
|
||||
var v1 = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V1,
|
||||
Scan = new ReplayScanMetadata
|
||||
{
|
||||
Id = "scan-legacy"
|
||||
},
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Kind = "static",
|
||||
Sha256 = "abc123",
|
||||
CasUri = "cas://reachability/graphs/abc123"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var v2 = ReplayManifestValidator.UpgradeToV2(v1);
|
||||
|
||||
Assert.Equal(ReplayManifestVersions.V2, v2.SchemaVersion);
|
||||
Assert.Single(v2.Reachability.Graphs);
|
||||
Assert.Equal("sha256:abc123", v2.Reachability.Graphs[0].Hash);
|
||||
Assert.Equal("sha256", v2.Reachability.Graphs[0].HashAlgorithm);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpgradeToV2_SortsGraphsByUri()
|
||||
{
|
||||
var v1 = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V1,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
Graphs = new List<ReplayReachabilityGraphReference>
|
||||
{
|
||||
new() { Sha256 = "zzz", CasUri = "cas://graphs/zzz" },
|
||||
new() { Sha256 = "aaa", CasUri = "cas://graphs/aaa" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var v2 = ReplayManifestValidator.UpgradeToV2(v1);
|
||||
|
||||
Assert.Equal("cas://graphs/aaa", v2.Reachability.Graphs[0].CasUri);
|
||||
Assert.Equal("cas://graphs/zzz", v2.Reachability.Graphs[1].CasUri);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReachabilityReplayWriter Tests
|
||||
|
||||
[Fact]
|
||||
public void BuildManifestV2_WithValidGraphs_CreatesSortedManifest()
|
||||
{
|
||||
var scan = new ReplayScanMetadata { Id = "test-scan" };
|
||||
var graphs = new[]
|
||||
{
|
||||
new ReplayReachabilityGraphReference
|
||||
{
|
||||
Hash = "blake3:zzzz",
|
||||
CasUri = "cas://graphs/zzzz"
|
||||
},
|
||||
new ReplayReachabilityGraphReference
|
||||
{
|
||||
Hash = "blake3:aaaa",
|
||||
CasUri = "cas://graphs/aaaa"
|
||||
}
|
||||
};
|
||||
|
||||
var manifest = ReachabilityReplayWriter.BuildManifestV2(
|
||||
scan,
|
||||
graphs,
|
||||
Array.Empty<ReplayReachabilityTraceReference>());
|
||||
|
||||
Assert.Equal(ReplayManifestVersions.V2, manifest.SchemaVersion);
|
||||
Assert.Equal("cas://graphs/aaaa", manifest.Reachability.Graphs[0].CasUri);
|
||||
Assert.Equal("cas://graphs/zzzz", manifest.Reachability.Graphs[1].CasUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildManifestV2_WithLegacySha256_MigratesHashField()
|
||||
{
|
||||
var scan = new ReplayScanMetadata { Id = "test-scan" };
|
||||
var graphs = new[]
|
||||
{
|
||||
new ReplayReachabilityGraphReference
|
||||
{
|
||||
Sha256 = "abc123",
|
||||
CasUri = "cas://graphs/abc123"
|
||||
}
|
||||
};
|
||||
|
||||
var manifest = ReachabilityReplayWriter.BuildManifestV2(
|
||||
scan,
|
||||
graphs,
|
||||
Array.Empty<ReplayReachabilityTraceReference>());
|
||||
|
||||
Assert.Equal("sha256:abc123", manifest.Reachability.Graphs[0].Hash);
|
||||
Assert.Equal("sha256", manifest.Reachability.Graphs[0].HashAlgorithm);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildManifestV2_InfersHashAlgorithmFromPrefix()
|
||||
{
|
||||
var scan = new ReplayScanMetadata { Id = "test-scan" };
|
||||
var graphs = new[]
|
||||
{
|
||||
new ReplayReachabilityGraphReference
|
||||
{
|
||||
Hash = "blake3:a1b2c3d4",
|
||||
CasUri = "cas://graphs/a1b2c3d4"
|
||||
}
|
||||
};
|
||||
|
||||
var manifest = ReachabilityReplayWriter.BuildManifestV2(
|
||||
scan,
|
||||
graphs,
|
||||
Array.Empty<ReplayReachabilityTraceReference>());
|
||||
|
||||
Assert.Equal("blake3-256", manifest.Reachability.Graphs[0].HashAlgorithm);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildManifestV2_RequiresAtLeastOneGraph()
|
||||
{
|
||||
var scan = new ReplayScanMetadata { Id = "test-scan" };
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
ReachabilityReplayWriter.BuildManifestV2(
|
||||
scan,
|
||||
Array.Empty<ReplayReachabilityGraphReference>(),
|
||||
Array.Empty<ReplayReachabilityTraceReference>()));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CodeIdCoverage Tests
|
||||
|
||||
[Fact]
|
||||
public void CodeIdCoverage_SerializesWithSnakeCaseKeys()
|
||||
{
|
||||
var coverage = new CodeIdCoverage
|
||||
{
|
||||
TotalNodes = 1247,
|
||||
NodesWithSymbolId = 1189,
|
||||
NodesWithCodeId = 58,
|
||||
CoveragePercent = 100.0
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(coverage, JsonOptions);
|
||||
|
||||
Assert.Contains("\"total_nodes\":1247", json);
|
||||
Assert.Contains("\"nodes_with_symbol_id\":1189", json);
|
||||
Assert.Contains("\"nodes_with_code_id\":58", json);
|
||||
Assert.Contains("\"coverage_percent\":100", json);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user