up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (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
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (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
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
This commit is contained in:
@@ -579,4 +579,213 @@ public sealed class PythonLanguageAnalyzerTests
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
// ===== SCAN-PY-405-007 Fixtures =====
|
||||
|
||||
[Fact]
|
||||
public async Task RequirementsWithIncludesAreFollowedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
// Create main requirements.txt that includes another file
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath, $"requests==2.28.0{Environment.NewLine}-r requirements-base.txt{Environment.NewLine}", cancellationToken);
|
||||
|
||||
// Create included requirements file
|
||||
var baseRequirementsPath = Path.Combine(fixturePath, "requirements-base.txt");
|
||||
await File.WriteAllTextAsync(baseRequirementsPath, $"urllib3==1.26.0{Environment.NewLine}certifi==2022.12.7{Environment.NewLine}", cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
// All three packages should be found (from both files)
|
||||
Assert.True(ComponentHasMetadata(root, "requests", "declaredOnly", "true"));
|
||||
Assert.True(ComponentHasMetadata(root, "urllib3", "declaredOnly", "true"));
|
||||
Assert.True(ComponentHasMetadata(root, "certifi", "declaredOnly", "true"));
|
||||
|
||||
// urllib3 and certifi should come from the included file
|
||||
Assert.True(ComponentHasMetadata(root, "urllib3", "lockSource", "requirements-base.txt"));
|
||||
Assert.True(ComponentHasMetadata(root, "certifi", "lockSource", "requirements-base.txt"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PipfileLockDevelopSectionIsParsedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
// Create Pipfile.lock with default and develop sections
|
||||
var pipfileLockPath = Path.Combine(fixturePath, "Pipfile.lock");
|
||||
var pipfileLock = """
|
||||
{
|
||||
"_meta": { "sources": [] },
|
||||
"default": {
|
||||
"requests": { "version": "==2.28.0" }
|
||||
},
|
||||
"develop": {
|
||||
"pytest": { "version": "==7.0.0" }
|
||||
}
|
||||
}
|
||||
""";
|
||||
await File.WriteAllTextAsync(pipfileLockPath, pipfileLock, cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
// Both packages should be found
|
||||
Assert.True(ComponentHasMetadata(root, "requests", "declaredOnly", "true"));
|
||||
Assert.True(ComponentHasMetadata(root, "pytest", "declaredOnly", "true"));
|
||||
|
||||
// requests should be prod scope, pytest should be dev scope
|
||||
Assert.True(ComponentHasMetadata(root, "requests", "scope", "prod"));
|
||||
Assert.True(ComponentHasMetadata(root, "pytest", "scope", "dev"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequirementsDevTxtGetsScopeDevAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
// Create requirements.txt for prod
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath, $"flask==2.0.0{Environment.NewLine}", cancellationToken);
|
||||
|
||||
// Create requirements-dev.txt for dev dependencies
|
||||
var requirementsDevPath = Path.Combine(fixturePath, "requirements-dev.txt");
|
||||
await File.WriteAllTextAsync(requirementsDevPath, $"pytest==7.0.0{Environment.NewLine}", cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
// flask should be prod scope (from requirements.txt)
|
||||
Assert.True(ComponentHasMetadata(root, "flask", "scope", "prod"));
|
||||
|
||||
// pytest should be dev scope (from requirements-dev.txt)
|
||||
Assert.True(ComponentHasMetadata(root, "pytest", "scope", "dev"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Pep508DirectReferenceIsParsedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
// Create requirements.txt with direct reference
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath,
|
||||
$"mypackage @ https://example.com/packages/mypackage-1.0.0.whl{Environment.NewLine}",
|
||||
cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
// Package should be found with URL reference
|
||||
Assert.True(ComponentHasMetadata(root, "mypackage", "declaredOnly", "true"));
|
||||
Assert.True(ComponentHasMetadata(root, "mypackage", "lockDirectUrl", "https://example.com/packages/mypackage-1.0.0.whl"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RequirementsCycleIsDetectedAndHandledAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
// Create requirements.txt that includes base
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath, $"requests==2.28.0{Environment.NewLine}-r requirements-base.txt{Environment.NewLine}", cancellationToken);
|
||||
|
||||
// Create requirements-base.txt that includes back to main (cycle)
|
||||
var baseRequirementsPath = Path.Combine(fixturePath, "requirements-base.txt");
|
||||
await File.WriteAllTextAsync(baseRequirementsPath, $"urllib3==1.26.0{Environment.NewLine}-r requirements.txt{Environment.NewLine}", cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
// Should not throw due to infinite loop
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
// Both packages should still be found (cycle handled gracefully)
|
||||
Assert.True(ComponentHasMetadata(root, "requests", "declaredOnly", "true"));
|
||||
Assert.True(ComponentHasMetadata(root, "urllib3", "declaredOnly", "true"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user