Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (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
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
136 lines
6.2 KiB
C#
136 lines
6.2 KiB
C#
using System.IO.Compression;
|
|
using System.Threading;
|
|
using StellaOps.Scanner.Analyzers.Lang.Java.Internal;
|
|
using StellaOps.Scanner.Analyzers.Lang.Java.Internal.ClassPath;
|
|
using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Reflection;
|
|
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
|
|
|
namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests;
|
|
|
|
public sealed class JavaReflectionAnalyzerTests
|
|
{
|
|
[Fact]
|
|
public void Analyze_ClassForNameLiteral_ProducesEdge()
|
|
{
|
|
var root = TestPaths.CreateTemporaryDirectory();
|
|
try
|
|
{
|
|
var jarPath = Path.Combine(root, "libs", "reflect.jar");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
|
using (var archive = new ZipArchive(new FileStream(jarPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None), ZipArchiveMode.Create, leaveOpen: false))
|
|
{
|
|
var entry = archive.CreateEntry("com/example/Reflective.class");
|
|
var bytes = JavaClassFileFactory.CreateClassForNameInvoker("com/example/Reflective", "com.example.Plugin");
|
|
using var stream = entry.Open();
|
|
stream.Write(bytes);
|
|
}
|
|
|
|
var cancellationToken = TestContext.Current.CancellationToken;
|
|
var context = new LanguageAnalyzerContext(root, TimeProvider.System);
|
|
var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken);
|
|
var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken);
|
|
var analysis = JavaReflectionAnalyzer.Analyze(classPath, cancellationToken);
|
|
|
|
var edge = Assert.Single(analysis.Edges);
|
|
Assert.Equal("com.example.Reflective", edge.SourceClass);
|
|
Assert.Equal("com.example.Plugin", edge.TargetType);
|
|
Assert.Equal(JavaReflectionReason.ClassForName, edge.Reason);
|
|
Assert.Equal(JavaReflectionConfidence.High, edge.Confidence);
|
|
}
|
|
finally
|
|
{
|
|
TestPaths.SafeDelete(root);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Analyze_TcclUsage_ProducesWarning()
|
|
{
|
|
var root = TestPaths.CreateTemporaryDirectory();
|
|
try
|
|
{
|
|
var jarPath = Path.Combine(root, "libs", "tccl.jar");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
|
using (var archive = new ZipArchive(new FileStream(jarPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None), ZipArchiveMode.Create, leaveOpen: false))
|
|
{
|
|
var entry = archive.CreateEntry("com/example/Tccl.class");
|
|
var bytes = JavaClassFileFactory.CreateTcclChecker("com/example/Tccl");
|
|
using var stream = entry.Open();
|
|
stream.Write(bytes);
|
|
}
|
|
|
|
var cancellationToken = TestContext.Current.CancellationToken;
|
|
var context = new LanguageAnalyzerContext(root, TimeProvider.System);
|
|
var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken);
|
|
var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken);
|
|
var analysis = JavaReflectionAnalyzer.Analyze(classPath, cancellationToken);
|
|
|
|
Assert.Empty(analysis.Edges);
|
|
var warning = Assert.Single(analysis.Warnings);
|
|
Assert.Equal("tccl", warning.WarningCode);
|
|
Assert.Equal("com.example.Tccl", warning.SourceClass);
|
|
}
|
|
finally
|
|
{
|
|
TestPaths.SafeDelete(root);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Analyze_SpringBootFatJar_ScansEmbeddedAndBootSegments()
|
|
{
|
|
var root = TestPaths.CreateTemporaryDirectory();
|
|
try
|
|
{
|
|
JavaFixtureBuilder.CreateSpringBootFatJar(root, "apps/app-fat.jar");
|
|
|
|
var cancellationToken = TestContext.Current.CancellationToken;
|
|
var context = new LanguageAnalyzerContext(root, TimeProvider.System);
|
|
var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken);
|
|
var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken);
|
|
var analysis = JavaReflectionAnalyzer.Analyze(classPath, cancellationToken);
|
|
|
|
// Expect at least one edge originating from BOOT-INF classes
|
|
Assert.Contains(analysis.Edges, edge => edge.SourceClass == "com.example.App" && edge.Reason == JavaReflectionReason.ClassForName);
|
|
Assert.Contains(analysis.Edges, edge => edge.SourceClass == "com.example.Lib" && edge.Reason == JavaReflectionReason.ClassForName);
|
|
}
|
|
finally
|
|
{
|
|
TestPaths.SafeDelete(root);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Analyze_ClassResourceLookup_ProducesResourceEdge()
|
|
{
|
|
var root = TestPaths.CreateTemporaryDirectory();
|
|
try
|
|
{
|
|
var jarPath = Path.Combine(root, "libs", "resources.jar");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
|
using (var archive = new ZipArchive(new FileStream(jarPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None), ZipArchiveMode.Create, leaveOpen: false))
|
|
{
|
|
var entry = archive.CreateEntry("com/example/Resources.class");
|
|
var bytes = JavaClassFileFactory.CreateClassResourceLookup("com/example/Resources", "/META-INF/plugin.properties");
|
|
using var stream = entry.Open();
|
|
stream.Write(bytes);
|
|
}
|
|
|
|
var cancellationToken = TestContext.Current.CancellationToken;
|
|
var context = new LanguageAnalyzerContext(root, TimeProvider.System);
|
|
var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken);
|
|
var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken);
|
|
var analysis = JavaReflectionAnalyzer.Analyze(classPath, cancellationToken);
|
|
|
|
var edge = Assert.Single(analysis.Edges.Where(edge => edge.Reason == JavaReflectionReason.ResourceLookup));
|
|
Assert.Equal("com.example.Resources", edge.SourceClass);
|
|
Assert.Equal("/META-INF/plugin.properties", edge.TargetType);
|
|
Assert.Equal(JavaReflectionConfidence.High, edge.Confidence);
|
|
}
|
|
finally
|
|
{
|
|
TestPaths.SafeDelete(root);
|
|
}
|
|
}
|
|
}
|