diff options
| -rw-r--r-- | src/main/java/derms/ReplicaManager.java | 24 | ||||
| -rw-r--r-- | src/main/java/derms/client/ResponderClient.java | 6 | ||||
| -rw-r--r-- | src/main/java/derms/frontend/FE.java | 3 | ||||
| -rw-r--r-- | src/main/java/derms/replica1/DERMSServerPublisher.java | 21 | ||||
| -rw-r--r-- | src/main/java/derms/replica1/Replica1.java | 2 | ||||
| -rw-r--r-- | src/main/java/derms/replica2/Replica2.java | 2 | ||||
| -rw-r--r-- | src/main/java/derms/util/LogComparator.java | 13 | ||||
| -rw-r--r-- | src/test/java/derms/test/SystemTest.java | 144 |
8 files changed, 203 insertions, 12 deletions
diff --git a/src/main/java/derms/ReplicaManager.java b/src/main/java/derms/ReplicaManager.java index d3ca1f9..1e89969 100644 --- a/src/main/java/derms/ReplicaManager.java +++ b/src/main/java/derms/ReplicaManager.java @@ -10,6 +10,7 @@ import derms.net.runicast.ReliableUnicastSender; import derms.net.tomulticast.TotalOrderMulticastSender; import derms.replica1.Replica1; import derms.replica2.Replica2; +import derms.util.*; import java.io.IOException; import java.net.InetAddress; @@ -62,6 +63,20 @@ public class ReplicaManager { replica = new derms.replica2.Replica2(city, this); break; } + + // [TEST] Logging + if (byzantine == 0) { + TestLogger.log("REPLICA " + replicaId + ": {BYZANTINE: FALSE}"); + } else { + TestLogger.log("REPLICA " + replicaId + ": {BYZANTINE: TRUE}"); + } + + if (crash == 0) { + TestLogger.log("REPLICA " + replicaId + ": {CRASH: FALSE}"); + } else { + TestLogger.log("REPLICA " + replicaId + ": {CRASH: TRUE}"); + } + replica.startProcess(byzantine, crash); } @@ -92,8 +107,12 @@ public class ReplicaManager { new Thread(() -> { while (true) { if (!replica.isAlive()) { + // [TEST] Logging + TestLogger.log("REPLICA " + replicaId + ": {CRASH: DETECTED}"); + informFrontEndRmIsDown(replica.getId()); replica.restart(); + TestLogger.log("REPLICA " + replicaId + ": {RESTARTED}"); } try { Thread.sleep(5000); // Example 5 seconds. @@ -114,8 +133,13 @@ public class ReplicaManager { public void handleByzantineFailure() { log.severe("Byzantine failure detected in Replica " + replica.getId()); + + // [TEST] Logging + TestLogger.log("REPLICA " + replicaId + ": {BYZANTINE: DETECTED}"); + replica.restart(); informFrontEndRmHasBug(replica.getId()); + TestLogger.log("REPLICA " + replicaId + ": {RESTARTED}"); } private void informFrontEndRmIsDown(int replicaId) { diff --git a/src/main/java/derms/client/ResponderClient.java b/src/main/java/derms/client/ResponderClient.java index 23361d7..ec599b4 100644 --- a/src/main/java/derms/client/ResponderClient.java +++ b/src/main/java/derms/client/ResponderClient.java @@ -9,7 +9,7 @@ public class ResponderClient extends CLI { private final DERMSInterface server; - private ResponderClient(String FEhost) throws MalformedURLException { + public ResponderClient(String FEhost) throws MalformedURLException { server = Client.connectToServer(FEhost); commands.put("add", new Add()); @@ -43,7 +43,7 @@ public class ResponderClient extends CLI { } } - private class Add implements Command { + public class Add implements Command { @Override public void exec(String[] args) { if (args.length < 3) @@ -52,7 +52,7 @@ public class ResponderClient extends CLI { add(args[0], args[1], args[2]); } - private void add(String resourceID, String resourceName, String durationStr) { + public void add(String resourceID, String resourceName, String durationStr) { try { int duration = Integer.parseInt(durationStr); if (duration < 0) { diff --git a/src/main/java/derms/frontend/FE.java b/src/main/java/derms/frontend/FE.java index f29459c..ee0a323 100644 --- a/src/main/java/derms/frontend/FE.java +++ b/src/main/java/derms/frontend/FE.java @@ -10,6 +10,7 @@ import derms.Request; import derms.Response; import derms.net.runicast.ReliableUnicastReceiver; import derms.net.runicast.ReliableUnicastSender; +import derms.util.TestLogger; import java.util.ArrayList; import java.util.List; @@ -51,6 +52,7 @@ public class FE { System.out.println("Rm:" + RmNumber + "has bug"); // sendMulticastFaultMessageToRms(errorMessage); sendUnicastToSequencer(errorMessage); + TestLogger.log("FE: {BYZANTINE: REPLICA" + RmNumber + "}"); } @Override @@ -60,6 +62,7 @@ public class FE { System.out.println("Rm:" + RmNumber + "is down"); // sendMulticastFaultMessageToRms(errorMessage); sendUnicastToSequencer(errorMessage); + TestLogger.log("FE: {CRASH: REPLICA" + RmNumber + "}"); } @Override diff --git a/src/main/java/derms/replica1/DERMSServerPublisher.java b/src/main/java/derms/replica1/DERMSServerPublisher.java index df175b6..9b5ba91 100644 --- a/src/main/java/derms/replica1/DERMSServerPublisher.java +++ b/src/main/java/derms/replica1/DERMSServerPublisher.java @@ -2,15 +2,22 @@ package derms.replica1; import javax.xml.ws.Endpoint;
+import derms.frontend.DERMSServerImpl;
+
public class DERMSServerPublisher {
+
+ private static Endpoint endpoint;
+
public static void main(String[] args) {
- try {
- Endpoint.publish("http://localhost:8387/ws/derms", new DERMSServer("MTL"));
-// Endpoint.publish("http://localhost:8081/ws/derms", new DERMSServer("QUE"));
-// Endpoint.publish("http://localhost:8082/ws/derms", new DERMSServer("SHE"));
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ // Publish the web service
+ endpoint = Endpoint.publish("http://127.0.0.1:8387/ws/derms", new DERMSServerImpl());
+ System.out.println("DERMS Server is published at http://127.0.0.1:8387/ws/derms");
+ }
+
+ public static void stop() {
+ if (endpoint != null && endpoint.isPublished()) {
+ endpoint.stop();
+ System.out.println("DERMS Server is stopped.");
}
- System.out.println("DERMS Web Service is published at http://localhost:8387/ws/derms");
}
}
\ No newline at end of file diff --git a/src/main/java/derms/replica1/Replica1.java b/src/main/java/derms/replica1/Replica1.java index 654ec44..64565e6 100644 --- a/src/main/java/derms/replica1/Replica1.java +++ b/src/main/java/derms/replica1/Replica1.java @@ -62,7 +62,7 @@ public class Replica1 implements Replica { } pool.execute(DERMSServer::new); - alive = true; + //alive = true; log.info(getClass().getSimpleName() + " started."); log.config("Local address is "+localAddr.toString()); } diff --git a/src/main/java/derms/replica2/Replica2.java b/src/main/java/derms/replica2/Replica2.java index 5f24e24..73a66b2 100644 --- a/src/main/java/derms/replica2/Replica2.java +++ b/src/main/java/derms/replica2/Replica2.java @@ -120,7 +120,7 @@ public class Replica2 implements Replica { log.info("Running"); log.config("Local address is "+localAddr.toString()); - alive = true; + //alive = true; log.info(getClass().getSimpleName() + " started."); } diff --git a/src/main/java/derms/util/LogComparator.java b/src/main/java/derms/util/LogComparator.java new file mode 100644 index 0000000..6b629a6 --- /dev/null +++ b/src/main/java/derms/util/LogComparator.java @@ -0,0 +1,13 @@ +package derms.util; + +import java.io.*; +import java.nio.file.*; + +public class LogComparator { + public static boolean compareLineCounts(String actualFilePath, String expectedFilePath) throws IOException { + long actualLineCount = Files.lines(Paths.get(actualFilePath)).count(); + long expectedLineCount = Files.lines(Paths.get(expectedFilePath)).count(); + + return actualLineCount == expectedLineCount; + } +}
\ No newline at end of file diff --git a/src/test/java/derms/test/SystemTest.java b/src/test/java/derms/test/SystemTest.java new file mode 100644 index 0000000..5354b54 --- /dev/null +++ b/src/test/java/derms/test/SystemTest.java @@ -0,0 +1,144 @@ +package derms.test; + +import derms.ReplicaManager; +import derms.Sequencer; +import derms.client.ResponderClient; +import derms.frontend.FE; +import derms.replica1.DERMSServerPublisher; + +import org.junit.jupiter.api.*; +import java.io.*; +import java.nio.file.*; +import java.util.*; +import derms.util.*; +import derms.replica3.*; + +import static org.junit.jupiter.api.Assertions.*; + +class SystemTest { + + private static final String TEST_LOG_PATH = "SystemTest.log"; + private static final String EXPECTED_LOG_PATH = "TestExpected.log"; + + // [TODO] + // input IP and NET config + private static String IP = "127.0.0.1"; + private static String NET = "en0"; + + @BeforeEach + void clearLogFile() throws IOException { + TestLogger.clearLog(); + } + + @BeforeAll + static void runMains() throws IOException { + String[] argsFE = {IP, IP}; + String[] argsSQ = {IP, NET}; + + Thread feThread = new Thread(() -> { + try { + FE.main(argsFE); + } catch (Exception e) { + e.printStackTrace(); + } + }); + feThread.start(); + + Thread sequencerThread = new Thread(() -> { + try { + Sequencer.main(argsSQ); + } catch (Exception e) { + e.printStackTrace(); + } + }); + sequencerThread.start(); + } + + @AfterEach + void stopServers() { + // Stop the DERMSServerPublisher + DERMSServerPublisher.stop(); + } + + @Test + void testNormal() throws IOException { + // Replica 1 + String[] argsRM = {"1", "MTL", IP, "0", "0"}; + + // [TODO] + // Run the main function of the desired replica, for example: + DERMSServerPublisher.main(new String[0]); + + ReplicaManager.main(argsRM); + ResponderClient responderClient = new ResponderClient(IP); + ResponderClient.Add addCommand = responderClient.new Add(); + addCommand.add("MTL1001", "ambulance", "10"); + + // Compare the number of lines in the log files, to determine if they match or not + assertTrue(LogComparator.compareLineCounts(TEST_LOG_PATH, EXPECTED_LOG_PATH)); + } + + @Test + void testByzantine() throws IOException { + // Replica 1 + String[] argsRM = {"1", "MTL", IP, "1", "0"}; + + // [TODO] + // Run the main function of the desired replica, for example: + DERMSServerPublisher.main(new String[0]); + + ReplicaManager.main(argsRM); + ResponderClient responderClient = new ResponderClient(IP); + ResponderClient.Add addCommand = responderClient.new Add(); + addCommand.add("MTL1001", "ambulance", "10"); + + // Compare the number of lines in the log files, to determine if they match or not + assertTrue(LogComparator.compareLineCounts(TEST_LOG_PATH, EXPECTED_LOG_PATH)); + } + + @Test + void testCrash() throws IOException { + // Replica 1 + String[] argsRM = {"1", "MTL", IP, "0", "1"}; + + // [TODO] + // Run the main function of the desired replica, for example: + DERMSServerPublisher.main(new String[0]); + + ReplicaManager.main(argsRM); + ResponderClient responderClient = new ResponderClient(IP); + ResponderClient.Add addCommand = responderClient.new Add(); + addCommand.add("MTL1001", "ambulance", "10"); + + // Compare the number of lines in the log files, to determine if they match or not + assertTrue(LogComparator.compareLineCounts(TEST_LOG_PATH, EXPECTED_LOG_PATH)); + } + + @Test + void testCombined() throws IOException { + // Replica 1 and 2 + String[] argsRM1 = {"1", "MTL", IP, "1", "0"}; + String[] argsRM3 = {"3", "MTL", IP, "0", "1"}; + + // [TODO] + // Run the main function of the desired TWO replicas, for example: + DERMSServerPublisher.main(new String[0]); + MTLServer.main(new String[0]); + QUEServer.main(new String[0]); + SHEServer.main(new String[0]); + + ReplicaManager.main(argsRM1); + ReplicaManager.main(argsRM3); + + ResponderClient responderClient = new ResponderClient(IP); + ResponderClient.Add addCommand = responderClient.new Add(); + addCommand.add("MTL1001", "ambulance", "10"); + + ResponderClient responderClient2 = new ResponderClient(IP); + ResponderClient.Add addCommand2 = responderClient2.new Add(); + addCommand2.add("MTL1002", "ambulance", "11"); + + // Compare the number of lines in the log files, to determine if they match or not + assertTrue(LogComparator.compareLineCounts(TEST_LOG_PATH, EXPECTED_LOG_PATH)); + } +}
\ No newline at end of file |