Skip to content

Commit fe19dbb

Browse files
committed
Add acceptance test
Signed-off-by: Fabio Di Fabio <[email protected]>
1 parent 173f825 commit fe19dbb

File tree

8 files changed

+251
-81
lines changed

8 files changed

+251
-81
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,19 @@
4848
import org.hyperledger.besu.tests.acceptance.dsl.transaction.web3.Web3Transactions;
4949

5050
import java.io.BufferedReader;
51+
import java.io.File;
5152
import java.io.IOException;
5253
import java.io.InputStreamReader;
5354
import java.math.BigInteger;
55+
import java.nio.file.Files;
56+
import java.nio.file.Path;
5457
import java.util.concurrent.ExecutorService;
5558
import java.util.concurrent.Executors;
59+
import java.util.concurrent.TimeUnit;
60+
import java.util.stream.Stream;
5661

5762
import org.apache.logging.log4j.ThreadContext;
63+
import org.awaitility.Awaitility;
5864
import org.junit.jupiter.api.AfterEach;
5965
import org.junit.jupiter.api.BeforeEach;
6066
import org.junit.jupiter.api.Test;
@@ -193,6 +199,21 @@ protected void waitForBlockHeight(final Node node, final long blockchainHeight)
193199
.isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight)));
194200
}
195201

202+
protected void waitForFile(final Path path) {
203+
final File file = path.toFile();
204+
Awaitility.waitAtMost(30, TimeUnit.SECONDS)
205+
.until(
206+
() -> {
207+
if (file.exists()) {
208+
try (final Stream<String> s = Files.lines(path)) {
209+
return s.count() > 0;
210+
}
211+
} else {
212+
return false;
213+
}
214+
});
215+
}
216+
196217
@Test
197218
public void dryRunDetector() {
198219
assertThat(true)

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,21 @@ public BesuNode createPluginsNode(
310310
.build());
311311
}
312312

