Commit 154cf858 authored by Michel Schudel's avatar Michel Schudel

wrote some unit tests to check p2p behaviour

parent b0164b02
package nl.craftsmen.blockchain.craftscoinnode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
class CraftsCoinConfig {
@Bean
protected RestTemplate restTemplate() {
return new RestTemplate();
}
}
......@@ -86,7 +86,7 @@ public class CraftsCoinRestController {
* @param peer the peer that initiated the request.
* @param block the new block.
*/
@PostMapping("/api/newblock")
@PostMapping("/api/addblock")
public void newBlock(@RequestHeader(value = "peer", required = false) String peer, @RequestBody Block block) {
blockchainService.newBlockReceived(block, peer);
}
......
......@@ -18,7 +18,7 @@ import java.util.Set;
* Persistence functionality for the list of peers.
*/
@Component
final class PeersRepository {
class PeersRepository {
private InstanceInfo instanceInfo;
......
......@@ -7,10 +7,9 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.*;
import java.util.Enumeration;
import java.util.List;
@Component
public class InstanceInfo {
......@@ -33,21 +32,18 @@ public class InstanceInfo {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress inetAddress = addresses.nextElement();
String hostAddress = inetAddress.getHostAddress();
if (hostAddress.startsWith("192")) {
host = hostAddress;
break;
List<InterfaceAddress> addresses = networkInterface.getInterfaceAddresses();
for (InterfaceAddress interfaceAddress: addresses) {
InetAddress address = interfaceAddress.getAddress();
String hostAddress1 = address.getHostAddress();
if (address.isSiteLocalAddress() && interfaceAddress.getNetworkPrefixLength() <= 16) {
host = hostAddress1;
break;
}
}
}
// String host = InetAddress
// .getLocalHost()
// .getHostAddress();
this.port = serverProperties.getPort();
this.node = host + ":" + serverProperties.getPort();
this.node = host + ":" + this.port;
LOGGER.info("node name of this node is {}", node);
} catch (SocketException e) {
throw new RuntimeException(e);
......
package nl.craftsmen.blockchain.craftscoinnode.network;
import nl.craftsmen.blockchain.craftscoinnode.blockchain.Block;
import nl.craftsmen.blockchain.craftscoinnode.blockchain.Blockchain;
import nl.craftsmen.blockchain.craftscoinnode.transaction.Transaction;
import nl.craftsmen.blockchain.craftscoinnode.util.InstanceInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class NetworkTest {
@Mock
private PeersRepository peersRepository;
@Mock
private InstanceInfo instanceInfo;
@Mock
private RestTemplate restTemplate;
@Captor
private ArgumentCaptor<Set<String>> peersCaptor;
@Captor
private ArgumentCaptor<HttpEntity<Block>> blockHttpEntityCaptor;
private Network network;
@Before
public void setup() {
when(instanceInfo.getNode()).thenReturn("localhost:8080");
when(instanceInfo.getPort()).thenReturn(8080);
network = new Network(instanceInfo, peersRepository, restTemplate, "localhost", 8080);
}
@Test
public void connectingToNetworkWithNoKnownPeersShouldRegisterThroughTheBootstrapPeer() {
network = new Network(instanceInfo, peersRepository, restTemplate, "localhost", 9000);
when(peersRepository.loadPeers()).thenReturn(Collections.emptySet());
Set<String> remotePeers = Stream.of("newRemotePeer:8080").collect(Collectors.toSet());
ResponseEntity<Set<String>> response = new ResponseEntity<>(remotePeers, HttpStatus.OK);
when(restTemplate.exchange(eq("http://localhost:9000/api/registernode"), eq(HttpMethod.POST), Matchers.<HttpEntity<Object>>any(),
Matchers.<ParameterizedTypeReference<Set<String>>>any())).thenReturn(response);
network.init();
network.connectToNetwork();
verify(peersRepository).savePeers(peersCaptor.capture());
assertThat(network.getPeers()).containsExactlyInAnyOrder("newRemotePeer:8080");
assertThat(peersCaptor.getValue()).containsExactlyInAnyOrder("newRemotePeer:8080");
}
@Test
public void connectingToNetworkWithAKnownPeerShouldAddAllNewPeersToThePeerList() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
Set<String> remotePeers = Stream.of("newRemotePeer:8080").collect(Collectors.toSet());
ResponseEntity<Set<String>> response = new ResponseEntity<>(remotePeers, HttpStatus.OK);
when(restTemplate.exchange(eq("http://alreadyKnownPeer:8080/api/registernode"), eq(HttpMethod.POST), Matchers.<HttpEntity<Object>>any(),
Matchers.<ParameterizedTypeReference<Set<String>>>any())).thenReturn(response);
network.init();
network.connectToNetwork();
verify(peersRepository).savePeers(peersCaptor.capture());
assertThat(network.getPeers()).containsExactlyInAnyOrder("newRemotePeer:8080","alreadyKnownPeer:8080");
assertThat(peersCaptor.getValue()).containsExactlyInAnyOrder("newRemotePeer:8080","alreadyKnownPeer:8080");
}
@Test
public void connectingToNetworkWithTwoKnownPeersOfWhichOneIsDownAddAllNewPeersToThePeerListAndRemoveTheBrokenNode() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer1:8080", "alreadyKnownPeer2:8080").collect(Collectors.toSet()));
Set<String> remotePeers = Stream.of("newRemotePeer:8080").collect(Collectors.toSet());
ResponseEntity<Set<String>> response = new ResponseEntity<>(remotePeers, HttpStatus.OK);
when(restTemplate.exchange(eq("http://alreadyKnownPeer1:8080/api/registernode"), eq(HttpMethod.POST), Matchers.<HttpEntity<Object>>any(),
Matchers.<ParameterizedTypeReference<Set<String>>>any())).thenThrow(new ResourceAccessException("connection refused"));
when(restTemplate.exchange(eq("http://alreadyKnownPeer2:8080/api/registernode"), eq(HttpMethod.POST), Matchers.<HttpEntity<Object>>any(),
Matchers.<ParameterizedTypeReference<Set<String>>>any())).thenReturn(response);
network.init();
network.connectToNetwork();
assertThat(network.getPeers()).containsExactlyInAnyOrder("newRemotePeer:8080","alreadyKnownPeer2:8080");
}
@Test
public void registerNewPeer() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
Set<String> remotePeers = Stream.of("newRemotePeer:8080").collect(Collectors.toSet());
ResponseEntity<Set<String>> response = new ResponseEntity<>(remotePeers, HttpStatus.OK);
when(restTemplate.exchange(eq("http://alreadyKnownPeer:8080/api/registernode"), eq(HttpMethod.POST), Matchers.<HttpEntity<Object>>any(),
Matchers.<ParameterizedTypeReference<Set<String>>>any())).thenReturn(response);
String newPeer = "newPeer:8080";
network.init();
Set<String> peersForRemote = network.registerNewPeer(newPeer);
verify(peersRepository).savePeers(peersCaptor.capture());
assertThat(network.getPeers()).containsExactlyInAnyOrder("newRemotePeer:8080","alreadyKnownPeer:8080", newPeer);
assertThat(peersCaptor.getValue()).containsExactlyInAnyOrder("newRemotePeer:8080","alreadyKnownPeer:8080", newPeer);
assertThat(peersForRemote).doesNotContain(newPeer);
}
@Test
public void notifyPeerOfNewTransaction() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
String sourcePeer = "sourcePeer:8080";
Transaction transaction = new Transaction("michel", "jan", BigDecimal.TEN);
network.init();
network.notifyPeersOfNewTransaction(transaction, sourcePeer);
verify(restTemplate).exchange(eq("http://alreadyKnownPeer:8080/api/addtransaction"), eq(HttpMethod.POST), Matchers.<HttpEntity<Transaction>>any(),
Matchers.<ParameterizedTypeReference<Object>>any());
}
@Test
public void notifyPeerOfNewBlock() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
String sourcePeer = "sourcePeer:8080";
Block block = new Block();
network.init();
network.notifyPeersOfNewBlock(block, sourcePeer);
verify(restTemplate).exchange(eq("http://alreadyKnownPeer:8080/api/addblock"), eq(HttpMethod.POST), blockHttpEntityCaptor.capture(),
Matchers.<ParameterizedTypeReference<Object>>any());
assertThat(blockHttpEntityCaptor.getValue().getHeaders().get("peer")).containsExactly("localhost:8080");
}
@Test
public void retrieveBlockchainFromPeers() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
Blockchain blockchain = new Blockchain();
when(restTemplate.getForObject(eq("http://alreadyKnownPeer:8080/api/blockchain"), eq(Blockchain.class))).thenReturn(blockchain);
network.init();
List<Blockchain> blockchains = network.retrieveBlockchainsFromPeers();
assertThat(blockchains).containsExactly(blockchain);
}
@Test
public void brokenPeerShouldReduceThePeersListWhenRetrievingBlockchainFromPeers() {
when(peersRepository.loadPeers()).thenReturn(Stream.of("alreadyKnownPeer:8080").collect(Collectors.toSet()));
when(restTemplate.getForObject(eq("http://alreadyKnownPeer:8080/api/blockchain"), eq(Blockchain.class))).thenThrow(new ResourceAccessException("connection refused"));
network.init();
List<Blockchain> blockchains = network.retrieveBlockchainsFromPeers();
verify(peersRepository).savePeers(peersCaptor.capture());
assertThat(network.getPeers()).doesNotContain("alreadyKnownPeer:8080");
assertThat(peersCaptor.getValue()).doesNotContain("alreadyKnownPeer:8080");
assertThat(blockchains).isEmpty();
}
}
\ No newline at end of file
package nl.craftsmen.blockchain.craftscoinnode.util;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class InstanceInfoTest {
private InstanceInfo instanceInfo;
@Before
public void setup() {
ServerProperties serverProperties = mock(ServerProperties.class);
when(serverProperties.getPort()).thenReturn(8080);
instanceInfo = new InstanceInfo(serverProperties);
}
@Test
public void test() {
instanceInfo.init();
assertThat(instanceInfo.getPort()).isEqualTo(8080);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment