Skip to content

Commit 5fa5c20

Browse files
committed
ATs for dependency conflicts in plugins
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
1 parent 2e49308 commit 5fa5c20

File tree

12 files changed

+310
-21
lines changed

12 files changed

+310
-21
lines changed

acceptance-tests/catalogless-test-plugins/build.gradle

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,8 @@
22
dependencies {
33
api 'org.slf4j:slf4j-api'
44

5-
implementation project(':acceptance-tests:dsl')
6-
implementation project(':app')
7-
implementation project(':crypto:algorithms')
8-
implementation project(':datatypes')
9-
implementation project(':ethereum:api')
10-
implementation project(':ethereum:core')
11-
implementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts')
12-
implementation project(':ethereum:eth')
13-
implementation project(':ethereum:rlp')
14-
implementation project(':evm')
155
implementation project(':plugin-api')
166
implementation 'com.google.auto.service:auto-service'
17-
implementation 'info.picocli:picocli'
187

198
testImplementation 'org.assertj:assertj-core'
209
testImplementation 'org.junit.jupiter:junit-jupiter'

acceptance-tests/detached-outdated-test-plugins/settings.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ pluginManagement {
77
}
88
}
99

10-
rootProject.name = 'outdated-test-plugins'
10+
rootProject.name = 'outdatedTestPlugins'

