Skip to content

Commit c953c14

Browse files
committed
✅ test: Ensure Dependency Resolution
Update integration tests to verify all dependencies have the following: - Checksum - Checksum algorithm - Resolved URL - Repository ID These checks do not succeed for the remote checksum feature, due to a bug in the parallel remote checksum cache feature. Assisted-by: Claude Code Signed-off-by: Adam Kaplan <adam.kaplan@redhat.com>
1 parent 9206c01 commit c953c14

1 file changed

Lines changed: 84 additions & 12 deletions

File tree

maven_plugin/src/test/java/it/IntegrationTestsIT.java

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package it;
22

33
import static com.soebes.itf.extension.assertj.MavenITAssertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThat;
45
import static org.junit.jupiter.api.Assertions.assertTrue;
56
import static org.junit.jupiter.api.Assertions.fail;
67

@@ -27,6 +28,49 @@
2728

2829
@MavenJupiterExtension
2930
public class IntegrationTestsIT {
31+
32+
@SuppressWarnings("null")
33+
public void assertDependencyNode(DependencyNode node) {
34+
assertThat(node.getChecksum())
35+
.as(
36+
"%s:%s:%s checksum",
37+
node.getGroupId().getValue(),
38+
node.getArtifactId().getValue(),
39+
node.getVersion().getValue())
40+
.isNotEmpty();
41+
assertThat(node.getChecksumAlgorithm())
42+
.as(
43+
"%s:%s:%s checksum algorithm",
44+
node.getGroupId().getValue(),
45+
node.getArtifactId().getValue(),
46+
node.getVersion().getValue())
47+
.isNotEmpty();
48+
assertThat(node.getResolved())
49+
.as(
50+
"%s:%s:%s resolved url",
51+
node.getGroupId().getValue(),
52+
node.getArtifactId().getValue(),
53+
node.getVersion().getValue())
54+
.isNotEqualTo(ResolvedUrl.Unresolved());
55+
assertThat(node.getRepositoryId())
56+
.as(
57+
"%s:%s:%s repository id",
58+
node.getGroupId().getValue(),
59+
node.getArtifactId().getValue(),
60+
node.getVersion().getValue())
61+
.isNotEqualTo(RepositoryId.None());
62+
}
63+
64+
public void assertAllDependencies(LockFile lockFile) {
65+
lockFile.getDependencies().stream()
66+
.flatMap(d -> flattenDependencies(d).stream())
67+
.forEach(node -> assertDependencyNode(node));
68+
lockFile.getMavenPlugins().stream()
69+
.flatMap(plugin -> plugin.getDependencies().stream())
70+
.flatMap(dep -> flattenDependencies(dep).stream())
71+
.forEach(node -> assertDependencyNode(node));
72+
}
73+
3074
@MavenTest
3175
public void simpleProject(MavenExecutionResult result) throws Exception {
3276
// contract: an empty project should generate an empty lock file
@@ -40,19 +84,20 @@ public void simpleProject(MavenExecutionResult result) throws Exception {
4084

4185
@MavenTest
4286
public void singleDependency(MavenExecutionResult result) throws Exception {
43-
// contract: an empty project should generate an empty lock file
87+
// contract: a project with a single dependency should generate a lockfile with the dependency data
4488
System.out.println("Running 'singleDependency' integration test.");
4589
assertThat(result).isSuccessful();
4690
Path lockFilePath = findFile(result, "lockfile.json");
4791
assertThat(lockFilePath).exists();
4892
var lockFile = LockFile.readLockFile(lockFilePath);
93+
assertAllDependencies(lockFile);
4994
assertThat(lockFile.getEnvironment()).isNotNull();
5095
assertThat(lockFile.getDependencies()).hasSize(1);
51-
var junitDep = lockFile.getDependencies().toArray(DependencyNode[]::new)[0];
52-
assertThat(junitDep.getArtifactId()).extracting(ArtifactId::getValue).isEqualTo("spoon-core");
53-
assertThat(junitDep.getGroupId()).extracting(GroupId::getValue).isEqualTo("fr.inria.gforge.spoon");
54-
assertThat(junitDep.getVersion()).extracting(VersionNumber::getValue).isEqualTo("10.3.0");
55-
assertThat(junitDep.getChecksum())
96+
var spoonDep = lockFile.getDependencies().toArray(DependencyNode[]::new)[0];
97+
assertThat(spoonDep.getArtifactId()).extracting(ArtifactId::getValue).isEqualTo("spoon-core");
98+
assertThat(spoonDep.getGroupId()).extracting(GroupId::getValue).isEqualTo("fr.inria.gforge.spoon");
99+
assertThat(spoonDep.getVersion()).extracting(VersionNumber::getValue).isEqualTo("10.3.0");
100+
assertThat(spoonDep.getChecksum())
56101
.isEqualTo("37a43de039cf9a6701777106e3c5921e7131e5417fa707709abf791d3d8d9174");
57102
}
58103

@@ -64,6 +109,7 @@ public void singleDependencyCheckCorrect(MavenExecutionResult result) throws Exc
64109
Path lockFilePath = findFile(result, "lockfile.json");
65110
assertThat(lockFilePath).exists();
66111
var lockFile = LockFile.readLockFile(lockFilePath);
112+
assertAllDependencies(lockFile);
67113
assertThat(lockFile.getDependencies()).hasSize(1);
68114
var junitDep = lockFile.getDependencies().toArray(DependencyNode[]::new)[0];
69115
assertThat(junitDep.getArtifactId()).extracting(ArtifactId::getValue).isEqualTo("junit-jupiter-api");
@@ -92,6 +138,7 @@ public void pluginProject(MavenExecutionResult result) throws Exception {
92138
Path lockFilePath = findFile(result, "lockfile.json");
93139
assertThat(lockFilePath).exists();
94140
var lockFile = LockFile.readLockFile(lockFilePath);
141+
assertAllDependencies(lockFile);
95142
assertThat(lockFile.getMavenPlugins()).isNotEmpty();
96143
assertThat(lockFile.getMavenPlugins())
97144
.allMatch(v -> !v.getChecksum().isBlank()
@@ -138,6 +185,7 @@ public void pluginUserDependency(MavenExecutionResult result) throws Exception {
138185
Path lockFilePath = findFile(result, "lockfile.json");
139186
assertThat(lockFilePath).exists();
140187
var lockFile = LockFile.readLockFile(lockFilePath);
188+
assertAllDependencies(lockFile);
141189
assertThat(lockFile.getMavenPlugins()).isNotEmpty();
142190
assertThat(lockFile.getMavenPlugins())
143191
.allMatch(v -> !v.getChecksum().isBlank()
@@ -280,6 +328,7 @@ void reduceLog4jAffected(MavenExecutionResult result) throws Exception {
280328
Path lockFilePath = findFile(result, "lockfile.json");
281329
assertThat(lockFilePath).exists();
282330
var lockFile = LockFile.readLockFile(lockFilePath);
331+
assertAllDependencies(lockFile);
283332
assertThat(lockFile.getDependencies().stream().flatMap(v -> flattenDependencies(v).stream()))
284333
.anyMatch(v -> v.getArtifactId().getValue().equals("log4j-core")
285334
&& v.getVersion().getValue().equals("2.0"));
@@ -292,6 +341,7 @@ void reduceLog4jNotAffected(MavenExecutionResult result) throws Exception {
292341
Path lockFilePath = findFile(result, "lockfile.json");
293342
assertThat(lockFilePath).exists();
294343
var lockFile = LockFile.readLockFile(lockFilePath);
344+
assertAllDependencies(lockFile);
295345
assertThat(lockFile.getDependencies().stream().flatMap(v -> flattenDependencies(v).stream()))
296346
.noneMatch(v -> v.getArtifactId().getValue().equals("log4j-core")
297347
&& v.getVersion().getValue().equals("2.0"));
@@ -328,6 +378,7 @@ private void classifier(MavenExecutionResult result) throws Exception {
328378
Path lockFilePath = findFile(result, "lockfile.json");
329379
assertThat(lockFilePath).exists();
330380
var lockFile = LockFile.readLockFile(lockFilePath);
381+
assertAllDependencies(lockFile);
331382
assertThat(lockFile.getDependencies()).hasSize(3);
332383

333384
var junitSourceDep = lockFile.getDependencies().toArray(DependencyNode[]::new)[0];
@@ -444,6 +495,7 @@ public void orderedLockfile(MavenExecutionResult result) throws Exception {
444495
Path lockFilePath = findFile(result, "lockfile.json");
445496
assertThat(lockFilePath).exists();
446497
var lockFile = LockFile.readLockFile(lockFilePath);
498+
assertAllDependencies(lockFile);
447499
var dependencyList = lockFile.getDependencies().stream()
448500
.map(it -> it.getComparatorString())
449501
.collect(Collectors.toList());
@@ -512,6 +564,10 @@ public void checksumModeRemote(MavenExecutionResult result) throws Exception {
512564
assertThat(lockfilePath).exists();
513565
var lockfile = LockFile.readLockFile(lockfilePath);
514566

567+
// Fails due to bug in parallel downloader for remote checksums
568+
// See https://github.com/chains-project/maven-lockfile/issues/1561
569+
// assertAllDependencies(lockfile);
570+
515571
// Verify: atlassian-bandana:0.2.0 is hosted on packages.atlassian.com which doesn't provide SHA-256, SHA-256
516572
// has
517573
// to be calculated
@@ -520,27 +576,34 @@ public void checksumModeRemote(MavenExecutionResult result) throws Exception {
520576
.getChecksum()
521577
.equals("12357e6d5c5eb6b5ed80bbb98f4ef7b70fcb08520a9f306c4af086c37d6ebc11"))
522578
.findAny();
523-
assertThat(dep1Checksum).isNotNull();
579+
assertThat(dep1Checksum.isPresent()).isTrue();
524580
result.getMavenLog();
525581

526582
// Verify: jsap:2.1 is hosted on repo.maven.apache.org which doesn't provide SHA-256, and who's SHA-1 has a
527583
// different format (providing `checksum path` instead of `checksum`). SHA-1 should still succeed as the
528584
// `checksum` is verified aganist up until the first space, thus excluding the path of the file when the
529585
// SHA-1 was generated. SHA-256 has to be calculated.
530586
var dep2Checksum = lockfile.getDependencies().stream()
587+
.flatMap(d -> flattenDependencies(d).stream())
531588
.filter(dependency -> dependency
532589
.getChecksum()
533590
.equals("331746fa62cfbc3368260c5a2e660936ad11be612308c120a044e120361d474e"))
534591
.findAny();
592+
// BUG: dep2Checksum is an Optional, so it will always be non-null
535593
assertThat(dep2Checksum).isNotNull();
594+
// With parallel download feature, this check consistently fails, potentially due to rate limiting on Maven Central.
595+
// assertThat(dep2Checksum.isPresent()).isTrue();
536596

537597
// Verify: spoon-core:11.1.0 is hosted on maven central and directly provides SHA-256 checksums
538598
var dep3Checksum = lockfile.getDependencies().stream()
539599
.filter(dependency -> dependency
540600
.getChecksum()
541601
.equals("a8ae41ae0a1578a7ef9ce4f8d562813a99e6cc015e8cb3b0482b5470d53f1c6b"))
542602
.findAny();
603+
// BUG: dep3Checksum is an Optional, so it will always be non-null
543604
assertThat(dep3Checksum).isNotNull();
605+
// With parallel download feature, this check consistently fails, potentially due to rate limiting on Maven Central.
606+
// assertThat(dep3Checksum.isPresent()).isTrue();
544607
}
545608

546609
@MavenTest
@@ -551,6 +614,7 @@ public void resolvedFieldShouldResolve(MavenExecutionResult result) throws Excep
551614
Path lockFilePath = findFile(result, "lockfile.json");
552615
assertThat(lockFilePath).exists();
553616
var lockFile = LockFile.readLockFile(lockFilePath);
617+
assertAllDependencies(lockFile);
554618
var atlassianResolved = lockFile.getDependencies().stream()
555619
.filter(
556620
dependency -> dependency
@@ -559,7 +623,7 @@ public void resolvedFieldShouldResolve(MavenExecutionResult result) throws Excep
559623
ResolvedUrl.of(
560624
"https://packages.atlassian.com/maven-public/atlassian-bandana/atlassian-bandana/0.2.0/atlassian-bandana-0.2.0.jar")))
561625
.findAny();
562-
assertThat(atlassianResolved).isNotNull();
626+
assertThat(atlassianResolved.isPresent()).isTrue();
563627
var mavenCentralResolved = lockFile.getDependencies().stream()
564628
.filter(
565629
dependency -> dependency
@@ -568,27 +632,28 @@ public void resolvedFieldShouldResolve(MavenExecutionResult result) throws Excep
568632
ResolvedUrl.of(
569633
"https://repo.maven.apache.org/maven2/org/sonatype/sisu/sisu-inject-bean/1.4.2/sisu-inject-bean-1.4.2.jar")))
570634
.findAny();
571-
assertThat(mavenCentralResolved).isNotNull();
635+
assertThat(mavenCentralResolved.isPresent()).isTrue();
572636
// Ensure dependencies with classifiers have correctly resolved urls.
573637
// sisu-guice with classifier noaop is a direct dependency of org.sonatype.sisu:sisu-inject-bean.
574638
var dependencyWithClassifierResolved = lockFile.getDependencies().stream()
639+
.flatMap(d -> flattenDependencies(d).stream())
575640
.filter(
576641
dependency -> dependency
577642
.getResolved()
578643
.equals(
579644
ResolvedUrl.of(
580645
"https://repo.maven.apache.org/maven2/org/sonatype/sisu/sisu-guice/2.1.7/sisu-guice-2.1.7-noaop.jar")))
581646
.findAny();
582-
assertThat(dependencyWithClassifierResolved).isNotNull();
647+
assertThat(dependencyWithClassifierResolved.isPresent()).isTrue();
583648
// Ensure repository ids are resolved.
584649
var atlassianRepositoryId = lockFile.getDependencies().stream()
585650
.filter(dependency -> dependency.getRepositoryId().equals(RepositoryId.of("maven-atlassian-all")))
586651
.findAny();
587-
assertThat(atlassianRepositoryId).isNotNull();
652+
assertThat(atlassianRepositoryId.isPresent()).isTrue();
588653
var mavenCentralRepositoryId = lockFile.getDependencies().stream()
589654
.filter(dependency -> dependency.getRepositoryId().equals(RepositoryId.of("central")))
590655
.findAny();
591-
assertThat(mavenCentralRepositoryId).isNotNull();
656+
assertThat(mavenCentralRepositoryId.isPresent()).isTrue();
592657
}
593658

594659
@MavenTest
@@ -628,6 +693,7 @@ public void externalParentPom(MavenExecutionResult result) throws Exception {
628693
Path lockFilePath = findFile(result, "lockfile.json");
629694
assertThat(lockFilePath).exists();
630695
var lockFile = LockFile.readLockFile(lockFilePath);
696+
assertAllDependencies(lockFile);
631697

632698
// Verify pom is present
633699
var pom = lockFile.getPom();
@@ -676,6 +742,7 @@ public void relativeParentPom(MavenExecutionResult result) throws Exception {
676742
Path lockFilePath = findFile(result, "lockfile.json");
677743
assertThat(lockFilePath).exists();
678744
var lockFile = LockFile.readLockFile(lockFilePath);
745+
assertAllDependencies(lockFile);
679746

680747
// Verify pom is present
681748
var pom = lockFile.getPom();
@@ -706,6 +773,7 @@ public void artifactTypeProject(MavenExecutionResult result) throws Exception {
706773
Path lockFilePath = findFile(result, "lockfile.json");
707774
assertThat(lockFilePath).exists();
708775
var lockFile = LockFile.readLockFile(lockFilePath);
776+
assertAllDependencies(lockFile);
709777
assertThat(lockFile.getDependencies()).isNotEmpty();
710778
// Verify at least one dependency has a non-null type (the pom-type dependency)
711779
assertThat(lockFile.getDependencies())
@@ -745,6 +813,7 @@ public void buildExtensionsMultiple(MavenExecutionResult result) throws Exceptio
745813
Path lockFilePath = findFile(result, "lockfile.json");
746814
assertThat(lockFilePath).exists();
747815
var lockFile = LockFile.readLockFile(lockFilePath);
816+
assertAllDependencies(lockFile);
748817
assertThat(lockFile.getMavenExtensions()).isNotEmpty();
749818
// wagon-ftp has no explicit version but is resolved from Maven's extensionArtifactMap — all 3 are recorded
750819
assertThat(lockFile.getMavenExtensions()).hasSize(3);
@@ -807,6 +876,7 @@ public void buildExtensionVersionFromParent(MavenExecutionResult result) throws
807876
Path lockFilePath = findFile(result, "lockfile.json");
808877
assertThat(lockFilePath).exists();
809878
var lockFile = LockFile.readLockFile(lockFilePath);
879+
assertAllDependencies(lockFile);
810880
assertThat(lockFile.getMavenExtensions()).hasSize(3);
811881
assertThat(new ArrayList<>(lockFile.getMavenExtensions()))
812882
.extracting(ext ->
@@ -840,6 +910,7 @@ public void bomPom(MavenExecutionResult result) throws Exception {
840910
Path lockFilePath = findFile(result, "lockfile.json");
841911
assertThat(lockFilePath).exists();
842912
var lockFile = LockFile.readLockFile(lockFilePath);
913+
assertAllDependencies(lockFile);
843914

844915
var junitDep = lockFile.getDependencies().stream()
845916
.filter(dep -> dep.getGroupId().getValue().equals("org.junit.jupiter")
@@ -863,6 +934,7 @@ public void bomPomWithParent(MavenExecutionResult result) throws Exception {
863934
Path lockFilePath = findFile(result, "lockfile.json");
864935
assertThat(lockFilePath).exists();
865936
var lockFile = LockFile.readLockFile(lockFilePath);
937+
assertAllDependencies(lockFile);
866938

867939
var foundBom = lockFile.getBoms().stream()
868940
.filter(bom -> bom.getGroupId().getValue().equals("io.netty")

0 commit comments

Comments
 (0)