feat(scanner): Implement Deno analyzer and associated tests
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Added Deno analyzer with comprehensive metadata and evidence structure. - Created a detailed implementation plan for Sprint 130 focusing on Deno analyzer. - Introduced AdvisoryAiGuardrailOptions for managing guardrail configurations. - Developed GuardrailPhraseLoader for loading blocked phrases from JSON files. - Implemented tests for AdvisoryGuardrailOptions binding and phrase loading. - Enhanced telemetry for Advisory AI with metrics tracking. - Added VexObservationProjectionService for querying VEX observations. - Created extensive tests for VexObservationProjectionService functionality. - Introduced Ruby language analyzer with tests for simple and complex workspaces. - Added Ruby application fixtures for testing purposes.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using System.Text.Json;
|
||||
using StellaOps.Scanner.Analyzers.Lang;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Ruby;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.Harness;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
||||
using StellaOps.Scanner.Core.Contracts;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Ruby.Tests;
|
||||
|
||||
public sealed class RubyLanguageAnalyzerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task SimpleWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "simple-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AnalyzerEmitsObservationPayloadWithSummaryAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "simple-app");
|
||||
var store = new ScanAnalysisStore();
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
var context = new LanguageAnalyzerContext(
|
||||
fixturePath,
|
||||
TimeProvider.System,
|
||||
usageHints: null,
|
||||
services: null,
|
||||
analysisStore: store);
|
||||
|
||||
var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken);
|
||||
var snapshots = result.ToSnapshots();
|
||||
|
||||
var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation");
|
||||
Assert.Equal("Ruby Observation Summary", summary.Name);
|
||||
Assert.Equal("observation::ruby", summary.ComponentKey);
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.packages", out var packageCount));
|
||||
Assert.Equal("11", packageCount);
|
||||
Assert.Equal("3", summary.Metadata["ruby.observation.runtime_edges"]);
|
||||
Assert.Equal("true", summary.Metadata["ruby.observation.capability.exec"]);
|
||||
Assert.Equal("true", summary.Metadata["ruby.observation.capability.net"]);
|
||||
Assert.Equal("true", summary.Metadata["ruby.observation.capability.serialization"]);
|
||||
Assert.Equal("2.4.22", summary.Metadata["ruby.observation.bundler_version"]);
|
||||
|
||||
Assert.True(store.TryGet(ScanAnalysisKeys.RubyObservationPayload, out AnalyzerObservationPayload payload));
|
||||
Assert.Equal("ruby", payload.AnalyzerId);
|
||||
Assert.Equal("ruby.observation", payload.Kind);
|
||||
Assert.Equal("application/json", payload.MediaType);
|
||||
Assert.NotNull(payload.Metadata);
|
||||
Assert.Equal("11", payload.Metadata!["ruby.observation.packages"]);
|
||||
|
||||
using var document = JsonDocument.Parse(payload.Content.ToArray());
|
||||
var root = document.RootElement;
|
||||
var packages = root.GetProperty("packages");
|
||||
Assert.Equal(11, packages.GetArrayLength());
|
||||
|
||||
var runtimeEdges = root.GetProperty("runtimeEdges");
|
||||
Assert.True(runtimeEdges.GetArrayLength() >= 1);
|
||||
|
||||
var capabilities = root.GetProperty("capabilities");
|
||||
Assert.True(capabilities.GetProperty("usesExec").GetBoolean());
|
||||
Assert.True(capabilities.GetProperty("usesNetwork").GetBoolean());
|
||||
Assert.True(capabilities.GetProperty("usesSerialization").GetBoolean());
|
||||
Assert.Equal("2.4.22", root.GetProperty("bundledWith").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ComplexWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "complex-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user