acceptance-tests/detached-test-plugins/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ jar {
2020
'Implementation-Version': project.version
2121
)
2222
}
23+
}
24+
25+
tasks.withType(AbstractArchiveTask).configureEach {
26+
archiveVersion = ''
27+
archiveBaseName = 'testPlugins'
2328
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
plugins {
2+
id 'net.consensys.besu-plugin-distribution' version '0.1.4'
3+
}
4+
5+
group = 'org.hyperledger.besu.tests'
6+
version = besuVersion
7+
8+
java {
9+
sourceCompatibility = JavaVersion.VERSION_21
10+
targetCompatibility = JavaVersion.VERSION_21
11+
}
12+
13+
dependencies {
14+
// this is just to force that dependency to be present in the plugin distribution
15+
// so we can create an ad-hoc conflict with the other plugin
16+
runtimeOnly 'org.junit.jupiter:junit-jupiter-api:5.14.2'
17+
}
18+
19+
jar {
20+
archiveFileName = 'dependencyConflict1.jar'
21+
manifest {
22+
attributes(
23+
'Specification-Title': archiveBaseName,
24+
'Specification-Version': project.version,
25+
'Implementation-Title': archiveBaseName,
26+
'Implementation-Version': project.version
27+
)
28+
}
29+
}
30+
31+
tasks.withType(AbstractArchiveTask).configureEach {
32+
archiveVersion = ''
33+
archiveBaseName = 'dependencyConflictPlugin2'
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.tests.acceptance.plugins;
16+
17+
import org.hyperledger.besu.plugin.BesuPlugin;
18+
import org.hyperledger.besu.plugin.ServiceManager;
19+
20+
import com.google.auto.service.AutoService;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
@AutoService(BesuPlugin.class)
25+
public class TestDependencyConflict1Plugin implements BesuPlugin {
26+
private static final Logger LOG = LoggerFactory.getLogger(TestDependencyConflict1Plugin.class);
27+
28+
@Override
29+
public void register(final ServiceManager serviceManager) {
30+
LOG.info("Registering TestDependencyConflict1Plugin");
31+
}
32+
33+
@Override
34+
public void start() {
35+
LOG.info("Starting TestDependencyConflict1Plugin");
36+
}
37+
38+
@Override
39+
public void stop() {
40+
LOG.info("Stopping TestDependencyConflict1Plugin");
41+
}
42+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
plugins {
2+
id 'net.consensys.besu-plugin-distribution' version '0.1.4'
3+
}
4+
5+
group = 'org.hyperledger.besu.tests'
6+
version = besuVersion
7+
8+
java {
9+
sourceCompatibility = JavaVersion.VERSION_21
10+
targetCompatibility = JavaVersion.VERSION_21
11+
}
12+
13+
dependencies {
14+
// this is just to force that dependency to be present in the plugin distribution
15+
// so we can create an ad-hoc conflict with the other plugin.
16+
// Be sure that the version is not the same as the other plugin.
17+
runtimeOnly 'org.junit.jupiter:junit-jupiter-api:5.14.1'
18+
}
19+
20+
jar {
21+
archiveFileName = 'dependencyConflict2.jar'
22+
manifest {
23+
attributes(
24+
'Specification-Title': archiveBaseName,
25+
'Specification-Version': project.version,
26+
'Implementation-Title': archiveBaseName,
27+
'Implementation-Version': project.version
28+
)
29+
}
30+
}
31+
32+
tasks.withType(AbstractArchiveTask).configureEach {
33+
archiveVersion = ''
34+
archiveBaseName = 'dependencyConflictPlugin1'
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.tests.acceptance.plugins;
16+
17+
import org.hyperledger.besu.plugin.BesuPlugin;
18+
import org.hyperledger.besu.plugin.ServiceManager;
19+
20+
import com.google.auto.service.AutoService;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
@AutoService(BesuPlugin.class)
25+
public class TestDependencyConflict2Plugin implements BesuPlugin {
26+
private static final Logger LOG = LoggerFactory.getLogger(TestDependencyConflict2Plugin.class);
27+
28+
@Override
29+
public void register(final ServiceManager serviceManager) {
30+
LOG.info("Registering TestDependencyConflict2Plugin");
31+
}
32+
33+
@Override
34+
public void start() {
35+
LOG.info("Starting TestDependencyConflict2Plugin");
36+
}
37+
38+
@Override
39+
public void stop() {
40+
LOG.info("Stopping TestDependencyConflict2Plugin");
41+
}
42+
}

acceptance-tests/detached-test-plugins/settings.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ pluginManagement {
77
}
88
}
99

10-
rootProject.name = 'test-plugins'
10+
rootProject.name = 'testPlugins'
11+
include 'dependency-conflict-1'
12+
include 'dependency-conflict-2'

acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656

5757
import java.io.File;
5858
import java.io.FileInputStream;
59+
import java.io.FileOutputStream;
5960
import java.io.IOException;
61+
import java.io.InputStream;
6062
import java.net.ConnectException;
6163
import java.net.URI;
6264
import java.nio.file.Files;
@@ -69,6 +71,8 @@
6971
import java.util.Optional;
7072
import java.util.Properties;
7173
import java.util.concurrent.TimeUnit;
74+
import java.util.zip.ZipEntry;
75+
import java.util.zip.ZipInputStream;
7276

7377
import com.google.common.base.MoreObjects;
7478
import com.google.common.io.MoreFiles;
@@ -223,11 +227,21 @@ public BesuNode(
223227
pluginName -> {
224228
try {
225229
homeDirectory.resolve("plugins").toFile().mkdirs();
226-
copyResource(
227-
pluginName + ".jar", homeDirectory.resolve("plugins/" + pluginName + ".jar"));
228-
BesuNode.this.plugins.add(pluginName);
229-
} catch (final IOException e) {
230-
LOG.error("Could not find plugin \"{}\" in resources", pluginName);
230+
try {
231+
copyResource(
232+
pluginName + ".jar", homeDirectory.resolve("plugins/" + pluginName + ".jar"));
233+
BesuNode.this.plugins.add(pluginName);
234+
} catch (final IllegalArgumentException jarException) {
235+
// JAR not found, try ZIP
236+
try {
237+
unzipPlugin(pluginName + ".zip", homeDirectory.resolve("plugins"));
238+
BesuNode.this.plugins.add(pluginName);
239+
} catch (final IOException zipException) {
240+
LOG.error("Could not find plugin \"{}\" as JAR or ZIP in resources", pluginName);
241+
}
242+
}
243+
} catch (final Exception e) {
244+
LOG.error("Error loading plugin \"{}\"", pluginName, e);
231245
}
232246
});
233247
this.requestedPlugins = requestedPlugins;
@@ -250,6 +264,34 @@ private static Path createTmpDataDirectory() {
250264
}
251265
}
252266

267+
private void unzipPlugin(final String zipResourceName, final Path targetDirectory)
268+
throws IOException {
269+
try (final InputStream zipInputStream =
270+
getClass().getClassLoader().getResourceAsStream(zipResourceName)) {
271+
if (zipInputStream == null) {
272+
throw new IOException("Resource not found: " + zipResourceName);
273+
}
274+
try (final ZipInputStream zis = new ZipInputStream(zipInputStream)) {
275+
ZipEntry entry;
276+
while ((entry = zis.getNextEntry()) != null) {
277+
if (!entry.isDirectory()) {
278+
// Extract only the file name without any directory path
279+
final String fileName = new File(entry.getName()).getName();
280+
final Path targetPath = targetDirectory.resolve(fileName);
281+
try (final FileOutputStream fos = new FileOutputStream(targetPath.toFile())) {
282+
final byte[] buffer = new byte[8192];
283+
int len;
284+
while ((len = zis.read(buffer)) > 0) {
285+
fos.write(buffer, 0, len);
286+
}
287+
}
288+
}
289+
zis.closeEntry();
290+
}
291+
}
292+
}
293+
}
294+
253295
@Override
254296
public boolean isJsonRpcEnabled() {
255297
return jsonRpcConfiguration().isEnabled();

acceptance-tests/tests/build.gradle

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,10 @@ test.enabled = false
8888
sourceSets {
8989
test {
9090
resources {
91-
srcDirs "${rootDir}/acceptance-tests/detached-test-plugins/build/libs"
92-
srcDirs "${rootDir}/acceptance-tests/detached-outdated-test-plugins/build/libs"
91+
srcDirs "${rootDir}/acceptance-tests/detached-test-plugins/build/distributions"
92+
srcDirs "${rootDir}/acceptance-tests/detached-test-plugins/dependency-conflict-1/build/distributions"
93+
srcDirs "${rootDir}/acceptance-tests/detached-test-plugins/dependency-conflict-2/build/distributions"
94+
srcDirs "${rootDir}/acceptance-tests/detached-outdated-test-plugins/build/distributions"
9395
srcDirs "${rootDir}/acceptance-tests/catalogless-test-plugins/build/libs"
9496
}
9597
}

0 commit comments

Comments
 (0)