Skip to content

test: unified converter tests#1085

Open
rrama wants to merge 21 commits into
mainfrom
test/unified-converter-test
Open

test: unified converter tests#1085
rrama wants to merge 21 commits into
mainfrom
test/unified-converter-test

Conversation

@rrama

@rrama rrama commented Dec 10, 2025

Copy link
Copy Markdown
Contributor

Description

AI took the tests from #1042 and updated them to work with #1054 which went into main. It took 2 days of the AI spinning in the background, I then took what it did and made the tests proper.
There is also a fix to ensure we don't panic if we receive malformed data with a shorter than expected dependency path.

Checklist

  • Tests added and all succeed
  • Regenerated mocks, etc. (make generate)
  • N/A
  • Linted (make lint-fix)
  • README.md updated, if user-facing
  • N/A
  • License file updated, if new 3rd-party dependency is introduced
  • N/A

And a cheeky fix to ensure we don't panic if we recieve malformed data with a shorter than expected dependency path.
@snyk-io

snyk-io Bot commented Dec 10, 2025

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @rrama, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on enhancing the robustness and test coverage of the unified converter logic. It introduces a new, extensive suite of AI-generated unit tests that validate the converter's functionality for building upgrade paths, generating remediation advice, and handling various dependency-related scenarios. Additionally, a critical defensive fix has been implemented to prevent application panics when encountering malformed dependency path data, ensuring more graceful error handling.

Highlights

  • New Test Suite: A comprehensive suite of unit tests has been added for the unified_converter.go file, significantly expanding test coverage for various scenarios.
  • Defensive Bug Fix: A fix was implemented in extractUpgradePackage to prevent a panic when processing malformed dependency path data that has fewer than two elements.
  • Extensive Test Coverage: The new tests cover critical functions like buildUpgradePath, buildRemediationAdvice, extractDependencyPath, buildMessage, getIntroducingFinding, extractUpgradePackage, and processIssue, including edge cases and dependency injection scenarios.
  • AI-Generated Tests: The majority of the new tests were generated by AI, building upon previous work and introducing a large number of new test cases.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces a crucial fix in unified_converter.go to prevent panics when handling malformed dependency paths, significantly improving the robustness of the converter. Additionally, a comprehensive suite of unit tests has been added in unified_converter_test.go, which is excellent for validating the conversion logic and covering various edge cases. However, the new tests also highlight some existing "FIXME"s and logical "quirks" within the production code, particularly concerning the extractDependencyPath function's behavior and the IsUpgradable flag. Addressing these identified areas in future work would further enhance the accuracy and reliability of the unified converter.

}