313+
public BesuNode createPluginsNode(
314+
final String name,
315+
final List<String> plugins,
316+
final UnaryOperator<BesuNodeConfigurationBuilder> configBuilder)
317+
throws IOException {
318+
319+
BesuNodeConfigurationBuilder builder =
320+
new BesuNodeConfigurationBuilder()
321+
.name(name)
322+
.webSocketConfiguration(node.createWebSocketEnabledConfig())
323+
.plugins(plugins);
324+
325+
return create(configBuilder.apply(builder).build());
326+
}
327+
313328
public BesuNode createArchiveNodeWithRpcApis(final String name, final String... enabledRpcApis)
314329
throws IOException {
315330
final JsonRpcConfiguration jsonRpcConfig = node.createJsonRpcEnabledConfig();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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 static java.nio.charset.StandardCharsets.UTF_8;
18+
19+
import org.hyperledger.besu.datatypes.HardforkId;
20+
import org.hyperledger.besu.plugin.BesuPlugin;
21+
import org.hyperledger.besu.plugin.ServiceManager;
22+
import org.hyperledger.besu.plugin.data.BlockHeader;
23+
import org.hyperledger.besu.plugin.services.BesuEvents;
24+
import org.hyperledger.besu.plugin.services.BlockchainService;
25+
26+
import java.io.File;
27+
import java.io.IOException;
28+
import java.nio.file.Files;
29+
import java.util.ArrayList;
30+
import java.util.List;
31+
import java.util.stream.Collectors;
32+
33+
import com.google.auto.service.AutoService;
34+
import org.slf4j.Logger;
35+
import org.slf4j.LoggerFactory;
36+
37+
@AutoService(BesuPlugin.class)
38+
public class TestBlockchainServicePlugin implements BesuPlugin {
39+
private static final Logger LOG = LoggerFactory.getLogger(TestBlockchainServicePlugin.class);
40+
private final List<HardforkSeen> seenHardforks = new ArrayList<>();
41+
private ServiceManager serviceManager;
42+
private File callbackDir;
43+
44+
@Override
45+
public void register(final ServiceManager serviceManager) {
46+
LOG.info("Registering TestBlockchainServicePlugin");
47+
this.serviceManager = serviceManager;
48+
callbackDir = new File(System.getProperty("besu.plugins.dir", "plugins"));
49+
}
50+
51+
@Override
52+
public void start() {
53+
LOG.info("Starting TestBlockchainServicePlugin");
54+
final var blockchainService = serviceManager.getService(BlockchainService.class).orElseThrow();
55+
56+
serviceManager
57+
.getService(BesuEvents.class)
58+
.orElseThrow()
59+
.addBlockAddedListener(
60+
addedBlockContext -> {
61+
LOG.info("Block added: {}", addedBlockContext);
62+
final var hardforkSeen =
63+
queryHardfork(blockchainService, addedBlockContext.getBlockHeader());
64+
seenHardforks.add(
65+
queryHardfork(blockchainService, addedBlockContext.getBlockHeader()));
66+
if (hardforkSeen.current.equals(HardforkId.MainnetHardforkId.LONDON)) {
67+
LOG.info("Writing seen hardforks: {}", seenHardforks);
68+
writeSeenHardforks();
69+
}
70+
});
71+
72+
seenHardforks.add(queryHardfork(blockchainService, blockchainService.getChainHeadHeader()));
73+
}
74+
75+
private HardforkSeen queryHardfork(
76+
final BlockchainService blockchainService, final BlockHeader header) {
77+
final var currentHardfork = blockchainService.getHardforkId(header);
78+
final var nextHardfork =
79+
blockchainService.getNextBlockHardforkId(header, header.getTimestamp() + 1);
80+
81+
return new HardforkSeen(header.getNumber(), currentHardfork, nextHardfork);
82+
}
83+
84+
@Override
85+
public void stop() {}
86+
87+
private void writeSeenHardforks() {
88+
try {
89+
final File callbackFile = new File(callbackDir, "hardfork.list");
90+
if (!callbackFile.getParentFile().exists()) {
91+
callbackFile.getParentFile().mkdirs();
92+
callbackFile.getParentFile().deleteOnExit();
93+
}
94+
95+
final var content =
96+
seenHardforks.stream()
97+
.map(
98+
r ->
99+
String.join(
100+
",", String.valueOf(r.blockNumber), r.current.name(), r.next.name()))
101+
.collect(Collectors.joining("\n"));
102+
103+
Files.write(callbackFile.toPath(), content.getBytes(UTF_8));
104+
callbackFile.deleteOnExit();
105+
} catch (final IOException ioe) {
106+
throw new RuntimeException(ioe);
107+
}
108+
}
109+
110+
private record HardforkSeen(long blockNumber, HardforkId current, HardforkId next) {}
111+
}

acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BadCLIOptionsPluginTest.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@
1919
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
2020
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
2121

22-
import java.io.File;
23-
import java.nio.file.Files;
2422
import java.nio.file.Path;
2523
import java.util.Collections;
26-
import java.util.concurrent.TimeUnit;
27-
import java.util.stream.Stream;
2824

29-
import org.awaitility.Awaitility;
3025
import org.junit.jupiter.api.AfterEach;
3126
import org.junit.jupiter.api.BeforeEach;
3227
import org.junit.jupiter.api.Disabled;
@@ -78,19 +73,4 @@ public void shouldNotStop() {
7873
assertThat(node.homeDirectory().resolve("plugins/badCliOptions.start")).doesNotExist();
7974
assertThat(node.homeDirectory().resolve("plugins/badCliOptions.stop")).doesNotExist();
8075
}
81-
82-
private void waitForFile(final Path path) {
83-
final File file = path.toFile();
84-
Awaitility.waitAtMost(30, TimeUnit.SECONDS)
85-
.until(
86-
() -> {
87-
if (file.exists()) {
88-
try (final Stream<String> s = Files.lines(path)) {
89-
return s.count() > 0;
90-
}
91-
} else {
92-
return false;
93-
}
94-
});
95-
}
9676
}

acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/BesuEventsPluginTest.java

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,8 @@
1717
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
1818
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
1919

20-
import java.io.File;
21-
import java.nio.file.Files;
22-
import java.nio.file.Path;
2320
import java.util.Collections;
24-
import java.util.concurrent.TimeUnit;
25-
import java.util.stream.Stream;
2621

27-
import org.awaitility.Awaitility;
2822
import org.junit.jupiter.api.BeforeEach;
2923
import org.junit.jupiter.api.Test;
3024

