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.jpms;
20  
21  import static io.earcam.instrumental.archive.Archive.archive;
22  import static io.earcam.instrumental.archive.jpms.AsJpmsModule.asJpmsModule;
23  import static io.earcam.instrumental.module.jpms.ExportModifier.MANDATED;
24  import static java.nio.charset.StandardCharsets.UTF_8;
25  import static org.hamcrest.MatcherAssert.assertThat;
26  import static org.hamcrest.Matchers.aMapWithSize;
27  import static org.hamcrest.Matchers.allOf;
28  import static org.hamcrest.Matchers.anEmptyMap;
29  import static org.hamcrest.Matchers.arrayContaining;
30  import static org.hamcrest.Matchers.contains;
31  import static org.hamcrest.Matchers.containsInAnyOrder;
32  import static org.hamcrest.Matchers.empty;
33  import static org.hamcrest.Matchers.equalTo;
34  import static org.hamcrest.Matchers.hasEntry;
35  import static org.hamcrest.Matchers.is;
36  import static org.hamcrest.Matchers.nullValue;
37  
38  import java.util.Comparator;
39  import java.util.function.Predicate;
40  
41  import org.junit.jupiter.api.Test;
42  
43  import com.acme.DummyIntComparator;
44  import com.acme.DummyMain;
45  import com.acme.ext.Ext;
46  import com.acme.internal.DummyInternal;
47  
48  import io.earcam.instrumental.archive.Archive;
49  import io.earcam.instrumental.archive.ArchiveResource;
50  import io.earcam.instrumental.module.jpms.Export;
51  import io.earcam.instrumental.module.jpms.ModuleInfo;
52  import io.earcam.instrumental.module.jpms.Require;
53  import io.earcam.instrumental.module.jpms.RequireModifier;
54  
55  public class AsJpmsModuleTest {
56  
57  	@Test
58  	void emptyModule()
59  	{
60  		Archive archive = archive()
61  				.configured(asJpmsModule()
62  						.named("foo")
63  						.versioned("0.42.1"))
64  				.toObjectModel();
65  
66  		ModuleInfo moduleInfo = moduleInfoFrom(archive);
67  
68  		assertThat(moduleInfo.name(), is("foo"));
69  		assertThat(moduleInfo.version(), is("0.42.1"));
70  
71  		assertThat(moduleInfo.mainClass(), is(nullValue()));
72  		assertThat(moduleInfo.packages(), is(empty()));
73  		assertThat(moduleInfo.exports(), is(empty()));
74  		assertThat(moduleInfo.opens(), is(empty()));
75  		assertThat(moduleInfo.uses(), is(empty()));
76  		assertThat(moduleInfo.requires(), is(empty()));
77  		assertThat(moduleInfo.provides(), is(anEmptyMap()));
78  	}
79  
80  
81  	@Test
82  	void mainClass()
83  	{
84  		Archive archive = archive()
85  				.configured(asJpmsModule()
86  						.named("foo")
87  						.launching(DummyMain.class))
88  				.toObjectModel();
89  
90  		ModuleInfo moduleInfo = moduleInfoFrom(archive);
91  
92  		assertThat(moduleInfo.mainClass(), is(equalTo(DummyMain.class.getCanonicalName())));
93  	}
94  
95  
96  	private ModuleInfo moduleInfoFrom(Archive archive)
97  	{
98  		ModuleInfo moduleInfo = archive
99  				.content("module-info.class")
100 				.map(ArchiveResource::bytes)
101 				.map(ModuleInfo::read)
102 				.orElseThrow(AssertionError::new);
103 		return moduleInfo;
104 	}
105 
106 
107 	@Test
108 	void provides()
109 	{
110 		Archive archive = archive()
111 				.configured(asJpmsModule()
112 						.named("foo")
113 						.providing(Comparator.class, DummyIntComparator.class))
114 				.toObjectModel();
115 
116 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
117 
118 		assertThat(moduleInfo.provides(), hasEntry(
119 				equalTo(cn(Comparator.class)),
120 				arrayContaining(cn(DummyIntComparator.class))));
121 	}
122 
123 
124 	private static String cn(Class<?> type)
125 	{
126 		return type.getCanonicalName();
127 	}
128 
129 
130 	@Test
131 	void export()
132 	{
133 		// EARCAM_SNIPPET_BEGIN: export-predicate
134 		Predicate<String> predicate = e -> !e.contains("internal");
135 
136 		Archive archive = archive()
137 				.configured(asJpmsModule()
138 						.named("foo")
139 						.exporting(predicate))
140 				.with(DummyIntComparator.class)
141 				.with(DummyInternal.class)
142 				.toObjectModel();
143 		// EARCAM_SNIPPET_END: export-predicate
144 
145 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
146 
147 		Export expectedExport = new Export(pkg(DummyIntComparator.class), MANDATED.access());
148 
149 		assertThat(moduleInfo.exports(), contains(expectedExport));
150 		assertThat(moduleInfo.opens(), is(empty()));
151 	}
152 
153 
154 	private static String pkg(Class<?> type)
155 	{
156 		return type.getPackage().getName();
157 	}
158 
159 
160 	@Test
161 	void exportsTo()
162 	{
163 		String packageA = pkg(DummyIntComparator.class);
164 		String packageB = pkg(Ext.class);
165 		Predicate<String> predicateA = Predicate.isEqual(packageA);
166 		Predicate<String> predicateB = Predicate.isEqual(packageB);
167 
168 		Archive archive = archive()
169 				.configured(asJpmsModule()
170 						.named("foo")
171 						.exporting(predicateA, "a")
172 						.exporting(predicateB, "b"))
173 				.with(DummyIntComparator.class)
174 				.with(DummyInternal.class)
175 				.with(Ext.class)
176 				.toObjectModel();
177 
178 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
179 
180 		Export expectedExportA = new Export(packageA, MANDATED.access(), "a");
181 		Export expectedExportB = new Export(packageB, MANDATED.access(), "b");
182 
183 		assertThat(moduleInfo.exports(), contains(expectedExportA, expectedExportB));
184 		assertThat(moduleInfo.opens(), is(empty()));
185 	}
186 
187 
188 	@Test
189 	void opens()
190 	{
191 		String packageA = pkg(DummyIntComparator.class);
192 		String packageB = pkg(Ext.class);
193 		Predicate<String> predicateA = Predicate.isEqual(packageA);
194 		Predicate<String> predicateB = Predicate.isEqual(packageB);
195 
196 		Archive archive = archive()
197 				.configured(asJpmsModule()
198 						.named("foo")
199 						.opening(predicateA, "a")
200 						.opening(predicateB))
201 				.with(DummyIntComparator.class)
202 				.with(DummyInternal.class)
203 				.with(Ext.class)
204 				.toObjectModel();
205 
206 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
207 
208 		Export expectedExportA = new Export(packageA, MANDATED.access(), "a");
209 		Export expectedExportB = new Export(packageB, MANDATED.access());
210 
211 		assertThat(moduleInfo.opens(), contains(expectedExportA, expectedExportB));
212 		assertThat(moduleInfo.exports(), is(empty()));
213 	}
214 
215 
216 	@Test
217 	void requires()
218 	{
219 		Archive archive = archive()
220 				.configured(asJpmsModule()
221 						.named("foo")
222 						.requiring("bar")
223 						.requiring("hum.bug", "1.42.0"))
224 				.toObjectModel();
225 
226 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
227 
228 		Require expectedRequire1 = new Require("bar", RequireModifier.MANDATED.access(), null);
229 		Require expectedRequire2 = new Require("hum.bug", RequireModifier.MANDATED.access(), "1.42.0");
230 
231 		assertThat(moduleInfo.requires(), containsInAnyOrder(expectedRequire1, expectedRequire2));
232 	}
233 
234 
235 	@Test
236 	void uses()
237 	{
238 		Archive archive = archive()
239 				.configured(asJpmsModule()
240 						.named("foo")
241 						.using(Comparator.class)
242 						.using(Predicate.class))
243 				.toObjectModel();
244 
245 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
246 
247 		assertThat(moduleInfo.uses(), containsInAnyOrder(cn(Comparator.class), cn(Predicate.class)));
248 	}
249 
250 
251 	@Test
252 	void packages()
253 	{
254 		Archive archive = archive()
255 				.configured(asJpmsModule()
256 						.named("foo")
257 						.listingPackages())
258 				.with(DummyIntComparator.class)
259 				.with(Ext.class)
260 				.toObjectModel();
261 
262 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
263 
264 		assertThat(moduleInfo.packages(), containsInAnyOrder(pkg(DummyIntComparator.class), pkg(Ext.class)));
265 	}
266 
267 
268 	@Test
269 	void providingFromMetaInfServices()
270 	{
271 		Archive archive = archive()
272 				.configured(asJpmsModule()
273 						.named("foo")
274 						.providingFromMetaInfServices())
275 				.with(DummyIntComparator.class)
276 				.with("META-INF/services/java.util.Comparator", cn(DummyIntComparator.class).getBytes(UTF_8))
277 				.with("META-INF/servicehistory", "one careful owner".getBytes(UTF_8))
278 				.toObjectModel();
279 
280 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
281 
282 		assertThat(moduleInfo.provides(), allOf(
283 				aMapWithSize(1),
284 				hasEntry(equalTo("java.util.Comparator"), arrayContaining(cn(DummyIntComparator.class)))));
285 	}
286 
287 
288 	@Test
289 	void notProvidingFromMetaInfServices()
290 	{
291 		Archive archive = archive()
292 				.configured(asJpmsModule()
293 						.named("foo"))
294 				.with(DummyIntComparator.class)
295 				.with("META-INF/services/java.util.Comparator", cn(DummyIntComparator.class).getBytes(UTF_8))
296 				.with("META-INF/servicehistory", "one careful owner".getBytes(UTF_8))
297 				.toObjectModel();
298 
299 		ModuleInfo moduleInfo = moduleInfoFrom(archive);
300 
301 		assertThat(moduleInfo.provides(), is(anEmptyMap()));
302 	}
303 }