1 package net.pterodactylus.fcp.quelaton;
3 import static org.hamcrest.MatcherAssert.assertThat;
4 import static org.hamcrest.Matchers.allOf;
5 import static org.hamcrest.Matchers.contains;
6 import static org.hamcrest.Matchers.containsInAnyOrder;
7 import static org.hamcrest.Matchers.hasItem;
8 import static org.hamcrest.Matchers.hasSize;
9 import static org.hamcrest.Matchers.is;
10 import static org.hamcrest.Matchers.not;
11 import static org.hamcrest.Matchers.notNullValue;
12 import static org.hamcrest.Matchers.startsWith;
14 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
18 import java.nio.charset.StandardCharsets;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Optional;
22 import java.util.concurrent.CopyOnWriteArrayList;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.ExecutorService;
25 import java.util.concurrent.Executors;
26 import java.util.concurrent.Future;
27 import java.util.function.Supplier;
28 import java.util.stream.Collectors;
30 import net.pterodactylus.fcp.ARK;
31 import net.pterodactylus.fcp.ConfigData;
32 import net.pterodactylus.fcp.DSAGroup;
33 import net.pterodactylus.fcp.FcpKeyPair;
34 import net.pterodactylus.fcp.Key;
35 import net.pterodactylus.fcp.NodeData;
36 import net.pterodactylus.fcp.NodeRef;
37 import net.pterodactylus.fcp.Peer;
38 import net.pterodactylus.fcp.PeerNote;
39 import net.pterodactylus.fcp.PluginInfo;
40 import net.pterodactylus.fcp.Priority;
41 import net.pterodactylus.fcp.fake.FakeTcpServer;
42 import net.pterodactylus.fcp.quelaton.ClientGetCommand.Data;
44 import com.google.common.io.ByteStreams;
45 import com.google.common.io.Files;
46 import com.nitorcreations.junit.runners.NestedRunner;
47 import org.hamcrest.Description;
48 import org.hamcrest.Matcher;
49 import org.hamcrest.TypeSafeDiagnosingMatcher;
50 import org.junit.After;
51 import org.junit.Assert;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
56 * Unit test for {@link DefaultFcpClient}.
58 * @author <a href="bombe@freenetproject.org">David ‘Bombe’ Roden</a>
60 @RunWith(NestedRunner.class)
61 public class DefaultFcpClientTest {
63 private static final String INSERT_URI =
64 "SSK@RVCHbJdkkyTCeNN9AYukEg76eyqmiosSaNKgE3U9zUw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQECAAE/";
65 private static final String REQUEST_URI =
66 "SSK@wtbgd2loNcJCXvtQVOftl2tuWBomDQHfqS6ytpPRhfw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQACAAE/";
68 private int threadCounter = 0;
69 private final ExecutorService threadPool =
70 Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++));
71 private final FakeTcpServer fcpServer;
72 private final DefaultFcpClient fcpClient;
74 public DefaultFcpClientTest() throws IOException {
75 fcpServer = new FakeTcpServer(threadPool);
76 fcpClient = new DefaultFcpClient(threadPool, "localhost", fcpServer.getPort(), () -> "Test");
80 public void tearDown() throws IOException {
82 threadPool.shutdown();
85 @Test(expected = ExecutionException.class)
86 public void defaultFcpClientThrowsExceptionIfItCanNotConnect()
87 throws IOException, ExecutionException, InterruptedException {
88 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
89 fcpServer.connect().get();
90 fcpServer.collectUntil(is("EndMessage"));
92 "CloseConnectionDuplicateClientName",
98 @Test(expected = ExecutionException.class)
99 public void defaultFcpClientThrowsExceptionIfConnectionIsClosed()
100 throws IOException, ExecutionException, InterruptedException {
101 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
102 fcpServer.connect().get();
103 fcpServer.collectUntil(is("EndMessage"));
109 public void defaultFcpClientCanGenerateKeypair() throws ExecutionException, InterruptedException, IOException {
110 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
112 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
113 String identifier = extractIdentifier(lines);
114 fcpServer.writeLine("SSKKeypair",
115 "InsertURI=" + INSERT_URI + "",
116 "RequestURI=" + REQUEST_URI + "",
117 "Identifier=" + identifier,
119 FcpKeyPair keyPair = keyPairFuture.get();
120 assertThat(keyPair.getPublicKey(), is(REQUEST_URI));
121 assertThat(keyPair.getPrivateKey(), is(INSERT_URI));
124 private void connectNode() throws InterruptedException, ExecutionException, IOException {
125 fcpServer.connect().get();
126 fcpServer.collectUntil(is("EndMessage"));
127 fcpServer.writeLine("NodeHello",
128 "CompressionCodecs=4 - GZIP(0), BZIP2(1), LZMA(2), LZMA_NEW(3)",
129 "Revision=build01466",
131 "Version=Fred,0.7,1.0,1466",
133 "ConnectionIdentifier=14318898267048452a81b36e7f13a3f0",
137 "NodeLanguage=ENGLISH",
144 public void clientGetCanDownloadData() throws InterruptedException, ExecutionException, IOException {
145 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
147 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
148 assertThat(lines, matchesFcpMessage("ClientGet", "ReturnType=direct", "URI=KSK@foo.txt"));
149 String identifier = extractIdentifier(lines);
152 "Identifier=" + identifier,
154 "StartupTime=1435610539000",
155 "CompletionTime=1435610540000",
156 "Metadata.ContentType=text/plain;charset=utf-8",
160 Optional<Data> data = dataFuture.get();
161 assertThat(data.get().getMimeType(), is("text/plain;charset=utf-8"));
162 assertThat(data.get().size(), is(6L));
163 assertThat(ByteStreams.toByteArray(data.get().getInputStream()),
164 is("Hello\n".getBytes(StandardCharsets.UTF_8)));
167 private String extractIdentifier(List<String> lines) {
168 return lines.stream()
169 .filter(s -> s.startsWith("Identifier="))
170 .map(s -> s.substring(s.indexOf('=') + 1))
176 public void clientGetDownloadsDataForCorrectIdentifier()
177 throws InterruptedException, ExecutionException, IOException {
178 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
180 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
181 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
182 String identifier = extractIdentifier(lines);
185 "Identifier=not-test",
187 "StartupTime=1435610539000",
188 "CompletionTime=1435610540000",
189 "Metadata.ContentType=text/plain;charset=latin-9",
195 "Identifier=" + identifier,
197 "StartupTime=1435610539000",
198 "CompletionTime=1435610540000",
199 "Metadata.ContentType=text/plain;charset=utf-8",
203 Optional<Data> data = dataFuture.get();
204 assertThat(data.get().getMimeType(), is("text/plain;charset=utf-8"));
205 assertThat(data.get().size(), is(6L));
206 assertThat(ByteStreams.toByteArray(data.get().getInputStream()),
207 is("Hello\n".getBytes(StandardCharsets.UTF_8)));
211 public void clientGetRecognizesGetFailed() throws InterruptedException, ExecutionException, IOException {
212 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
214 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
215 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
216 String identifier = extractIdentifier(lines);
219 "Identifier=" + identifier,
223 Optional<Data> data = dataFuture.get();
224 assertThat(data.isPresent(), is(false));
228 public void clientGetRecognizesGetFailedForCorrectIdentifier()
229 throws InterruptedException, ExecutionException, IOException {
230 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
232 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
233 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
234 String identifier = extractIdentifier(lines);
237 "Identifier=not-test",
243 "Identifier=" + identifier,
247 Optional<Data> data = dataFuture.get();
248 assertThat(data.isPresent(), is(false));
251 @Test(expected = ExecutionException.class)
252 public void clientGetRecognizesConnectionClosed() throws InterruptedException, ExecutionException, IOException {
253 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
255 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
256 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
262 public void defaultFcpClientReusesConnection() throws InterruptedException, ExecutionException, IOException {
263 Future<FcpKeyPair> keyPair = fcpClient.generateKeypair().execute();
265 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
266 String identifier = extractIdentifier(lines);
269 "InsertURI=" + INSERT_URI + "",
270 "RequestURI=" + REQUEST_URI + "",
271 "Identifier=" + identifier,
275 keyPair = fcpClient.generateKeypair().execute();
276 lines = fcpServer.collectUntil(is("EndMessage"));
277 identifier = extractIdentifier(lines);
280 "InsertURI=" + INSERT_URI + "",
281 "RequestURI=" + REQUEST_URI + "",
282 "Identifier=" + identifier,
289 public void defaultFcpClientCanReconnectAfterConnectionHasBeenClosed()
290 throws InterruptedException, ExecutionException, IOException {
291 Future<FcpKeyPair> keyPair = fcpClient.generateKeypair().execute();
293 fcpServer.collectUntil(is("EndMessage"));
298 } catch (ExecutionException e) {
300 keyPair = fcpClient.generateKeypair().execute();
302 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
303 String identifier = extractIdentifier(lines);
306 "InsertURI=" + INSERT_URI + "",
307 "RequestURI=" + REQUEST_URI + "",
308 "Identifier=" + identifier,
315 public void clientGetWithIgnoreDataStoreSettingSendsCorrectCommands()
316 throws InterruptedException, ExecutionException, IOException {
317 fcpClient.clientGet().ignoreDataStore().uri("KSK@foo.txt").execute();
319 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
320 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "IgnoreDS=true"));
324 public void clientGetWithDataStoreOnlySettingSendsCorrectCommands()
325 throws InterruptedException, ExecutionException, IOException {
326 fcpClient.clientGet().dataStoreOnly().uri("KSK@foo.txt").execute();
328 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
329 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "DSonly=true"));
333 public void clientGetWithMaxSizeSettingSendsCorrectCommands()
334 throws InterruptedException, ExecutionException, IOException {
335 fcpClient.clientGet().maxSize(1048576).uri("KSK@foo.txt").execute();
337 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
338 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "MaxSize=1048576"));
342 public void clientGetWithPrioritySettingSendsCorrectCommands()
343 throws InterruptedException, ExecutionException, IOException {
344 fcpClient.clientGet().priority(Priority.interactive).uri("KSK@foo.txt").execute();
346 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
347 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "PriorityClass=1"));
351 public void clientGetWithRealTimeSettingSendsCorrectCommands()
352 throws InterruptedException, ExecutionException, IOException {
353 fcpClient.clientGet().realTime().uri("KSK@foo.txt").execute();
355 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
356 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "RealTimeFlag=true"));
360 public void clientGetWithGlobalSettingSendsCorrectCommands()
361 throws InterruptedException, ExecutionException, IOException {
362 fcpClient.clientGet().global().uri("KSK@foo.txt").execute();
364 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
365 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true"));
368 private Matcher<List<String>> matchesFcpMessage(String name, String... requiredLines) {
369 return new TypeSafeDiagnosingMatcher<List<String>>() {
371 protected boolean matchesSafely(List<String> item, Description mismatchDescription) {
372 if (!item.get(0).equals(name)) {
373 mismatchDescription.appendText("FCP message is named ").appendValue(item.get(0));
376 for (String requiredLine : requiredLines) {
377 if (item.indexOf(requiredLine) < 1) {
378 mismatchDescription.appendText("FCP message does not contain ").appendValue(requiredLine);
386 public void describeTo(Description description) {
387 description.appendText("FCP message named ").appendValue(name);
388 description.appendValueList(", containing the lines ", ", ", "", requiredLines);
394 public void clientPutWithDirectDataSendsCorrectCommand()
395 throws IOException, ExecutionException, InterruptedException {
396 fcpClient.clientPut()
397 .from(new ByteArrayInputStream("Hello\n".getBytes()))
402 List<String> lines = fcpServer.collectUntil(is("Hello"));
403 assertThat(lines, matchesFcpMessage("ClientPut", "UploadFrom=direct", "DataLength=6", "URI=KSK@foo.txt"));
407 public void clientPutWithDirectDataSucceedsOnCorrectIdentifier()
408 throws InterruptedException, ExecutionException, IOException {
409 Future<Optional<Key>> key = fcpClient.clientPut()
410 .from(new ByteArrayInputStream("Hello\n".getBytes()))
415 List<String> lines = fcpServer.collectUntil(is("Hello"));
416 String identifier = extractIdentifier(lines);
419 "Identifier=not-the-right-one",
425 "Identifier=" + identifier,
428 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
432 public void clientPutWithDirectDataFailsOnCorrectIdentifier()
433 throws InterruptedException, ExecutionException, IOException {
434 Future<Optional<Key>> key = fcpClient.clientPut()
435 .from(new ByteArrayInputStream("Hello\n".getBytes()))
440 List<String> lines = fcpServer.collectUntil(is("Hello"));
441 String identifier = extractIdentifier(lines);
444 "Identifier=not-the-right-one",
450 "Identifier=" + identifier,
453 assertThat(key.get().isPresent(), is(false));
457 public void clientPutWithRenamedDirectDataSendsCorrectCommand()
458 throws InterruptedException, ExecutionException, IOException {
459 fcpClient.clientPut()
460 .named("otherName.txt")
461 .from(new ByteArrayInputStream("Hello\n".getBytes()))
466 List<String> lines = fcpServer.collectUntil(is("Hello"));
467 assertThat(lines, matchesFcpMessage("ClientPut", "TargetFilename=otherName.txt", "UploadFrom=direct",
468 "DataLength=6", "URI=KSK@foo.txt"));
472 public void clientPutWithRedirectSendsCorrectCommand()
473 throws IOException, ExecutionException, InterruptedException {
474 fcpClient.clientPut().redirectTo("KSK@bar.txt").uri("KSK@foo.txt").execute();
476 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
478 matchesFcpMessage("ClientPut", "UploadFrom=redirect", "URI=KSK@foo.txt", "TargetURI=KSK@bar.txt"));
482 public void clientPutWithFileSendsCorrectCommand() throws InterruptedException, ExecutionException, IOException {
483 fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
485 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
487 matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt", "Filename=/tmp/data.txt"));
491 public void clientPutWithFileCanCompleteTestDdaSequence()
492 throws IOException, ExecutionException, InterruptedException {
493 File tempFile = createTempFile();
494 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
496 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
497 String identifier = extractIdentifier(lines);
500 "Identifier=" + identifier,
504 lines = fcpServer.collectUntil(is("EndMessage"));
505 assertThat(lines, matchesFcpMessage(
507 "Directory=" + tempFile.getParent(),
508 "WantReadDirectory=true",
509 "WantWriteDirectory=false",
514 "Directory=" + tempFile.getParent(),
515 "ReadFilename=" + tempFile,
518 lines = fcpServer.collectUntil(is("EndMessage"));
519 assertThat(lines, matchesFcpMessage(
521 "Directory=" + tempFile.getParent(),
522 "ReadContent=test-content",
527 "Directory=" + tempFile.getParent(),
528 "ReadDirectoryAllowed=true",
531 lines = fcpServer.collectUntil(is("EndMessage"));
533 matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt",
534 "Filename=" + new File(tempFile.getParent(), "test.dat")));
537 private File createTempFile() throws IOException {
538 File tempFile = File.createTempFile("test-dda-", ".dat");
539 tempFile.deleteOnExit();
540 Files.write("test-content", tempFile, StandardCharsets.UTF_8);
545 public void clientPutDoesNotReactToProtocolErrorForDifferentIdentifier()
546 throws InterruptedException, ExecutionException, IOException {
547 Future<Optional<Key>> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
549 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
550 String identifier = extractIdentifier(lines);
553 "Identifier=not-the-right-one",
559 "Identifier=" + identifier,
563 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
567 public void clientPutAbortsOnProtocolErrorOtherThan25()
568 throws InterruptedException, ExecutionException, IOException {
569 Future<Optional<Key>> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
571 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
572 String identifier = extractIdentifier(lines);
575 "Identifier=" + identifier,
579 assertThat(key.get().isPresent(), is(false));
583 public void clientPutDoesNotReplyToWrongTestDdaReply() throws IOException, ExecutionException,
584 InterruptedException {
585 File tempFile = createTempFile();
586 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
588 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
589 String identifier = extractIdentifier(lines);
592 "Identifier=" + identifier,
596 lines = fcpServer.collectUntil(is("EndMessage"));
597 assertThat(lines, matchesFcpMessage(
599 "Directory=" + tempFile.getParent(),
600 "WantReadDirectory=true",
601 "WantWriteDirectory=false",
606 "Directory=/some-other-directory",
607 "ReadFilename=" + tempFile,
612 "Directory=" + tempFile.getParent(),
613 "ReadFilename=" + tempFile,
616 lines = fcpServer.collectUntil(is("EndMessage"));
617 assertThat(lines, matchesFcpMessage(
619 "Directory=" + tempFile.getParent(),
620 "ReadContent=test-content",
626 public void clientPutSendsResponseEvenIfFileCanNotBeRead()
627 throws IOException, ExecutionException, InterruptedException {
628 File tempFile = createTempFile();
629 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
631 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
632 String identifier = extractIdentifier(lines);
635 "Identifier=" + identifier,
639 lines = fcpServer.collectUntil(is("EndMessage"));
640 assertThat(lines, matchesFcpMessage(
642 "Directory=" + tempFile.getParent(),
643 "WantReadDirectory=true",
644 "WantWriteDirectory=false",
649 "Directory=" + tempFile.getParent(),
650 "ReadFilename=" + tempFile + ".foo",
653 lines = fcpServer.collectUntil(is("EndMessage"));
654 assertThat(lines, matchesFcpMessage(
656 "Directory=" + tempFile.getParent(),
657 "ReadContent=failed-to-read",
663 public void clientPutDoesNotResendOriginalClientPutOnTestDDACompleteWithWrongDirectory()
664 throws IOException, ExecutionException, InterruptedException {
665 File tempFile = createTempFile();
666 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
668 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
669 String identifier = extractIdentifier(lines);
672 "Directory=/some-other-directory",
677 "Identifier=" + identifier,
681 lines = fcpServer.collectUntil(is("EndMessage"));
682 assertThat(lines, matchesFcpMessage(
684 "Directory=" + tempFile.getParent(),
685 "WantReadDirectory=true",
686 "WantWriteDirectory=false",
692 public void clientPutSendsNotificationsForGeneratedKeys()
693 throws InterruptedException, ExecutionException, IOException {
694 List<String> generatedKeys = new CopyOnWriteArrayList<>();
695 Future<Optional<Key>> key = fcpClient.clientPut()
696 .onKeyGenerated(generatedKeys::add)
697 .from(new ByteArrayInputStream("Hello\n".getBytes()))
702 List<String> lines = fcpServer.collectUntil(is("Hello"));
703 String identifier = extractIdentifier(lines);
706 "Identifier=" + identifier,
713 "Identifier=" + identifier,
716 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
717 assertThat(generatedKeys, contains("KSK@foo.txt"));
721 public void clientCanListPeers() throws IOException, ExecutionException, InterruptedException {
722 Future<Collection<Peer>> peers = fcpClient.listPeers().execute();
724 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
725 assertThat(lines, matchesFcpMessage(
727 "WithVolatile=false",
728 "WithMetadata=false",
731 String identifier = extractIdentifier(lines);
734 "Identifier=" + identifier,
740 "Identifier=" + identifier,
746 "Identifier=" + identifier,
749 assertThat(peers.get(), hasSize(2));
750 assertThat(peers.get().stream().map(Peer::getIdentity).collect(Collectors.toList()),
751 containsInAnyOrder("id1", "id2"));
755 public void clientCanListPeersWithMetadata() throws IOException, ExecutionException, InterruptedException {
756 Future<Collection<Peer>> peers = fcpClient.listPeers().includeMetadata().execute();
758 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
759 assertThat(lines, matchesFcpMessage(
761 "WithVolatile=false",
765 String identifier = extractIdentifier(lines);
768 "Identifier=" + identifier,
775 "Identifier=" + identifier,
782 "Identifier=" + identifier,
785 assertThat(peers.get(), hasSize(2));
786 assertThat(peers.get().stream().map(peer -> peer.getMetadata("foo")).collect(Collectors.toList()),
787 containsInAnyOrder("bar1", "bar2"));
791 public void clientCanListPeersWithVolatiles() throws IOException, ExecutionException, InterruptedException {
792 Future<Collection<Peer>> peers = fcpClient.listPeers().includeVolatile().execute();
794 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
795 assertThat(lines, matchesFcpMessage(
798 "WithMetadata=false",
801 String identifier = extractIdentifier(lines);
804 "Identifier=" + identifier,
811 "Identifier=" + identifier,
818 "Identifier=" + identifier,
821 assertThat(peers.get(), hasSize(2));
822 assertThat(peers.get().stream().map(peer -> peer.getVolatile("foo")).collect(Collectors.toList()),
823 containsInAnyOrder("bar1", "bar2"));
827 public void defaultFcpClientCanGetNodeInformation() throws InterruptedException, ExecutionException, IOException {
828 Future<NodeData> nodeData = fcpClient.getNode().execute();
830 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
831 String identifier = extractIdentifier(lines);
832 assertThat(lines, matchesFcpMessage(
834 "Identifier=" + identifier,
835 "GiveOpennetRef=false",
837 "WithVolatile=false",
842 "Identifier=" + identifier,
843 "ark.pubURI=SSK@3YEf.../ark",
846 "version=Fred,0.7,1.0,1466",
847 "lastGoodVersion=Fred,0.7,1.0,1466",
850 assertThat(nodeData.get(), notNullValue());
854 public void defaultFcpClientCanGetNodeInformationWithOpennetRef()
855 throws InterruptedException, ExecutionException, IOException {
856 Future<NodeData> nodeData = fcpClient.getNode().opennetRef().execute();
858 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
859 String identifier = extractIdentifier(lines);
860 assertThat(lines, matchesFcpMessage(
862 "Identifier=" + identifier,
863 "GiveOpennetRef=true",
865 "WithVolatile=false",
870 "Identifier=" + identifier,
872 "ark.pubURI=SSK@3YEf.../ark",
875 "version=Fred,0.7,1.0,1466",
876 "lastGoodVersion=Fred,0.7,1.0,1466",
879 assertThat(nodeData.get().getVersion().toString(), is("Fred,0.7,1.0,1466"));
883 public void defaultFcpClientCanGetNodeInformationWithPrivateData()
884 throws InterruptedException, ExecutionException, IOException {
885 Future<NodeData> nodeData = fcpClient.getNode().includePrivate().execute();
887 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
888 String identifier = extractIdentifier(lines);
889 assertThat(lines, matchesFcpMessage(
891 "Identifier=" + identifier,
892 "GiveOpennetRef=false",
894 "WithVolatile=false",
899 "Identifier=" + identifier,
901 "ark.pubURI=SSK@3YEf.../ark",
904 "version=Fred,0.7,1.0,1466",
905 "lastGoodVersion=Fred,0.7,1.0,1466",
906 "ark.privURI=SSK@XdHMiRl",
909 assertThat(nodeData.get().getARK().getPrivateURI(), is("SSK@XdHMiRl"));
913 public void defaultFcpClientCanGetNodeInformationWithVolatileData()
914 throws InterruptedException, ExecutionException, IOException {
915 Future<NodeData> nodeData = fcpClient.getNode().includeVolatile().execute();
917 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
918 String identifier = extractIdentifier(lines);
919 assertThat(lines, matchesFcpMessage(
921 "Identifier=" + identifier,
922 "GiveOpennetRef=false",
929 "Identifier=" + identifier,
931 "ark.pubURI=SSK@3YEf.../ark",
934 "version=Fred,0.7,1.0,1466",
935 "lastGoodVersion=Fred,0.7,1.0,1466",
936 "volatile.freeJavaMemory=205706528",
939 assertThat(nodeData.get().getVolatile("freeJavaMemory"), is("205706528"));
943 public void defaultFcpClientCanListSinglePeerByIdentity()
944 throws InterruptedException, ExecutionException, IOException {
945 Future<Optional<Peer>> peer = fcpClient.listPeer().byIdentity("id1").execute();
947 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
948 String identifier = extractIdentifier(lines);
949 assertThat(lines, matchesFcpMessage(
951 "Identifier=" + identifier,
952 "NodeIdentifier=id1",
957 "Identifier=" + identifier,
960 "ark.pubURI=SSK@3YEf.../ark",
963 "version=Fred,0.7,1.0,1466",
964 "lastGoodVersion=Fred,0.7,1.0,1466",
967 assertThat(peer.get().get().getIdentity(), is("id1"));
971 public void defaultFcpClientCanListSinglePeerByHostAndPort()
972 throws InterruptedException, ExecutionException, IOException {
973 Future<Optional<Peer>> peer = fcpClient.listPeer().byHostAndPort("host.free.net", 12345).execute();
975 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
976 String identifier = extractIdentifier(lines);
977 assertThat(lines, matchesFcpMessage(
979 "Identifier=" + identifier,
980 "NodeIdentifier=host.free.net:12345",
985 "Identifier=" + identifier,
988 "ark.pubURI=SSK@3YEf.../ark",
991 "version=Fred,0.7,1.0,1466",
992 "lastGoodVersion=Fred,0.7,1.0,1466",
995 assertThat(peer.get().get().getIdentity(), is("id1"));
999 public void defaultFcpClientCanListSinglePeerByName()
1000 throws InterruptedException, ExecutionException, IOException {
1001 Future<Optional<Peer>> peer = fcpClient.listPeer().byName("FriendNode").execute();
1003 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1004 String identifier = extractIdentifier(lines);
1005 assertThat(lines, matchesFcpMessage(
1007 "Identifier=" + identifier,
1008 "NodeIdentifier=FriendNode",
1011 fcpServer.writeLine(
1013 "Identifier=" + identifier,
1016 "ark.pubURI=SSK@3YEf.../ark",
1019 "version=Fred,0.7,1.0,1466",
1020 "lastGoodVersion=Fred,0.7,1.0,1466",
1023 assertThat(peer.get().get().getIdentity(), is("id1"));
1027 public void defaultFcpClientRecognizesUnknownNodeIdentifiers()
1028 throws InterruptedException, ExecutionException, IOException {
1029 Future<Optional<Peer>> peer = fcpClient.listPeer().byIdentity("id2").execute();
1031 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1032 String identifier = extractIdentifier(lines);
1033 assertThat(lines, matchesFcpMessage(
1035 "Identifier=" + identifier,
1036 "NodeIdentifier=id2",
1039 fcpServer.writeLine(
1040 "UnknownNodeIdentifier",
1041 "Identifier=" + identifier,
1042 "NodeIdentifier=id2",
1045 assertThat(peer.get().isPresent(), is(false));
1049 public void defaultFcpClientCanAddPeerFromFile() throws InterruptedException, ExecutionException, IOException {
1050 Future<Optional<Peer>> peer = fcpClient.addPeer().fromFile(new File("/tmp/ref.txt")).execute();
1052 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1053 String identifier = extractIdentifier(lines);
1054 assertThat(lines, matchesFcpMessage(
1056 "Identifier=" + identifier,
1057 "File=/tmp/ref.txt",
1060 fcpServer.writeLine(
1062 "Identifier=" + identifier,
1065 "ark.pubURI=SSK@3YEf.../ark",
1068 "version=Fred,0.7,1.0,1466",
1069 "lastGoodVersion=Fred,0.7,1.0,1466",
1072 assertThat(peer.get().get().getIdentity(), is("id1"));
1076 public void defaultFcpClientCanAddPeerFromURL() throws InterruptedException, ExecutionException, IOException {
1077 Future<Optional<Peer>> peer = fcpClient.addPeer().fromURL(new URL("http://node.ref/")).execute();
1079 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1080 String identifier = extractIdentifier(lines);
1081 assertThat(lines, matchesFcpMessage(
1083 "Identifier=" + identifier,
1084 "URL=http://node.ref/",
1087 fcpServer.writeLine(
1089 "Identifier=" + identifier,
1092 "ark.pubURI=SSK@3YEf.../ark",
1095 "version=Fred,0.7,1.0,1466",
1096 "lastGoodVersion=Fred,0.7,1.0,1466",
1099 assertThat(peer.get().get().getIdentity(), is("id1"));
1103 public void defaultFcpClientCanAddPeerFromNodeRef() throws InterruptedException, ExecutionException, IOException {
1104 NodeRef nodeRef = new NodeRef();
1105 nodeRef.setIdentity("id1");
1106 nodeRef.setName("name");
1107 nodeRef.setARK(new ARK("public", "1"));
1108 nodeRef.setDSAGroup(new DSAGroup("base", "prime", "subprime"));
1109 nodeRef.setNegotiationTypes(new int[] { 3, 5 });
1110 nodeRef.setPhysicalUDP("1.2.3.4:5678");
1111 nodeRef.setDSAPublicKey("dsa-public");
1112 nodeRef.setSignature("sig");
1113 Future<Optional<Peer>> peer = fcpClient.addPeer().fromNodeRef(nodeRef).execute();
1115 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1116 String identifier = extractIdentifier(lines);
1117 assertThat(lines, matchesFcpMessage(
1119 "Identifier=" + identifier,
1122 "ark.pubURI=public",
1126 "dsaGroup.q=subprime",
1127 "dsaPubKey.y=dsa-public",
1128 "physical.udp=1.2.3.4:5678",
1129 "auth.negTypes=3;5",
1133 fcpServer.writeLine(
1135 "Identifier=" + identifier,
1138 "ark.pubURI=SSK@3YEf.../ark",
1141 "version=Fred,0.7,1.0,1466",
1142 "lastGoodVersion=Fred,0.7,1.0,1466",
1145 assertThat(peer.get().get().getIdentity(), is("id1"));
1149 public void listPeerNotesCanGetPeerNotesByNodeName() throws InterruptedException, ExecutionException, IOException {
1150 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute();
1152 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1153 String identifier = extractIdentifier(lines);
1154 assertThat(lines, matchesFcpMessage(
1156 "NodeIdentifier=Friend1",
1159 fcpServer.writeLine(
1161 "Identifier=" + identifier,
1162 "NodeIdentifier=Friend1",
1163 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1167 fcpServer.writeLine(
1169 "Identifier=" + identifier,
1172 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1173 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1177 public void listPeerNotesReturnsEmptyOptionalWhenNodeIdenfierUnknown()
1178 throws InterruptedException, ExecutionException,
1180 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute();
1182 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1183 String identifier = extractIdentifier(lines);
1184 assertThat(lines, matchesFcpMessage(
1186 "NodeIdentifier=Friend1",
1189 fcpServer.writeLine(
1190 "UnknownNodeIdentifier",
1191 "Identifier=" + identifier,
1192 "NodeIdentifier=Friend1",
1195 assertThat(peerNote.get().isPresent(), is(false));
1199 public void listPeerNotesCanGetPeerNotesByNodeIdentifier()
1200 throws InterruptedException, ExecutionException, IOException {
1201 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byIdentity("id1").execute();
1203 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1204 String identifier = extractIdentifier(lines);
1205 assertThat(lines, matchesFcpMessage(
1207 "NodeIdentifier=id1",
1210 fcpServer.writeLine(
1212 "Identifier=" + identifier,
1213 "NodeIdentifier=id1",
1214 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1218 fcpServer.writeLine(
1220 "Identifier=" + identifier,
1223 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1224 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1228 public void listPeerNotesCanGetPeerNotesByHostNameAndPortNumber()
1229 throws InterruptedException, ExecutionException, IOException {
1230 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byHostAndPort("1.2.3.4", 5678).execute();
1232 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1233 String identifier = extractIdentifier(lines);
1234 assertThat(lines, matchesFcpMessage(
1236 "NodeIdentifier=1.2.3.4:5678",
1239 fcpServer.writeLine(
1241 "Identifier=" + identifier,
1242 "NodeIdentifier=id1",
1243 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1247 fcpServer.writeLine(
1249 "Identifier=" + identifier,
1252 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1253 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1257 public void defaultFcpClientCanEnablePeerByName() throws InterruptedException, ExecutionException, IOException {
1258 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byName("Friend1").execute();
1260 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1261 String identifier = extractIdentifier(lines);
1262 assertThat(lines, matchesFcpMessage(
1264 "Identifier=" + identifier,
1265 "NodeIdentifier=Friend1",
1269 fcpServer.writeLine(
1271 "Identifier=" + identifier,
1272 "NodeIdentifier=Friend1",
1276 assertThat(peer.get().get().getIdentity(), is("id1"));
1280 public void defaultFcpClientCanDisablePeerByName() throws InterruptedException, ExecutionException, IOException {
1281 Future<Optional<Peer>> peer = fcpClient.modifyPeer().disable().byName("Friend1").execute();
1283 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1284 String identifier = extractIdentifier(lines);
1285 assertThat(lines, matchesFcpMessage(
1287 "Identifier=" + identifier,
1288 "NodeIdentifier=Friend1",
1292 fcpServer.writeLine(
1294 "Identifier=" + identifier,
1295 "NodeIdentifier=Friend1",
1299 assertThat(peer.get().get().getIdentity(), is("id1"));
1303 public void defaultFcpClientCanEnablePeerByIdentity() throws InterruptedException, ExecutionException, IOException {
1304 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute();
1306 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1307 String identifier = extractIdentifier(lines);
1308 assertThat(lines, matchesFcpMessage(
1310 "Identifier=" + identifier,
1311 "NodeIdentifier=id1",
1315 fcpServer.writeLine(
1317 "Identifier=" + identifier,
1318 "NodeIdentifier=Friend1",
1322 assertThat(peer.get().get().getIdentity(), is("id1"));
1326 public void defaultFcpClientCanEnablePeerByHostAndPort()
1327 throws InterruptedException, ExecutionException, IOException {
1328 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byHostAndPort("1.2.3.4", 5678).execute();
1330 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1331 String identifier = extractIdentifier(lines);
1332 assertThat(lines, matchesFcpMessage(
1334 "Identifier=" + identifier,
1335 "NodeIdentifier=1.2.3.4:5678",
1339 fcpServer.writeLine(
1341 "Identifier=" + identifier,
1342 "NodeIdentifier=Friend1",
1346 assertThat(peer.get().get().getIdentity(), is("id1"));
1350 public void defaultFcpClientCanNotModifyPeerOfUnknownNode()
1351 throws InterruptedException, ExecutionException, IOException {
1352 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute();
1354 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1355 String identifier = extractIdentifier(lines);
1356 assertThat(lines, matchesFcpMessage(
1358 "Identifier=" + identifier,
1359 "NodeIdentifier=id1",
1363 fcpServer.writeLine(
1364 "UnknownNodeIdentifier",
1365 "Identifier=" + identifier,
1366 "NodeIdentifier=id1",
1369 assertThat(peer.get().isPresent(), is(false));
1373 public void defaultFcpClientCanAllowLocalAddressesOfPeer()
1374 throws InterruptedException, ExecutionException, IOException {
1375 Future<Optional<Peer>> peer = fcpClient.modifyPeer().allowLocalAddresses().byIdentity("id1").execute();
1377 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1378 String identifier = extractIdentifier(lines);
1379 assertThat(lines, matchesFcpMessage(
1381 "Identifier=" + identifier,
1382 "NodeIdentifier=id1",
1383 "AllowLocalAddresses=true",
1386 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1387 fcpServer.writeLine(
1389 "Identifier=" + identifier,
1390 "NodeIdentifier=Friend1",
1394 assertThat(peer.get().get().getIdentity(), is("id1"));
1398 public void defaultFcpClientCanDisallowLocalAddressesOfPeer()
1399 throws InterruptedException, ExecutionException, IOException {
1400 Future<Optional<Peer>> peer = fcpClient.modifyPeer().disallowLocalAddresses().byIdentity("id1").execute();
1402 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1403 String identifier = extractIdentifier(lines);
1404 assertThat(lines, matchesFcpMessage(
1406 "Identifier=" + identifier,
1407 "NodeIdentifier=id1",
1408 "AllowLocalAddresses=false",
1411 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1412 fcpServer.writeLine(
1414 "Identifier=" + identifier,
1415 "NodeIdentifier=Friend1",
1419 assertThat(peer.get().get().getIdentity(), is("id1"));
1423 public void defaultFcpClientCanSetBurstOnlyForPeer()
1424 throws InterruptedException, ExecutionException, IOException {
1425 Future<Optional<Peer>> peer = fcpClient.modifyPeer().setBurstOnly().byIdentity("id1").execute();
1427 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1428 String identifier = extractIdentifier(lines);
1429 assertThat(lines, matchesFcpMessage(
1431 "Identifier=" + identifier,
1432 "NodeIdentifier=id1",
1436 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1437 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1438 fcpServer.writeLine(
1440 "Identifier=" + identifier,
1441 "NodeIdentifier=Friend1",
1445 assertThat(peer.get().get().getIdentity(), is("id1"));
1449 public void defaultFcpClientCanClearBurstOnlyForPeer()
1450 throws InterruptedException, ExecutionException, IOException {
1451 Future<Optional<Peer>> peer = fcpClient.modifyPeer().clearBurstOnly().byIdentity("id1").execute();
1453 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1454 String identifier = extractIdentifier(lines);
1455 assertThat(lines, matchesFcpMessage(
1457 "Identifier=" + identifier,
1458 "NodeIdentifier=id1",
1459 "IsBurstOnly=false",
1462 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1463 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1464 fcpServer.writeLine(
1466 "Identifier=" + identifier,
1467 "NodeIdentifier=Friend1",
1471 assertThat(peer.get().get().getIdentity(), is("id1"));
1475 public void defaultFcpClientCanSetListenOnlyForPeer()
1476 throws InterruptedException, ExecutionException, IOException {
1477 Future<Optional<Peer>> peer = fcpClient.modifyPeer().setListenOnly().byIdentity("id1").execute();
1479 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1480 String identifier = extractIdentifier(lines);
1481 assertThat(lines, matchesFcpMessage(
1483 "Identifier=" + identifier,
1484 "NodeIdentifier=id1",
1485 "IsListenOnly=true",
1488 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1489 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1490 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1491 fcpServer.writeLine(
1493 "Identifier=" + identifier,
1494 "NodeIdentifier=Friend1",
1498 assertThat(peer.get().get().getIdentity(), is("id1"));
1502 public void defaultFcpClientCanClearListenOnlyForPeer()
1503 throws InterruptedException, ExecutionException, IOException {
1504 Future<Optional<Peer>> peer = fcpClient.modifyPeer().clearListenOnly().byIdentity("id1").execute();
1506 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1507 String identifier = extractIdentifier(lines);
1508 assertThat(lines, matchesFcpMessage(
1510 "Identifier=" + identifier,
1511 "NodeIdentifier=id1",
1512 "IsListenOnly=false",
1515 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1516 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1517 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1518 fcpServer.writeLine(
1520 "Identifier=" + identifier,
1521 "NodeIdentifier=Friend1",
1525 assertThat(peer.get().get().getIdentity(), is("id1"));
1529 public void defaultFcpClientCanIgnoreSourceForPeer()
1530 throws InterruptedException, ExecutionException, IOException {
1531 Future<Optional<Peer>> peer = fcpClient.modifyPeer().ignoreSource().byIdentity("id1").execute();
1533 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1534 String identifier = extractIdentifier(lines);
1535 assertThat(lines, matchesFcpMessage(
1537 "Identifier=" + identifier,
1538 "NodeIdentifier=id1",
1539 "IgnoreSourcePort=true",
1542 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1543 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1544 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1545 assertThat(lines, not(contains(startsWith("IsListenOnly="))));
1546 fcpServer.writeLine(
1548 "Identifier=" + identifier,
1549 "NodeIdentifier=Friend1",
1553 assertThat(peer.get().get().getIdentity(), is("id1"));
1557 public void defaultFcpClientCanUseSourceForPeer()
1558 throws InterruptedException, ExecutionException, IOException {
1559 Future<Optional<Peer>> peer = fcpClient.modifyPeer().useSource().byIdentity("id1").execute();
1561 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1562 String identifier = extractIdentifier(lines);
1563 assertThat(lines, matchesFcpMessage(
1565 "Identifier=" + identifier,
1566 "NodeIdentifier=id1",
1567 "IgnoreSourcePort=false",
1570 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1571 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1572 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1573 assertThat(lines, not(contains(startsWith("IsListenOnly="))));
1574 fcpServer.writeLine(
1576 "Identifier=" + identifier,
1577 "NodeIdentifier=Friend1",
1581 assertThat(peer.get().get().getIdentity(), is("id1"));
1585 public void defaultFcpClientCanRemovePeerByName() throws InterruptedException, ExecutionException, IOException {
1586 Future<Boolean> peer = fcpClient.removePeer().byName("Friend1").execute();
1588 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1589 String identifier = extractIdentifier(lines);
1590 assertThat(lines, matchesFcpMessage(
1592 "Identifier=" + identifier,
1593 "NodeIdentifier=Friend1",
1596 fcpServer.writeLine(
1598 "Identifier=" + identifier,
1599 "NodeIdentifier=Friend1",
1602 assertThat(peer.get(), is(true));
1606 public void defaultFcpClientCanNotRemovePeerByInvalidName()
1607 throws InterruptedException, ExecutionException, IOException {
1608 Future<Boolean> peer = fcpClient.removePeer().byName("NotFriend1").execute();
1610 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1611 String identifier = extractIdentifier(lines);
1612 assertThat(lines, matchesFcpMessage(
1614 "Identifier=" + identifier,
1615 "NodeIdentifier=NotFriend1",
1618 fcpServer.writeLine(
1619 "UnknownNodeIdentifier",
1620 "Identifier=" + identifier,
1623 assertThat(peer.get(), is(false));
1627 public void defaultFcpClientCanRemovePeerByIdentity() throws InterruptedException, ExecutionException, IOException {
1628 Future<Boolean> peer = fcpClient.removePeer().byIdentity("id1").execute();
1630 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1631 String identifier = extractIdentifier(lines);
1632 assertThat(lines, matchesFcpMessage(
1634 "Identifier=" + identifier,
1635 "NodeIdentifier=id1",
1638 fcpServer.writeLine(
1640 "Identifier=" + identifier,
1641 "NodeIdentifier=Friend1",
1644 assertThat(peer.get(), is(true));
1648 public void defaultFcpClientCanRemovePeerByHostAndPort()
1649 throws InterruptedException, ExecutionException, IOException {
1650 Future<Boolean> peer = fcpClient.removePeer().byHostAndPort("1.2.3.4", 5678).execute();
1652 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1653 String identifier = extractIdentifier(lines);
1654 assertThat(lines, matchesFcpMessage(
1656 "Identifier=" + identifier,
1657 "NodeIdentifier=1.2.3.4:5678",
1660 fcpServer.writeLine(
1662 "Identifier=" + identifier,
1663 "NodeIdentifier=Friend1",
1666 assertThat(peer.get(), is(true));
1670 public void defaultFcpClientCanModifyPeerNoteByName()
1671 throws InterruptedException, ExecutionException, IOException {
1672 Future<Boolean> noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute();
1674 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1675 String identifier = extractIdentifier(lines);
1676 assertThat(lines, matchesFcpMessage(
1678 "Identifier=" + identifier,
1679 "NodeIdentifier=Friend1",
1684 fcpServer.writeLine(
1686 "Identifier=" + identifier,
1687 "NodeIdentifier=Friend1",
1692 assertThat(noteUpdated.get(), is(true));
1696 public void defaultFcpClientKnowsPeerNoteWasNotModifiedOnUnknownNodeIdentifier()
1697 throws InterruptedException, ExecutionException, IOException {
1698 Future<Boolean> noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute();
1700 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1701 String identifier = extractIdentifier(lines);
1702 assertThat(lines, matchesFcpMessage(
1704 "Identifier=" + identifier,
1705 "NodeIdentifier=Friend1",
1710 fcpServer.writeLine(
1711 "UnknownNodeIdentifier",
1712 "Identifier=" + identifier,
1713 "NodeIdentifier=Friend1",
1716 assertThat(noteUpdated.get(), is(false));
1720 public void defaultFcpClientFailsToModifyPeerNoteWithoutPeerNote()
1721 throws InterruptedException, ExecutionException, IOException {
1722 Future<Boolean> noteUpdated = fcpClient.modifyPeerNote().byName("Friend1").execute();
1723 assertThat(noteUpdated.get(), is(false));
1727 public void defaultFcpClientCanModifyPeerNoteByIdentifier()
1728 throws InterruptedException, ExecutionException, IOException {
1729 Future<Boolean> noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byIdentifier("id1").execute();
1731 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1732 String identifier = extractIdentifier(lines);
1733 assertThat(lines, matchesFcpMessage(
1735 "Identifier=" + identifier,
1736 "NodeIdentifier=id1",
1741 fcpServer.writeLine(
1743 "Identifier=" + identifier,
1744 "NodeIdentifier=id1",
1749 assertThat(noteUpdated.get(), is(true));
1753 public void defaultFcpClientCanModifyPeerNoteByHostAndPort()
1754 throws InterruptedException, ExecutionException, IOException {
1755 Future<Boolean> noteUpdated =
1756 fcpClient.modifyPeerNote().darknetComment("foo").byHostAndPort("1.2.3.4", 5678).execute();
1758 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1759 String identifier = extractIdentifier(lines);
1760 assertThat(lines, matchesFcpMessage(
1762 "Identifier=" + identifier,
1763 "NodeIdentifier=1.2.3.4:5678",
1768 fcpServer.writeLine(
1770 "Identifier=" + identifier,
1771 "NodeIdentifier=1.2.3.4:5678",
1776 assertThat(noteUpdated.get(), is(true));
1780 public void defaultFcpClientCanGetConfigWithoutDetails()
1781 throws InterruptedException, ExecutionException, IOException {
1782 Future<ConfigData> configData = fcpClient.getConfig().execute();
1784 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1785 String identifier = extractIdentifier(lines);
1786 assertThat(lines, matchesFcpMessage(
1788 "Identifier=" + identifier,
1791 fcpServer.writeLine(
1793 "Identifier=" + identifier,
1796 assertThat(configData.get(), notNullValue());
1800 public void defaultFcpClientCanGetConfigWithCurrent()
1801 throws InterruptedException, ExecutionException, IOException {
1802 Future<ConfigData> configData = fcpClient.getConfig().withCurrent().execute();
1804 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1805 String identifier = extractIdentifier(lines);
1806 assertThat(lines, matchesFcpMessage(
1808 "Identifier=" + identifier,
1812 fcpServer.writeLine(
1814 "Identifier=" + identifier,
1818 assertThat(configData.get().getCurrent("foo"), is("bar"));
1822 public void defaultFcpClientCanGetConfigWithDefaults()
1823 throws InterruptedException, ExecutionException, IOException {
1824 Future<ConfigData> configData = fcpClient.getConfig().withDefaults().execute();
1826 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1827 String identifier = extractIdentifier(lines);
1828 assertThat(lines, matchesFcpMessage(
1830 "Identifier=" + identifier,
1831 "WithDefaults=true",
1834 fcpServer.writeLine(
1836 "Identifier=" + identifier,
1840 assertThat(configData.get().getDefault("foo"), is("bar"));
1844 public void defaultFcpClientCanGetConfigWithSortOrder()
1845 throws InterruptedException, ExecutionException, IOException {
1846 Future<ConfigData> configData = fcpClient.getConfig().withSortOrder().execute();
1848 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1849 String identifier = extractIdentifier(lines);
1850 assertThat(lines, matchesFcpMessage(
1852 "Identifier=" + identifier,
1853 "WithSortOrder=true",
1856 fcpServer.writeLine(
1858 "Identifier=" + identifier,
1862 assertThat(configData.get().getSortOrder("foo"), is(17));
1866 public void defaultFcpClientCanGetConfigWithExpertFlag()
1867 throws InterruptedException, ExecutionException, IOException {
1868 Future<ConfigData> configData = fcpClient.getConfig().withExpertFlag().execute();
1870 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1871 String identifier = extractIdentifier(lines);
1872 assertThat(lines, matchesFcpMessage(
1874 "Identifier=" + identifier,
1875 "WithExpertFlag=true",
1878 fcpServer.writeLine(
1880 "Identifier=" + identifier,
1881 "expertFlag.foo=true",
1884 assertThat(configData.get().getExpertFlag("foo"), is(true));
1888 public void defaultFcpClientCanGetConfigWithForceWriteFlag()
1889 throws InterruptedException, ExecutionException, IOException {
1890 Future<ConfigData> configData = fcpClient.getConfig().withForceWriteFlag().execute();
1892 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1893 String identifier = extractIdentifier(lines);
1894 assertThat(lines, matchesFcpMessage(
1896 "Identifier=" + identifier,
1897 "WithForceWriteFlag=true",
1900 fcpServer.writeLine(
1902 "Identifier=" + identifier,
1903 "forceWriteFlag.foo=true",
1906 assertThat(configData.get().getForceWriteFlag("foo"), is(true));
1910 public void defaultFcpClientCanGetConfigWithShortDescription()
1911 throws InterruptedException, ExecutionException, IOException {
1912 Future<ConfigData> configData = fcpClient.getConfig().withShortDescription().execute();
1914 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1915 String identifier = extractIdentifier(lines);
1916 assertThat(lines, matchesFcpMessage(
1918 "Identifier=" + identifier,
1919 "WithShortDescription=true",
1922 fcpServer.writeLine(
1924 "Identifier=" + identifier,
1925 "shortDescription.foo=bar",
1928 assertThat(configData.get().getShortDescription("foo"), is("bar"));
1932 public void defaultFcpClientCanGetConfigWithLongDescription()
1933 throws InterruptedException, ExecutionException, IOException {
1934 Future<ConfigData> configData = fcpClient.getConfig().withLongDescription().execute();
1936 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1937 String identifier = extractIdentifier(lines);
1938 assertThat(lines, matchesFcpMessage(
1940 "Identifier=" + identifier,
1941 "WithLongDescription=true",
1944 fcpServer.writeLine(
1946 "Identifier=" + identifier,
1947 "longDescription.foo=bar",
1950 assertThat(configData.get().getLongDescription("foo"), is("bar"));
1954 public void defaultFcpClientCanGetConfigWithDataTypes()
1955 throws InterruptedException, ExecutionException, IOException {
1956 Future<ConfigData> configData = fcpClient.getConfig().withDataTypes().execute();
1958 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1959 String identifier = extractIdentifier(lines);
1960 assertThat(lines, matchesFcpMessage(
1962 "Identifier=" + identifier,
1963 "WithDataTypes=true",
1966 fcpServer.writeLine(
1968 "Identifier=" + identifier,
1969 "dataType.foo=number",
1972 assertThat(configData.get().getDataType("foo"), is("number"));
1976 public void defaultFcpClientCanModifyConfigData() throws InterruptedException, ExecutionException, IOException {
1977 Future<ConfigData> newConfigData = fcpClient.modifyConfig().set("foo.bar").to("baz").execute();
1979 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1980 String identifier = extractIdentifier(lines);
1981 assertThat(lines, matchesFcpMessage(
1983 "Identifier=" + identifier,
1987 fcpServer.writeLine(
1989 "Identifier=" + identifier,
1990 "current.foo.bar=baz",
1993 assertThat(newConfigData.get().getCurrent("foo.bar"), is("baz"));
1996 public class PluginCommands {
1998 private static final String CLASS_NAME = "foo.plugin.Plugin";
2000 private List<String> lines;
2001 private String identifier;
2003 private void connectAndAssert(Supplier<Matcher<List<String>>> requestMatcher)
2004 throws InterruptedException, ExecutionException, IOException {
2006 lines = fcpServer.collectUntil(is("EndMessage"));
2007 identifier = extractIdentifier(lines);
2008 assertThat(lines, requestMatcher.get());
2011 private void replyWithPluginInfo() throws IOException {
2012 fcpServer.writeLine(
2014 "Identifier=" + identifier,
2015 "PluginName=superPlugin",
2017 "LongVersion=1.2.3",
2019 "OriginUri=superPlugin",
2025 private void verifyPluginInfo(Future<Optional<PluginInfo>> pluginInfo)
2026 throws InterruptedException, ExecutionException {
2027 assertThat(pluginInfo.get().get().getPluginName(), is("superPlugin"));
2028 assertThat(pluginInfo.get().get().getOriginalURI(), is("superPlugin"));
2029 assertThat(pluginInfo.get().get().isTalkable(), is(true));
2030 assertThat(pluginInfo.get().get().getVersion(), is("42"));
2031 assertThat(pluginInfo.get().get().getLongVersion(), is("1.2.3"));
2032 assertThat(pluginInfo.get().get().isStarted(), is(true));
2035 public class LoadPlugin {
2037 public class OfficialPlugins {
2040 public void fromFreenet() throws ExecutionException, InterruptedException, IOException {
2041 Future<Optional<PluginInfo>> pluginInfo =
2042 fcpClient.loadPlugin().officialFromFreenet("superPlugin").execute();
2043 connectAndAssert(() -> createMatcherForOfficialSource("freenet"));
2044 assertThat(lines, not(contains(startsWith("Store="))));
2045 replyWithPluginInfo();
2046 verifyPluginInfo(pluginInfo);
2050 public void persistentFromFreenet() throws ExecutionException, InterruptedException, IOException {
2051 Future<Optional<PluginInfo>> pluginInfo =
2052 fcpClient.loadPlugin().addToConfig().officialFromFreenet("superPlugin").execute();
2053 connectAndAssert(() -> createMatcherForOfficialSource("freenet"));
2054 assertThat(lines, hasItem("Store=true"));
2055 replyWithPluginInfo();
2056 verifyPluginInfo(pluginInfo);
2060 public void fromHttps() throws ExecutionException, InterruptedException, IOException {
2061 Future<Optional<PluginInfo>> pluginInfo =
2062 fcpClient.loadPlugin().officialFromHttps("superPlugin").execute();
2063 connectAndAssert(() -> createMatcherForOfficialSource("https"));
2064 replyWithPluginInfo();
2065 verifyPluginInfo(pluginInfo);
2068 private Matcher<List<String>> createMatcherForOfficialSource(String officialSource) {
2069 return matchesFcpMessage(
2071 "Identifier=" + identifier,
2072 "PluginURL=superPlugin",
2074 "OfficialSource=" + officialSource,
2081 public class FromOtherSources {
2083 private static final String FILE_PATH = "/path/to/plugin.jar";
2084 private static final String URL = "http://server.com/plugin.jar";
2085 private static final String KEY = "KSK@plugin.jar";
2088 public void fromFile() throws ExecutionException, InterruptedException, IOException {
2089 Future<Optional<PluginInfo>> pluginInfo = fcpClient.loadPlugin().fromFile(FILE_PATH).execute();
2090 connectAndAssert(() -> createMatcher("file", FILE_PATH));
2091 replyWithPluginInfo();
2092 verifyPluginInfo(pluginInfo);
2096 public void fromUrl() throws ExecutionException, InterruptedException, IOException {
2097 Future<Optional<PluginInfo>> pluginInfo = fcpClient.loadPlugin().fromUrl(URL).execute();
2098 connectAndAssert(() -> createMatcher("url", URL));
2099 replyWithPluginInfo();
2100 verifyPluginInfo(pluginInfo);
2104 public void fromFreenet() throws ExecutionException, InterruptedException, IOException {
2105 Future<Optional<PluginInfo>> pluginInfo = fcpClient.loadPlugin().fromFreenet(KEY).execute();
2106 connectAndAssert(() -> createMatcher("freenet", KEY));
2107 replyWithPluginInfo();
2108 verifyPluginInfo(pluginInfo);
2111 private Matcher<List<String>> createMatcher(String urlType, String url) {
2112 return matchesFcpMessage(
2114 "Identifier=" + identifier,
2116 "URLType=" + urlType,
2123 public class Failed {
2126 public void failedLoad() throws ExecutionException, InterruptedException, IOException {
2127 Future<Optional<PluginInfo>> pluginInfo =
2128 fcpClient.loadPlugin().officialFromFreenet("superPlugin").execute();
2130 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
2131 String identifier = extractIdentifier(lines);
2132 fcpServer.writeLine(
2134 "Identifier=" + identifier,
2137 assertThat(pluginInfo.get().isPresent(), is(false));
2144 public class ReloadPlugin {
2147 public void reloadingPluginWorks() throws InterruptedException, ExecutionException, IOException {
2148 Future<Optional<PluginInfo>> pluginInfo = fcpClient.reloadPlugin().plugin(CLASS_NAME).execute();
2149 connectAndAssert(() -> matchReloadPluginMessage());
2150 replyWithPluginInfo();
2151 verifyPluginInfo(pluginInfo);
2155 public void reloadingPluginWithMaxWaitTimeWorks()
2156 throws InterruptedException, ExecutionException, IOException {
2157 Future<Optional<PluginInfo>> pluginInfo =
2158 fcpClient.reloadPlugin().waitFor(1234).plugin(CLASS_NAME).execute();
2159 connectAndAssert(() -> allOf(matchReloadPluginMessage(), hasItem("MaxWaitTime=1234")));
2160 replyWithPluginInfo();
2161 verifyPluginInfo(pluginInfo);
2165 public void reloadingPluginWithPurgeWorks()
2166 throws InterruptedException, ExecutionException, IOException {
2167 Future<Optional<PluginInfo>> pluginInfo =
2168 fcpClient.reloadPlugin().purge().plugin(CLASS_NAME).execute();
2169 connectAndAssert(() -> allOf(matchReloadPluginMessage(), hasItem("Purge=true")));
2170 replyWithPluginInfo();
2171 verifyPluginInfo(pluginInfo);
2175 public void reloadingPluginWithStoreWorks()
2176 throws InterruptedException, ExecutionException, IOException {
2177 Future<Optional<PluginInfo>> pluginInfo =
2178 fcpClient.reloadPlugin().addToConfig().plugin(CLASS_NAME).execute();
2179 connectAndAssert(() -> allOf(matchReloadPluginMessage(), hasItem("Store=true")));
2180 replyWithPluginInfo();
2181 verifyPluginInfo(pluginInfo);
2184 private Matcher<List<String>> matchReloadPluginMessage() {
2185 return matchesFcpMessage(
2187 "Identifier=" + identifier,
2188 "PluginName=" + CLASS_NAME,
2195 public class RemovePlugin {
2198 public void removingPluginWorks() throws InterruptedException, ExecutionException, IOException {
2199 Future<Boolean> pluginRemoved = fcpClient.removePlugin().plugin(CLASS_NAME).execute();
2200 connectAndAssert(() -> matchPluginRemovedMessage());
2201 replyWithPluginRemoved();
2202 assertThat(pluginRemoved.get(), is(true));
2206 public void removingPluginWithMaxWaitTimeWorks()
2207 throws InterruptedException, ExecutionException, IOException {
2208 Future<Boolean> pluginRemoved = fcpClient.removePlugin().waitFor(1234).plugin(CLASS_NAME).execute();
2209 connectAndAssert(() -> allOf(matchPluginRemovedMessage(), hasItem("MaxWaitTime=1234")));
2210 replyWithPluginRemoved();
2211 assertThat(pluginRemoved.get(), is(true));
2215 public void removingPluginWithPurgeWorks()
2216 throws InterruptedException, ExecutionException, IOException {
2217 Future<Boolean> pluginRemoved = fcpClient.removePlugin().purge().plugin(CLASS_NAME).execute();
2218 connectAndAssert(() -> allOf(matchPluginRemovedMessage(), hasItem("Purge=true")));
2219 replyWithPluginRemoved();
2220 assertThat(pluginRemoved.get(), is(true));
2223 private void replyWithPluginRemoved() throws IOException {
2224 fcpServer.writeLine(
2226 "Identifier=" + identifier,
2227 "PluginName=" + CLASS_NAME,
2232 private Matcher<List<String>> matchPluginRemovedMessage() {
2233 return matchesFcpMessage(
2235 "Identifier=" + identifier,
2236 "PluginName=" + CLASS_NAME,