Skip to content

Commit e071c79

Browse files
committed
fix(go): merge children on MVS version key collision instead of overwriting
In getFinalPackagesVersionsForModule(), when multiple original parent versions remap to the same MVS-selected version, HashMap.put() was overwriting the children list, losing transitive dependencies. Replace put() with merge() using a LinkedHashSet to combine children lists while deduplicating entries. Before: 134 components (4 lost due to key collisions) After: 138 components (matching JS client output) Implements TC-4127 Assisted-by: Claude Code
1 parent 1aee31c commit e071c79

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

src/main/java/io/github/guacsec/trustifyda/providers/GoModulesProvider.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,14 @@ private Map<String, List<String>> getFinalPackagesVersionsForModule(
354354
}
355355
List<String> packagesWithFinalVersions =
356356
getListOfPackagesWithFinalVersions(finalModulesVersions, value);
357-
listWithModifiedVersions.put(packageWithSelectedVersion, packagesWithFinalVersions);
357+
listWithModifiedVersions.merge(
358+
packageWithSelectedVersion,
359+
packagesWithFinalVersions,
360+
(existing, incoming) -> {
361+
var combined = new java.util.LinkedHashSet<>(existing);
362+
combined.addAll(incoming);
363+
return new ArrayList<>(combined);
364+
});
358365
});
359366

360367
return listWithModifiedVersions;

src/test/java/io/github/guacsec/trustifyda/providers/Golang_Modules_Provider_Test.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,40 @@ void Test_Golang_MvS_Logic_Disabled() throws IOException {
198198
== 1);
199199
}
200200

201+
/**
202+
* Verifies that MVS-enabled mode preserves all transitive dependencies (TC-3818).
203+
*
204+
* <p>When MVS is enabled (the default), {@code getFinalPackagesVersionsForModule()} uses {@code
205+
* HashMap.put()} which overwrites children when two original parent versions remap to the same
206+
* MVS-selected version. This causes the Java client to produce fewer components than the JS
207+
* client.
208+
*
209+
* <p>The JS client produces 138 components for this fixture. This test is expected to FAIL until
210+
* the HashMap.put() collision bug is fixed.
211+
*/
212+
@Test
213+
void Test_Golang_MvS_Enabled_Preserves_All_Transitive_Dependencies() throws IOException {
214+
// Given the MVS test fixture with MVS enabled (the default — no property override)
215+
String goModPath = getFileFromResource("go.mod", "msc/golang/mvs_logic/go.mod");
216+
Path manifest = Path.of(goModPath);
217+
GoModulesProvider goModulesProvider = new GoModulesProvider(manifest);
218+
219+
// When generating the SBOM with stack analysis
220+
String resultSbom =
221+
dropIgnoredKeepFormat(
222+
goModulesProvider.getDependenciesSbom(manifest, true).getAsJsonString());
223+
224+
// Then the SBOM should contain exactly 138 components (matching JS client output)
225+
JsonNode sbomTree = JSON_MAPPER.readTree(resultSbom);
226+
int componentCount = sbomTree.path("components").size();
227+
assertEquals(
228+
138,
229+
componentCount,
230+
"MVS-enabled SBOM should contain 138 components (matching JS client). "
231+
+ "A lower count indicates the HashMap.put() collision bug in "
232+
+ "getFinalPackagesVersionsForModule() is losing transitive dependencies.");
233+
}
234+
201235
@Test
202236
void test_isGoToolchainEntry_filters_go_and_toolchain() {
203237
// go@* entries should be filtered

0 commit comments

Comments
 (0)