X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fnet%2Fpterodactylus%2Ffcp%2Fquelaton%2FDefaultFcpClientTest.java;h=d210acc2e3e30946f053441a33ffe283d8ee0055;hb=8d70659996b99bd55b677e7235005bc0fcb05e1b;hp=16c6190b81101b632a761f2e5f166e60a07368da;hpb=d1f191436ae44c4113f90976ea8fd9cc545c0216;p=jFCPlib.git diff --git a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java index 16c6190..d210acc 100644 --- a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java +++ b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java @@ -1,30 +1,49 @@ package net.pterodactylus.fcp.quelaton; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.startsWith; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.stream.Collectors; +import net.pterodactylus.fcp.ARK; +import net.pterodactylus.fcp.ConfigData; +import net.pterodactylus.fcp.DSAGroup; import net.pterodactylus.fcp.FcpKeyPair; import net.pterodactylus.fcp.Key; +import net.pterodactylus.fcp.NodeData; +import net.pterodactylus.fcp.NodeRef; +import net.pterodactylus.fcp.Peer; +import net.pterodactylus.fcp.PeerNote; import net.pterodactylus.fcp.Priority; import net.pterodactylus.fcp.fake.FakeTcpServer; import net.pterodactylus.fcp.quelaton.ClientGetCommand.Data; import com.google.common.io.ByteStreams; +import com.google.common.io.Files; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; import org.junit.After; +import org.junit.Assert; import org.junit.Test; /** @@ -40,14 +59,14 @@ public class DefaultFcpClientTest { "SSK@wtbgd2loNcJCXvtQVOftl2tuWBomDQHfqS6ytpPRhfw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQACAAE/"; private static int threadCounter = 0; - private final ExecutorService threadPool = - Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++)); private final FakeTcpServer fcpServer; private final DefaultFcpClient fcpClient; public DefaultFcpClientTest() throws IOException { + ExecutorService threadPool = + Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++)); fcpServer = new FakeTcpServer(threadPool); - fcpClient = new DefaultFcpClient(threadPool, "localhost", fcpServer.getPort(), () -> "Test", () -> "2.0"); + fcpClient = new DefaultFcpClient(threadPool, "localhost", fcpServer.getPort(), () -> "Test"); } @After @@ -55,15 +74,39 @@ public class DefaultFcpClientTest { fcpServer.close(); } + @Test(expected = ExecutionException.class) + public void defaultFcpClientThrowsExceptionIfItCanNotConnect() + throws IOException, ExecutionException, InterruptedException { + Future keyPairFuture = fcpClient.generateKeypair().execute(); + fcpServer.connect().get(); + fcpServer.collectUntil(is("EndMessage")); + fcpServer.writeLine( + "CloseConnectionDuplicateClientName", + "EndMessage" + ); + keyPairFuture.get(); + } + + @Test(expected = ExecutionException.class) + public void defaultFcpClientThrowsExceptionIfConnectionIsClosed() + throws IOException, ExecutionException, InterruptedException { + Future keyPairFuture = fcpClient.generateKeypair().execute(); + fcpServer.connect().get(); + fcpServer.collectUntil(is("EndMessage")); + fcpServer.close(); + keyPairFuture.get(); + } + @Test public void defaultFcpClientCanGenerateKeypair() throws ExecutionException, InterruptedException, IOException { Future keyPairFuture = fcpClient.generateKeypair().execute(); connectNode(); - fcpServer.collectUntil(is("EndMessage")); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); fcpServer.writeLine("SSKKeypair", "InsertURI=" + INSERT_URI + "", "RequestURI=" + REQUEST_URI + "", - "Identifier=My Identifier from GenerateSSK", + "Identifier=" + identifier, "EndMessage"); FcpKeyPair keyPair = keyPairFuture.get(); assertThat(keyPair.getPublicKey(), is(REQUEST_URI)); @@ -91,7 +134,7 @@ public class DefaultFcpClientTest { @Test public void clientGetCanDownloadData() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "ReturnType=direct", "URI=KSK@foo.txt")); @@ -124,7 +167,7 @@ public class DefaultFcpClientTest { @Test public void clientGetDownloadsDataForCorrectIdentifier() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); @@ -158,7 +201,7 @@ public class DefaultFcpClientTest { @Test public void clientGetRecognizesGetFailed() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); @@ -176,7 +219,7 @@ public class DefaultFcpClientTest { @Test public void clientGetRecognizesGetFailedForCorrectIdentifier() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); @@ -197,21 +240,73 @@ public class DefaultFcpClientTest { assertThat(data.isPresent(), is(false)); } - @Test + @Test(expected = ExecutionException.class) public void clientGetRecognizesConnectionClosed() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); fcpServer.close(); - Optional data = dataFuture.get(); - assertThat(data.isPresent(), is(false)); + dataFuture.get(); + } + + @Test + public void defaultFcpClientReusesConnection() throws InterruptedException, ExecutionException, IOException { + Future keyPair = fcpClient.generateKeypair().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "SSKKeypair", + "InsertURI=" + INSERT_URI + "", + "RequestURI=" + REQUEST_URI + "", + "Identifier=" + identifier, + "EndMessage" + ); + keyPair.get(); + keyPair = fcpClient.generateKeypair().execute(); + lines = fcpServer.collectUntil(is("EndMessage")); + identifier = extractIdentifier(lines); + fcpServer.writeLine( + "SSKKeypair", + "InsertURI=" + INSERT_URI + "", + "RequestURI=" + REQUEST_URI + "", + "Identifier=" + identifier, + "EndMessage" + ); + keyPair.get(); + } + + @Test + public void defaultFcpClientCanReconnectAfterConnectionHasBeenClosed() + throws InterruptedException, ExecutionException, IOException { + Future keyPair = fcpClient.generateKeypair().execute(); + connectNode(); + fcpServer.collectUntil(is("EndMessage")); + fcpServer.close(); + try { + keyPair.get(); + Assert.fail(); + } catch (ExecutionException e) { + } + keyPair = fcpClient.generateKeypair().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "SSKKeypair", + "InsertURI=" + INSERT_URI + "", + "RequestURI=" + REQUEST_URI + "", + "Identifier=" + identifier, + "EndMessage" + ); + keyPair.get(); } @Test public void clientGetWithIgnoreDataStoreSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().ignoreDataStore().uri("KSK@foo.txt"); + fcpClient.clientGet().ignoreDataStore().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "IgnoreDS=true")); @@ -220,7 +315,7 @@ public class DefaultFcpClientTest { @Test public void clientGetWithDataStoreOnlySettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().dataStoreOnly().uri("KSK@foo.txt"); + fcpClient.clientGet().dataStoreOnly().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "DSonly=true")); @@ -229,7 +324,7 @@ public class DefaultFcpClientTest { @Test public void clientGetWithMaxSizeSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().maxSize(1048576).uri("KSK@foo.txt"); + fcpClient.clientGet().maxSize(1048576).uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "MaxSize=1048576")); @@ -238,7 +333,7 @@ public class DefaultFcpClientTest { @Test public void clientGetWithPrioritySettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().priority(Priority.interactive).uri("KSK@foo.txt"); + fcpClient.clientGet().priority(Priority.interactive).uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "PriorityClass=1")); @@ -247,7 +342,7 @@ public class DefaultFcpClientTest { @Test public void clientGetWithRealTimeSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().realTime().uri("KSK@foo.txt"); + fcpClient.clientGet().realTime().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "RealTimeFlag=true")); @@ -256,7 +351,7 @@ public class DefaultFcpClientTest { @Test public void clientGetWithGlobalSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().global().uri("KSK@foo.txt"); + fcpClient.clientGet().global().uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true")); @@ -293,7 +388,8 @@ public class DefaultFcpClientTest { fcpClient.clientPut() .from(new ByteArrayInputStream("Hello\n".getBytes())) .length(6) - .key(new Key("KSK@foo.txt")); + .uri("KSK@foo.txt") + .execute(); connectNode(); List lines = fcpServer.collectUntil(is("Hello")); assertThat(lines, matchesFcpMessage("ClientPut", "UploadFrom=direct", "DataLength=6", "URI=KSK@foo.txt")); @@ -305,7 +401,8 @@ public class DefaultFcpClientTest { Future> key = fcpClient.clientPut() .from(new ByteArrayInputStream("Hello\n".getBytes())) .length(6) - .key(new Key("KSK@foo.txt")); + .uri("KSK@foo.txt") + .execute(); connectNode(); List lines = fcpServer.collectUntil(is("Hello")); String identifier = extractIdentifier(lines); @@ -329,7 +426,8 @@ public class DefaultFcpClientTest { Future> key = fcpClient.clientPut() .from(new ByteArrayInputStream("Hello\n".getBytes())) .length(6) - .key(new Key("KSK@foo.txt")); + .uri("KSK@foo.txt") + .execute(); connectNode(); List lines = fcpServer.collectUntil(is("Hello")); String identifier = extractIdentifier(lines); @@ -354,7 +452,8 @@ public class DefaultFcpClientTest { .named("otherName.txt") .from(new ByteArrayInputStream("Hello\n".getBytes())) .length(6) - .key(new Key("KSK@foo.txt")); + .uri("KSK@foo.txt") + .execute(); connectNode(); List lines = fcpServer.collectUntil(is("Hello")); assertThat(lines, matchesFcpMessage("ClientPut", "TargetFilename=otherName.txt", "UploadFrom=direct", @@ -364,7 +463,7 @@ public class DefaultFcpClientTest { @Test public void clientPutWithRedirectSendsCorrectCommand() throws IOException, ExecutionException, InterruptedException { - fcpClient.clientPut().redirectTo(new Key("KSK@bar.txt")).key(new Key("KSK@foo.txt")); + fcpClient.clientPut().redirectTo("KSK@bar.txt").uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, @@ -373,11 +472,1408 @@ public class DefaultFcpClientTest { @Test public void clientPutWithFileSendsCorrectCommand() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientPut().from(new File("/tmp/data.txt")).key(new Key("KSK@foo.txt")); + fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute(); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); assertThat(lines, matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt", "Filename=/tmp/data.txt")); } + @Test + public void clientPutWithFileCanCompleteTestDdaSequence() + throws IOException, ExecutionException, InterruptedException { + File tempFile = createTempFile(); + fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "Code=25", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDARequest", + "Directory=" + tempFile.getParent(), + "WantReadDirectory=true", + "WantWriteDirectory=false", + "EndMessage" + )); + fcpServer.writeLine( + "TestDDAReply", + "Directory=" + tempFile.getParent(), + "ReadFilename=" + tempFile, + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDAResponse", + "Directory=" + tempFile.getParent(), + "ReadContent=test-content", + "EndMessage" + )); + fcpServer.writeLine( + "TestDDAComplete", + "Directory=" + tempFile.getParent(), + "ReadDirectoryAllowed=true", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, + matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt", + "Filename=" + new File(tempFile.getParent(), "test.dat"))); + } + + private File createTempFile() throws IOException { + File tempFile = File.createTempFile("test-dda-", ".dat"); + tempFile.deleteOnExit(); + Files.write("test-content", tempFile, StandardCharsets.UTF_8); + return tempFile; + } + + @Test + public void clientPutDoesNotReactToProtocolErrorForDifferentIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=not-the-right-one", + "Code=25", + "EndMessage" + ); + fcpServer.writeLine( + "PutSuccessful", + "Identifier=" + identifier, + "URI=KSK@foo.txt", + "EndMessage" + ); + assertThat(key.get().get().getKey(), is("KSK@foo.txt")); + } + + @Test + public void clientPutAbortsOnProtocolErrorOtherThan25() + throws InterruptedException, ExecutionException, IOException { + Future> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "Code=1", + "EndMessage" + ); + assertThat(key.get().isPresent(), is(false)); + } + + @Test + public void clientPutDoesNotReplyToWrongTestDdaReply() throws IOException, ExecutionException, + InterruptedException { + File tempFile = createTempFile(); + fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "Code=25", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDARequest", + "Directory=" + tempFile.getParent(), + "WantReadDirectory=true", + "WantWriteDirectory=false", + "EndMessage" + )); + fcpServer.writeLine( + "TestDDAReply", + "Directory=/some-other-directory", + "ReadFilename=" + tempFile, + "EndMessage" + ); + fcpServer.writeLine( + "TestDDAReply", + "Directory=" + tempFile.getParent(), + "ReadFilename=" + tempFile, + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDAResponse", + "Directory=" + tempFile.getParent(), + "ReadContent=test-content", + "EndMessage" + )); + } + + @Test + public void clientPutSendsResponseEvenIfFileCanNotBeRead() + throws IOException, ExecutionException, InterruptedException { + File tempFile = createTempFile(); + fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "Code=25", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDARequest", + "Directory=" + tempFile.getParent(), + "WantReadDirectory=true", + "WantWriteDirectory=false", + "EndMessage" + )); + fcpServer.writeLine( + "TestDDAReply", + "Directory=" + tempFile.getParent(), + "ReadFilename=" + tempFile + ".foo", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDAResponse", + "Directory=" + tempFile.getParent(), + "ReadContent=failed-to-read", + "EndMessage" + )); + } + + @Test + public void clientPutDoesNotResendOriginalClientPutOnTestDDACompleteWithWrongDirectory() + throws IOException, ExecutionException, InterruptedException { + File tempFile = createTempFile(); + fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "TestDDAComplete", + "Directory=/some-other-directory", + "EndMessage" + ); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "Code=25", + "EndMessage" + ); + lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "TestDDARequest", + "Directory=" + tempFile.getParent(), + "WantReadDirectory=true", + "WantWriteDirectory=false", + "EndMessage" + )); + } + + @Test + public void clientPutSendsNotificationsForGeneratedKeys() + throws InterruptedException, ExecutionException, IOException { + List generatedKeys = new CopyOnWriteArrayList<>(); + Future> key = fcpClient.clientPut() + .onKeyGenerated(generatedKeys::add) + .from(new ByteArrayInputStream("Hello\n".getBytes())) + .length(6) + .uri("KSK@foo.txt") + .execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("Hello")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "URIGenerated", + "Identifier=" + identifier, + "URI=KSK@foo.txt", + "EndMessage" + ); + fcpServer.writeLine( + "PutSuccessful", + "URI=KSK@foo.txt", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(key.get().get().getKey(), is("KSK@foo.txt")); + assertThat(generatedKeys, contains("KSK@foo.txt")); + } + + @Test + public void clientCanListPeers() throws IOException, ExecutionException, InterruptedException { + Future> peers = fcpClient.listPeers().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "ListPeers", + "WithVolatile=false", + "WithMetadata=false", + "EndMessage" + )); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "EndMessage" + ); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id2", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeers", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peers.get(), hasSize(2)); + assertThat(peers.get().stream().map(Peer::getIdentity).collect(Collectors.toList()), + containsInAnyOrder("id1", "id2")); + } + + @Test + public void clientCanListPeersWithMetadata() throws IOException, ExecutionException, InterruptedException { + Future> peers = fcpClient.listPeers().includeMetadata().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "ListPeers", + "WithVolatile=false", + "WithMetadata=true", + "EndMessage" + )); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "metadata.foo=bar1", + "EndMessage" + ); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id2", + "metadata.foo=bar2", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeers", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peers.get(), hasSize(2)); + assertThat(peers.get().stream().map(peer -> peer.getMetadata("foo")).collect(Collectors.toList()), + containsInAnyOrder("bar1", "bar2")); + } + + @Test + public void clientCanListPeersWithVolatiles() throws IOException, ExecutionException, InterruptedException { + Future> peers = fcpClient.listPeers().includeVolatile().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + assertThat(lines, matchesFcpMessage( + "ListPeers", + "WithVolatile=true", + "WithMetadata=false", + "EndMessage" + )); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "volatile.foo=bar1", + "EndMessage" + ); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id2", + "volatile.foo=bar2", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeers", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peers.get(), hasSize(2)); + assertThat(peers.get().stream().map(peer -> peer.getVolatile("foo")).collect(Collectors.toList()), + containsInAnyOrder("bar1", "bar2")); + } + + @Test + public void defaultFcpClientCanGetNodeInformation() throws InterruptedException, ExecutionException, IOException { + Future nodeData = fcpClient.getNode().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetNode", + "Identifier=" + identifier, + "GiveOpennetRef=false", + "WithPrivate=false", + "WithVolatile=false", + "EndMessage" + )); + fcpServer.writeLine( + "NodeData", + "Identifier=" + identifier, + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(nodeData.get(), notNullValue()); + } + + @Test + public void defaultFcpClientCanGetNodeInformationWithOpennetRef() + throws InterruptedException, ExecutionException, IOException { + Future nodeData = fcpClient.getNode().opennetRef().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetNode", + "Identifier=" + identifier, + "GiveOpennetRef=true", + "WithPrivate=false", + "WithVolatile=false", + "EndMessage" + )); + fcpServer.writeLine( + "NodeData", + "Identifier=" + identifier, + "opennet=true", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(nodeData.get().getVersion().toString(), is("Fred,0.7,1.0,1466")); + } + + @Test + public void defaultFcpClientCanGetNodeInformationWithPrivateData() + throws InterruptedException, ExecutionException, IOException { + Future nodeData = fcpClient.getNode().includePrivate().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetNode", + "Identifier=" + identifier, + "GiveOpennetRef=false", + "WithPrivate=true", + "WithVolatile=false", + "EndMessage" + )); + fcpServer.writeLine( + "NodeData", + "Identifier=" + identifier, + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "ark.privURI=SSK@XdHMiRl", + "EndMessage" + ); + assertThat(nodeData.get().getARK().getPrivateURI(), is("SSK@XdHMiRl")); + } + + @Test + public void defaultFcpClientCanGetNodeInformationWithVolatileData() + throws InterruptedException, ExecutionException, IOException { + Future nodeData = fcpClient.getNode().includeVolatile().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetNode", + "Identifier=" + identifier, + "GiveOpennetRef=false", + "WithPrivate=false", + "WithVolatile=true", + "EndMessage" + )); + fcpServer.writeLine( + "NodeData", + "Identifier=" + identifier, + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "volatile.freeJavaMemory=205706528", + "EndMessage" + ); + assertThat(nodeData.get().getVolatile("freeJavaMemory"), is("205706528")); + } + + @Test + public void defaultFcpClientCanListSinglePeerByIdentity() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanListSinglePeerByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byHostAndPort("host.free.net", 12345).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=host.free.net:12345", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanListSinglePeerByName() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byName("FriendNode").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=FriendNode", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientRecognizesUnknownNodeIdentifiers() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.listPeer().byIdentity("id2").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeer", + "Identifier=" + identifier, + "NodeIdentifier=id2", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=id2", + "EndMessage" + ); + assertThat(peer.get().isPresent(), is(false)); + } + + @Test + public void defaultFcpClientCanAddPeerFromFile() throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.addPeer().fromFile(new File("/tmp/ref.txt")).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "AddPeer", + "Identifier=" + identifier, + "File=/tmp/ref.txt", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanAddPeerFromURL() throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.addPeer().fromURL(new URL("http://node.ref/")).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "AddPeer", + "Identifier=" + identifier, + "URL=http://node.ref/", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanAddPeerFromNodeRef() throws InterruptedException, ExecutionException, IOException { + NodeRef nodeRef = new NodeRef(); + nodeRef.setIdentity("id1"); + nodeRef.setName("name"); + nodeRef.setARK(new ARK("public", "1")); + nodeRef.setDSAGroup(new DSAGroup("base", "prime", "subprime")); + nodeRef.setNegotiationTypes(new int[] { 3, 5 }); + nodeRef.setPhysicalUDP("1.2.3.4:5678"); + nodeRef.setDSAPublicKey("dsa-public"); + nodeRef.setSignature("sig"); + Future> peer = fcpClient.addPeer().fromNodeRef(nodeRef).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "AddPeer", + "Identifier=" + identifier, + "identity=id1", + "myName=name", + "ark.pubURI=public", + "ark.number=1", + "dsaGroup.g=base", + "dsaGroup.p=prime", + "dsaGroup.q=subprime", + "dsaPubKey.y=dsa-public", + "physical.udp=1.2.3.4:5678", + "auth.negTypes=3;5", + "sig=sig", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "identity=id1", + "opennet=false", + "ark.pubURI=SSK@3YEf.../ark", + "ark.number=78", + "auth.negTypes=2", + "version=Fred,0.7,1.0,1466", + "lastGoodVersion=Fred,0.7,1.0,1466", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void listPeerNotesCanGetPeerNotesByNodeName() throws InterruptedException, ExecutionException, IOException { + Future> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeerNotes", + "NodeIdentifier=Friend1", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "NoteText=RXhhbXBsZSBUZXh0Lg==", + "PeerNoteType=1", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeerNotes", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg==")); + assertThat(peerNote.get().get().getPeerNoteType(), is(1)); + } + + @Test + public void listPeerNotesReturnsEmptyOptionalWhenNodeIdenfierUnknown() + throws InterruptedException, ExecutionException, + IOException { + Future> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeerNotes", + "NodeIdentifier=Friend1", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(peerNote.get().isPresent(), is(false)); + } + + @Test + public void listPeerNotesCanGetPeerNotesByNodeIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future> peerNote = fcpClient.listPeerNotes().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeerNotes", + "NodeIdentifier=id1", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "NoteText=RXhhbXBsZSBUZXh0Lg==", + "PeerNoteType=1", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeerNotes", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg==")); + assertThat(peerNote.get().get().getPeerNoteType(), is(1)); + } + + @Test + public void listPeerNotesCanGetPeerNotesByHostNameAndPortNumber() + throws InterruptedException, ExecutionException, IOException { + Future> peerNote = fcpClient.listPeerNotes().byHostAndPort("1.2.3.4", 5678).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ListPeerNotes", + "NodeIdentifier=1.2.3.4:5678", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "NoteText=RXhhbXBsZSBUZXh0Lg==", + "PeerNoteType=1", + "EndMessage" + ); + fcpServer.writeLine( + "EndListPeerNotes", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg==")); + assertThat(peerNote.get().get().getPeerNoteType(), is(1)); + } + + @Test + public void defaultFcpClientCanEnablePeerByName() throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().enable().byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "IsDisabled=false", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanDisablePeerByName() throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().disable().byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "IsDisabled=true", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanEnablePeerByIdentity() throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsDisabled=false", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanEnablePeerByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().enable().byHostAndPort("1.2.3.4", 5678).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "IsDisabled=false", + "EndMessage" + )); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanNotModifyPeerOfUnknownNode() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsDisabled=false", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "EndMessage" + ); + assertThat(peer.get().isPresent(), is(false)); + } + + @Test + public void defaultFcpClientCanAllowLocalAddressesOfPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().allowLocalAddresses().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "AllowLocalAddresses=true", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanDisallowLocalAddressesOfPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().disallowLocalAddresses().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "AllowLocalAddresses=false", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanSetBurstOnlyForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().setBurstOnly().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsBurstOnly=true", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanClearBurstOnlyForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().clearBurstOnly().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsBurstOnly=false", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanSetListenOnlyForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().setListenOnly().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsListenOnly=true", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + assertThat(lines, not(contains(startsWith("IsBurstOnly=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanClearListenOnlyForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().clearListenOnly().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IsListenOnly=false", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + assertThat(lines, not(contains(startsWith("IsBurstOnly=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanIgnoreSourceForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().ignoreSource().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IgnoreSourcePort=true", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + assertThat(lines, not(contains(startsWith("IsBurstOnly=")))); + assertThat(lines, not(contains(startsWith("IsListenOnly=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanUseSourceForPeer() + throws InterruptedException, ExecutionException, IOException { + Future> peer = fcpClient.modifyPeer().useSource().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "IgnoreSourcePort=false", + "EndMessage" + )); + assertThat(lines, not(contains(startsWith("AllowLocalAddresses=")))); + assertThat(lines, not(contains(startsWith("IsDisabled=")))); + assertThat(lines, not(contains(startsWith("IsBurstOnly=")))); + assertThat(lines, not(contains(startsWith("IsListenOnly=")))); + fcpServer.writeLine( + "Peer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "identity=id1", + "EndMessage" + ); + assertThat(peer.get().get().getIdentity(), is("id1")); + } + + @Test + public void defaultFcpClientCanRemovePeerByName() throws InterruptedException, ExecutionException, IOException { + Future peer = fcpClient.removePeer().byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "RemovePeer", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + )); + fcpServer.writeLine( + "PeerRemoved", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(peer.get(), is(true)); + } + + @Test + public void defaultFcpClientCanNotRemovePeerByInvalidName() + throws InterruptedException, ExecutionException, IOException { + Future peer = fcpClient.removePeer().byName("NotFriend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "RemovePeer", + "Identifier=" + identifier, + "NodeIdentifier=NotFriend1", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(peer.get(), is(false)); + } + + @Test + public void defaultFcpClientCanRemovePeerByIdentity() throws InterruptedException, ExecutionException, IOException { + Future peer = fcpClient.removePeer().byIdentity("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "RemovePeer", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "EndMessage" + )); + fcpServer.writeLine( + "PeerRemoved", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(peer.get(), is(true)); + } + + @Test + public void defaultFcpClientCanRemovePeerByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future peer = fcpClient.removePeer().byHostAndPort("1.2.3.4", 5678).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "RemovePeer", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "EndMessage" + )); + fcpServer.writeLine( + "PeerRemoved", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(peer.get(), is(true)); + } + + @Test + public void defaultFcpClientCanModifyPeerNoteByName() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientKnowsPeerNoteWasNotModifiedOnUnknownNodeIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(false)); + } + + @Test + public void defaultFcpClientFailsToModifyPeerNoteWithoutPeerNote() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().byName("Friend1").execute(); + assertThat(noteUpdated.get(), is(false)); + } + + @Test + public void defaultFcpClientCanModifyPeerNoteByIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byIdentifier("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientCanModifyPeerNoteByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = + fcpClient.modifyPeerNote().darknetComment("foo").byHostAndPort("1.2.3.4", 5678).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientCanGetConfigWithoutDetails() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(configData.get(), notNullValue()); + } + + @Test + public void defaultFcpClientCanGetConfigWithCurrent() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withCurrent().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithCurrent=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "current.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getCurrent("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithDefaults() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withDefaults().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithDefaults=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "default.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getDefault("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithSortOrder() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withSortOrder().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithSortOrder=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "sortOrder.foo=17", + "EndMessage" + ); + assertThat(configData.get().getSortOrder("foo"), is(17)); + } + + @Test + public void defaultFcpClientCanGetConfigWithExpertFlag() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withExpertFlag().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithExpertFlag=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "expertFlag.foo=true", + "EndMessage" + ); + assertThat(configData.get().getExpertFlag("foo"), is(true)); + } + }