@@ -45,19 +39,4 @@ public void setUp() throws Exception {
4539
public void blockIsAnnounced() {
4640
waitForFile(pluginNode.homeDirectory().resolve("plugins/newBlock.2"));
4741
}
48-
49-
private void waitForFile(final Path path) {
50-
final File file = path.toFile();
51-
Awaitility.waitAtMost(30, TimeUnit.SECONDS)
52-
.until(
53-
() -> {
54-
if (file.exists()) {
55-
try (final Stream<String> s = Files.lines(path)) {
56-
return s.count() > 0;
57-
}
58-
} else {
59-
return false;
60-
}
61-
});
62-
}
6342
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 static org.assertj.core.api.AssertionsForClassTypes.assertThat;
18+
19+
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
20+
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
21+
22+
import java.io.IOException;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
import java.util.Collections;
26+
import java.util.List;
27+
28+
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Test;
30+
31+
public class BlockchainServicePluginTest extends AcceptanceTestBase {
32+
private BesuNode minerNode;
33+
private BesuNode pluginNode;
34+
35+
@BeforeEach
36+
public void setUp() throws Exception {
37+
minerNode =
38+
besu.createMinerNode(
39+
"minerNode",
40+
besuNodeConfigurationBuilder -> besuNodeConfigurationBuilder.devMode(false));
41+
minerNode.setGenesisConfig(GENESIS_CONFIG);
42+
pluginNode =
43+
besu.createPluginsNode(
44+
"pluginNode",
45+
Collections.singletonList("testPlugins"),
46+
besuNodeConfigurationBuilder -> besuNodeConfigurationBuilder.devMode(false));
47+
pluginNode.setGenesisConfig(GENESIS_CONFIG);
48+
49+
cluster.start(pluginNode, minerNode);
50+
}
51+
52+
@Test
53+
public void hardforkListIsCorrect() throws IOException {
54+
final Path hardforkListFile = pluginNode.homeDirectory().resolve("plugins/hardfork.list");
55+
waitForFile(hardforkListFile);
56+
final var fileContents = Files.readAllLines(hardforkListFile);
57+
58+
final var expectedLines = List.of("0,BERLIN,BERLIN", "1,BERLIN,LONDON", "2,LONDON,LONDON");
59+
60+
for (int i = 0; i < expectedLines.size(); i++) {
61+
assertThat(fileContents.get(i)).isEqualTo(expectedLines.get(i));
62+
}
63+
}
64+
65+
private static final String GENESIS_CONFIG =
66+
"""
67+
{
68+
"config": {
69+
"chainId": 1337,
70+
"berlinBlock": 0,
71+
"londonBlock": 2,
72+
"contractSizeLimit": 2147483647,
73+
"ethash": {
74+
"fixeddifficulty": 100
75+
}
76+
},
77+
"nonce": "0x42",
78+
"baseFeePerGas":"0x0",
79+
"timestamp": "0x0",
80+
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
81+
"gasLimit": "0x1fffffffffffff",
82+
"difficulty": "0x10000",
83+
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
84+
"coinbase": "0x0000000000000000000000000000000000000000",
85+
"alloc": {
86+
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
87+
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
88+
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
89+
"balance": "0xad78ebc5ac6200000"
90+
},
91+
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
92+
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
93+
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
94+
"balance": "90000000000000000000000"
95+
},
96+
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
97+
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
98+
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
99+
"balance": "90000000000000000000000"
100+
}
101+
}
102+
}
103+
""";
104+
}

acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PicoCLIOptionsPluginTest.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,11 @@
1919
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
2020
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
2121

22-
import java.io.File;
2322
import java.io.IOException;
2423
import java.nio.file.Files;
2524
import java.nio.file.Path;
2625
import java.util.Collections;
27-
import java.util.concurrent.TimeUnit;
28-
import java.util.stream.Stream;
2926

30-
import org.awaitility.Awaitility;
3127
import org.junit.jupiter.api.BeforeEach;
3228
import org.junit.jupiter.api.Disabled;
3329
import org.junit.jupiter.api.Test;
@@ -75,19 +71,4 @@ public void shouldStop() {
7571
cluster.stopNode(node);
7672
waitForFile(node.homeDirectory().resolve("plugins/pluginLifecycle.stopped"));
7773
}
78-
79-
private void waitForFile(final Path path) {
80-
final File file = path.toFile();
81-
Awaitility.waitAtMost(30, TimeUnit.SECONDS)
82-
.until(
83-
() -> {
84-
if (file.exists()) {
85-
try (final Stream<String> s = Files.lines(path)) {
86-
return s.count() > 0;
87-
}
88-
} else {
89-
return false;
90-
}
91-
});
92-
}
9374
}

0 commit comments

Comments
 (0)