View Javadoc
1   /*-
2    * #%L
3    * io.earcam.instrumental.archive.jpms
4    * %%
5    * Copyright (C) 2018 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */
19  package io.earcam.instrumental.archive.maven;
20  
21  import static io.earcam.instrumental.archive.Archive.archive;
22  import static io.earcam.instrumental.archive.AsJar.asJar;
23  import static io.earcam.instrumental.archive.maven.Maven.CENTRAL_ID;
24  import static io.earcam.instrumental.archive.maven.Maven.CENTRAL_URL;
25  import static io.earcam.instrumental.archive.maven.Maven.DEFAULT_TYPE;
26  import static io.earcam.instrumental.archive.maven.Maven.ID_LOCAL_AS_REMOTE;
27  import static io.earcam.instrumental.archive.maven.Maven.maven;
28  import static java.nio.charset.StandardCharsets.UTF_8;
29  import static java.util.stream.Collectors.toList;
30  import static org.hamcrest.MatcherAssert.assertThat;
31  import static org.hamcrest.Matchers.aMapWithSize;
32  import static org.hamcrest.Matchers.*;
33  import static org.hamcrest.Matchers.contains;
34  import static org.hamcrest.Matchers.containsInAnyOrder;
35  import static org.hamcrest.Matchers.endsWith;
36  import static org.hamcrest.Matchers.equalTo;
37  import static org.hamcrest.Matchers.hasKey;
38  import static org.hamcrest.Matchers.is;
39  import static org.hamcrest.io.FileMatchers.aFileNamed;
40  import static org.junit.jupiter.api.Assertions.fail;
41  
42  import java.io.File;
43  import java.nio.file.Files;
44  import java.nio.file.Path;
45  import java.nio.file.Paths;
46  import java.util.List;
47  import java.util.Map;
48  
49  import org.eclipse.aether.repository.RemoteRepository;
50  import org.junit.jupiter.api.Nested;
51  import org.junit.jupiter.api.Test;
52  
53  import io.earcam.instrumental.archive.Archive;
54  import io.earcam.unexceptional.Exceptional;
55  
56  public class MavenTest {
57  
58  	@Nested
59  	public class UsingCustomLocalRepository {
60  
61  		@Test
62  		public void givenExistingDirectory()
63  		{
64  			Path path = Paths.get(".", "src", "test", "resources");
65  
66  			Maven maven = maven().usingLocal(path);
67  
68  			assertThat(maven.local.getBasedir(), is(equalTo(path.toAbsolutePath().toFile())));
69  		}
70  
71  
72  		@Test
73  		public void givenNonExistentDirectory()
74  		{
75  			Path path = Paths.get(".", "src", "test", "resources", "THIS_DOES_NOT_EXIST");
76  
77  			Maven maven = maven().usingLocal(path);
78  
79  			assertThat(maven.local.getBasedir(), is(equalTo(path.toAbsolutePath().toFile())));
80  		}
81  
82  
83  		@Test
84  		public void throwsWhenNotADirectory()
85  		{
86  			Path path = Paths.get(".", "pom.xml");
87  			try {
88  				maven().usingLocal(path);
89  				fail();
90  			} catch(IllegalArgumentException e) {}
91  		}
92  	}
93  
94  
95  	private void runWithFakeUserHome(String fakeHome, Runnable runnable)
96  	{
97  		String realHome = System.getProperty("user.home");
98  		try {
99  			System.setProperty("user.home", fakeHome);
100 			runnable.run();
101 		} finally {
102 			System.setProperty("user.home", realHome);
103 		}
104 	}
105 
106 	@Nested
107 	public class UsingDefaultLocalRepository {
108 
109 		@Test
110 		public void customLocalRepositoryFoundInSettings()
111 		{
112 			String fake = Paths.get(".", "src", "test", "resources", "fake.user.home", "local.in.settings").toAbsolutePath().toString();
113 			runWithFakeUserHome(fake, () -> {
114 				Maven maven = maven()
115 						.usingDefaultLocal();
116 
117 				assertThat(maven.local.getBasedir(), aFileNamed(endsWith("nonstandard.repository")));
118 			});
119 		}
120 
121 
122 		@Test
123 		public void givenCustomLocalRepositoryFoundInSettingsWhenNotADirectoryThenThrows()
124 		{
125 			String fake = Paths.get(".", "src", "test", "resources", "fake.user.home", "bad.local.in.settings").toAbsolutePath().toString();
126 			runWithFakeUserHome(fake, () -> {
127 				try {
128 					maven().usingDefaultLocal();
129 					fail();
130 				} catch(IllegalStateException e) {}
131 			});
132 		}
133 
134 
135 		@Test
136 		public void givenAbsolutePathForCustomLocalRepositoryFoundInSettingsWhenNotADirectoryThenThrows()
137 		{
138 			String fake = Paths.get(".", "src", "test", "resources", "fake.user.home", "bad.abs.local.in.settings").toAbsolutePath().toString();
139 			runWithFakeUserHome(fake, () -> {
140 				try {
141 					maven().usingDefaultLocal();
142 					fail();
143 				} catch(IllegalStateException e) {}
144 			});
145 		}
146 
147 
148 		@Test
149 		public void givenNoSettingsAndNoDefaultLocalRepositoryThenThrows()
150 		{
151 			String fake = Paths.get(".", "src", "test", "resources", "fake.user.home", "no.local.no.settings").toAbsolutePath().toString();
152 			runWithFakeUserHome(fake, () -> {
153 				try {
154 					maven().usingDefaultLocal();
155 					fail();
156 				} catch(IllegalStateException e) {}
157 			});
158 		}
159 
160 
161 		@Test
162 		public void givenNoLocalRepositoryFoundSettingsWhenDefaultLocalIsPresentThenDefaultUsed()
163 		{
164 			Path path = Paths.get(".", "src", "test", "resources", "fake.user.home", "no.local.in.settings").toAbsolutePath();
165 			String fake = path.toString();
166 			File expected = path.resolve(Paths.get(".m2", "repository")).toFile();
167 			runWithFakeUserHome(fake, () -> {
168 				Maven maven = maven().usingDefaultLocal();
169 
170 				assertThat(maven.local.getBasedir(), is(equalTo(expected)));
171 			});
172 		}
173 
174 
175 		@Test
176 		public void givenNoSettingsWhenDefaultRepositoryPresentThenUsed()
177 		{
178 			Path path = Paths.get(".", "src", "test", "resources", "fake.user.home", "local.no.settings").toAbsolutePath();
179 
180 			File expected = path.resolve(Paths.get(".m2", "repository")).toFile();
181 			String fake = path.toString();
182 			runWithFakeUserHome(fake, () -> {
183 				Maven maven = maven()
184 						.usingDefaultLocal();
185 
186 				assertThat(maven.local.getBasedir(), is(equalTo(expected)));
187 			});
188 		}
189 	}
190 
191 	@Nested
192 	public class UsingRemoteRepository {
193 
194 		@Test
195 		public void usingCentral()
196 		{
197 			Maven maven = maven().usingCentral();
198 
199 			RemoteRepository expected = new RemoteRepository.Builder(CENTRAL_ID, DEFAULT_TYPE, CENTRAL_URL).build();
200 
201 			assertThat(maven.remotes, contains(expected));
202 		}
203 
204 
205 		@Test
206 		public void usingCustom()
207 		{
208 			Maven maven = maven().usingRemote("id", DEFAULT_TYPE, "http://repo.acme.corp/maven");
209 
210 			RemoteRepository expected = new RemoteRepository.Builder("id", DEFAULT_TYPE, "http://repo.acme.corp/maven").build();
211 
212 			assertThat(maven.remotes, contains(expected));
213 		}
214 
215 
216 		@Test
217 		public void usingMultiple()
218 		{
219 			Maven maven = maven()
220 					.usingCentral()
221 					.usingRemote("a", DEFAULT_TYPE, "http://repo.acme.corp/a")
222 					.usingRemote("b", DEFAULT_TYPE, "http://repo.acme.corp/b");
223 
224 			RemoteRepository a = new RemoteRepository.Builder("a", DEFAULT_TYPE, "http://repo.acme.corp/a").build();
225 			RemoteRepository b = new RemoteRepository.Builder("b", DEFAULT_TYPE, "http://repo.acme.corp/b").build();
226 			RemoteRepository c = new RemoteRepository.Builder(CENTRAL_ID, DEFAULT_TYPE, CENTRAL_URL).build();
227 
228 			assertThat(maven.remotes, containsInAnyOrder(a, b, c));
229 		}
230 
231 	}
232 
233 
234 	@Test
235 	void useALocalAsARemote() throws Exception
236 	{
237 		Path fakeHome = Paths.get(".", "target", "local-as-remote-fake-home").toAbsolutePath();
238 		fakeHome.resolve(Paths.get(".m2", "repository")).toFile().mkdirs();
239 
240 		runWithFakeUserHome(fakeHome.toString(), () -> {
241 			maven()
242 					.usingCentral()
243 					.usingDefaultLocal()
244 					.dependencies("junit:junit:4.12");
245 
246 			Path localPath = Paths.get(".", "target", "repo-local-from-local-as-remote");
247 
248 			Map<MavenArtifact, Archive> dependencies = maven()
249 					.usingDefaultLocalAsARemote()
250 					.usingLocal(localPath)
251 					.dependencies("junit:junit:4.12");
252 
253 			MavenArtifact junit = new MavenArtifact("junit", "junit", "4.12", "jar", "");
254 			MavenArtifact hamcrest = new MavenArtifact("org.hamcrest", "hamcrest-core", "1.3", "jar", "");
255 
256 			assertThat(dependencies, allOf(
257 					aMapWithSize(2),
258 					hasKey(junit),
259 					hasKey(hamcrest)));
260 
261 			Path remotesIndex = localPath.resolve(Paths.get("junit", "junit", "4.12", "_remote.repositories"));
262 			String meta = new String(Exceptional.apply(Files::readAllBytes, remotesIndex), UTF_8);
263 
264 			assertThat(meta, allOf(
265 					containsString(ID_LOCAL_AS_REMOTE),
266 					not(containsString("central"))));
267 		});
268 	}
269 
270 
271 	@Test
272 	void dependenciesToArchives() throws Exception
273 	{
274 		// EARCAM_SNIPPET_BEGIN: resolve-dependencies
275 		Map<MavenArtifact, Archive> dependencies = maven()
276 				.usingCentral()
277 				.usingLocal(Paths.get(".", "target", "repo-resolve-depgraph"))
278 				.dependencies("junit:junit:4.12");
279 
280 		MavenArtifact junit = new MavenArtifact("junit", "junit", "4.12", "jar", "");
281 		MavenArtifact hamcrest = new MavenArtifact("org.hamcrest", "hamcrest-core", "1.3", "jar", "");
282 
283 		assertThat(dependencies, allOf(
284 				aMapWithSize(2),
285 				hasKey(junit),
286 				hasKey(hamcrest)));
287 		// EARCAM_SNIPPET_END: resolve-dependencies
288 	}
289 
290 
291 	@SuppressWarnings("unchecked")
292 	@Test
293 	void dependenciesToClassPath() throws Exception
294 	{
295 		// EARCAM_SNIPPET_BEGIN: classpath
296 		List<String> classpath = maven()
297 				.usingCentral()
298 				.usingLocal(Paths.get(".", "target", "repo-resolve-classpath"))
299 				.classpath("junit:junit:4.12")
300 				.stream()
301 				.map(Object::toString)
302 				.collect(toList());
303 
304 		assertThat(classpath, containsInAnyOrder(
305 				endsWith("junit-4.12.jar"),
306 				endsWith("hamcrest-core-1.3.jar")));
307 
308 		// EARCAM_SNIPPET_END: classpath
309 	}
310 
311 
312 	@Test
313 	void installArchiveWithZeroDependenciesToLocal()
314 	{
315 		Archive archive = archive()
316 				.configured(asJar())
317 				.with(MavenTest.class)
318 				.toObjectModel();
319 
320 		Maven maven = maven()
321 				.usingCentral()
322 				.usingLocal(Paths.get(".", "target", "repo-install"));
323 
324 		MavenArtifact artifact = new MavenArtifact("com.acme", "com.acme.api", "0.0.1", "jar", "");
325 		maven.install(artifact, archive);
326 
327 		Map<MavenArtifact, Archive> dependencies = maven.dependencies("com.acme:com.acme.api:0.0.1");
328 
329 		assertThat(dependencies, hasKey(artifact));
330 	}
331 }