use of org.hyperledger.besu.testutil.MockExecutorService in project besu by hyperledger.
the class FastWorldStateDownloaderTest method testCancellation.
@SuppressWarnings("unchecked")
private void testCancellation(final boolean shouldCancelFuture) {
final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create();
// Prevent the persistence service from running
final MockExecutorService serviceExecutor = ((DeterministicEthScheduler) ethProtocolManager.ethContext().getScheduler()).mockServiceExecutor();
serviceExecutor.setAutoRun(false);
// Setup "remote" state
final WorldStateArchive remoteWorldStateArchive = createInMemoryWorldStateArchive();
final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable();
// Generate accounts and save corresponding state root
dataGen.createRandomContractAccountsWithNonEmptyStorage(remoteWorldState, 20);
final Hash stateRoot = remoteWorldState.rootHash();
final BlockHeader header = dataGen.block(BlockOptions.create().setStateRoot(stateRoot).setBlockNumber(10)).getHeader();
// Create some peers
final List<RespondingEthPeer> peers = Stream.generate(() -> EthProtocolManagerTestUtil.createPeer(ethProtocolManager, header.getNumber())).limit(5).collect(Collectors.toList());
final InMemoryTasksPriorityQueues<NodeDataRequest> taskCollection = new InMemoryTasksPriorityQueues<>();
final WorldStateStorage localStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
final WorldStateDownloader downloader = createDownloader(ethProtocolManager.ethContext(), localStorage, taskCollection);
final FastSyncState fastSyncState = new FastSyncState(header);
final CompletableFuture<Void> result = downloader.run(null, fastSyncState);
// Send a few responses
final RespondingEthPeer.Responder responder = RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive);
for (int i = 0; i < 3; i++) {
for (final RespondingEthPeer peer : peers) {
peer.respond(responder);
}
giveOtherThreadsAGo();
}
// Sanity check
assertThat(result.isDone()).isFalse();
// Reset taskCollection so we can track interactions after the cancellation
reset(taskCollection);
if (shouldCancelFuture) {
result.cancel(true);
} else {
downloader.cancel();
assertThat(result).isCancelled();
}
// Send some more responses after cancelling
for (int i = 0; i < 3; i++) {
for (final RespondingEthPeer peer : peers) {
peer.respond(responder);
}
giveOtherThreadsAGo();
}
// Now allow the persistence service to run which should exit immediately
serviceExecutor.runPendingFutures();
verify(taskCollection, times(1)).clear();
verify(taskCollection, never()).remove();
verify(taskCollection, never()).add(any(NodeDataRequest.class));
// Target world state should not be available
assertThat(localStorage.isWorldStateAvailable(header.getStateRoot(), header.getHash())).isFalse();
}
use of org.hyperledger.besu.testutil.MockExecutorService in project besu by hyperledger.
the class FastWorldStateDownloaderTest method canRecoverFromTimeouts.
@Test
public void canRecoverFromTimeouts() {
final DeterministicEthScheduler.TimeoutPolicy timeoutPolicy = DeterministicEthScheduler.TimeoutPolicy.timeoutXTimes(2);
final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(timeoutPolicy);
final MockExecutorService serviceExecutor = ((DeterministicEthScheduler) ethProtocolManager.ethContext().getScheduler()).mockServiceExecutor();
serviceExecutor.setAutoRun(false);
// Setup "remote" state
final WorldStateArchive remoteWorldStateArchive = createInMemoryWorldStateArchive();
final MutableWorldState remoteWorldState = remoteWorldStateArchive.getMutable();
// Generate accounts and save corresponding state root
final List<Account> accounts = dataGen.createRandomAccounts(remoteWorldState, 20);
final Hash stateRoot = remoteWorldState.rootHash();
// Sanity check
assertThat(stateRoot).isNotEqualTo(EMPTY_TRIE_ROOT);
final BlockHeader header = dataGen.block(BlockOptions.create().setStateRoot(stateRoot).setBlockNumber(10)).getHeader();
// Create some peers
final List<RespondingEthPeer> peers = Stream.generate(() -> EthProtocolManagerTestUtil.createPeer(ethProtocolManager, header.getNumber())).limit(5).collect(Collectors.toList());
final InMemoryTasksPriorityQueues<NodeDataRequest> taskCollection = new InMemoryTasksPriorityQueues<>();
final WorldStateStorage localStorage = new WorldStateKeyValueStorage(new InMemoryKeyValueStorage());
final WorldStateDownloader downloader = createDownloader(ethProtocolManager.ethContext(), localStorage, taskCollection);
final FastSyncState fastSyncState = new FastSyncState(header);
final CompletableFuture<Void> result = downloader.run(null, fastSyncState);
serviceExecutor.runPendingFuturesInSeparateThreads(persistenceThread);
// Respond to node data requests
final RespondingEthPeer.Responder responder = RespondingEthPeer.blockchainResponder(mock(Blockchain.class), remoteWorldStateArchive);
respondUntilDone(peers, responder, result);
// Check that all expected account data was downloaded
final WorldStateArchive localWorldStateArchive = new DefaultWorldStateArchive(localStorage, createPreimageStorage());
final WorldState localWorldState = localWorldStateArchive.get(stateRoot, null).get();
assertThat(result).isDone();
assertAccountsMatch(localWorldState, accounts);
}
use of org.hyperledger.besu.testutil.MockExecutorService in project besu by hyperledger.
the class PrunerIntegrationTest method testPruner.
private void testPruner(final int numCycles, final int accountsPerBlock, final int blockConfirmations, final int numBlocksToKeep, final int opsPerTransaction) {
final var markSweepPruner = new MarkSweepPruner(worldStateStorage, blockchain, markStorage, metricsSystem, opsPerTransaction);
final var pruner = new Pruner(markSweepPruner, blockchain, new PrunerConfiguration(blockConfirmations, numBlocksToKeep), new MockExecutorService());
pruner.start();
for (int cycle = 0; cycle < numCycles; ++cycle) {
int numBlockInCycle = numBlocksToKeep + // +1 to get it to switch from MARKING_COMPLETE TO SWEEPING on each cycle
1;
var fullyMarkedBlockNum = cycle * numBlockInCycle + 1;
// This should cause a full mark and sweep cycle
assertThat(pruner.getPruningPhase()).isEqualByComparingTo(PruningPhase.IDLE);
generateBlockchainData(numBlockInCycle, accountsPerBlock);
assertThat(pruner.getPruningPhase()).isEqualByComparingTo(PruningPhase.IDLE);
// Collect the nodes we expect to keep
final Set<Bytes> expectedNodes = new HashSet<>();
for (int i = fullyMarkedBlockNum; i <= blockchain.getChainHeadBlockNumber(); i++) {
final Hash stateRoot = blockchain.getBlockHeader(i).get().getStateRoot();
collectWorldStateNodes(stateRoot, expectedNodes);
}
if (accountsPerBlock != 0) {
assertThat(hashValueStore.size()).isGreaterThanOrEqualTo(// Sanity check
expectedNodes.size());
}
// Assert that blocks from mark point onward are still accessible
for (int i = fullyMarkedBlockNum; i <= blockchain.getChainHeadBlockNumber(); i++) {
final BlockHeader blockHeader = blockchain.getBlockHeader(i).get();
final Hash stateRoot = blockHeader.getStateRoot();
assertThat(worldStateArchive.get(stateRoot, blockHeader.getHash())).isPresent();
final WorldState markedState = worldStateArchive.get(stateRoot, blockHeader.getHash()).get();
// Traverse accounts and make sure all are accessible
final int expectedAccounts = accountsPerBlock * i;
final long accounts = markedState.streamAccounts(Bytes32.ZERO, expectedAccounts * 2).count();
assertThat(accounts).isEqualTo(expectedAccounts);
// Traverse storage to ensure that all storage is accessible
markedState.streamAccounts(Bytes32.ZERO, expectedAccounts * 2).forEach(a -> a.storageEntriesFrom(Bytes32.ZERO, 1000));
}
// All other state roots should have been removed
for (int i = 0; i < fullyMarkedBlockNum; i++) {
final BlockHeader curHeader = blockchain.getBlockHeader(i).get();
if (!curHeader.getStateRoot().equals(Hash.EMPTY_TRIE_HASH)) {
assertThat(worldStateArchive.get(curHeader.getStateRoot(), curHeader.getHash())).isEmpty();
}
}
// Check that storage contains only the values we expect
assertThat(hashValueStore.size()).isEqualTo(expectedNodes.size());
assertThat(hashValueStore.values()).containsExactlyInAnyOrderElementsOf(expectedNodes.stream().map(Bytes::toArrayUnsafe).collect(Collectors.toSet()));
}
pruner.stop();
}
use of org.hyperledger.besu.testutil.MockExecutorService in project besu by hyperledger.
the class AbstractEthTaskTest method shouldIgnoreMultipleRuns.
@Test
public void shouldIgnoreMultipleRuns() {
final AtomicInteger calls = new AtomicInteger(0);
final AbstractEthTask<Void> incrementingTask = new AbstractEthTask<>(new NoOpMetricsSystem()) {
@Override
protected void executeTask() {
calls.incrementAndGet();
result.complete(null);
}
};
incrementingTask.run();
incrementingTask.run();
incrementingTask.runAsync(new MockExecutorService());
assertThat(calls).hasValue(1);
}
Aggregations