Restructure solution layout by module
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using StellaOps.Scanner.Analyzers.OS;
|
||||
using StellaOps.Scanner.Analyzers.OS.Apk;
|
||||
using StellaOps.Scanner.Analyzers.OS.Dpkg;
|
||||
using StellaOps.Scanner.Analyzers.OS.Rpm;
|
||||
using StellaOps.Scanner.Analyzers.OS.Rpm.Internal;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
using StellaOps.Scanner.Analyzers.OS.Tests.TestUtilities;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.OS.Tests;
|
||||
|
||||
public sealed class OsAnalyzerDeterminismTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ApkAnalyzerMatchesGolden()
|
||||
{
|
||||
using var fixture = FixtureManager.UseFixture("apk", out var rootPath);
|
||||
var analyzer = new ApkPackageAnalyzer(NullLogger<ApkPackageAnalyzer>.Instance);
|
||||
var context = CreateContext(rootPath);
|
||||
|
||||
var result = await analyzer.AnalyzeAsync(context, CancellationToken.None);
|
||||
var snapshot = SnapshotSerializer.Serialize(new[] { result });
|
||||
GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("apk.json"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DpkgAnalyzerMatchesGolden()
|
||||
{
|
||||
using var fixture = FixtureManager.UseFixture("dpkg", out var rootPath);
|
||||
var analyzer = new DpkgPackageAnalyzer(NullLogger<DpkgPackageAnalyzer>.Instance);
|
||||
var context = CreateContext(rootPath);
|
||||
|
||||
var result = await analyzer.AnalyzeAsync(context, CancellationToken.None);
|
||||
var snapshot = SnapshotSerializer.Serialize(new[] { result });
|
||||
GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("dpkg.json"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RpmAnalyzerMatchesGolden()
|
||||
{
|
||||
var headers = new[]
|
||||
{
|
||||
CreateRpmHeader(
|
||||
name: "openssl-libs",
|
||||
version: "3.2.1",
|
||||
architecture: "x86_64",
|
||||
release: "8.el9",
|
||||
epoch: "1",
|
||||
license: "OpenSSL",
|
||||
sourceRpm: "openssl-3.2.1-8.el9.src.rpm",
|
||||
provides: new[] { "libcrypto.so.3()(64bit)", "openssl-libs" },
|
||||
requires: new[] { "glibc(x86-64) >= 2.34" },
|
||||
files: new[]
|
||||
{
|
||||
new RpmFileEntry("/usr/lib64/libcrypto.so.3", false, new Dictionary<string, string> { ["sha256"] = "abc123" }),
|
||||
new RpmFileEntry("/etc/pki/tls/openssl.cnf", true, new Dictionary<string, string> { ["md5"] = "c0ffee" })
|
||||
},
|
||||
changeLogs: new[] { "Resolves: CVE-2025-1234" },
|
||||
metadata: new Dictionary<string, string?> { ["summary"] = "TLS toolkit" })
|
||||
};
|
||||
|
||||
var reader = new StubRpmDatabaseReader(headers);
|
||||
var analyzer = new RpmPackageAnalyzer(
|
||||
NullLogger<RpmPackageAnalyzer>.Instance,
|
||||
reader);
|
||||
|
||||
var context = CreateContext("/tmp/nonexistent");
|
||||
var result = await analyzer.AnalyzeAsync(context, CancellationToken.None);
|
||||
var snapshot = SnapshotSerializer.Serialize(new[] { result });
|
||||
GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("rpm.json"));
|
||||
}
|
||||
|
||||
private static OSPackageAnalyzerContext CreateContext(string rootPath)
|
||||
{
|
||||
var metadata = new Dictionary<string, string>
|
||||
{
|
||||
[ScanMetadataKeys.RootFilesystemPath] = rootPath
|
||||
};
|
||||
|
||||
return new OSPackageAnalyzerContext(rootPath, workspacePath: null, TimeProvider.System, NullLoggerFactory.Instance.CreateLogger("os-analyzer-tests"), metadata);
|
||||
}
|
||||
|
||||
private static RpmHeader CreateRpmHeader(
|
||||
string name,
|
||||
string version,
|
||||
string architecture,
|
||||
string? release,
|
||||
string? epoch,
|
||||
string? license,
|
||||
string? sourceRpm,
|
||||
IReadOnlyList<string> provides,
|
||||
IReadOnlyList<string> requires,
|
||||
IReadOnlyList<RpmFileEntry> files,
|
||||
IReadOnlyList<string> changeLogs,
|
||||
IReadOnlyDictionary<string, string?> metadata)
|
||||
{
|
||||
return new RpmHeader(
|
||||
name,
|
||||
version,
|
||||
architecture,
|
||||
release,
|
||||
epoch,
|
||||
metadata.TryGetValue("summary", out var summary) ? summary : null,
|
||||
metadata.TryGetValue("description", out var description) ? description : null,
|
||||
license,
|
||||
sourceRpm,
|
||||
metadata.TryGetValue("url", out var url) ? url : null,
|
||||
metadata.TryGetValue("vendor", out var vendor) ? vendor : null,
|
||||
buildTime: null,
|
||||
installTime: null,
|
||||
provides,
|
||||
provideVersions: provides.Select(_ => string.Empty).ToArray(),
|
||||
requires,
|
||||
requireVersions: requires.Select(_ => string.Empty).ToArray(),
|
||||
files,
|
||||
changeLogs,
|
||||
metadata);
|
||||
}
|
||||
|
||||
private sealed class StubRpmDatabaseReader : IRpmDatabaseReader
|
||||
{
|
||||
private readonly IReadOnlyList<RpmHeader> _headers;
|
||||
|
||||
public StubRpmDatabaseReader(IReadOnlyList<RpmHeader> headers)
|
||||
{
|
||||
_headers = headers;
|
||||
}
|
||||
|
||||
public IReadOnlyList<RpmHeader> ReadHeaders(string rootPath, CancellationToken cancellationToken)
|
||||
=> _headers;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user