From 4cdde96468f8c85dc449bad7dc72780e5275e040 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Mon, 6 Jul 2015 19:28:07 +0200 Subject: [PATCH] Generate identifiers randomly --- .../fcp/quelaton/ClientGetCommand.java | 1 - .../fcp/quelaton/ClientGetCommandImpl.java | 23 +-- .../fcp/quelaton/RandomIdentifierGenerator.java | 25 ++++ .../fcp/quelaton/DefaultFcpClientTest.java | 160 ++++++++------------- 4 files changed, 99 insertions(+), 110 deletions(-) create mode 100644 src/main/java/net/pterodactylus/fcp/quelaton/RandomIdentifierGenerator.java diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java index 60a46d0..280daae 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java @@ -13,7 +13,6 @@ import net.pterodactylus.fcp.Priority; */ public interface ClientGetCommand { - ClientGetCommand identifier(String identifier); ClientGetCommand ignoreDataStore(); ClientGetCommand dataStoreOnly(); ClientGetCommand maxSize(long maxSize); diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java index b4e391a..98c416f 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java @@ -6,9 +6,11 @@ import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import net.pterodactylus.fcp.AllData; import net.pterodactylus.fcp.ClientGet; +import net.pterodactylus.fcp.FcpMessage; import net.pterodactylus.fcp.FcpUtils.TempInputStream; import net.pterodactylus.fcp.GetFailed; import net.pterodactylus.fcp.Priority; @@ -24,7 +26,6 @@ class ClientGetCommandImpl implements ClientGetCommand { private final ExecutorService threadPool; private final ConnectionSupplier connectionSupplier; - private String identifier; private boolean ignoreDataStore; private boolean dataStoreOnly; private Long maxSize; @@ -38,12 +39,6 @@ class ClientGetCommandImpl implements ClientGetCommand { } @Override - public ClientGetCommand identifier(String identifier) { - this.identifier = identifier; - return this; - } - - @Override public ClientGetCommand ignoreDataStore() { ignoreDataStore = true; return this; @@ -86,6 +81,7 @@ class ClientGetCommandImpl implements ClientGetCommand { } private ClientGet createClientGetCommand(String uri) { + String identifier = new RandomIdentifierGenerator().generate(); ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct); if (ignoreDataStore) { clientGet.setIgnoreDataStore(true); @@ -110,11 +106,10 @@ class ClientGetCommandImpl implements ClientGetCommand { private class ClientGetReplySequence extends FcpReplySequence> { + private final AtomicReference identifier = new AtomicReference<>(); private final AtomicBoolean finished = new AtomicBoolean(); private final AtomicBoolean failed = new AtomicBoolean(); - private final String identifier = ClientGetCommandImpl.this.identifier; - private String contentType; private long dataLength; private InputStream payload; @@ -150,7 +145,7 @@ class ClientGetCommandImpl implements ClientGetCommand { @Override protected void consumeAllData(AllData allData) { - if (allData.getIdentifier().equals(identifier)) { + if (allData.getIdentifier().equals(identifier.get())) { synchronized (this) { contentType = allData.getContentType(); dataLength = allData.getDataLength(); @@ -167,7 +162,7 @@ class ClientGetCommandImpl implements ClientGetCommand { @Override protected void consumeGetFailed(GetFailed getFailed) { - if (getFailed.getIdentifier().equals(identifier)) { + if (getFailed.getIdentifier().equals(identifier.get())) { failed.set(true); } } @@ -177,6 +172,12 @@ class ClientGetCommandImpl implements ClientGetCommand { failed.set(true); } + @Override + public Future> send(FcpMessage fcpMessage) throws IOException { + identifier.set(fcpMessage.getField("Identifier")); + return super.send(fcpMessage); + } + } } diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/RandomIdentifierGenerator.java b/src/main/java/net/pterodactylus/fcp/quelaton/RandomIdentifierGenerator.java new file mode 100644 index 0000000..df5aaf6 --- /dev/null +++ b/src/main/java/net/pterodactylus/fcp/quelaton/RandomIdentifierGenerator.java @@ -0,0 +1,25 @@ +package net.pterodactylus.fcp.quelaton; + +import java.util.Random; +import java.util.stream.IntStream; + +/** + * Generates random identifiers. + * + * @author David ‘Bombe’ Roden + */ +public class RandomIdentifierGenerator { + + private final Random random = new Random(); + + public String generate() { + StringBuilder stringBuilder = new StringBuilder(32); + IntStream.range(0, 32).forEach((i) -> stringBuilder.append(generateRandomLetter())); + return stringBuilder.toString(); + } + + private char generateRandomLetter() { + return (char) (65 + (random.nextInt(26)) + (random.nextBoolean() ? 32 : 0)); + } + +} diff --git a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java index 020ee33..7163462 100644 --- a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java +++ b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java @@ -19,6 +19,9 @@ import net.pterodactylus.fcp.fake.FakeTcpServer; import net.pterodactylus.fcp.quelaton.ClientGetCommand.Data; import com.google.common.io.ByteStreams; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeDiagnosingMatcher; import org.junit.After; import org.junit.Test; @@ -83,19 +86,14 @@ public class DefaultFcpClientTest { @Test public void clientGetCanDownloadData() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().identifier("test").uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "ReturnType=direct", "URI=KSK@foo.txt")); + String identifier = extractIdentifier(lines); fcpServer.writeLine( "AllData", - "Identifier=test", + "Identifier=" + identifier, "DataLength=6", "StartupTime=1435610539000", "CompletionTime=1435610540000", @@ -109,18 +107,17 @@ public class DefaultFcpClientTest { assertThat(ByteStreams.toByteArray(data.get().getInputStream()), is("Hello\n".getBytes(StandardCharsets.UTF_8))); } + private String extractIdentifier(List lines) { + return lines.stream().filter(s -> s.startsWith("Identifier=")).map(s -> s.substring(s.indexOf('=') + 1)).findFirst().orElse(""); + } + @Test public void clientGetDownloadsDataForCorrectIdentifier() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().identifier("test").uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); + String identifier = extractIdentifier(lines); fcpServer.writeLine( "AllData", "Identifier=not-test", @@ -133,7 +130,7 @@ public class DefaultFcpClientTest { ); fcpServer.writeLine( "AllData", - "Identifier=test", + "Identifier=" + identifier, "DataLength=6", "StartupTime=1435610539000", "CompletionTime=1435610540000", @@ -149,19 +146,14 @@ public class DefaultFcpClientTest { @Test public void clientGetRecognizesGetFailed() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().identifier("test").uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); + String identifier = extractIdentifier(lines); fcpServer.writeLine( "GetFailed", - "Identifier=test", + "Identifier=" + identifier, "Code=3", "EndMessage" ); @@ -171,16 +163,11 @@ public class DefaultFcpClientTest { @Test public void clientGetRecognizesGetFailedForCorrectIdentifier() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().identifier("test").uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); + String identifier = extractIdentifier(lines); fcpServer.writeLine( "GetFailed", "Identifier=not-test", @@ -189,7 +176,7 @@ public class DefaultFcpClientTest { ); fcpServer.writeLine( "GetFailed", - "Identifier=test", + "Identifier=" + identifier, "Code=3", "EndMessage" ); @@ -199,16 +186,10 @@ public class DefaultFcpClientTest { @Test public void clientGetRecognizesConnectionClosed() throws InterruptedException, ExecutionException, IOException { - Future> dataFuture = fcpClient.clientGet().identifier("test").uri("KSK@foo.txt"); + Future> dataFuture = fcpClient.clientGet().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt")); fcpServer.close(); Optional data = dataFuture.get(); assertThat(data.isPresent(), is(false)); @@ -216,92 +197,75 @@ public class DefaultFcpClientTest { @Test public void clientGetWithIgnoreDataStoreSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().ignoreDataStore().identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().ignoreDataStore().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "IgnoreDS=true", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "IgnoreDS=true")); } @Test public void clientGetWithDataStoreOnlySettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().dataStoreOnly().identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().dataStoreOnly().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "DSonly=true", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "DSonly=true")); } @Test public void clientGetWithMaxSizeSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().maxSize(1048576).identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().maxSize(1048576).uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "MaxSize=1048576", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "MaxSize=1048576")); } @Test public void clientGetWithPrioritySettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().priority(Priority.interactive).identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().priority(Priority.interactive).uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "PriorityClass=1", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "PriorityClass=1")); } @Test public void clientGetWithRealTimeSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().realTime().identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().realTime().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "RealTimeFlag=true", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "RealTimeFlag=true")); } @Test public void clientGetWithGlobalSettingSendsCorrectCommands() throws InterruptedException, ExecutionException, IOException { - fcpClient.clientGet().global().identifier("test").uri("KSK@foo.txt"); + fcpClient.clientGet().global().uri("KSK@foo.txt"); connectNode(); List lines = fcpServer.collectUntil(is("EndMessage")); - assertThat(lines, containsInAnyOrder( - "ClientGet", - "Identifier=test", - "ReturnType=direct", - "URI=KSK@foo.txt", - "Global=true", - "EndMessage" - )); + assertThat(lines, matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true")); + } + + private Matcher> matchesFcpMessage(String name, String... requiredLines) { + return new TypeSafeDiagnosingMatcher>() { + @Override + protected boolean matchesSafely(List item, Description mismatchDescription) { + if (!item.get(0).equals(name)) { + mismatchDescription.appendText("FCP message is named ").appendValue(item.get(0)); + return false; + } + for (String requiredLine : requiredLines) { + if (item.indexOf(requiredLine) < 1) { + mismatchDescription.appendText("FCP message does not contain ").appendValue(requiredLine); + return false; + } + } + return true; + } + + @Override + public void describeTo(Description description) { + description.appendText("FCP message named ").appendValue(name); + description.appendValueList(", containing the lines", ", ", "", requiredLines); + } + }; } } -- 2.7.4