/*
* Copyright (c) [2016] [ <ether.camp> ]
* This file is part of the ethereumJ library.
*
* The ethereumJ library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The ethereumJ library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the ethereumJ library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.ethereum.net.eth.handler;
import org.ethereum.config.CommonConfig;
import org.ethereum.config.NoAutoscan;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Block;
import org.ethereum.core.BlockHeader;
import org.ethereum.core.Blockchain;
import org.ethereum.core.BlockchainImpl;
import org.ethereum.db.BlockStore;
import org.ethereum.db.BlockStoreDummy;
import org.ethereum.listener.CompositeEthereumListener;
import org.ethereum.net.eth.message.EthMessage;
import org.ethereum.net.eth.message.GetBlockBodiesMessage;
import org.ethereum.net.eth.message.GetBlockHeadersMessage;
import org.ethereum.sync.SyncManager;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mockito;
import org.spongycastle.util.encoders.Hex;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Testing whether Eth handler {@link Eth62} is blocking {@link BlockchainImpl}
*/
public class LockBlockchainTest {
private final AtomicBoolean result = new AtomicBoolean();
private Blockchain blockchain;
private final static long DELAY = 1000; //Default delay in ms
private final static String BLOCK_RLP = "f901f8f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808080a0000000000000000000000000000000000000000000000000000000000000000088000000000000002ac0c0";
public LockBlockchainTest() {
SysPropConfig1.props.overrideParams(
"peer.discovery.enabled", "false",
"peer.listen.port", "37777",
"peer.privateKey", "3ec771c31cac8c0dba77a69e503765701d3c2bb62435888d4ffa38fed60c445c",
"genesis", "genesis-light.json",
"database.dir", "testDB-1");
final BlockStore blockStoreDummy = new BlockStoreDummy() {
@Override
public synchronized Block getChainBlockByNumber(long blockNumber) {
return super.getChainBlockByNumber(blockNumber);
}
@Override
public synchronized List<BlockHeader> getListHeadersEndWith(byte[] hash, long qty) {
return super.getListHeadersEndWith(hash, qty);
}
@Override
public synchronized Block getBestBlock() {
return new Block(Hex.decode(BLOCK_RLP));
}
};
this.blockchain = new BlockchainImpl(SysPropConfig1.props) {
@Override
public synchronized boolean isBlockExist(byte[] hash) {
try {
this.blockStore = blockStoreDummy;
Thread.sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
};
SysPropConfig1.testHandler = new Eth62(SysPropConfig1.props, blockchain, blockStoreDummy,
new CompositeEthereumListener()) {
{
this.blockstore = blockStoreDummy;
this.syncManager = Mockito.mock(SyncManager.class);
}
@Override
public synchronized void sendStatus() {
super.sendStatus();
}
@Override
protected void sendMessage(EthMessage message) {
result.set(true);
System.out.println("Mocking message sending...");
}
};
}
@Before
public void setUp() throws Exception {
result.set(false);
}
@Configuration
@NoAutoscan
public static class SysPropConfig1 {
static Eth62 testHandler = null;
@Bean
@Scope("prototype")
public Eth62 eth62() {
return testHandler;
}
static SystemProperties props = new SystemProperties();
@Bean
public SystemProperties systemProperties() {
return props;
}
}
@Test
public synchronized void testHeadersWithoutSkip() throws FileNotFoundException, InterruptedException {
ExecutorService executor1 = Executors.newSingleThreadExecutor();
executor1.submit(new Runnable() {
@Override
public void run() {
blockchain.isBlockExist(null);
}
}
);
this.wait(DELAY);
ExecutorService executor2 = Executors.newSingleThreadExecutor();
executor2.submit(new Runnable() {
@Override
public void run() {
GetBlockHeadersMessage msg = new GetBlockHeadersMessage(1L, new byte[0], 10, 0, false);
SysPropConfig1.testHandler.processGetBlockHeaders(msg);
}
}
);
this.wait(DELAY);
assert result.get();
}
@Test
public synchronized void testHeadersWithSkip() throws FileNotFoundException, InterruptedException {
ExecutorService executor1 = Executors.newSingleThreadExecutor();
executor1.submit(new Runnable() {
@Override
public void run() {
blockchain.isBlockExist(null);
}
}
);
this.wait(DELAY);
ExecutorService executor2 = Executors.newSingleThreadExecutor();
executor2.submit(new Runnable() {
@Override
public void run() {
GetBlockHeadersMessage msg = new GetBlockHeadersMessage(1L, new byte[0], 10, 5, false);
SysPropConfig1.testHandler.processGetBlockHeaders(msg);
}
}
);
this.wait(DELAY);
assert result.get();
}
@Test
public synchronized void testBodies() throws FileNotFoundException, InterruptedException {
ExecutorService executor1 = Executors.newSingleThreadExecutor();
executor1.submit(new Runnable() {
@Override
public void run() {
blockchain.isBlockExist(null);
}
}
);
this.wait(DELAY);
ExecutorService executor2 = Executors.newSingleThreadExecutor();
executor2.submit(new Runnable() {
@Override
public void run() {
List<byte[]> hashes = new ArrayList<>();
hashes.add(new byte[] {1, 2, 3});
hashes.add(new byte[] {4, 5, 6});
GetBlockBodiesMessage msg = new GetBlockBodiesMessage(hashes);
SysPropConfig1.testHandler.processGetBlockBodies(msg);
}
}
);
this.wait(DELAY);
assert result.get();
}
@Test
public synchronized void testStatus() throws FileNotFoundException, InterruptedException {
ExecutorService executor1 = Executors.newSingleThreadExecutor();
executor1.submit(new Runnable() {
@Override
public void run() {
blockchain.isBlockExist(null);
}
}
);
this.wait(DELAY);
ExecutorService executor2 = Executors.newSingleThreadExecutor();
executor2.submit(new Runnable() {
@Override
public void run() {
try {
SysPropConfig1.testHandler.sendStatus();
} catch (Exception e) {
e.printStackTrace();
}
}
}
);
this.wait(DELAY);
assert result.get();
}
}