if len(dependencyPath) == 0 {
if len(dependencyPath) < 2 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The change from len(dependencyPath) == 0 to len(dependencyPath) < 2 is a critical improvement. Accessing dependencyPath[1] when the slice has fewer than two elements would lead to a runtime panic. This fix correctly handles cases where the dependency path is empty or contains only a single element, preventing potential crashes.

Comment on lines +284 to +287
name: "Wrong behavior: multiple dependency paths - returns first one only (FIXME in prod code)",
// TODO: Delete this test and enable the test above when the fix has been implemented in the prod code.
finding: createFindingWithMultipleDependencyPaths(t, "goof@1.0.0", []string{"lodash@4.17.20"}, []string{"other-pkg@1.0.0"}),
expected: []string{"goof@1.0.0", "lodash@4.17.20"},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This test case correctly identifies a "Wrong behavior" in the extractDependencyPath function, which currently only returns the first dependency path found, rather than all of them. The FIXME comment in the production code (unified_converter.go, line 333) also points to this. This limitation means that if a vulnerability is introduced through multiple dependency paths, the system might not fully represent all relevant information. It's important to address this in the extractDependencyPath function to ensure comprehensive vulnerability reporting.

Comment on lines +1153 to +1155
// Note: IsUpgradable is based on len(upgradePath) > 0, so [false] makes it true
// This is a quirk of the current implementation - might want to change to len(upgradePath) > 1
assert.True(t, additionalData.IsUpgradable, "Current behavior: marked as upgradable when upgradePath=[false]")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment highlights a logical inconsistency where IsUpgradable is determined by len(upgradePath) > 0. If upgradePath contains only [false], it implies no actual upgrade is available, yet len(upgradePath) would be 1, making IsUpgradable true. This could lead to misleading information being presented to the user. Consider adjusting the logic to len(upgradePath) > 1 to accurately reflect when a true upgrade path exists.

@rrama rrama requested a review from acke December 18, 2025 11:02
rrama added 11 commits January 28, 2026 18:03
Plus reduce `createFindingWithFixRelationship` and `createFindingWithMultipleUpgradePaths` into one function.
Update an incorrect comment about issues with fixed versions but without update paths in the code.
Remove the edge cases that were there just for the sake of padding out the tests.
Remove the duplicate truncation checking test.
Also removed the test which lied in the name about testing a finding with no evidence.
Added a skipped test for when the prod code is updated to return multiple findings.
Ensure clarity on scenarios and ensure we cover all expected scenarios.
These tests can not be enabled until the prod code is fixed.
@rrama rrama marked this pull request as ready for review March 9, 2026 17:22
@rrama rrama requested review from a team as code owners March 9, 2026 17:22
@snyk-pr-review-bot

This comment has been minimized.

@rrama

rrama commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

No stale, just de-prioritised and no one has touched the code since for me to push it onto them.

@snyk-pr-review-bot

This comment has been minimized.

@snyk-pr-review-bot

This comment has been minimized.

@snyk-pr-review-bot

Copy link
Copy Markdown

PR Reviewer Guide 🔍

🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Defensive Fix 🟡 [minor]

The update to the length check in extractUpgradePackage correctly prevents a panic when dependencyPath has exactly one element. The previous check only guarded against empty slices, while the subsequent code accessed dependencyPath[1]. The new check for len(dependencyPath) < 2 safely handles single-node paths which might occur with malformed upstream data.

if len(dependencyPath) < 2 {
	return nil
}


// Create deps with WRONG types (strings instead of proper types)
deps := map[string]any{
ctx2.DepConfig: "not-a-config", // Should be *config.Config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Critical] This test file does not compile against main — it was written against an older API and not recompiled after merge. go vet ./infrastructure/oss/ fails, and because Go builds one test binary per package, this breaks the entire infrastructure/oss test suite: every test in the package fails to run, so the coverage this PR adds is currently zero. Confirmed undefined symbols:

  • ctx2.DepConfig (lines 705, 854) — the context package defines DepConfigResolver/DepConfiguration/DepEngine/…, there is no DepConfig.
  • c.SetSnykOSSQuickFixCodeActionsEnabled (line 833) — exists nowhere in the repo.
  • error_reporting.NewTestErrorReporter() (line 846) — signature is NewTestErrorReporter(workflow.Engine), called with 0 args.
  • The anonymous Relationships struct literals (lines ~988, ~1192) no longer match testapi.FindingData (Id fields are oapi-codegen/runtime/types.UUID, and a Project relationship was added).

Fix: rebuild the test against current APIs — use the real DI keys (DepEngine + ConfigResolverFromContext + FolderConfigFromContext), the real config-flag mechanism, NewTestErrorReporter(engine), and current generated types. Add go test ./infrastructure/oss/ to CI as a build gate — a green CI here would mean the package's tests aren't being compiled.

— AI review


if len(dependencyPath) == 0 {
if len(dependencyPath) < 2 {
return nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Should Fix] Good fix here — but the identical bug class remains a few lines below at line 412:

if len(path) > 0 && path[1].Name == depPathPackageName {

path[1] requires length ≥ 2, but the guard only checks len(path) > 0, so a single-element UpgradePath.DependencyPath (API data) panics with index-out-of-range — exactly what you just fixed for dependencyPath. Tighten to len(path) > 1, and add a test feeding a length-1 upgrade path (mirroring the single-element case you already added for the input side). 3 of 4 reviewers flagged this; no current test exercises it.

— AI review

@bastiandoetsch

Copy link
Copy Markdown
Contributor

Context for this review: the only prior review on this PR was from gemini-code-assist (a bot), so it hadn't had a human/auth review yet.

The source change is correct: extractUpgradePackage line 405 (len(dependencyPath) == 0< 2) is a genuine root-cause fix for the dependencyPath[1] access two lines down, and the comment edits are net-positive (incl. the vuln.problem. typo fix). Security scan: clean, no PR-attributable issues. Where it compiles, the tests assert real behaviour against real production functions (not tautologies) — the single-element cases would genuinely panic against the old guard.

Non-blocking follow-ups once the compile is fixed:

  • [Suggestion] The skipped 'TODO' + active 'Wrong behavior' tests deliberately pin a known production bug (//FIXME: don't stop at the first dependency path) as passing. The pattern is honest (with delete-me notes), but please ensure a Jira ticket tracks the FIXME so these don't become permanent.
  • [Suggestion] The 'deep transitive returns empty remediation' test proves the function returns "" but not that empty remediation is the intended product behaviour — worth confirming against legacy parity (an empty remediation flows into buildMessage as a trailing ". ").
  • [Suggestion] The ~45-line anonymous Relationships struct is inlined in ~4 helpers; have createCompleteUnifiedFinding reuse createBaseFindingWithRelationshipsStruct so an upstream testapi regen doesn't break all copies at once.
  • [Suggestion] Four near-identical npm/yarn/maven/pip cases test per-ecosystem text at the wrong layer — collapse to two, or test buildOutdatedDependencyMessage directly.

— AI review


// Create deps with WRONG types (strings instead of proper types)
deps := map[string]any{
ctx2.DepConfig: "not-a-config", // Should be *config.Config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical — this test file does not compile against HEAD, so the entire infrastructure/oss test package fails to build. go test ./infrastructure/oss/ fails (this is also why CI lint is red and the unit/race/integration jobs are skipped — none of the ~1300 new lines of assertions have ever run). The file references an API that no longer exists at HEAD:

  • ctx2.DepConfig (here at line 705, and line 854) — undefined. The context package has DepEngine, DepConfigResolver, DepConfiguration, DepLearnService, DepErrorReporter, but no DepConfig.
  • config.Config (line ~818) — no such exported type in application/config.
  • c.SetSnykOSSQuickFixCodeActionsEnabled(...) (line ~833) — c is the workflow.Engine returned by testutil.UnitTestWithCtx, which has no such method.
  • error_reporting.NewTestErrorReporter() (line ~846) — now requires a workflow.Engine argument; see the sibling call in vulnerability_count_test.go.
  • The hand-rolled anonymous Relationships struct literals (lines ~988, ~1192) no longer match the generated testapi type — it gained a Project field and uses oapi-codegen/runtime/types.UUID for Id, while the literals use github.com/google/uuid.UUID and omit Project.

This needs a rebase onto current main and an update to the live API: obtain the engine/reporter the way the package's existing tests do, key deps by the real Dep* constants, and build Relationships from the generated testapi types rather than re-declaring the anonymous struct (the duplicated struct shape is the root cause of the last breakage and will keep breaking on every API change). Confirm go test ./infrastructure/oss/ passes before merge.

— AI review

}

if len(dependencyPath) == 0 {
if len(dependencyPath) < 2 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guard fix is correct — dependencyPath[1] at line 407 would panic on a length-1 path, and < 2 cleanly rejects both empty and single-element inputs while preserving behavior for valid (len ≥ 2) inputs.

Should fix — the structurally identical twin panic just below is still unguarded. At line 412, path[1].Name is reached after only len(path) > 0, so an upgrade DependencyPath with exactly one package panics with index-out-of-range. That path slice comes from the API (upgradeAction.UpgradePaths[…].DependencyPath) and has no length invariant. Since this PR's theme is hardening this exact access pattern, tighten line 412 to len(path) > 1 to match, and add a test case with a single-element upgrade path — none of the new tests currently feed one, so the "avoid panic" coverage they imply doesn't actually exist.

— AI review

@basti-snyk

Copy link
Copy Markdown
Contributor

ℹ️ Automated AI review summary — non-blocking format; the actionable items are inline.

Reviewed origin/main...HEAD with four reviewers. Strong consensus.

Merge blocker (inline on the test file): unified_converter_test.go does not compile against current mainundefined: ctx2.DepConfig, undefined: config.Config, SetSnykOSSQuickFixCodeActionsEnabled called on a workflow.Engine, NewTestErrorReporter arg-count mismatch, and Relationships anonymous-struct type mismatches. go test ./infrastructure/oss/ fails to build the whole package. This is why CI lint is red and the test jobs are skipped — none of the ~1300 new assertions have ever executed. Needs a rebase onto main and an update to the live API (and ideally building Relationships from the generated testapi types rather than re-declaring the anonymous struct, which is the recurring breakage source).

Should fix (inline on unified_converter.go:404): the PR correctly hardens the dependencyPath[1] access (== 0< 2), but leaves the structurally identical twin at line 412 (path[1].Name guarded only by len(path) > 0) — a single-element upgrade path still panics. Tighten to len(path) > 1 and add a single-element-upgrade-path test.

Positives: the production change at line 404 is the correct root-cause panic fix and is behavior-preserving for valid inputs; the two comment corrections are accurate. Where the tests do target the production change (Test_extractUpgradePackage, Test_buildUpgradePath, Test_buildRemediationAdvice) the assertions are meaningful and setupProcessIssueTest is integration-leaning (mocks only learn.Service, uses real testdata) rather than over-mocked — so once it compiles, coverage of the production change looks adequate.

Suggestions: a couple of skipped TODO tests (~120 lines) stage unbuilt "return all dependency paths" behavior — better tracked in the issue tracker and landed with that change; one assert.NotEmpty(UpgradePath) is effectively vacuous (the path is always seeded with [false]) so it can never fail; the anonymous Relationships/Fix struct shapes are duplicated across several helpers.

Security: no findings introduced (the change is comment + bounds-guard; security-neutral-to-positive).

— AI review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants