1 package net.pterodactylus.fcp.quelaton;
3 import static org.hamcrest.MatcherAssert.assertThat;
4 import static org.hamcrest.Matchers.contains;
5 import static org.hamcrest.Matchers.containsInAnyOrder;
6 import static org.hamcrest.Matchers.hasSize;
7 import static org.hamcrest.Matchers.is;
8 import static org.hamcrest.Matchers.not;
9 import static org.hamcrest.Matchers.notNullValue;
10 import static org.hamcrest.Matchers.startsWith;
12 import java.io.ByteArrayInputStream;
14 import java.io.IOException;
16 import java.nio.charset.StandardCharsets;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.Optional;
20 import java.util.concurrent.CopyOnWriteArrayList;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.ExecutorService;
23 import java.util.concurrent.Executors;
24 import java.util.concurrent.Future;
25 import java.util.stream.Collectors;
27 import net.pterodactylus.fcp.ARK;
28 import net.pterodactylus.fcp.DSAGroup;
29 import net.pterodactylus.fcp.FcpKeyPair;
30 import net.pterodactylus.fcp.Key;
31 import net.pterodactylus.fcp.NodeData;
32 import net.pterodactylus.fcp.NodeRef;
33 import net.pterodactylus.fcp.Peer;
34 import net.pterodactylus.fcp.PeerNote;
35 import net.pterodactylus.fcp.Priority;
36 import net.pterodactylus.fcp.fake.FakeTcpServer;
37 import net.pterodactylus.fcp.quelaton.ClientGetCommand.Data;
39 import com.google.common.io.ByteStreams;
40 import com.google.common.io.Files;
41 import org.hamcrest.Description;
42 import org.hamcrest.Matcher;
43 import org.hamcrest.TypeSafeDiagnosingMatcher;
44 import org.junit.After;
45 import org.junit.Assert;
46 import org.junit.Test;
49 * Unit test for {@link DefaultFcpClient}.
51 * @author <a href="bombe@freenetproject.org">David ‘Bombe’ Roden</a>
53 public class DefaultFcpClientTest {
55 private static final String INSERT_URI =
56 "SSK@RVCHbJdkkyTCeNN9AYukEg76eyqmiosSaNKgE3U9zUw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQECAAE/";
57 private static final String REQUEST_URI =
58 "SSK@wtbgd2loNcJCXvtQVOftl2tuWBomDQHfqS6ytpPRhfw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQACAAE/";
60 private static int threadCounter = 0;
61 private final FakeTcpServer fcpServer;
62 private final DefaultFcpClient fcpClient;
64 public DefaultFcpClientTest() throws IOException {
65 ExecutorService threadPool =
66 Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++));
67 fcpServer = new FakeTcpServer(threadPool);
68 fcpClient = new DefaultFcpClient(threadPool, "localhost", fcpServer.getPort(), () -> "Test");
72 public void tearDown() throws IOException {
76 @Test(expected = ExecutionException.class)
77 public void defaultFcpClientThrowsExceptionIfItCanNotConnect()
78 throws IOException, ExecutionException, InterruptedException {
79 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
80 fcpServer.connect().get();
81 fcpServer.collectUntil(is("EndMessage"));
83 "CloseConnectionDuplicateClientName",
89 @Test(expected = ExecutionException.class)
90 public void defaultFcpClientThrowsExceptionIfConnectionIsClosed()
91 throws IOException, ExecutionException, InterruptedException {
92 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
93 fcpServer.connect().get();
94 fcpServer.collectUntil(is("EndMessage"));
100 public void defaultFcpClientCanGenerateKeypair() throws ExecutionException, InterruptedException, IOException {
101 Future<FcpKeyPair> keyPairFuture = fcpClient.generateKeypair().execute();
103 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
104 String identifier = extractIdentifier(lines);
105 fcpServer.writeLine("SSKKeypair",
106 "InsertURI=" + INSERT_URI + "",
107 "RequestURI=" + REQUEST_URI + "",
108 "Identifier=" + identifier,
110 FcpKeyPair keyPair = keyPairFuture.get();
111 assertThat(keyPair.getPublicKey(), is(REQUEST_URI));
112 assertThat(keyPair.getPrivateKey(), is(INSERT_URI));
115 private void connectNode() throws InterruptedException, ExecutionException, IOException {
116 fcpServer.connect().get();
117 fcpServer.collectUntil(is("EndMessage"));
118 fcpServer.writeLine("NodeHello",
119 "CompressionCodecs=4 - GZIP(0), BZIP2(1), LZMA(2), LZMA_NEW(3)",
120 "Revision=build01466",
122 "Version=Fred,0.7,1.0,1466",
124 "ConnectionIdentifier=14318898267048452a81b36e7f13a3f0",
128 "NodeLanguage=ENGLISH",
135 public void clientGetCanDownloadData() throws InterruptedException, ExecutionException, IOException {
136 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
138 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
139 assertThat(lines, matchesFcpMessage("ClientGet", "ReturnType=direct", "URI=KSK@foo.txt"));
140 String identifier = extractIdentifier(lines);
143 "Identifier=" + identifier,
145 "StartupTime=1435610539000",
146 "CompletionTime=1435610540000",
147 "Metadata.ContentType=text/plain;charset=utf-8",
151 Optional<Data> data = dataFuture.get();
152 assertThat(data.get().getMimeType(), is("text/plain;charset=utf-8"));
153 assertThat(data.get().size(), is(6L));
154 assertThat(ByteStreams.toByteArray(data.get().getInputStream()),
155 is("Hello\n".getBytes(StandardCharsets.UTF_8)));
158 private String extractIdentifier(List<String> lines) {
159 return lines.stream()
160 .filter(s -> s.startsWith("Identifier="))
161 .map(s -> s.substring(s.indexOf('=') + 1))
167 public void clientGetDownloadsDataForCorrectIdentifier()
168 throws InterruptedException, ExecutionException, IOException {
169 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
171 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
172 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
173 String identifier = extractIdentifier(lines);
176 "Identifier=not-test",
178 "StartupTime=1435610539000",
179 "CompletionTime=1435610540000",
180 "Metadata.ContentType=text/plain;charset=latin-9",
186 "Identifier=" + identifier,
188 "StartupTime=1435610539000",
189 "CompletionTime=1435610540000",
190 "Metadata.ContentType=text/plain;charset=utf-8",
194 Optional<Data> data = dataFuture.get();
195 assertThat(data.get().getMimeType(), is("text/plain;charset=utf-8"));
196 assertThat(data.get().size(), is(6L));
197 assertThat(ByteStreams.toByteArray(data.get().getInputStream()),
198 is("Hello\n".getBytes(StandardCharsets.UTF_8)));
202 public void clientGetRecognizesGetFailed() throws InterruptedException, ExecutionException, IOException {
203 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
205 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
206 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
207 String identifier = extractIdentifier(lines);
210 "Identifier=" + identifier,
214 Optional<Data> data = dataFuture.get();
215 assertThat(data.isPresent(), is(false));
219 public void clientGetRecognizesGetFailedForCorrectIdentifier()
220 throws InterruptedException, ExecutionException, IOException {
221 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
223 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
224 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
225 String identifier = extractIdentifier(lines);
228 "Identifier=not-test",
234 "Identifier=" + identifier,
238 Optional<Data> data = dataFuture.get();
239 assertThat(data.isPresent(), is(false));
242 @Test(expected = ExecutionException.class)
243 public void clientGetRecognizesConnectionClosed() throws InterruptedException, ExecutionException, IOException {
244 Future<Optional<Data>> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt").execute();
246 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
247 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt"));
253 public void defaultFcpClientReusesConnection() throws InterruptedException, ExecutionException, IOException {
254 Future<FcpKeyPair> keyPair = fcpClient.generateKeypair().execute();
256 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
257 String identifier = extractIdentifier(lines);
260 "InsertURI=" + INSERT_URI + "",
261 "RequestURI=" + REQUEST_URI + "",
262 "Identifier=" + identifier,
266 keyPair = fcpClient.generateKeypair().execute();
267 lines = fcpServer.collectUntil(is("EndMessage"));
268 identifier = extractIdentifier(lines);
271 "InsertURI=" + INSERT_URI + "",
272 "RequestURI=" + REQUEST_URI + "",
273 "Identifier=" + identifier,
280 public void defaultFcpClientCanReconnectAfterConnectionHasBeenClosed()
281 throws InterruptedException, ExecutionException, IOException {
282 Future<FcpKeyPair> keyPair = fcpClient.generateKeypair().execute();
284 fcpServer.collectUntil(is("EndMessage"));
289 } catch (ExecutionException e) {
291 keyPair = fcpClient.generateKeypair().execute();
293 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
294 String identifier = extractIdentifier(lines);
297 "InsertURI=" + INSERT_URI + "",
298 "RequestURI=" + REQUEST_URI + "",
299 "Identifier=" + identifier,
306 public void clientGetWithIgnoreDataStoreSettingSendsCorrectCommands()
307 throws InterruptedException, ExecutionException, IOException {
308 fcpClient.clientGet().ignoreDataStore().uri("KSK@foo.txt").execute();
310 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
311 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "IgnoreDS=true"));
315 public void clientGetWithDataStoreOnlySettingSendsCorrectCommands()
316 throws InterruptedException, ExecutionException, IOException {
317 fcpClient.clientGet().dataStoreOnly().uri("KSK@foo.txt").execute();
319 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
320 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "DSonly=true"));
324 public void clientGetWithMaxSizeSettingSendsCorrectCommands()
325 throws InterruptedException, ExecutionException, IOException {
326 fcpClient.clientGet().maxSize(1048576).uri("KSK@foo.txt").execute();
328 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
329 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "MaxSize=1048576"));
333 public void clientGetWithPrioritySettingSendsCorrectCommands()
334 throws InterruptedException, ExecutionException, IOException {
335 fcpClient.clientGet().priority(Priority.interactive).uri("KSK@foo.txt").execute();
337 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
338 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "PriorityClass=1"));
342 public void clientGetWithRealTimeSettingSendsCorrectCommands()
343 throws InterruptedException, ExecutionException, IOException {
344 fcpClient.clientGet().realTime().uri("KSK@foo.txt").execute();
346 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
347 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "RealTimeFlag=true"));
351 public void clientGetWithGlobalSettingSendsCorrectCommands()
352 throws InterruptedException, ExecutionException, IOException {
353 fcpClient.clientGet().global().uri("KSK@foo.txt").execute();
355 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
356 assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true"));
359 private Matcher<List<String>> matchesFcpMessage(String name, String... requiredLines) {
360 return new TypeSafeDiagnosingMatcher<List<String>>() {
362 protected boolean matchesSafely(List<String> item, Description mismatchDescription) {
363 if (!item.get(0).equals(name)) {
364 mismatchDescription.appendText("FCP message is named ").appendValue(item.get(0));
367 for (String requiredLine : requiredLines) {
368 if (item.indexOf(requiredLine) < 1) {
369 mismatchDescription.appendText("FCP message does not contain ").appendValue(requiredLine);
377 public void describeTo(Description description) {
378 description.appendText("FCP message named ").appendValue(name);
379 description.appendValueList(", containing the lines ", ", ", "", requiredLines);
385 public void clientPutWithDirectDataSendsCorrectCommand()
386 throws IOException, ExecutionException, InterruptedException {
387 fcpClient.clientPut()
388 .from(new ByteArrayInputStream("Hello\n".getBytes()))
393 List<String> lines = fcpServer.collectUntil(is("Hello"));
394 assertThat(lines, matchesFcpMessage("ClientPut", "UploadFrom=direct", "DataLength=6", "URI=KSK@foo.txt"));
398 public void clientPutWithDirectDataSucceedsOnCorrectIdentifier()
399 throws InterruptedException, ExecutionException, IOException {
400 Future<Optional<Key>> key = fcpClient.clientPut()
401 .from(new ByteArrayInputStream("Hello\n".getBytes()))
406 List<String> lines = fcpServer.collectUntil(is("Hello"));
407 String identifier = extractIdentifier(lines);
410 "Identifier=not-the-right-one",
416 "Identifier=" + identifier,
419 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
423 public void clientPutWithDirectDataFailsOnCorrectIdentifier()
424 throws InterruptedException, ExecutionException, IOException {
425 Future<Optional<Key>> key = fcpClient.clientPut()
426 .from(new ByteArrayInputStream("Hello\n".getBytes()))
431 List<String> lines = fcpServer.collectUntil(is("Hello"));
432 String identifier = extractIdentifier(lines);
435 "Identifier=not-the-right-one",
441 "Identifier=" + identifier,
444 assertThat(key.get().isPresent(), is(false));
448 public void clientPutWithRenamedDirectDataSendsCorrectCommand()
449 throws InterruptedException, ExecutionException, IOException {
450 fcpClient.clientPut()
451 .named("otherName.txt")
452 .from(new ByteArrayInputStream("Hello\n".getBytes()))
457 List<String> lines = fcpServer.collectUntil(is("Hello"));
458 assertThat(lines, matchesFcpMessage("ClientPut", "TargetFilename=otherName.txt", "UploadFrom=direct",
459 "DataLength=6", "URI=KSK@foo.txt"));
463 public void clientPutWithRedirectSendsCorrectCommand()
464 throws IOException, ExecutionException, InterruptedException {
465 fcpClient.clientPut().redirectTo("KSK@bar.txt").uri("KSK@foo.txt").execute();
467 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
469 matchesFcpMessage("ClientPut", "UploadFrom=redirect", "URI=KSK@foo.txt", "TargetURI=KSK@bar.txt"));
473 public void clientPutWithFileSendsCorrectCommand() throws InterruptedException, ExecutionException, IOException {
474 fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
476 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
478 matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt", "Filename=/tmp/data.txt"));
482 public void clientPutWithFileCanCompleteTestDdaSequence()
483 throws IOException, ExecutionException, InterruptedException {
484 File tempFile = createTempFile();
485 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
487 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
488 String identifier = extractIdentifier(lines);
491 "Identifier=" + identifier,
495 lines = fcpServer.collectUntil(is("EndMessage"));
496 assertThat(lines, matchesFcpMessage(
498 "Directory=" + tempFile.getParent(),
499 "WantReadDirectory=true",
500 "WantWriteDirectory=false",
505 "Directory=" + tempFile.getParent(),
506 "ReadFilename=" + tempFile,
509 lines = fcpServer.collectUntil(is("EndMessage"));
510 assertThat(lines, matchesFcpMessage(
512 "Directory=" + tempFile.getParent(),
513 "ReadContent=test-content",
518 "Directory=" + tempFile.getParent(),
519 "ReadDirectoryAllowed=true",
522 lines = fcpServer.collectUntil(is("EndMessage"));
524 matchesFcpMessage("ClientPut", "UploadFrom=disk", "URI=KSK@foo.txt",
525 "Filename=" + new File(tempFile.getParent(), "test.dat")));
528 private File createTempFile() throws IOException {
529 File tempFile = File.createTempFile("test-dda-", ".dat");
530 tempFile.deleteOnExit();
531 Files.write("test-content", tempFile, StandardCharsets.UTF_8);
536 public void clientPutDoesNotReactToProtocolErrorForDifferentIdentifier()
537 throws InterruptedException, ExecutionException, IOException {
538 Future<Optional<Key>> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
540 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
541 String identifier = extractIdentifier(lines);
544 "Identifier=not-the-right-one",
550 "Identifier=" + identifier,
554 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
558 public void clientPutAbortsOnProtocolErrorOtherThan25()
559 throws InterruptedException, ExecutionException, IOException {
560 Future<Optional<Key>> key = fcpClient.clientPut().from(new File("/tmp/data.txt")).uri("KSK@foo.txt").execute();
562 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
563 String identifier = extractIdentifier(lines);
566 "Identifier=" + identifier,
570 assertThat(key.get().isPresent(), is(false));
574 public void clientPutDoesNotReplyToWrongTestDdaReply() throws IOException, ExecutionException,
575 InterruptedException {
576 File tempFile = createTempFile();
577 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
579 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
580 String identifier = extractIdentifier(lines);
583 "Identifier=" + identifier,
587 lines = fcpServer.collectUntil(is("EndMessage"));
588 assertThat(lines, matchesFcpMessage(
590 "Directory=" + tempFile.getParent(),
591 "WantReadDirectory=true",
592 "WantWriteDirectory=false",
597 "Directory=/some-other-directory",
598 "ReadFilename=" + tempFile,
603 "Directory=" + tempFile.getParent(),
604 "ReadFilename=" + tempFile,
607 lines = fcpServer.collectUntil(is("EndMessage"));
608 assertThat(lines, matchesFcpMessage(
610 "Directory=" + tempFile.getParent(),
611 "ReadContent=test-content",
617 public void clientPutSendsResponseEvenIfFileCanNotBeRead()
618 throws IOException, ExecutionException, InterruptedException {
619 File tempFile = createTempFile();
620 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
622 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
623 String identifier = extractIdentifier(lines);
626 "Identifier=" + identifier,
630 lines = fcpServer.collectUntil(is("EndMessage"));
631 assertThat(lines, matchesFcpMessage(
633 "Directory=" + tempFile.getParent(),
634 "WantReadDirectory=true",
635 "WantWriteDirectory=false",
640 "Directory=" + tempFile.getParent(),
641 "ReadFilename=" + tempFile + ".foo",
644 lines = fcpServer.collectUntil(is("EndMessage"));
645 assertThat(lines, matchesFcpMessage(
647 "Directory=" + tempFile.getParent(),
648 "ReadContent=failed-to-read",
654 public void clientPutDoesNotResendOriginalClientPutOnTestDDACompleteWithWrongDirectory()
655 throws IOException, ExecutionException, InterruptedException {
656 File tempFile = createTempFile();
657 fcpClient.clientPut().from(new File(tempFile.getParent(), "test.dat")).uri("KSK@foo.txt").execute();
659 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
660 String identifier = extractIdentifier(lines);
663 "Directory=/some-other-directory",
668 "Identifier=" + identifier,
672 lines = fcpServer.collectUntil(is("EndMessage"));
673 assertThat(lines, matchesFcpMessage(
675 "Directory=" + tempFile.getParent(),
676 "WantReadDirectory=true",
677 "WantWriteDirectory=false",
683 public void clientPutSendsNotificationsForGeneratedKeys()
684 throws InterruptedException, ExecutionException, IOException {
685 List<String> generatedKeys = new CopyOnWriteArrayList<>();
686 Future<Optional<Key>> key = fcpClient.clientPut()
687 .onKeyGenerated(generatedKeys::add)
688 .from(new ByteArrayInputStream("Hello\n".getBytes()))
693 List<String> lines = fcpServer.collectUntil(is("Hello"));
694 String identifier = extractIdentifier(lines);
697 "Identifier=" + identifier,
704 "Identifier=" + identifier,
707 assertThat(key.get().get().getKey(), is("KSK@foo.txt"));
708 assertThat(generatedKeys, contains("KSK@foo.txt"));
712 public void clientCanListPeers() throws IOException, ExecutionException, InterruptedException {
713 Future<Collection<Peer>> peers = fcpClient.listPeers().execute();
715 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
716 assertThat(lines, matchesFcpMessage(
718 "WithVolatile=false",
719 "WithMetadata=false",
722 String identifier = extractIdentifier(lines);
725 "Identifier=" + identifier,
731 "Identifier=" + identifier,
737 "Identifier=" + identifier,
740 assertThat(peers.get(), hasSize(2));
741 assertThat(peers.get().stream().map(Peer::getIdentity).collect(Collectors.toList()),
742 containsInAnyOrder("id1", "id2"));
746 public void clientCanListPeersWithMetadata() throws IOException, ExecutionException, InterruptedException {
747 Future<Collection<Peer>> peers = fcpClient.listPeers().includeMetadata().execute();
749 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
750 assertThat(lines, matchesFcpMessage(
752 "WithVolatile=false",
756 String identifier = extractIdentifier(lines);
759 "Identifier=" + identifier,
766 "Identifier=" + identifier,
773 "Identifier=" + identifier,
776 assertThat(peers.get(), hasSize(2));
777 assertThat(peers.get().stream().map(peer -> peer.getMetadata("foo")).collect(Collectors.toList()),
778 containsInAnyOrder("bar1", "bar2"));
782 public void clientCanListPeersWithVolatiles() throws IOException, ExecutionException, InterruptedException {
783 Future<Collection<Peer>> peers = fcpClient.listPeers().includeVolatile().execute();
785 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
786 assertThat(lines, matchesFcpMessage(
789 "WithMetadata=false",
792 String identifier = extractIdentifier(lines);
795 "Identifier=" + identifier,
802 "Identifier=" + identifier,
809 "Identifier=" + identifier,
812 assertThat(peers.get(), hasSize(2));
813 assertThat(peers.get().stream().map(peer -> peer.getVolatile("foo")).collect(Collectors.toList()),
814 containsInAnyOrder("bar1", "bar2"));
818 public void defaultFcpClientCanGetNodeInformation() throws InterruptedException, ExecutionException, IOException {
819 Future<NodeData> nodeData = fcpClient.getNode().execute();
821 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
822 String identifier = extractIdentifier(lines);
823 assertThat(lines, matchesFcpMessage(
825 "Identifier=" + identifier,
826 "GiveOpennetRef=false",
828 "WithVolatile=false",
833 "Identifier=" + identifier,
834 "ark.pubURI=SSK@3YEf.../ark",
837 "version=Fred,0.7,1.0,1466",
838 "lastGoodVersion=Fred,0.7,1.0,1466",
841 assertThat(nodeData.get(), notNullValue());
845 public void defaultFcpClientCanGetNodeInformationWithOpennetRef()
846 throws InterruptedException, ExecutionException, IOException {
847 Future<NodeData> nodeData = fcpClient.getNode().opennetRef().execute();
849 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
850 String identifier = extractIdentifier(lines);
851 assertThat(lines, matchesFcpMessage(
853 "Identifier=" + identifier,
854 "GiveOpennetRef=true",
856 "WithVolatile=false",
861 "Identifier=" + identifier,
863 "ark.pubURI=SSK@3YEf.../ark",
866 "version=Fred,0.7,1.0,1466",
867 "lastGoodVersion=Fred,0.7,1.0,1466",
870 assertThat(nodeData.get().getVersion().toString(), is("Fred,0.7,1.0,1466"));
874 public void defaultFcpClientCanGetNodeInformationWithPrivateData()
875 throws InterruptedException, ExecutionException, IOException {
876 Future<NodeData> nodeData = fcpClient.getNode().includePrivate().execute();
878 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
879 String identifier = extractIdentifier(lines);
880 assertThat(lines, matchesFcpMessage(
882 "Identifier=" + identifier,
883 "GiveOpennetRef=false",
885 "WithVolatile=false",
890 "Identifier=" + identifier,
892 "ark.pubURI=SSK@3YEf.../ark",
895 "version=Fred,0.7,1.0,1466",
896 "lastGoodVersion=Fred,0.7,1.0,1466",
897 "ark.privURI=SSK@XdHMiRl",
900 assertThat(nodeData.get().getARK().getPrivateURI(), is("SSK@XdHMiRl"));
904 public void defaultFcpClientCanGetNodeInformationWithVolatileData()
905 throws InterruptedException, ExecutionException, IOException {
906 Future<NodeData> nodeData = fcpClient.getNode().includeVolatile().execute();
908 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
909 String identifier = extractIdentifier(lines);
910 assertThat(lines, matchesFcpMessage(
912 "Identifier=" + identifier,
913 "GiveOpennetRef=false",
920 "Identifier=" + identifier,
922 "ark.pubURI=SSK@3YEf.../ark",
925 "version=Fred,0.7,1.0,1466",
926 "lastGoodVersion=Fred,0.7,1.0,1466",
927 "volatile.freeJavaMemory=205706528",
930 assertThat(nodeData.get().getVolatile("freeJavaMemory"), is("205706528"));
934 public void defaultFcpClientCanListSinglePeerByIdentity()
935 throws InterruptedException, ExecutionException, IOException {
936 Future<Optional<Peer>> peer = fcpClient.listPeer().byIdentity("id1").execute();
938 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
939 String identifier = extractIdentifier(lines);
940 assertThat(lines, matchesFcpMessage(
942 "Identifier=" + identifier,
943 "NodeIdentifier=id1",
948 "Identifier=" + identifier,
951 "ark.pubURI=SSK@3YEf.../ark",
954 "version=Fred,0.7,1.0,1466",
955 "lastGoodVersion=Fred,0.7,1.0,1466",
958 assertThat(peer.get().get().getIdentity(), is("id1"));
962 public void defaultFcpClientCanListSinglePeerByHostAndPort()
963 throws InterruptedException, ExecutionException, IOException {
964 Future<Optional<Peer>> peer = fcpClient.listPeer().byHostAndPort("host.free.net", 12345).execute();
966 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
967 String identifier = extractIdentifier(lines);
968 assertThat(lines, matchesFcpMessage(
970 "Identifier=" + identifier,
971 "NodeIdentifier=host.free.net:12345",
976 "Identifier=" + identifier,
979 "ark.pubURI=SSK@3YEf.../ark",
982 "version=Fred,0.7,1.0,1466",
983 "lastGoodVersion=Fred,0.7,1.0,1466",
986 assertThat(peer.get().get().getIdentity(), is("id1"));
990 public void defaultFcpClientCanListSinglePeerByName()
991 throws InterruptedException, ExecutionException, IOException {
992 Future<Optional<Peer>> peer = fcpClient.listPeer().byName("FriendNode").execute();
994 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
995 String identifier = extractIdentifier(lines);
996 assertThat(lines, matchesFcpMessage(
998 "Identifier=" + identifier,
999 "NodeIdentifier=FriendNode",
1002 fcpServer.writeLine(
1004 "Identifier=" + identifier,
1007 "ark.pubURI=SSK@3YEf.../ark",
1010 "version=Fred,0.7,1.0,1466",
1011 "lastGoodVersion=Fred,0.7,1.0,1466",
1014 assertThat(peer.get().get().getIdentity(), is("id1"));
1018 public void defaultFcpClientRecognizesUnknownNodeIdentifiers()
1019 throws InterruptedException, ExecutionException, IOException {
1020 Future<Optional<Peer>> peer = fcpClient.listPeer().byIdentity("id2").execute();
1022 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1023 String identifier = extractIdentifier(lines);
1024 assertThat(lines, matchesFcpMessage(
1026 "Identifier=" + identifier,
1027 "NodeIdentifier=id2",
1030 fcpServer.writeLine(
1031 "UnknownNodeIdentifier",
1032 "Identifier=" + identifier,
1033 "NodeIdentifier=id2",
1036 assertThat(peer.get().isPresent(), is(false));
1040 public void defaultFcpClientCanAddPeerFromFile() throws InterruptedException, ExecutionException, IOException {
1041 Future<Optional<Peer>> peer = fcpClient.addPeer().fromFile(new File("/tmp/ref.txt")).execute();
1043 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1044 String identifier = extractIdentifier(lines);
1045 assertThat(lines, matchesFcpMessage(
1047 "Identifier=" + identifier,
1048 "File=/tmp/ref.txt",
1051 fcpServer.writeLine(
1053 "Identifier=" + identifier,
1056 "ark.pubURI=SSK@3YEf.../ark",
1059 "version=Fred,0.7,1.0,1466",
1060 "lastGoodVersion=Fred,0.7,1.0,1466",
1063 assertThat(peer.get().get().getIdentity(), is("id1"));
1067 public void defaultFcpClientCanAddPeerFromURL() throws InterruptedException, ExecutionException, IOException {
1068 Future<Optional<Peer>> peer = fcpClient.addPeer().fromURL(new URL("http://node.ref/")).execute();
1070 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1071 String identifier = extractIdentifier(lines);
1072 assertThat(lines, matchesFcpMessage(
1074 "Identifier=" + identifier,
1075 "URL=http://node.ref/",
1078 fcpServer.writeLine(
1080 "Identifier=" + identifier,
1083 "ark.pubURI=SSK@3YEf.../ark",
1086 "version=Fred,0.7,1.0,1466",
1087 "lastGoodVersion=Fred,0.7,1.0,1466",
1090 assertThat(peer.get().get().getIdentity(), is("id1"));
1094 public void defaultFcpClientCanAddPeerFromNodeRef() throws InterruptedException, ExecutionException, IOException {
1095 NodeRef nodeRef = new NodeRef();
1096 nodeRef.setIdentity("id1");
1097 nodeRef.setName("name");
1098 nodeRef.setARK(new ARK("public", "1"));
1099 nodeRef.setDSAGroup(new DSAGroup("base", "prime", "subprime"));
1100 nodeRef.setNegotiationTypes(new int[] { 3, 5 });
1101 nodeRef.setPhysicalUDP("1.2.3.4:5678");
1102 nodeRef.setDSAPublicKey("dsa-public");
1103 nodeRef.setSignature("sig");
1104 Future<Optional<Peer>> peer = fcpClient.addPeer().fromNodeRef(nodeRef).execute();
1106 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1107 String identifier = extractIdentifier(lines);
1108 assertThat(lines, matchesFcpMessage(
1110 "Identifier=" + identifier,
1113 "ark.pubURI=public",
1117 "dsaGroup.q=subprime",
1118 "dsaPubKey.y=dsa-public",
1119 "physical.udp=1.2.3.4:5678",
1120 "auth.negTypes=3;5",
1124 fcpServer.writeLine(
1126 "Identifier=" + identifier,
1129 "ark.pubURI=SSK@3YEf.../ark",
1132 "version=Fred,0.7,1.0,1466",
1133 "lastGoodVersion=Fred,0.7,1.0,1466",
1136 assertThat(peer.get().get().getIdentity(), is("id1"));
1140 public void listPeerNotesCanGetPeerNotesByNodeName() throws InterruptedException, ExecutionException, IOException {
1141 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute();
1143 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1144 String identifier = extractIdentifier(lines);
1145 assertThat(lines, matchesFcpMessage(
1147 "NodeIdentifier=Friend1",
1150 fcpServer.writeLine(
1152 "Identifier=" + identifier,
1153 "NodeIdentifier=Friend1",
1154 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1158 fcpServer.writeLine(
1160 "Identifier=" + identifier,
1163 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1164 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1168 public void listPeerNotesReturnsEmptyOptionalWhenNodeIdenfierUnknown()
1169 throws InterruptedException, ExecutionException,
1171 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byName("Friend1").execute();
1173 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1174 String identifier = extractIdentifier(lines);
1175 assertThat(lines, matchesFcpMessage(
1177 "NodeIdentifier=Friend1",
1180 fcpServer.writeLine(
1181 "UnknownNodeIdentifier",
1182 "Identifier=" + identifier,
1183 "NodeIdentifier=Friend1",
1186 assertThat(peerNote.get().isPresent(), is(false));
1190 public void listPeerNotesCanGetPeerNotesByNodeIdentifier()
1191 throws InterruptedException, ExecutionException, IOException {
1192 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byIdentity("id1").execute();
1194 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1195 String identifier = extractIdentifier(lines);
1196 assertThat(lines, matchesFcpMessage(
1198 "NodeIdentifier=id1",
1201 fcpServer.writeLine(
1203 "Identifier=" + identifier,
1204 "NodeIdentifier=id1",
1205 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1209 fcpServer.writeLine(
1211 "Identifier=" + identifier,
1214 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1215 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1219 public void listPeerNotesCanGetPeerNotesByHostNameAndPortNumber()
1220 throws InterruptedException, ExecutionException, IOException {
1221 Future<Optional<PeerNote>> peerNote = fcpClient.listPeerNotes().byHostAndPort("1.2.3.4", 5678).execute();
1223 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1224 String identifier = extractIdentifier(lines);
1225 assertThat(lines, matchesFcpMessage(
1227 "NodeIdentifier=1.2.3.4:5678",
1230 fcpServer.writeLine(
1232 "Identifier=" + identifier,
1233 "NodeIdentifier=id1",
1234 "NoteText=RXhhbXBsZSBUZXh0Lg==",
1238 fcpServer.writeLine(
1240 "Identifier=" + identifier,
1243 assertThat(peerNote.get().get().getNoteText(), is("RXhhbXBsZSBUZXh0Lg=="));
1244 assertThat(peerNote.get().get().getPeerNoteType(), is(1));
1248 public void defaultFcpClientCanEnablePeerByName() throws InterruptedException, ExecutionException, IOException {
1249 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byName("Friend1").execute();
1251 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1252 String identifier = extractIdentifier(lines);
1253 assertThat(lines, matchesFcpMessage(
1255 "Identifier=" + identifier,
1256 "NodeIdentifier=Friend1",
1260 fcpServer.writeLine(
1262 "Identifier=" + identifier,
1263 "NodeIdentifier=Friend1",
1267 assertThat(peer.get().get().getIdentity(), is("id1"));
1271 public void defaultFcpClientCanDisablePeerByName() throws InterruptedException, ExecutionException, IOException {
1272 Future<Optional<Peer>> peer = fcpClient.modifyPeer().disable().byName("Friend1").execute();
1274 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1275 String identifier = extractIdentifier(lines);
1276 assertThat(lines, matchesFcpMessage(
1278 "Identifier=" + identifier,
1279 "NodeIdentifier=Friend1",
1283 fcpServer.writeLine(
1285 "Identifier=" + identifier,
1286 "NodeIdentifier=Friend1",
1290 assertThat(peer.get().get().getIdentity(), is("id1"));
1294 public void defaultFcpClientCanEnablePeerByIdentity() throws InterruptedException, ExecutionException, IOException {
1295 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute();
1297 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1298 String identifier = extractIdentifier(lines);
1299 assertThat(lines, matchesFcpMessage(
1301 "Identifier=" + identifier,
1302 "NodeIdentifier=id1",
1306 fcpServer.writeLine(
1308 "Identifier=" + identifier,
1309 "NodeIdentifier=Friend1",
1313 assertThat(peer.get().get().getIdentity(), is("id1"));
1317 public void defaultFcpClientCanEnablePeerByHostAndPort()
1318 throws InterruptedException, ExecutionException, IOException {
1319 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byHostAndPort("1.2.3.4", 5678).execute();
1321 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1322 String identifier = extractIdentifier(lines);
1323 assertThat(lines, matchesFcpMessage(
1325 "Identifier=" + identifier,
1326 "NodeIdentifier=1.2.3.4:5678",
1330 fcpServer.writeLine(
1332 "Identifier=" + identifier,
1333 "NodeIdentifier=Friend1",
1337 assertThat(peer.get().get().getIdentity(), is("id1"));
1341 public void defaultFcpClientCanNotModifyPeerOfUnknownNode()
1342 throws InterruptedException, ExecutionException, IOException {
1343 Future<Optional<Peer>> peer = fcpClient.modifyPeer().enable().byIdentity("id1").execute();
1345 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1346 String identifier = extractIdentifier(lines);
1347 assertThat(lines, matchesFcpMessage(
1349 "Identifier=" + identifier,
1350 "NodeIdentifier=id1",
1354 fcpServer.writeLine(
1355 "UnknownNodeIdentifier",
1356 "Identifier=" + identifier,
1357 "NodeIdentifier=id1",
1360 assertThat(peer.get().isPresent(), is(false));
1364 public void defaultFcpClientCanAllowLocalAddressesOfPeer()
1365 throws InterruptedException, ExecutionException, IOException {
1366 Future<Optional<Peer>> peer = fcpClient.modifyPeer().allowLocalAddresses().byIdentity("id1").execute();
1368 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1369 String identifier = extractIdentifier(lines);
1370 assertThat(lines, matchesFcpMessage(
1372 "Identifier=" + identifier,
1373 "NodeIdentifier=id1",
1374 "AllowLocalAddresses=true",
1377 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1378 fcpServer.writeLine(
1380 "Identifier=" + identifier,
1381 "NodeIdentifier=Friend1",
1385 assertThat(peer.get().get().getIdentity(), is("id1"));
1389 public void defaultFcpClientCanDisallowLocalAddressesOfPeer()
1390 throws InterruptedException, ExecutionException, IOException {
1391 Future<Optional<Peer>> peer = fcpClient.modifyPeer().disallowLocalAddresses().byIdentity("id1").execute();
1393 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1394 String identifier = extractIdentifier(lines);
1395 assertThat(lines, matchesFcpMessage(
1397 "Identifier=" + identifier,
1398 "NodeIdentifier=id1",
1399 "AllowLocalAddresses=false",
1402 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1403 fcpServer.writeLine(
1405 "Identifier=" + identifier,
1406 "NodeIdentifier=Friend1",
1410 assertThat(peer.get().get().getIdentity(), is("id1"));
1414 public void defaultFcpClientCanSetBurstOnlyForPeer()
1415 throws InterruptedException, ExecutionException, IOException {
1416 Future<Optional<Peer>> peer = fcpClient.modifyPeer().setBurstOnly().byIdentity("id1").execute();
1418 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1419 String identifier = extractIdentifier(lines);
1420 assertThat(lines, matchesFcpMessage(
1422 "Identifier=" + identifier,
1423 "NodeIdentifier=id1",
1427 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1428 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1429 fcpServer.writeLine(
1431 "Identifier=" + identifier,
1432 "NodeIdentifier=Friend1",
1436 assertThat(peer.get().get().getIdentity(), is("id1"));
1440 public void defaultFcpClientCanClearBurstOnlyForPeer()
1441 throws InterruptedException, ExecutionException, IOException {
1442 Future<Optional<Peer>> peer = fcpClient.modifyPeer().clearBurstOnly().byIdentity("id1").execute();
1444 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1445 String identifier = extractIdentifier(lines);
1446 assertThat(lines, matchesFcpMessage(
1448 "Identifier=" + identifier,
1449 "NodeIdentifier=id1",
1450 "IsBurstOnly=false",
1453 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1454 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1455 fcpServer.writeLine(
1457 "Identifier=" + identifier,
1458 "NodeIdentifier=Friend1",
1462 assertThat(peer.get().get().getIdentity(), is("id1"));
1466 public void defaultFcpClientCanSetListenOnlyForPeer()
1467 throws InterruptedException, ExecutionException, IOException {
1468 Future<Optional<Peer>> peer = fcpClient.modifyPeer().setListenOnly().byIdentity("id1").execute();
1470 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1471 String identifier = extractIdentifier(lines);
1472 assertThat(lines, matchesFcpMessage(
1474 "Identifier=" + identifier,
1475 "NodeIdentifier=id1",
1476 "IsListenOnly=true",
1479 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1480 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1481 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1482 fcpServer.writeLine(
1484 "Identifier=" + identifier,
1485 "NodeIdentifier=Friend1",
1489 assertThat(peer.get().get().getIdentity(), is("id1"));
1493 public void defaultFcpClientCanClearListenOnlyForPeer()
1494 throws InterruptedException, ExecutionException, IOException {
1495 Future<Optional<Peer>> peer = fcpClient.modifyPeer().clearListenOnly().byIdentity("id1").execute();
1497 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1498 String identifier = extractIdentifier(lines);
1499 assertThat(lines, matchesFcpMessage(
1501 "Identifier=" + identifier,
1502 "NodeIdentifier=id1",
1503 "IsListenOnly=false",
1506 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1507 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1508 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1509 fcpServer.writeLine(
1511 "Identifier=" + identifier,
1512 "NodeIdentifier=Friend1",
1516 assertThat(peer.get().get().getIdentity(), is("id1"));
1520 public void defaultFcpClientCanIgnoreSourceForPeer()
1521 throws InterruptedException, ExecutionException, IOException {
1522 Future<Optional<Peer>> peer = fcpClient.modifyPeer().ignoreSource().byIdentity("id1").execute();
1524 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1525 String identifier = extractIdentifier(lines);
1526 assertThat(lines, matchesFcpMessage(
1528 "Identifier=" + identifier,
1529 "NodeIdentifier=id1",
1530 "IgnoreSourcePort=true",
1533 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1534 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1535 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1536 assertThat(lines, not(contains(startsWith("IsListenOnly="))));
1537 fcpServer.writeLine(
1539 "Identifier=" + identifier,
1540 "NodeIdentifier=Friend1",
1544 assertThat(peer.get().get().getIdentity(), is("id1"));
1548 public void defaultFcpClientCanUseSourceForPeer()
1549 throws InterruptedException, ExecutionException, IOException {
1550 Future<Optional<Peer>> peer = fcpClient.modifyPeer().useSource().byIdentity("id1").execute();
1552 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1553 String identifier = extractIdentifier(lines);
1554 assertThat(lines, matchesFcpMessage(
1556 "Identifier=" + identifier,
1557 "NodeIdentifier=id1",
1558 "IgnoreSourcePort=false",
1561 assertThat(lines, not(contains(startsWith("AllowLocalAddresses="))));
1562 assertThat(lines, not(contains(startsWith("IsDisabled="))));
1563 assertThat(lines, not(contains(startsWith("IsBurstOnly="))));
1564 assertThat(lines, not(contains(startsWith("IsListenOnly="))));
1565 fcpServer.writeLine(
1567 "Identifier=" + identifier,
1568 "NodeIdentifier=Friend1",
1572 assertThat(peer.get().get().getIdentity(), is("id1"));
1576 public void defaultFcpClientCanRemovePeerByName() throws InterruptedException, ExecutionException, IOException {
1577 Future<Boolean> peer = fcpClient.removePeer().byName("Friend1").execute();
1579 List<String> lines = fcpServer.collectUntil(is("EndMessage"));
1580 String identifier = extractIdentifier(lines);
1581 assertThat(lines, matchesFcpMessage(
1583 "Identifier=" + identifier,
1584 "NodeIdentifier=Friend1",
1587 fcpServer.writeLine(
1589 "Identifier=" + identifier,
1590 "NodeIdentifier=Friend1",
1593 assertThat(peer.get(), is(true));