Skip to content

Commit 5132849

Browse files
committed
Make the target test plugable so they can be reused (e.g. by Tycho)
One of the important parts is that Tycho+m2e behave the same in regard to the m2e target support so that if something works in the IDE it also works in the build. This is an attempt to generlaize the tests in a way so they can be reused at Tycho by providing a small loader that transform the Tycho content into something understood by the test, so ideally we can run the same tests in Tycho as in m2e. Signed-off-by: Christoph Läubrich <[email protected]>
1 parent 2294d62 commit 5132849

13 files changed

+360
-127
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.eclipse.m2e.pde.target.tests.spi.M2ETargetLocationLoader

org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/AbstractMavenTargetTest.java

Lines changed: 59 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import java.util.HashMap;
2626
import java.util.List;
2727
import java.util.Map;
28+
import java.util.ServiceLoader;
29+
import java.util.ServiceLoader.Provider;
2830
import java.util.Set;
2931
import java.util.function.BiPredicate;
3032
import java.util.function.Function;
@@ -33,51 +35,51 @@
3335
import java.util.jar.JarFile;
3436
import java.util.stream.Collectors;
3537

36-
import org.eclipse.core.runtime.CoreException;
38+
import org.eclipse.core.runtime.IStatus;
39+
import org.eclipse.core.runtime.MultiStatus;
40+
import org.eclipse.core.runtime.Status;
3741
import org.eclipse.core.runtime.URIUtil;
3842
import org.eclipse.equinox.frameworkadmin.BundleInfo;
39-
import org.eclipse.m2e.core.embedder.ArtifactKey;
40-
import org.eclipse.m2e.pde.target.MavenTargetLocationFactory;
41-
import org.eclipse.pde.core.target.ITargetDefinition;
43+
import org.eclipse.m2e.pde.target.tests.spi.TargetLocationLoader;
4244
import org.eclipse.pde.core.target.ITargetLocation;
43-
import org.eclipse.pde.core.target.ITargetPlatformService;
4445
import org.eclipse.pde.core.target.NameVersionDescriptor;
4546
import org.eclipse.pde.core.target.TargetBundle;
4647
import org.eclipse.pde.core.target.TargetFeature;
48+
import org.junit.Rule;
49+
import org.junit.rules.TemporaryFolder;
4750

