feat(rust): Implement RustCargoLockParser and RustFingerprintScanner
- Added RustCargoLockParser to parse Cargo.lock files and extract package information. - Introduced RustFingerprintScanner to scan for Rust fingerprint records in JSON files. - Created test fixtures for Rust language analysis, including Cargo.lock and fingerprint JSON files. - Developed tests for RustLanguageAnalyzer to ensure deterministic output based on provided fixtures. - Added expected output files for both simple and signed Rust applications.
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Scanner.Analyzers.Lang.DotNet;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
||||
@@ -25,4 +28,79 @@ public sealed class DotNetLanguageAnalyzerTests
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SignedFixtureCapturesAssemblyMetadataAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "signed");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new DotNetLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var inspector = new StubAuthenticodeInspector();
|
||||
var services = new SingleServiceProvider(inspector);
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
usageHints: null,
|
||||
services: services);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SelfContainedFixtureHandlesNativeAssetsAndUsageAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "selfcontained");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var usageHints = new LanguageUsageHints(new[]
|
||||
{
|
||||
Path.Combine(fixturePath, "lib", "net10.0", "StellaOps.Toolkit.dll"),
|
||||
Path.Combine(fixturePath, "runtimes", "linux-x64", "native", "libstellaopsnative.so")
|
||||
});
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new DotNetLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
usageHints);
|
||||
}
|
||||
|
||||
private sealed class StubAuthenticodeInspector : IDotNetAuthenticodeInspector
|
||||
{
|
||||
public DotNetAuthenticodeMetadata? TryInspect(string assemblyPath, CancellationToken cancellationToken)
|
||||
=> new DotNetAuthenticodeMetadata(
|
||||
Subject: "CN=StellaOps Test Signing",
|
||||
Issuer: "CN=StellaOps Root",
|
||||
NotBefore: new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
NotAfter: new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
Thumbprint: "AA11BB22CC33DD44EE55FF66GG77HH88II99JJ00",
|
||||
SerialNumber: "0123456789ABCDEF");
|
||||
}
|
||||
|
||||
private sealed class SingleServiceProvider : IServiceProvider
|
||||
{
|
||||
private readonly object _service;
|
||||
|
||||
public SingleServiceProvider(object service)
|
||||
{
|
||||
_service = service;
|
||||
}
|
||||
|
||||
public object? GetService(Type serviceType)
|
||||
=> serviceType == typeof(IDotNetAuthenticodeInspector) ? _service : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0",
|
||||
"signature": null
|
||||
},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0/linux-x64": {
|
||||
"MyApp/1.0.0": {
|
||||
"dependencies": {
|
||||
"StellaOps.Toolkit": "1.2.3",
|
||||
"StellaOps.Runtime.SelfContained": "2.1.0"
|
||||
},
|
||||
"runtime": {
|
||||
"MyApp.dll": {}
|
||||
}
|
||||
},
|
||||
"StellaOps.Toolkit/1.2.3": {
|
||||
"runtime": {
|
||||
"lib/net10.0/StellaOps.Toolkit.dll": {
|
||||
"assemblyVersion": "1.2.3.0",
|
||||
"fileVersion": "1.2.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Runtime.SelfContained/2.1.0": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/linux-x64/native/libstellaopsnative.so": {
|
||||
"rid": "linux-x64",
|
||||
"assetType": "native"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
".NETCoreApp,Version=v10.0/win-x64": {
|
||||
"MyApp/1.0.0": {
|
||||
"dependencies": {
|
||||
"StellaOps.Toolkit": "1.2.3",
|
||||
"StellaOps.Runtime.SelfContained": "2.1.0"
|
||||
},
|
||||
"runtime": {
|
||||
"MyApp.dll": {}
|
||||
}
|
||||
},
|
||||
"StellaOps.Toolkit/1.2.3": {
|
||||
"runtime": {
|
||||
"lib/net10.0/StellaOps.Toolkit.dll": {
|
||||
"assemblyVersion": "1.2.3.0",
|
||||
"fileVersion": "1.2.3.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StellaOps.Runtime.SelfContained/2.1.0": {
|
||||
"runtimeTargets": {
|
||||
"runtimes/win-x64/native/stellaopsnative.dll": {
|
||||
"rid": "win-x64",
|
||||
"assetType": "native"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"MyApp/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false,
|
||||
"sha512": "",
|
||||
"path": null,
|
||||
"hashPath": null
|
||||
},
|
||||
"StellaOps.Toolkit/1.2.3": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-FAKE_TOOLKIT_SHA==",
|
||||
"path": "stellaops.toolkit/1.2.3",
|
||||
"hashPath": "stellaops.toolkit.1.2.3.nupkg.sha512"
|
||||
},
|
||||
"StellaOps.Runtime.SelfContained/2.1.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-FAKE_RUNTIME_SHA==",
|
||||
"path": "stellaops.runtime.selfcontained/2.1.0",
|
||||
"hashPath": "stellaops.runtime.selfcontained.2.1.0.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net10.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "10.0.0"
|
||||
},
|
||||
"includedFrameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.DotNetAppHost",
|
||||
"version": "10.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "dotnet",
|
||||
"componentKey": "purl::pkg:nuget/stellaops.runtime.selfcontained@2.1.0",
|
||||
"purl": "pkg:nuget/stellaops.runtime.selfcontained@2.1.0",
|
||||
"name": "StellaOps.Runtime.SelfContained",
|
||||
"version": "2.1.0",
|
||||
"type": "nuget",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"deps.path[0]": "MyApp.deps.json",
|
||||
"deps.rid[0]": "linux-x64",
|
||||
"deps.rid[1]": "win-x64",
|
||||
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"native[0].assetPath": "runtimes/linux-x64/native/libstellaopsnative.so",
|
||||
"native[0].path": "runtimes/linux-x64/native/libstellaopsnative.so",
|
||||
"native[0].rid[0]": "linux-x64",
|
||||
"native[0].sha256": "c22d4a6584a3bb8fad4d255d1ab9e5a80d553eec35ea8dfcc2dd750e8581d3cb",
|
||||
"native[0].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"native[1].assetPath": "runtimes/win-x64/native/stellaopsnative.dll",
|
||||
"native[1].path": "runtimes/win-x64/native/stellaopsnative.dll",
|
||||
"native[1].rid[0]": "win-x64",
|
||||
"native[1].sha256": "29cddd69702aedc715050304bec85aad2ae017ee1f9390df5e68ebe79a8d4745",
|
||||
"native[1].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"package.hashPath[0]": "stellaops.runtime.selfcontained.2.1.0.nupkg.sha512",
|
||||
"package.id": "StellaOps.Runtime.SelfContained",
|
||||
"package.id.normalized": "stellaops.runtime.selfcontained",
|
||||
"package.path[0]": "stellaops.runtime.selfcontained/2.1.0",
|
||||
"package.serviceable": "true",
|
||||
"package.sha512[0]": "sha512-FAKE_RUNTIME_SHA==",
|
||||
"package.version": "2.1.0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "deps.json",
|
||||
"locator": "MyApp.deps.json",
|
||||
"value": "StellaOps.Runtime.SelfContained/2.1.0"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "native",
|
||||
"locator": "runtimes/linux-x64/native/libstellaopsnative.so",
|
||||
"value": "runtimes/linux-x64/native/libstellaopsnative.so",
|
||||
"sha256": "c22d4a6584a3bb8fad4d255d1ab9e5a80d553eec35ea8dfcc2dd750e8581d3cb"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "native",
|
||||
"locator": "runtimes/win-x64/native/stellaopsnative.dll",
|
||||
"value": "runtimes/win-x64/native/stellaopsnative.dll",
|
||||
"sha256": "29cddd69702aedc715050304bec85aad2ae017ee1f9390df5e68ebe79a8d4745"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "dotnet",
|
||||
"componentKey": "purl::pkg:nuget/stellaops.toolkit@1.2.3",
|
||||
"purl": "pkg:nuget/stellaops.toolkit@1.2.3",
|
||||
"name": "StellaOps.Toolkit",
|
||||
"version": "1.2.3",
|
||||
"type": "nuget",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"assembly[0].assetPath": "lib/net10.0/StellaOps.Toolkit.dll",
|
||||
"assembly[0].fileVersion": "1.2.3.0",
|
||||
"assembly[0].path": "lib/net10.0/StellaOps.Toolkit.dll",
|
||||
"assembly[0].rid[0]": "linux-x64",
|
||||
"assembly[0].rid[1]": "win-x64",
|
||||
"assembly[0].sha256": "5b82fd11cf6c2ba6b351592587c4203f6af48b89427b954903534eac0e9f17f7",
|
||||
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"assembly[0].version": "1.2.3.0",
|
||||
"deps.path[0]": "MyApp.deps.json",
|
||||
"deps.rid[0]": "linux-x64",
|
||||
"deps.rid[1]": "win-x64",
|
||||
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"package.hashPath[0]": "stellaops.toolkit.1.2.3.nupkg.sha512",
|
||||
"package.id": "StellaOps.Toolkit",
|
||||
"package.id.normalized": "stellaops.toolkit",
|
||||
"package.path[0]": "stellaops.toolkit/1.2.3",
|
||||
"package.serviceable": "true",
|
||||
"package.sha512[0]": "sha512-FAKE_TOOLKIT_SHA==",
|
||||
"package.version": "1.2.3"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "assembly",
|
||||
"locator": "lib/net10.0/StellaOps.Toolkit.dll",
|
||||
"value": "lib/net10.0/StellaOps.Toolkit.dll",
|
||||
"sha256": "5b82fd11cf6c2ba6b351592587c4203f6af48b89427b954903534eac0e9f17f7"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "deps.json",
|
||||
"locator": "MyApp.deps.json",
|
||||
"value": "StellaOps.Toolkit/1.2.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
ELF FAKE STELLAOPS NATIVE LIB
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"runtimeTarget": {
|
||||
"name": ".NETCoreApp,Version=v10.0/linux-x64"
|
||||
},
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v10.0": {
|
||||
"Signed.App/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Logging": "9.0.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Logging/9.0.0": {
|
||||
"runtime": {
|
||||
"lib/net9.0/Microsoft.Extensions.Logging.dll": {
|
||||
"assemblyVersion": "9.0.0.0",
|
||||
"fileVersion": "9.0.24.52809"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
".NETCoreApp,Version=v10.0/linux-x64": {
|
||||
"Microsoft.Extensions.Logging/9.0.0": {
|
||||
"runtime": {
|
||||
"runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"Signed.App/1.0.0": {
|
||||
"type": "project",
|
||||
"serviceable": false
|
||||
},
|
||||
"Microsoft.Extensions.Logging/9.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-FAKE_LOGGING_SHA==",
|
||||
"path": "microsoft.extensions.logging/9.0.0",
|
||||
"hashPath": "microsoft.extensions.logging.9.0.0.nupkg.sha512"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net10.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "10.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "dotnet",
|
||||
"componentKey": "purl::pkg:nuget/microsoft.extensions.logging@9.0.0",
|
||||
"purl": "pkg:nuget/microsoft.extensions.logging@9.0.0",
|
||||
"name": "Microsoft.Extensions.Logging",
|
||||
"version": "9.0.0",
|
||||
"type": "nuget",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"assembly[0].assetPath": "lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[0].authenticode.issuer": "CN=StellaOps Root",
|
||||
"assembly[0].authenticode.notAfter": "2026-01-01T00:00:00.000Z",
|
||||
"assembly[0].authenticode.notBefore": "2025-01-01T00:00:00.000Z",
|
||||
"assembly[0].authenticode.serialNumber": "0123456789ABCDEF",
|
||||
"assembly[0].authenticode.subject": "CN=StellaOps Test Signing",
|
||||
"assembly[0].authenticode.thumbprint": "AA11BB22CC33DD44EE55FF66GG77HH88II99JJ00",
|
||||
"assembly[0].company": "Microsoft Corporation",
|
||||
"assembly[0].fileDescription": "Microsoft.Extensions.Logging",
|
||||
"assembly[0].fileVersion": "9.0.24.52809",
|
||||
"assembly[0].path": "packages/microsoft.extensions.logging/9.0.0/lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[0].product": "Microsoft\u00ae .NET",
|
||||
"assembly[0].productVersion": "9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3",
|
||||
"assembly[0].publicKeyToken": "adb9793829ddae60",
|
||||
"assembly[0].sha256": "faed6cb5c9ca0d6077feaeb2df251251adccf0241f7a80b91c58e014cd5ad48f",
|
||||
"assembly[0].strongName": "Microsoft.Extensions.Logging, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60",
|
||||
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"assembly[0].version": "9.0.0.0",
|
||||
"assembly[1].assetPath": "runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[1].rid[0]": "linux-x64",
|
||||
"assembly[1].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"deps.path[0]": "Signed.App.deps.json",
|
||||
"deps.rid[0]": "linux-x64",
|
||||
"deps.tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"package.hashPath[0]": "microsoft.extensions.logging.9.0.0.nupkg.sha512",
|
||||
"package.id": "Microsoft.Extensions.Logging",
|
||||
"package.id.normalized": "microsoft.extensions.logging",
|
||||
"package.path[0]": "microsoft.extensions.logging/9.0.0",
|
||||
"package.serviceable": "true",
|
||||
"package.sha512[0]": "sha512-FAKE_LOGGING_SHA==",
|
||||
"package.version": "9.0.0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "assembly",
|
||||
"locator": "packages/microsoft.extensions.logging/9.0.0/lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"value": "lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"sha256": "faed6cb5c9ca0d6077feaeb2df251251adccf0241f7a80b91c58e014cd5ad48f"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "deps.json",
|
||||
"locator": "Signed.App.deps.json",
|
||||
"value": "Microsoft.Extensions.Logging/9.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -8,6 +8,16 @@
|
||||
"type": "nuget",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"assembly[0].assetPath": "lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[0].fileVersion": "9.0.24.52809",
|
||||
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"assembly[0].version": "9.0.0.0",
|
||||
"assembly[1].assetPath": "runtimes/linux-x64/lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[1].rid[0]": "linux-x64",
|
||||
"assembly[1].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"assembly[2].assetPath": "runtimes/win-x86/lib/net9.0/Microsoft.Extensions.Logging.dll",
|
||||
"assembly[2].rid[0]": "win-x86",
|
||||
"assembly[2].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"deps.path[0]": "Sample.App.deps.json",
|
||||
"deps.rid[0]": "linux-x64",
|
||||
"deps.rid[1]": "win-x86",
|
||||
@@ -38,6 +48,10 @@
|
||||
"type": "nuget",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"assembly[0].assetPath": "lib/net10.0/StellaOps.Toolkit.dll",
|
||||
"assembly[0].fileVersion": "1.2.3.0",
|
||||
"assembly[0].tfm[0]": ".NETCoreApp,Version=v10.0",
|
||||
"assembly[0].version": "1.2.3.0",
|
||||
"deps.dependency[0]": "microsoft.extensions.logging",
|
||||
"deps.path[0]": "Sample.App.deps.json",
|
||||
"deps.rid[0]": "linux-x64",
|
||||
|
||||
12
src/StellaOps.Scanner.Analyzers.Lang.Tests/Fixtures/lang/rust/simple/Cargo.lock
generated
Normal file
12
src/StellaOps.Scanner.Analyzers.Lang.Tests/Fixtures/lang/rust/simple/Cargo.lock
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
[[package]]
|
||||
name = "my_app"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abc123"
|
||||
@@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "rust",
|
||||
"componentKey": "bin::sha256:22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e",
|
||||
"name": "unknown_tool",
|
||||
"type": "bin",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"binary.path": "usr/local/bin/unknown_tool",
|
||||
"binary.sha256": "22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e",
|
||||
"provenance": "binary"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "binary",
|
||||
"locator": "usr/local/bin/unknown_tool",
|
||||
"sha256": "22caa7413d89026b52db64c8abc254bf9e7647ab9216e79c6972a39451f8c41e"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "rust",
|
||||
"componentKey": "purl::pkg:cargo/my_app@0.1.0",
|
||||
"purl": "pkg:cargo/my_app@0.1.0",
|
||||
"name": "my_app",
|
||||
"version": "0.1.0",
|
||||
"type": "cargo",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"binary.paths": "usr/local/bin/my_app",
|
||||
"binary.sha256": "a95a4f4854bf973deacbd937bd1189fc3d0eef7a4fd4f7960f37cf66162c82fd",
|
||||
"cargo.lock.path": "Cargo.lock",
|
||||
"fingerprint.profile": "debug",
|
||||
"fingerprint.targetKind": "bin",
|
||||
"source": "registry\u002Bhttps://github.com/rust-lang/crates.io-index"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "binary",
|
||||
"locator": "usr/local/bin/my_app",
|
||||
"sha256": "a95a4f4854bf973deacbd937bd1189fc3d0eef7a4fd4f7960f37cf66162c82fd"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "cargo.fingerprint",
|
||||
"locator": "target/debug/.fingerprint/my_app-1234567890abcdef/bin-my_app-1234567890abcdef.json",
|
||||
"value": "bin"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "cargo.lock",
|
||||
"locator": "Cargo.lock",
|
||||
"value": "my_app 0.1.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "rust",
|
||||
"componentKey": "purl::pkg:cargo/serde@1.0.188",
|
||||
"purl": "pkg:cargo/serde@1.0.188",
|
||||
"name": "serde",
|
||||
"version": "1.0.188",
|
||||
"type": "cargo",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"cargo.lock.path": "Cargo.lock",
|
||||
"checksum": "abc123",
|
||||
"fingerprint.profile": "release",
|
||||
"fingerprint.targetKind": "lib",
|
||||
"source": "registry\u002Bhttps://github.com/rust-lang/crates.io-index"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "cargo.fingerprint",
|
||||
"locator": "target/debug/.fingerprint/serde-abcdef1234567890/libserde-abcdef1234567890.json",
|
||||
"value": "lib"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "cargo.lock",
|
||||
"locator": "Cargo.lock",
|
||||
"value": "serde 1.0.188",
|
||||
"sha256": "abc123"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"pkgid": "my_app 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"profile": "debug",
|
||||
"target_kind": ["bin"]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"pkgid": "serde 1.0.188 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"profile": "release",
|
||||
"target_kind": ["lib"]
|
||||
}
|
||||
@@ -4,23 +4,23 @@ namespace StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
|
||||
|
||||
public static class LanguageAnalyzerTestHarness
|
||||
{
|
||||
public static async Task<string> RunToJsonAsync(string fixturePath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fixturePath))
|
||||
{
|
||||
throw new ArgumentException("Fixture path is required", nameof(fixturePath));
|
||||
}
|
||||
|
||||
var engine = new LanguageAnalyzerEngine(analyzers ?? Array.Empty<ILanguageAnalyzer>());
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System, usageHints);
|
||||
var result = await engine.AnalyzeAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
return result.ToJson(indent: true);
|
||||
}
|
||||
|
||||
public static async Task AssertDeterministicAsync(string fixturePath, string goldenPath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null)
|
||||
{
|
||||
var actual = await RunToJsonAsync(fixturePath, analyzers, cancellationToken, usageHints).ConfigureAwait(false);
|
||||
var expected = await File.ReadAllTextAsync(goldenPath, cancellationToken).ConfigureAwait(false);
|
||||
public static async Task<string> RunToJsonAsync(string fixturePath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null, IServiceProvider? services = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fixturePath))
|
||||
{
|
||||
throw new ArgumentException("Fixture path is required", nameof(fixturePath));
|
||||
}
|
||||
|
||||
var engine = new LanguageAnalyzerEngine(analyzers ?? Array.Empty<ILanguageAnalyzer>());
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System, usageHints, services);
|
||||
var result = await engine.AnalyzeAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
return result.ToJson(indent: true);
|
||||
}
|
||||
|
||||
public static async Task AssertDeterministicAsync(string fixturePath, string goldenPath, IEnumerable<ILanguageAnalyzer> analyzers, CancellationToken cancellationToken = default, LanguageUsageHints? usageHints = null, IServiceProvider? services = null)
|
||||
{
|
||||
var actual = await RunToJsonAsync(fixturePath, analyzers, cancellationToken, usageHints, services).ConfigureAwait(false);
|
||||
var expected = await File.ReadAllTextAsync(goldenPath, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Normalize newlines for portability.
|
||||
actual = NormalizeLineEndings(actual).TrimEnd();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.IO;
|
||||
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 RustLanguageAnalyzerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task SimpleFixtureProducesDeterministicOutputAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "rust", "simple");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var usageHints = new LanguageUsageHints(new[]
|
||||
{
|
||||
Path.Combine(fixturePath, "usr/local/bin/my_app")
|
||||
});
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new RustLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
usageHints);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang\StellaOps.Scanner.Analyzers.Lang.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang.DotNet\StellaOps.Scanner.Analyzers.Lang.DotNet.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Analyzers.Lang.Rust\StellaOps.Scanner.Analyzers.Lang.Rust.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Core\StellaOps.Scanner.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user