Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Write test for assignment example #3

Merged
merged 2 commits into from Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file added lib/apiguardian-api-1.0.0.jar
Binary file not shown.
Binary file added lib/junit-jupiter-api-5.0.0.jar
Binary file not shown.
Binary file added lib/junit-platform-commons-1.0.0.jar
Binary file not shown.
Binary file added lib/opentest4j-1.0.0.jar
Binary file not shown.
12 changes: 10 additions & 2 deletions src/main/java/Main.java
Expand Up @@ -67,7 +67,11 @@ public static void main(String[] args) {
"<PORT OF EXISTING PEER IN NETWORK> " +
"<KEY (INTEGER)> <VALUE (STRING)> to use this command.");

PutClient.put(args);
PutClient.put( args[1]
, Common.parseInteger(args[2])
, Common.parseInteger(args[3])
, args[4]
);
break;
case GET:
if (args.length != 5)
Expand All @@ -77,7 +81,11 @@ public static void main(String[] args) {
"<OWN PORT TO BIND TO> <KEY (INTEGER)>) to use" +
"this command.");

GetClient.get(args);
GetClient.get( args[1]
, Common.parseInteger(args[2])
, Common.parseInteger(args[3])
, Common.parseInteger(args[4])
);
break;
}
} catch (IllegalArgumentException e) {
Expand Down
54 changes: 35 additions & 19 deletions src/main/java/Peer.java
Expand Up @@ -41,21 +41,32 @@ public class Peer {
// Key-value pairs that this peer is responsible for storing
private final Map<Integer, String> storedData;

// Thread that is listening
private Listener listener;

Peer(PeerAddress ownAddress) {
this.ownAddress = ownAddress;
this.incomingMessageHandler = new IncomingMessageHandler(this);
this.storedData = new HashMap<>();

System.out.println(String.format("Peer started on %s:%d (ID: %s)",
this.ownAddress.getIp(),
this.ownAddress.getPort(),
this.ownAddress.getHashId()));
System.out.println(String.format("Peer started on %s", this.ownAddress));

this.listener = new Listener(this);
this.listener.start(); // Starts to listen for incoming connections
}

public void stop() {
this.listener.abort();
}

new Listener(this).start(); // Starts to listen for incoming connections
@Override
public String toString() {
return this.ownAddress.toString();
}

private class Listener extends Thread {
private final Peer peer; // Reference to peer that initialized this thread
private ServerSocket socket; // Reference to listening socket (needed to kill Listener via "abort")

private Listener(Peer peer) {
this.peer = peer;
Expand All @@ -67,15 +78,28 @@ private Listener(Peer peer) {
*/
@Override
public void run() {
try (ServerSocket socket = new ServerSocket(this.peer.ownAddress.getPort())) {
try {
this.socket = new ServerSocket(this.peer.ownAddress.getPort());
System.out.println("Listening...");

while (true) {
Socket clientSocket = socket.accept();
new ClientHandler(clientSocket, this.peer).start();
}
} catch (IOException e) {
e.printStackTrace();
System.out.println( String.format("Peer %s exited.", this.peer)
+ " Exception: \"" + e.getMessage() + "\""
);
} finally {
runeksvendsen marked this conversation as resolved.
Show resolved Hide resolved
this.abort();
}
}

void abort() {
try {
this.socket.close();
} catch (IOException e) {
// Ignore exception from closing socket
}
}
}
Expand Down Expand Up @@ -191,11 +215,9 @@ public void sendMessageToPeer(PeerAddress destinationPeer, Message message) thro
outputStream.writeObject(message);
} else {
Logging.debugLog(String.format("Failed to send message (type: %s) to peer " +
"(IP: %s, port: %d, ID: %s)",
"%s",
message.getClass().toString(),
destinationPeer.getIp(),
destinationPeer.getPort(),
destinationPeer.getHashId()), true);
destinationPeer), true);
}
} catch (IOException e) {
e.printStackTrace();
Expand All @@ -217,10 +239,7 @@ public PeerAddress getSuccessor() {
public void setSuccessor(PeerAddress newSuccessor) {
this.successor = newSuccessor;

Logging.debugLog(String.format("Updated successor to %s:%d (ID: %s)",
newSuccessor.getIp(),
newSuccessor.getPort(),
newSuccessor.getHashId()),
Logging.debugLog(String.format("Updated successor to %s", newSuccessor),
false);
}

Expand All @@ -231,10 +250,7 @@ public PeerAddress getNextSuccessor() {
public void setNextSuccessor(PeerAddress newNextSuccessor) {
this.nextSuccessor = newNextSuccessor;

Logging.debugLog(String.format("Updated next successor to %s:%d (ID: %s)",
newNextSuccessor.getIp(),
newNextSuccessor.getPort(),
newNextSuccessor.getHashId()),
Logging.debugLog(String.format("Updated next successor to %s", newNextSuccessor),
false);
}

Expand Down
9 changes: 9 additions & 0 deletions src/main/java/PeerAddress.java
Expand Up @@ -30,4 +30,13 @@ public int getPort() {
public BigInteger getHashId() {
return hashId;
}

@Override
public String toString() {
return String.format("%s:%d (ID: %s)",
this.getIp(),
this.getPort(),
this.getHashId()
);
}
}
16 changes: 7 additions & 9 deletions src/main/java/clients/GetClient.java
Expand Up @@ -18,14 +18,8 @@ public class GetClient {
* Sends a 'GetMessage' to the peer which address is taken as argument to program.
* Afterwards listen on the port - also taken as argument to program - for any response.
*/
public static void get(String[] programArguments) {
String peerAddress = programArguments[1];
int peerPort = Common.parseInteger(programArguments[2]);

public static PutMessage get(String peerAddress, int peerPort, int ownPort, int key) {
String ownIp = Common.getOwnIp();
int ownPort = Common.parseInteger(programArguments[3]);

int key = Common.parseInteger(programArguments[4]);

try {
Socket requestSocket = new Socket(peerAddress, peerPort); // Socket for sending 'GetMessage' to peer
Expand All @@ -37,6 +31,8 @@ public static void get(String[] programArguments) {
ServerSocket listenSocket = new ServerSocket(ownPort); // Socket to listen for response to 'GetMessage'
// Waits for incoming connection with response
Socket responseSocket = listenSocket.accept();
// Stop listening
listenSocket.close();
ObjectInputStream responseInputStream = new ObjectInputStream(responseSocket.getInputStream());

Object input = responseInputStream.readObject();
Expand All @@ -47,16 +43,18 @@ public static void get(String[] programArguments) {

if (message.getValue() == null) {
System.out.println(String.format("Value not found. Key: %d", message.getKey()));
return;
} else {
System.out.println(String.format("Key: %d, value: %s", message.getKey(), message.getValue()));
}

System.out.println(String.format("Key: %d, value: %s", message.getKey(), message.getValue()));
return message;
}
} catch (SocketException e) {
Logging.debugLog("Could not establish connection to given peer. Full error details: " + e.getMessage(),
true);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
8 changes: 1 addition & 7 deletions src/main/java/clients/PutClient.java
Expand Up @@ -14,13 +14,7 @@ public class PutClient {
* Sends a 'PutMessage' to the peer which address is taken as argument to program.
* Terminates the process afterwards.
*/
public static void put(String[] programArguments) {
String peerAddress = programArguments[1];
int peerPort = Common.parseInteger(programArguments[2]);

int key = Common.parseInteger(programArguments[3]);
String value = programArguments[4];

public static void put(String peerAddress, int peerPort, int key, String value) {
try (
Socket socket = new Socket(peerAddress, peerPort);
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/messages/PutMessage.java
Expand Up @@ -3,6 +3,7 @@
import main.java.utilities.SHA1Hasher;

import java.math.BigInteger;
import java.util.Objects;

/**
* Message containing the data that has to be stored in the network
Expand All @@ -29,4 +30,23 @@ public BigInteger getKeyHashId() {
public String getValue() {
return this.value;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PutMessage that = (PutMessage) o;
return key == that.key &&
Objects.equals(value, that.value);
}

@Override
public int hashCode() {
return Objects.hash(key, value);
}

@Override
public String toString() {
return "Put(" + key + ", " + value + ')';
}
}
81 changes: 81 additions & 0 deletions test/main/java/MainTest.java
@@ -0,0 +1,81 @@
package main.java;

import main.java.clients.GetClient;
import main.java.clients.PutClient;
import main.java.messages.PutMessage;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class MainTest {
private static String OWN_IP = "localhost";

/*
https://learnit.itu.dk/mod/assign/view.php?id=92747

Node starts at 1025.
Node starts at 1026, knowing 1025.
Client PUT(1, A) to 1025.
Client at 2048 sends GET(1, 2048) to 1025; eventually receives PUT(1, A) at 2048 from someone.
Client at 2049 sends GET(1, 2049) to 1026; eventually receives PUT(1, A) at 2049 from someone.
Client at 2049 sends GET(2, 2049) to 1025; eventually receives message saying the resource is not found.
Node C starts at 1027, knowing 1026.
Client at 2048 sends GET(1, 2048) to 1027; eventually receives PUT(1, A) at 2048 from someone.
PUT(2, B) to 1025.
Node 1025 crashes.
Client at 2048 sends GET(2, 2048) to 1026, eventually receives PUT(2, B) from someone.
*/
@Test
void main() {
// Node starts at 1025
Peer peer1025 = new Peer(new PeerAddress(OWN_IP, 1025));
WAIT(1000);

// Node starts at 1026, knowing 1025
Peer peer1026 = new Peer(new PeerAddress(OWN_IP, 1026));
peer1026.joinNetworkByExistingPeer(new PeerAddress(OWN_IP, 1025));
WAIT(1000);

// Client PUT(1, A) to 1025
PutClient.put(OWN_IP, 1025, 1, "A");

// Client at 2048 sends GET(1, 2048) to 1025; eventually receives PUT(1, A) at 2048 from someone
assertEquals(new PutMessage(1, "A"), GET(1, 2048, 1025));

// Client at 2049 sends GET(1, 2049) to 1026; eventually receives PUT(1, A) at 2049 from someone.
assertEquals(new PutMessage(1, "A"), GET(1, 2049, 1026));

// Client at 2049 sends GET(2, 2049) to 1025; eventually receives message saying the resource is not found.
assertEquals(new PutMessage(2, null), GET(2, 2049, 1025));

// Node C starts at 1027, knowing 1026.
Peer peer1027 = new Peer(new PeerAddress(OWN_IP, 1027));
peer1027.joinNetworkByExistingPeer(new PeerAddress(OWN_IP, 1026));
WAIT(1000);

// Client at 2048 sends GET(1, 2048) to 1027; eventually receives PUT(1, A) at 2048 from someone.
assertEquals(new PutMessage(1, "A"), GET(1, 2048, 1027));

// PUT(2, B) to 1025.
PutClient.put(OWN_IP, 1025, 2, "B");

// Node 1025 crashes.
peer1025.stop();
WAIT(1000);

// Client at 2048 sends GET(2, 2048) to 1026, eventually receives PUT(2, B) from someone.
assertEquals(new PutMessage(2, "B"), GET(2, 2048, 1026));
}

private static PutMessage GET(int key, int ownPort, int peerPort) {
return GetClient.get(OWN_IP, peerPort, ownPort, key);
}

private static void WAIT(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}