nuget reorganization
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Deno.Internal.Runtime;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Deno.Tests.Deno;
|
||||
|
||||
public sealed class DenoRuntimeShimTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task WritesShimToDirectory()
|
||||
{
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
try
|
||||
{
|
||||
var path = await DenoRuntimeShim.WriteAsync(root, TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(File.Exists(path));
|
||||
var content = await File.ReadAllTextAsync(path, TestContext.Current.CancellationToken);
|
||||
Assert.Contains("deno-runtime.ndjson", content);
|
||||
Assert.Contains("deno.module.load", content);
|
||||
Assert.Contains("deno.permission.use", content);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Text;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Deno.Internal.Runtime;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Deno.Tests.Deno;
|
||||
|
||||
public sealed class DenoRuntimeTraceProbeTests
|
||||
{
|
||||
[Fact]
|
||||
public void ComputesMetadataAndHashFromNdjson()
|
||||
{
|
||||
const string ndjson =
|
||||
@"{\""type\"":\"\"deno.module.load\"",\""ts\"":\"\"2025-11-17T12:00:00Z\"",\""reason\"":\"\"dynamic-import\"",\""permissions\"":[\"\"fs\""],\""origin\"":\"\"https://deno.land\""}
|
||||
{\""type\"":\"\"deno.permission.use\"",\""ts\"":\"\"2025-11-17T12:00:01Z\"",\""permission\"":\"\"NET\""}
|
||||
{\""type\"":\"\"deno.npm.resolution\"",\""ts\"":\"\"2025-11-17T12:00:02Z\""}
|
||||
{\""type\"":\"\"deno.wasm.load\"",\""ts\"":\"\"2025-11-17T12:00:03Z\""}
|
||||
";
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(ndjson);
|
||||
var (metadata, hash) = DenoRuntimeTraceProbe.Analyze(bytes);
|
||||
|
||||
Assert.Equal(4, metadata.EventCount);
|
||||
Assert.Equal(1, metadata.ModuleLoads);
|
||||
Assert.Equal(1, metadata.PermissionUses);
|
||||
Assert.Equal(1, metadata.NpmResolutions);
|
||||
Assert.Equal(1, metadata.WasmLoads);
|
||||
Assert.Equal(1, metadata.DynamicImports);
|
||||
Assert.Equal(new[] { "https://deno.land" }, metadata.RemoteOrigins);
|
||||
Assert.Equal(new[] { "fs", "net" }, metadata.UniquePermissions);
|
||||
|
||||
Assert.Equal("8f67e4b77f2ea4155d9101c5e6a45922e4ac1e19006955c3e6c2afe1938f0a8d", hash);
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,13 @@ public sealed class JavaLanguageAnalyzerTests
|
||||
Assert.Equal("demo-framework.jar!META-INF/services/jakarta.ws.rs.ext.RuntimeDelegate", metadata.GetProperty("config.jaxrs").GetString());
|
||||
Assert.Equal("demo-framework.jar!logback.xml", metadata.GetProperty("config.logging").GetString());
|
||||
Assert.Equal("demo-framework.jar!META-INF/native-image/demo/reflect-config.json", metadata.GetProperty("config.graal").GetString());
|
||||
|
||||
var evidence = component.GetProperty("evidence").EnumerateArray().ToArray();
|
||||
Assert.Contains(evidence, e =>
|
||||
string.Equals(e.GetProperty("source").GetString(), "framework-config", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(e.GetProperty("locator").GetString(), "demo-framework.jar!META-INF/spring.factories", StringComparison.OrdinalIgnoreCase) &&
|
||||
e.TryGetProperty("sha256", out var sha) &&
|
||||
!string.IsNullOrWhiteSpace(sha.GetString()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/yarn-pnp-demo@1.0.0",
|
||||
"purl": "pkg:npm/yarn-pnp-demo@1.0.0",
|
||||
"name": "yarn-pnp-demo",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"path": ".",
|
||||
"yarnPnp": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "yarn-pnp-demo",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -62,4 +62,42 @@ public sealed class NodeLanguageAnalyzerTests
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task YarnPnpCachePackagesAreParsedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "yarn-pnp");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new NodeLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task YarnPnpFlagIsEmittedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "yarn-pnp");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new NodeLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,70 @@ public sealed class SurfaceEnvironmentBuilderTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Throws_WhenEndpointMissing_AndRequired()
|
||||
{
|
||||
var services = CreateServices();
|
||||
var exception = Assert.Throws<SurfaceEnvironmentException>(() =>
|
||||
SurfaceEnvironmentFactory.Create(services, options => options.RequireSurfaceEndpoint = true));
|
||||
|
||||
Assert.Equal("SURFACE_FS_ENDPOINT", exception.Variable);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Throws_WhenEndpointInvalid()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", "not-a-uri");
|
||||
try
|
||||
{
|
||||
var services = CreateServices();
|
||||
var ex = Assert.Throws<SurfaceEnvironmentException>(() => SurfaceEnvironmentFactory.Create(services));
|
||||
Assert.Equal("SURFACE_FS_ENDPOINT", ex.Variable);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", null);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_Throws_WhenTlsCertificateMissing()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", "https://surface.example.test");
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_TLS_CERT_PATH", "/does/not/exist.pem");
|
||||
try
|
||||
{
|
||||
var services = CreateServices();
|
||||
var ex = Assert.Throws<SurfaceEnvironmentException>(() => SurfaceEnvironmentFactory.Create(services));
|
||||
Assert.Equal("SURFACE_TLS_CERT_PATH", ex.Variable);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_TLS_CERT_PATH", null);
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", null);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Build_UsesTenantResolver_WhenNotProvided()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", "https://surface.example.test");
|
||||
try
|
||||
{
|
||||
var services = CreateServices();
|
||||
var environment = SurfaceEnvironmentFactory.Create(services, options =>
|
||||
{
|
||||
options.TenantResolver = _ => "resolved-tenant";
|
||||
});
|
||||
|
||||
Assert.Equal("resolved-tenant", environment.Settings.Tenant);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable("SCANNER_SURFACE_FS_ENDPOINT", null);
|
||||
}
|
||||
}
|
||||
|
||||
private static IServiceProvider CreateServices(Action<IServiceCollection>? configure = null)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.FS;
|
||||
using StellaOps.Scanner.WebService.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.WebService.Tests;
|
||||
|
||||
public sealed class SurfaceManifestStoreOptionsConfiguratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Configure_UsesSurfaceEnvironmentAndCacheRoot()
|
||||
{
|
||||
var cacheRoot = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")));
|
||||
var settings = new SurfaceEnvironmentSettings(
|
||||
new Uri("https://surface.example"),
|
||||
"surface-bucket",
|
||||
null,
|
||||
cacheRoot,
|
||||
1024,
|
||||
false,
|
||||
Array.Empty<string>(),
|
||||
new SurfaceSecretsConfiguration("file", "tenant-a", "/etc/secrets", null, null, false),
|
||||
"tenant-a",
|
||||
new SurfaceTlsConfiguration(null, null, new X509Certificate2Collection()));
|
||||
|
||||
var environment = new StubSurfaceEnvironment(settings);
|
||||
var cacheOptions = Options.Create(new SurfaceCacheOptions { RootDirectory = cacheRoot.FullName });
|
||||
var configurator = new SurfaceManifestStoreOptionsConfigurator(environment, cacheOptions);
|
||||
var options = new SurfaceManifestStoreOptions();
|
||||
|
||||
configurator.Configure(options);
|
||||
|
||||
Assert.Equal("https", options.Scheme);
|
||||
Assert.Equal("surface-bucket", options.Bucket);
|
||||
Assert.Equal(Path.Combine(cacheRoot.FullName, "manifests"), options.RootDirectory);
|
||||
}
|
||||
|
||||
private sealed class StubSurfaceEnvironment : ISurfaceEnvironment
|
||||
{
|
||||
public StubSurfaceEnvironment(SurfaceEnvironmentSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public SurfaceEnvironmentSettings Settings { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, string> RawVariables { get; } = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Scanner.Surface.Env;
|
||||
using StellaOps.Scanner.Surface.FS;
|
||||
using StellaOps.Scanner.Worker;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Scanner.Worker.Tests;
|
||||
|
||||
public sealed class SurfaceManifestStoreOptionsConfiguratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Configure_UsesSurfaceEnvironmentEndpointAndBucket()
|
||||
{
|
||||
var cacheRoot = new DirectoryInfo(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")));
|
||||
var settings = new SurfaceEnvironmentSettings(
|
||||
new Uri("https://surface.example"),
|
||||
"surface-bucket",
|
||||
null,
|
||||
cacheRoot,
|
||||
1024,
|
||||
false,
|
||||
Array.Empty<string>(),
|
||||
new SurfaceSecretsConfiguration("file", "tenant-a", "/etc/secrets", null, null, false),
|
||||
"tenant-a",
|
||||
new SurfaceTlsConfiguration(null, null, new X509Certificate2Collection()));
|
||||
|
||||
var environment = new StubSurfaceEnvironment(settings);
|
||||
var cacheOptions = Options.Create(new SurfaceCacheOptions { RootDirectory = cacheRoot.FullName });
|
||||
var configurator = new SurfaceManifestStoreOptionsConfigurator(environment, cacheOptions);
|
||||
var options = new SurfaceManifestStoreOptions();
|
||||
|
||||
configurator.Configure(options);
|
||||
|
||||
Assert.Equal("https", options.Scheme);
|
||||
Assert.Equal("surface-bucket", options.Bucket);
|
||||
Assert.Equal(Path.Combine(cacheRoot.FullName, "manifests"), options.RootDirectory);
|
||||
}
|
||||
|
||||
private sealed class StubSurfaceEnvironment : ISurfaceEnvironment
|
||||
{
|
||||
public StubSurfaceEnvironment(SurfaceEnvironmentSettings settings)
|
||||
{
|
||||
Settings = settings;
|
||||
}
|
||||
|
||||
public SurfaceEnvironmentSettings Settings { get; }
|
||||
|
||||
public IReadOnlyDictionary<string, string> RawVariables { get; } = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user