4851
public abstract class AbstractMavenTargetTest {
4952
static final String SOURCE_BUNDLE_SUFFIX = ".source";
5053
static final TargetBundle[] EMPTY = {};
5154

52-
static ITargetDefinition resolveMavenTarget(String targetXML) throws CoreException {
53-
@SuppressWarnings("restriction")
54-
ITargetPlatformService s = org.eclipse.pde.internal.core.PDECore.getDefault()
55-
.acquireService(ITargetPlatformService.class);
56-
ITargetDefinition target = s.newTarget();
55+
@Rule
56+
public TemporaryFolder temporaryFolder = new TemporaryFolder();
5757

58-
setMavenTargetLocationAndResolver(target, targetXML);
59-
return target;
60-
}
58+
private static ServiceLoader<TargetLocationLoader> LOCATION_LOADER = ServiceLoader.load(TargetLocationLoader.class,
59+
AbstractMavenTargetTest.class.getClassLoader());
60+
private static TargetLocationLoader loader;
6161

62-
static void setMavenTargetLocationAndResolver(ITargetDefinition target, String targetXML) throws CoreException {
63-
ITargetLocation targetLocation = new MavenTargetLocationFactory().getTargetLocation("Maven", targetXML);
64-
target.setTargetLocations(new ITargetLocation[] { targetLocation });
65-
target.resolve(null);
62+
ITargetLocation resolveMavenTarget(String targetXML) throws Exception {
63+
return getLoader().resolveMavenTarget(targetXML, temporaryFolder.newFolder());
6664
}
6765

68-
// --- common assertion utilities ---
69-
70-
interface ExpectedUnit {
71-
72-
String id();
73-
74-
boolean isSourceBundle();
75-
76-
boolean isOriginal();
66+
private static TargetLocationLoader getLoader() {
67+
if (loader == null) {
68+
Provider<TargetLocationLoader> provider = LOCATION_LOADER.stream().sorted().findFirst().orElseThrow(
69+
() -> new IllegalStateException("No TargetLocationLoader found on classpath of test!"));
70+
loader = provider.get();
71+
}
72+
return loader;
73+
}
7774

78-
ArtifactKey key();
75+
protected static void assertStatusOk(IStatus status) {
76+
if (!status.isOK()) {
77+
throw new AssertionError(status.toString(), status.getException());
78+
}
7979
}
8080

81+
// --- common assertion utilities ---
82+
8183
private static <U extends ExpectedUnit, T> Map<U, T> assertTargetContent(List<U> expectedUnits, T[] allUnit,
8284
BiPredicate<U, T> matcher, Function<T, URI> getLocation, Predicate<T> isSourceUnit,
8385
Function<T, String> getSourceTarget, Function<T, String> toString) {
@@ -130,20 +132,6 @@ private static <T> boolean isOriginalArtifact(ExpectedUnit expectedUnit, T unit,
130132

131133
// --- assertion utilities for Bundles in target ---
132134

133-
static record ExpectedBundle(String bsn, String version, boolean isSourceBundle, boolean isOriginal,
134-
ArtifactKey key) implements ExpectedUnit {
135-
136-
@Override
137-
public String id() {
138-
return bsn();
139-
}
140-
141-
@Override
142-
public String toString() {
143-
return bsn + ":" + version;
144-
}
145-
}
146-
147135
static ExpectedBundle originalOSGiBundle(String bsn, String version, String groupArtifact) {
148136
return originalOSGiBundle(bsn, version, groupArtifact, version);
149137
}
@@ -161,8 +149,8 @@ static ExpectedBundle generatedBundle(String bsn, String version, String groupAr
161149
static List<ExpectedBundle> withSourceBundles(List<ExpectedBundle> mainBundles) {
162150
return mainBundles.stream().<ExpectedBundle>mapMulti((unit, downStream) -> {
163151
downStream.accept(unit);
164-
String sourceId = unit.bsn + SOURCE_BUNDLE_SUFFIX;
165-
ExpectedBundle sourceUnit = new ExpectedBundle(sourceId, unit.version, true, false, unit.key);
152+
String sourceId = unit.bsn() + SOURCE_BUNDLE_SUFFIX;
153+
ExpectedBundle sourceUnit = new ExpectedBundle(sourceId, unit.version(), true, false, unit.key());
166154
downStream.accept(sourceUnit);
167155
}).toList();
168156
}
@@ -175,12 +163,12 @@ static Attributes getManifestMainAttributes(TargetBundle targetBundle) throws IO
175163
}
176164
}
177165

178-
static void assertTargetBundles(ITargetDefinition target, List<ExpectedBundle> expectedUnits) {
179-
assertTargetContent(expectedUnits, target.getAllBundles(), //
166+
static void assertTargetBundles(ITargetLocation target, List<ExpectedBundle> expectedUnits) {
167+
assertTargetContent(expectedUnits, target.getBundles(), //
180168
(expectedBundle, bundle) -> {
181169
BundleInfo info = bundle.getBundleInfo();
182170
return expectedBundle.bsn().equals(info.getSymbolicName())
183-
&& expectedBundle.version.equals(info.getVersion());
171+
&& expectedBundle.version().equals(info.getVersion());
184172
}, //
185173
tb -> tb.getBundleInfo().getLocation(), //
186174
tb -> tb.isSourceBundle(),
@@ -190,15 +178,6 @@ static void assertTargetBundles(ITargetDefinition target, List<ExpectedBundle> e
190178

191179
// --- assertion utilities for Features in a target ---
192180

193-
static record ExpectedFeature(String id, String version, boolean isSourceBundle, boolean isOriginal,
194-
ArtifactKey key, List<NameVersionDescriptor> containedPlugins) implements ExpectedUnit {
195-
196-
@Override
197-
public String toString() {
198-
return id + ":" + version;
199-
}
200-
}
201-
202181
static ExpectedFeature originalFeature(String id, String version, String groupArtifact,
203182
List<NameVersionDescriptor> containedPlugins) {
204183
ArtifactKey key = ArtifactKey.fromPortableString(groupArtifact + ":" + version + "::");
@@ -217,19 +196,19 @@ static List<ExpectedFeature> withSourceFeatures(List<ExpectedFeature> mainFeatur
217196
return mainFeatures.stream().<ExpectedFeature>mapMulti((feature, downStream) -> {
218197
downStream.accept(feature);
219198
String sourceId = feature.id() + SOURCE_BUNDLE_SUFFIX;
220-
List<NameVersionDescriptor> sourcePlugins = feature.containedPlugins.stream()
199+
List<NameVersionDescriptor> sourcePlugins = feature.containedPlugins().stream()
221200
.map(d -> featurePlugin(d.getId() + SOURCE_BUNDLE_SUFFIX, d.getVersion())).toList();
222-
ExpectedFeature sourceUnit = new ExpectedFeature(sourceId, feature.version, true, false, feature.key,
201+
ExpectedFeature sourceUnit = new ExpectedFeature(sourceId, feature.version(), true, false, feature.key(),
223202
sourcePlugins);
224203
downStream.accept(sourceUnit);
225204
}).toList();
226205
}
227206

228-
static Map<ExpectedFeature, TargetFeature> assertTargetFeatures(ITargetDefinition target,
207+
static Map<ExpectedFeature, TargetFeature> assertTargetFeatures(ITargetLocation target,
229208
List<ExpectedFeature> expectedFeatures) {
230-
var encounteredFeatures = assertTargetContent(expectedFeatures, target.getAllFeatures(), //
209+
var encounteredFeatures = assertTargetContent(expectedFeatures, target.getFeatures(), //
231210
(expectedFeature, feature) -> expectedFeature.id().equals(feature.getId())
232-
&& expectedFeature.version.equals(feature.getVersion()), //
211+
&& expectedFeature.version().equals(feature.getVersion()), //
233212
f -> Path.of(f.getLocation()).toUri(), //
234213
f -> isSourceFeature(f), //
235214
f -> isSourceFeature(f) ? f.getId().substring(0, f.getId().length() - SOURCE_BUNDLE_SUFFIX.length())
@@ -241,8 +220,27 @@ static Map<ExpectedFeature, TargetFeature> assertTargetFeatures(ITargetDefinitio
241220
return encounteredFeatures;
242221
}
243222

244-
private static boolean isSourceFeature(TargetFeature f) {
223+
static boolean isSourceFeature(TargetFeature f) {
245224
return f.getId().endsWith(SOURCE_BUNDLE_SUFFIX)
246225
&& Arrays.stream(f.getPlugins()).allMatch(d -> d.getId().endsWith(SOURCE_BUNDLE_SUFFIX));
247226
}
227+
228+
static IStatus getTargetStatus(ITargetLocation target) {
229+
IStatus status = target.getStatus();
230+
if (status != null && !status.isOK()) {
231+
return status;
232+
}
233+
MultiStatus result = new MultiStatus("org.eclipse.pde.core", 0,
234+
"Problems occurred getting the plug-ins in this container", null);
235+
for (TargetBundle targetBundle : target.getBundles()) {
236+
IStatus bundleStatus = targetBundle.getStatus();
237+
if (!bundleStatus.isOK()) {
238+
result.add(bundleStatus);
239+
}
240+
}
241+
if (result.isOK()) {
242+
return Status.OK_STATUS;
243+
}
244+
return result;
245+
}
248246
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2008-2022 Sonatype, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License 2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Sonatype, Inc. - initial API and implementation
12+
* Hannes Wellmann - Convert to record
13+
*******************************************************************************/
14+
15+
package org.eclipse.m2e.pde.target.tests;
16+
17+
import java.io.Serializable;
18+
19+
import org.eclipse.osgi.util.NLS;
20+
21+
public record ArtifactKey(String groupId, String artifactId, String version, String classifier)
22+
implements Serializable {
23+
public static ArtifactKey fromPortableString(String str) {
24+
int p = 0;
25+
int c = nextColonIndex(str, p);
26+
String groupId = substring(str, p, c);
27+
28+
p = c + 1;
29+
c = nextColonIndex(str, p);
30+
String artifactId = substring(str, p, c);
31+
32+
p = c + 1;
33+
c = nextColonIndex(str, p);
34+
String version = substring(str, p, c);
35+
36+
p = c + 1;
37+
c = nextColonIndex(str, p);
38+
String classifier = substring(str, p, c);
39+
40+
return new ArtifactKey(groupId, artifactId, version, classifier);
41+
}
42+
43+
private static String substring(String str, int start, int end) {
44+
String substring = str.substring(start, end);
45+
return "".equals(substring) ? null : substring; //$NON-NLS-1$
46+
}
47+
48+
private static int nextColonIndex(String str, int pos) {
49+
int idx = str.indexOf(':', pos);
50+
if (idx < 0) {
51+
throw new IllegalArgumentException(NLS.bind("Invalid portable string: {0}", str));
52+
}
53+
return idx;
54+
}
55+
}

org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/DependencyExclusionTest.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@
1313
package org.eclipse.m2e.pde.target.tests;
1414

1515
import static org.junit.Assert.assertArrayEquals;
16-
import static org.junit.Assert.assertTrue;
1716

1817
import java.util.List;
1918

20-
import org.eclipse.pde.core.target.ITargetDefinition;
19+
import org.eclipse.pde.core.target.ITargetLocation;
2120
import org.junit.Test;
2221
import org.junit.runner.RunWith;
2322
import org.junit.runners.Parameterized;
@@ -36,7 +35,7 @@ public static List<Boolean> dependencyConfigurations() {
3635

3736
@Test
3837
public void testExclusionOfDirectRequirement() throws Exception {
39-
ITargetDefinition target = resolveMavenTarget(String.format(
38+
ITargetLocation target = resolveMavenTarget(String.format(
4039
"""
4140
<location includeDependencyDepth="infinite" includeDependencyScopes="compile" includeSource="%s" missingManifest="error" type="Maven">
4241
<dependencies>
@@ -51,15 +50,16 @@ public void testExclusionOfDirectRequirement() throws Exception {
5150
</location>
5251
""",
5352
includeSource));
54-
assertTrue(target.getStatus().isOK());
55-
assertArrayEquals(EMPTY, target.getAllFeatures());
53+
assertStatusOk(target.getStatus());
54+
assertArrayEquals(EMPTY, target.getFeatures());
5655
List<ExpectedBundle> expectedBundles = List.of(junitPlatformCommons("1.9.3"));
5756
assertTargetBundles(target, includeSource ? withSourceBundles(expectedBundles) : expectedBundles);
5857
}
5958

6059
@Test
6160
public void testExclusionOfDirectAndTransitivRequirement() throws Exception {
62-
ITargetDefinition target = resolveMavenTarget(String.format(
61+
ITargetLocation target = resolveMavenTarget(String
62+
.format(
6363
"""
6464
<location includeDependencyDepth="infinite" includeDependencyScopes="compile" includeSource="%s" missingManifest="error" type="Maven">
6565
<dependencies>
@@ -74,8 +74,8 @@ public void testExclusionOfDirectAndTransitivRequirement() throws Exception {
7474
</location>
7575
""",
7676
includeSource));
77-
assertTrue(target.getStatus().isOK());
78-
assertArrayEquals(EMPTY, target.getAllFeatures());
77+
assertStatusOk(target.getStatus());
78+
assertArrayEquals(EMPTY, target.getFeatures());
7979
List<ExpectedBundle> expectedBundles = List.of(//
8080
junitJupiterAPI(), //
8181
junitPlatformCommons("1.9.3"), //
@@ -86,7 +86,8 @@ public void testExclusionOfDirectAndTransitivRequirement() throws Exception {
8686

8787
@Test
8888
public void testExclusionOfMultipleVersions() throws Exception {
89-
ITargetDefinition target = resolveMavenTarget(String.format(
89+
ITargetLocation target = resolveMavenTarget(String
90+
.format(
9091
"""
9192
<location includeDependencyDepth="infinite" includeDependencyScopes="compile" includeSource="%s" missingManifest="error" type="Maven">
9293
<dependencies>
@@ -108,8 +109,8 @@ public void testExclusionOfMultipleVersions() throws Exception {
108109
</location>
109110
""",
110111
includeSource));
111-
assertTrue(target.getStatus().isOK());
112-
assertArrayEquals(EMPTY, target.getAllFeatures());
112+
assertStatusOk(target.getStatus());
113+
assertArrayEquals(EMPTY, target.getFeatures());
113114
List<ExpectedBundle> expectedBundles = List.of(//
114115
junitJupiterAPI(), //
115116
junitPlatformCommons("1.9.3"), //
@@ -120,7 +121,8 @@ public void testExclusionOfMultipleVersions() throws Exception {
120121

121122
@Test
122123
public void testExclusionOfDifferentVersions() throws Exception {
123-
ITargetDefinition target = resolveMavenTarget(String.format(
124+
ITargetLocation target = resolveMavenTarget(String
125+
.format(
124126
"""
125127
<location includeDependencyDepth="infinite" includeDependencyScopes="compile" includeSource="%s" missingManifest="error" type="Maven">
126128
<dependencies>
@@ -141,8 +143,8 @@ public void testExclusionOfDifferentVersions() throws Exception {
141143
</location>
142144
""",
143145
includeSource));
144-
assertTrue(target.getStatus().isOK());
145-
assertArrayEquals(EMPTY, target.getAllFeatures());
146+
assertStatusOk(target.getStatus());
147+
assertArrayEquals(EMPTY, target.getFeatures());
146148
List<ExpectedBundle> expectedBundles = List.of(//
147149
junitJupiterAPI(), //
148150
junitPlatformCommons("1.9.3"), //
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2023, 2023 Hannes Wellmann and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* https://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Hannes Wellmann - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.m2e.pde.target.tests;
14+
15+
public record ExpectedBundle(String bsn, String version, boolean isSourceBundle, boolean isOriginal,
16+
ArtifactKey key) implements ExpectedUnit {
17+
18+
@Override
19+
public String id() {
20+
return bsn();
21+
}
22+
23+
@Override
24+
public String toString() {
25+
return bsn + ":" + version;
26+
}
27+
}

0 commit comments

Comments
 (0)