Skip to content

Commit 4501579

Browse files
committed
Test working
1 parent aa57cb6 commit 4501579

File tree

11 files changed

+346
-214
lines changed

11 files changed

+346
-214
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ out/
2020
pom.xml.versionsBackup
2121
**/src/generated/java/META-INF
2222
**.java-version
23-
.rewrite-cache
23+
.rewrite-cache

sbm-support-rewrite/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
testcode/reposilite-test/reposilite-data/**
2+
!testcode/reposilite-test/reposilite-data/shared.configuration.json

sbm-support-rewrite/src/test/java/org/springframework/sbm/PrivateArtifactRepositoryTest.java

+163-102
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,21 @@
1616
package org.springframework.sbm;
1717

1818
import org.apache.maven.shared.invoker.*;
19-
import org.junit.jupiter.api.BeforeEach;
20-
import org.junit.jupiter.api.DisplayName;
21-
import org.junit.jupiter.api.Test;
22-
import org.junitpioneer.jupiter.*;
19+
import org.junit.jupiter.api.*;
20+
import org.openrewrite.SourceFile;
21+
import org.openrewrite.java.JavaParser;
22+
import org.openrewrite.java.internal.JavaTypeCache;
23+
import org.openrewrite.java.marker.JavaSourceSet;
24+
import org.openrewrite.java.tree.J;
25+
import org.openrewrite.java.tree.JavaType;
26+
import org.springframework.beans.factory.annotation.Autowired;
2327
import org.springframework.boot.test.context.SpringBootTest;
2428
import org.springframework.sbm.boot.autoconfigure.SbmSupportRewriteConfiguration;
29+
import org.springframework.sbm.parsers.RewriteProjectParser;
30+
import org.springframework.sbm.parsers.RewriteProjectParsingResult;
31+
import org.springframework.sbm.parsers.maven.RewriteMavenProjectParser;
32+
import org.springframework.sbm.parsers.maven.SbmTestConfiguration;
33+
import org.springframework.util.FileSystemUtils;
2534
import org.testcontainers.containers.GenericContainer;
2635
import org.testcontainers.junit.jupiter.Container;
2736
import org.testcontainers.junit.jupiter.Testcontainers;
@@ -32,136 +41,188 @@
3241
import java.io.IOException;
3342
import java.nio.file.Files;
3443
import java.nio.file.Path;
44+
import java.util.Arrays;
3545
import java.util.List;
3646
import java.util.regex.Matcher;
3747
import java.util.regex.Pattern;
3848

3949
import static org.assertj.core.api.Assertions.assertThat;
40-
import static org.assertj.core.api.Assertions.in;
50+
import static org.assertj.core.api.Fail.fail;
4151

4252
/**
4353
* @author Fabian Krüger
4454
*/
45-
@SpringBootTest(classes = SbmSupportRewriteConfiguration.class)
55+
@SpringBootTest(classes = {SbmSupportRewriteConfiguration.class, SbmTestConfiguration.class})
4656
@Testcontainers
57+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
4758
public class PrivateArtifactRepositoryTest {
59+
public static final String $USER_HOME_PLACEHOLDER = "${user.home}";
60+
public static final String $PORT_PLACEHOLDER = "${port}";
61+
public static final String TESTCODE_DIR = "testcode/reposilite-test";
62+
public static final String DEPENDENCY_CLASS_FQNAME = "com.example.dependency.DependencyClass";
4863
@Container
4964
static GenericContainer reposilite = new GenericContainer(DockerImageName.parse("dzikoysk/reposilite:3.4.10"))
5065
.withExposedPorts(8080)
51-
.withEnv("REPOSILITE_OPTS", "--token user:secret");
66+
.withCopyFileToContainer(
67+
MountableFile.forHostPath("./" + TESTCODE_DIR + "/reposilite-data/shared.configuration.json"),
68+
"/app/data/shared.configuration.json"
69+
)
70+
// Create temp user 'user' with password 'secret'
71+
.withEnv("REPOSILITE_OPTS", "--token user:secret --shared-config shared.configuration.json");
5272

53-
@BeforeEach
54-
void beforeEach() {
73+
private static String originalUserHome;
74+
private static String newUserHome;
5575

76+
@Autowired
77+
private RewriteProjectParser parser;
78+
79+
@Autowired
80+
private RewriteMavenProjectParser comparingParser;
81+
private File localMavenRepository = Path.of(TESTCODE_DIR + "/user.home/.m2/repository").toFile();
82+
83+
private Path dependencyPathInLocalMavenRepo = Path.of(TESTCODE_DIR + "/user.home/.m2/repository/com/example/dependency/dependency-project");
84+
85+
@BeforeAll
86+
static void beforeAll() {
87+
originalUserHome = System.getProperty("user.home");
88+
newUserHome = Path.of(".").resolve(TESTCODE_DIR + "/user.home").toAbsolutePath().normalize().toString();
89+
System.setProperty("user.home", newUserHome);
90+
}
91+
92+
@AfterAll
93+
static void afterAll() {
94+
System.setProperty("user.home", originalUserHome);
5695
}
5796

5897
@Test
98+
@Order(1)
5999
@DisplayName("Maven settings should be read")
60-
@SetSystemProperty(key = "user.home", value = "testcode/reposilite-test/user.home")
100+
// @SetSystemProperty(key = "user.home", value = "testcode/reposilite-test/user.home")
61101
void mavenSettingsShouldBeRead() throws IOException, MavenInvocationException, InterruptedException {
62-
System.out.println(System.getenv("MAVEN_HOME"));
63-
64102
Integer port = reposilite.getMappedPort(8080);
103+
System.out.println("Reposilite: http://localhost:" + port + " login with user:secret");
104+
105+
// create pom.xml with correct port for dependency-project
106+
Path dependencyPomTmplPath = Path.of(TESTCODE_DIR + "/dependency-project/pom.xml.template").toAbsolutePath().normalize();
107+
Path dependencyPomPath = renderPomXml(port, dependencyPomTmplPath);
108+
109+
// create pom.xml with correct port for dependent-project
110+
Path dependentPomTmplPath = Path.of(TESTCODE_DIR + "/dependent-project/pom.xml.template").toAbsolutePath().normalize();
111+
Path dependentPomPath = renderPomXml(port, dependentPomTmplPath);
112+
113+
// adjust path in settings.xml
114+
Path settingsXmlTmplPath = Path.of("./").resolve(newUserHome + "/.m2/settings.xml.template").toAbsolutePath().normalize();
115+
Path settingsXmlPath = renderSettingsXml(newUserHome, settingsXmlTmplPath);
65116

66-
// adjust host:port information in pom.xml
67-
Path pomXmlPath = Path.of("testcode/reposilite-test/reposilite-test/pom.xml").toAbsolutePath().normalize();
68-
String pomXmlContent = Files.readString(pomXmlPath);
69-
String pomXmlCurrentPort = replacePort(pomXmlContent, port);
70-
Files.writeString(pomXmlPath, pomXmlCurrentPort);
117+
deployDependency(dependencyPomPath);
118+
// the project 'testcode/reposilite-test/reposilite-test' has been deployed to reposilite
71119

72120
InvocationRequest request = new DefaultInvocationRequest();
73-
request.setPomFile(pomXmlPath.toFile());
74-
request.setGoals(List.of("deploy"));
121+
request.setPomFile(dependentPomPath.toFile());
122+
request.setShowErrors(true);
123+
request.setUserSettingsFile(Path.of(TESTCODE_DIR + "/user.home/.m2/settings.xml").toFile());
124+
request.setGoals(List.of("-v", "clean", "package"));
125+
request.setLocalRepositoryDirectory(localMavenRepository);
126+
request.setBatchMode(true);
75127
Invoker invoker = new DefaultInvoker();
76-
invoker.setMavenHome(new File(System.getenv("MAVEN_HOME")));
77-
invoker.execute(request);
128+
invoker.setMavenHome(Path.of(TESTCODE_DIR + "/user.home/apache-maven-3.9.5").toFile());
129+
InvocationResult result = invoker.execute(request);
130+
if (result.getExitCode() != 0) {
131+
if (result.getExecutionException() != null) {
132+
fail("Maven clean package failed.", result.getExecutionException());
133+
} else {
134+
fail("Maven clean package. Exit code: " + result.getExitCode());
135+
}
136+
}
137+
138+
clearDependencyFromLocalMavenRepo();
139+
verifyDependenciesFromPrivateRepoWereResolved();
78140
}
79141

142+
// @Test
143+
// @Order(2)
144+
@DisplayName("verify dependencies from private repo were resolved")
145+
void verifyDependenciesFromPrivateRepoWereResolved() {
146+
// verify dependency does not exist in local Maven repo
147+
Path dependencyArtifactDir = dependencyPathInLocalMavenRepo.getParent();
148+
assertThat(Files.isDirectory(dependencyArtifactDir)).isTrue();
149+
assertThat(dependencyArtifactDir.toFile().listFiles()).isEmpty();
80150

81-
@Test
82-
@DisplayName("searchAndReplace")
83-
void searchAndReplace() {
84-
String given =
85-
"""
86-
<?xml version="1.0" encoding="UTF-8"?>
87-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
88-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
89-
<modelVersion>4.0.0</modelVersion>
90-
91-
<groupId>com.example</groupId>
92-
<artifactId>reposilite-test</artifactId>
93-
<version>1.0-SNAPSHOT</version>
94-
<name>reposilite-test</name>
95-
96-
<properties>
97-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
98-
<maven.compiler.source>1.7</maven.compiler.source>
99-
<maven.compiler.target>1.7</maven.compiler.target>
100-
</properties>
101-
102-
<dependencies>
103-
<dependency>
104-
<groupId>javax.validation</groupId>
105-
<artifactId>validation-api</artifactId>
106-
<version>2.0.1.Final</version>
107-
</dependency>
108-
</dependencies>
109-
110-
<distributionManagement>
111-
<repository>
112-
<id>reposilite-repository-releases</id>
113-
<name>Reposilite Repository</name>
114-
<url>http://localhost:8085/snapshots</url>
115-
</repository>
116-
</distributionManagement>
117-
</project>
118-
""";
119-
120-
String s1 = replacePort(given, 1234);
121-
122-
assertThat(s1).isEqualTo(
123-
"""
124-
<?xml version="1.0" encoding="UTF-8"?>
125-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
126-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
127-
<modelVersion>4.0.0</modelVersion>
128-
129-
<groupId>com.example</groupId>
130-
<artifactId>reposilite-test</artifactId>
131-
<version>1.0-SNAPSHOT</version>
132-
<name>reposilite-test</name>
133-
134-
<properties>
135-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
136-
<maven.compiler.source>1.7</maven.compiler.source>
137-
<maven.compiler.target>1.7</maven.compiler.target>
138-
</properties>
139-
140-
<dependencies>
141-
<dependency>
142-
<groupId>javax.validation</groupId>
143-
<artifactId>validation-api</artifactId>
144-
<version>2.0.1.Final</version>
145-
</dependency>
146-
</dependencies>
147-
148-
<distributionManagement>
149-
<repository>
150-
<id>reposilite-repository-releases</id>
151-
<name>Reposilite Repository</name>
152-
<url>http://localhost:1234/snapshots</url>
153-
</repository>
154-
</distributionManagement>
155-
</project>
156-
"""
157-
);
151+
// scan a project that depends on this dependency
152+
Path migrateApplication = Path.of(TESTCODE_DIR + "/dependent-project");
153+
RewriteProjectParsingResult parsingResult = parser.parse(migrateApplication);
154+
155+
// verify dependency was downloaded
156+
Path snapshotDir = dependencyPathInLocalMavenRepo.resolve("1.0-SNAPSHOT");
157+
assertThat(snapshotDir).isDirectory();
158+
assertThat(Arrays.stream(snapshotDir.toFile().listFiles()).map(f -> f.getName()).findFirst().get()).matches("dependency-project-1.0-.*\\.jar");
159+
160+
// verify that DependencyClass type can be resolved
161+
J.CompilationUnit cu = (J.CompilationUnit) parsingResult.sourceFiles().stream().filter(s -> s.getSourcePath().toFile().getName().endsWith(".java")).findFirst().get();
162+
List<String> fqClassesInUse = cu.getTypesInUse().getTypesInUse().stream().filter(JavaType.FullyQualified.class::isInstance).map(JavaType.FullyQualified.class::cast).map(JavaType.FullyQualified::getFullyQualifiedName).toList();
163+
164+
// DependencyClass must be in list of used types
165+
assertThat(fqClassesInUse).contains(DEPENDENCY_CLASS_FQNAME);
166+
167+
// type should be on classpath
168+
List<String> classpathFqNames = cu.getMarkers().findFirst(JavaSourceSet.class).get().getClasspath().stream().map(fqn -> fqn.getFullyQualifiedName()).toList();
169+
assertThat(classpathFqNames).contains(DEPENDENCY_CLASS_FQNAME);
170+
171+
// Type of member should be resolvable
172+
J.ClassDeclaration classDeclaration = cu.getClasses().get(0);
173+
JavaType.Class type = (JavaType.Class) ((J.VariableDeclarations) classDeclaration.getBody().getStatements().get(0)).getType();
174+
assertThat(type.getFullyQualifiedName()).isEqualTo(DEPENDENCY_CLASS_FQNAME);
175+
}
176+
177+
178+
private Path renderSettingsXml(String testcodeDir, Path settingsXmlTmplPath) throws IOException {
179+
String settingsXmlContent = Files.readString(settingsXmlTmplPath);
180+
String replaced = settingsXmlContent.replace($USER_HOME_PLACEHOLDER, testcodeDir);
181+
Path settingsXmlPath = Path.of(settingsXmlTmplPath.toString().replace(".template", ""));
182+
return Files.writeString(settingsXmlPath, replaced);
158183
}
159184

160-
private static String replacePort(String given, Integer port) {
161-
String regex = "(<url>http:\\/\\/localhost:)(\\d{1,5})(\\/snapshots<\\/url>)";
185+
186+
private static String replace(String content, Object replacement, String regex) {
162187
Pattern compile = Pattern.compile(regex);
163-
Matcher matcher = compile.matcher(given);
164-
String s1 = matcher.replaceFirst("$1" + port + "$3");
188+
Matcher matcher = compile.matcher(content);
189+
String s1 = matcher.replaceFirst("$1" + replacement + "$3");
165190
return s1;
166191
}
192+
193+
private static Path renderPomXml(Integer port, Path pomXmlTmplPath) throws IOException {
194+
String given = Files.readString(pomXmlTmplPath);
195+
String replaced = given.replace($PORT_PLACEHOLDER, port.toString());
196+
Path pomXmlPath = Path.of(pomXmlTmplPath.toString().replace(".template", ""));
197+
return Files.writeString(pomXmlPath, replaced);
198+
}
199+
200+
private void clearDependencyFromLocalMavenRepo() {
201+
try {
202+
FileSystemUtils.deleteRecursively(dependencyPathInLocalMavenRepo);
203+
} catch (IOException e) {
204+
throw new RuntimeException(e);
205+
}
206+
}
207+
208+
private void deployDependency(Path pomXmlPath) throws MavenInvocationException {
209+
InvocationRequest request = new DefaultInvocationRequest();
210+
request.setPomFile(pomXmlPath.toFile());
211+
request.setShowErrors(true);
212+
request.setUserSettingsFile(Path.of(TESTCODE_DIR + "/user.home/.m2/settings.xml").toFile());
213+
request.setGoals(List.of("deploy"));
214+
request.setLocalRepositoryDirectory(localMavenRepository);
215+
request.setBatchMode(true);
216+
Invoker invoker = new DefaultInvoker();
217+
invoker.setMavenHome(Path.of(TESTCODE_DIR + "/user.home/apache-maven-3.9.5").toFile());
218+
InvocationResult result = invoker.execute(request);
219+
if (result.getExitCode() != 0) {
220+
if (result.getExecutionException() != null) {
221+
fail("Maven deploy failed.", result.getExecutionException());
222+
} else {
223+
fail("Maven deploy failed. Exit code: " + result.getExitCode());
224+
}
225+
}
226+
}
227+
167228
}

sbm-support-rewrite/src/test/java/org/springframework/sbm/parsers/maven/MavenExecutionRequestFactory.java

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.codehaus.plexus.PlexusContainer;
2929
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
3030

31+
import java.io.File;
3132
import java.nio.file.Path;
3233
import java.util.List;
3334
import java.util.Map;
@@ -60,6 +61,10 @@ public MavenExecutionRequest createMavenExecutionRequest(PlexusContainer plexusC
6061
request.setShowErrors(true);
6162
request.setLocalRepositoryPath(LOCAL_REPOSITORY);
6263
request.setPluginArtifactRepositories(List.of(repository));
64+
File userSettingsFile = Path.of(System.getProperty("user.home")).resolve(".m2/settings.xml").toFile();
65+
if(userSettingsFile.exists()) {
66+
request.setUserSettingsFile(userSettingsFile);
67+
}
6368

6469
List<String> activatedProfiles = mavenConfigFileParser.getActivatedProfiles(baseDir);
6570
if (activatedProfiles.isEmpty()) {
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
# Artifact Repository Test
22

3-
Test that artifacts available in a private artifact repository configured in `~/.m2/settings.xml` and `~/.m2/security-settings.xml` can be accessed.
3+
Test that artifacts available in a private artifact repository configured in `~/.m2/settings.xml` can be accessed.
44
This is important as many enterprise projects use their private artifact repository to retrieve private dependencies.
55

6-
A local and private artifact repository (https://github.com/dzikoysk/reposilite[reposilite]) is started in a docker container.
6+
- A private artifact repository using (https://github.com/dzikoysk/reposilite[reposilite]) is started in a Docker container.
77
The reposilite instance has a user configured (admin:secret) which can deploy and access artifacts.
88
9-
A project that uses this dependency is parsed.
10-
After successful dependency resolution the types of this artifact must be available on the AST.
9+
- The repositories in the artifact repository (e.g. snapshot) require successful authentication (deploy + download).
10+
11+
- `dependency-project` has a simple class `DependencyClass` and gets deployed to the artifact repository.
12+
13+
- `dependent-project` depends on `dependency-project` and has a class `DependentClass` that uses `DependencyClass`
14+
15+
- `dependent-project` gets parsed
16+
17+
- The resulting AST has the type information of `dependency-project` resolved when the repository information and credentials were read from `settings.xml` and `security-settings.xml`.
18+
19+
Technical requirements:
20+
21+
- The port of the Docker container is dynamic and used in settings.xml and pom.xml.
22+
- The local Maven installation of any system should not be affected by this test.
23+
- The location of the Maven dir `.m2` must therefore point to a different location while the test is running.
24+
25+
26+
27+
28+
29+
30+
This requires temporarily a different `.m2` location, here `testcode/reposilite-test/user.home/.m2`.
31+
When deploying the `dependency-project` the path to `settings.xml` is provided, pointing to `testcode/reposilite-test/user.home/.m2/settings.xml`.
32+
This file declares the location of the local Maven repository pointing to the same dir.
33+
Because these paths can't be relative for this test and absolute paths
34+
1135

1236
The `user.home` is set to point to `testcode/reposilite-test/user.home` which contains a `.m2` directory providing access configuration to the reposilite instance through `.m2/settings.xml` and `.m2/security-settings.xml`,

0 commit comments

Comments
 (0)