X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fnet%2Fpterodactylus%2Ffcp%2Fquelaton%2FDefaultFcpClientTest.java;h=7ba009cfa9345dfe22a43a2059f2e0dbdd0c2805;hb=26fe1c162b89b0dbd9505b538a5daf527599be54;hp=2cfce9825e780980e47fe0526ed166a5e5cdda5e;hpb=0d14eb6f2a26155c15c30f9c2a7a5a8c6a2ed8bd;p=jFCPlib.git diff --git a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java index 2cfce98..7ba009c 100644 --- a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java +++ b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java @@ -3,6 +3,7 @@ package net.pterodactylus.fcp.quelaton; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; @@ -22,9 +23,11 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.function.Supplier; import java.util.stream.Collectors; import net.pterodactylus.fcp.ARK; +import net.pterodactylus.fcp.ConfigData; import net.pterodactylus.fcp.DSAGroup; import net.pterodactylus.fcp.FcpKeyPair; import net.pterodactylus.fcp.Key; @@ -32,24 +35,28 @@ import net.pterodactylus.fcp.NodeData; import net.pterodactylus.fcp.NodeRef; import net.pterodactylus.fcp.Peer; import net.pterodactylus.fcp.PeerNote; +import net.pterodactylus.fcp.PluginInfo; import net.pterodactylus.fcp.Priority; import net.pterodactylus.fcp.fake.FakeTcpServer; import net.pterodactylus.fcp.quelaton.ClientGetCommand.Data; import com.google.common.io.ByteStreams; import com.google.common.io.Files; +import com.nitorcreations.junit.runners.NestedRunner; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; import org.junit.After; import org.junit.Assert; import org.junit.Test; +import org.junit.runner.RunWith; /** * Unit test for {@link DefaultFcpClient}. * * @author David ‘Bombe’ Roden */ +@RunWith(NestedRunner.class) public class DefaultFcpClientTest { private static final String INSERT_URI = @@ -57,13 +64,13 @@ public class DefaultFcpClientTest { private static final String REQUEST_URI = "SSK@wtbgd2loNcJCXvtQVOftl2tuWBomDQHfqS6ytpPRhfw,7SHH53gletBVb9JD7nBsyClbLQsBubDPEIcwg908r7Y,AQACAAE/"; - private static int threadCounter = 0; + private int threadCounter = 0; + private final ExecutorService threadPool = + Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++)); private final FakeTcpServer fcpServer; private final DefaultFcpClient fcpClient; public DefaultFcpClientTest() throws IOException { - ExecutorService threadPool = - Executors.newCachedThreadPool(r -> new Thread(r, "Test-Thread-" + threadCounter++)); fcpServer = new FakeTcpServer(threadPool); fcpClient = new DefaultFcpClient(threadPool, "localhost", fcpServer.getPort(), () -> "Test"); } @@ -71,6 +78,7 @@ public class DefaultFcpClientTest { @After public void tearDown() throws IOException { fcpServer.close(); + threadPool.shutdown(); } @Test(expected = ExecutionException.class) @@ -1657,4 +1665,498 @@ public class DefaultFcpClientTest { assertThat(peer.get(), is(true)); } + @Test + public void defaultFcpClientCanModifyPeerNoteByName() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientKnowsPeerNoteWasNotModifiedOnUnknownNodeIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byName("Friend1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "UnknownNodeIdentifier", + "Identifier=" + identifier, + "NodeIdentifier=Friend1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(false)); + } + + @Test + public void defaultFcpClientFailsToModifyPeerNoteWithoutPeerNote() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().byName("Friend1").execute(); + assertThat(noteUpdated.get(), is(false)); + } + + @Test + public void defaultFcpClientCanModifyPeerNoteByIdentifier() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = fcpClient.modifyPeerNote().darknetComment("foo").byIdentifier("id1").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=id1", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientCanModifyPeerNoteByHostAndPort() + throws InterruptedException, ExecutionException, IOException { + Future noteUpdated = + fcpClient.modifyPeerNote().darknetComment("foo").byHostAndPort("1.2.3.4", 5678).execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyPeerNote", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "PeerNoteType=1", + "NoteText=Zm9v", + "EndMessage" + )); + fcpServer.writeLine( + "PeerNote", + "Identifier=" + identifier, + "NodeIdentifier=1.2.3.4:5678", + "NoteText=Zm9v", + "PeerNoteType=1", + "EndMessage" + ); + assertThat(noteUpdated.get(), is(true)); + } + + @Test + public void defaultFcpClientCanGetConfigWithoutDetails() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(configData.get(), notNullValue()); + } + + @Test + public void defaultFcpClientCanGetConfigWithCurrent() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withCurrent().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithCurrent=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "current.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getCurrent("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithDefaults() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withDefaults().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithDefaults=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "default.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getDefault("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithSortOrder() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withSortOrder().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithSortOrder=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "sortOrder.foo=17", + "EndMessage" + ); + assertThat(configData.get().getSortOrder("foo"), is(17)); + } + + @Test + public void defaultFcpClientCanGetConfigWithExpertFlag() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withExpertFlag().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithExpertFlag=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "expertFlag.foo=true", + "EndMessage" + ); + assertThat(configData.get().getExpertFlag("foo"), is(true)); + } + + @Test + public void defaultFcpClientCanGetConfigWithForceWriteFlag() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withForceWriteFlag().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithForceWriteFlag=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "forceWriteFlag.foo=true", + "EndMessage" + ); + assertThat(configData.get().getForceWriteFlag("foo"), is(true)); + } + + @Test + public void defaultFcpClientCanGetConfigWithShortDescription() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withShortDescription().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithShortDescription=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "shortDescription.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getShortDescription("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithLongDescription() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withLongDescription().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithLongDescription=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "longDescription.foo=bar", + "EndMessage" + ); + assertThat(configData.get().getLongDescription("foo"), is("bar")); + } + + @Test + public void defaultFcpClientCanGetConfigWithDataTypes() + throws InterruptedException, ExecutionException, IOException { + Future configData = fcpClient.getConfig().withDataTypes().execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "GetConfig", + "Identifier=" + identifier, + "WithDataTypes=true", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "dataType.foo=number", + "EndMessage" + ); + assertThat(configData.get().getDataType("foo"), is("number")); + } + + @Test + public void defaultFcpClientCanModifyConfigData() throws InterruptedException, ExecutionException, IOException { + Future newConfigData = fcpClient.modifyConfig().set("foo.bar").to("baz").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + assertThat(lines, matchesFcpMessage( + "ModifyConfig", + "Identifier=" + identifier, + "foo.bar=baz", + "EndMessage" + )); + fcpServer.writeLine( + "ConfigData", + "Identifier=" + identifier, + "current.foo.bar=baz", + "EndMessage" + ); + assertThat(newConfigData.get().getCurrent("foo.bar"), is("baz")); + } + + public class PluginCommands { + + private List lines; + private String identifier; + + private void connectAndAssert(Supplier>> requestMatcher) + throws InterruptedException, ExecutionException, IOException { + connectNode(); + lines = fcpServer.collectUntil(is("EndMessage")); + identifier = extractIdentifier(lines); + assertThat(lines, requestMatcher.get()); + } + + private void replyWithPluginInfo() throws IOException { + fcpServer.writeLine( + "PluginInfo", + "Identifier=" + identifier, + "PluginName=superPlugin", + "IsTalkable=true", + "LongVersion=1.2.3", + "Version=42", + "OriginUri=superPlugin", + "Started=true", + "EndMessage" + ); + } + + private void verifyPluginInfo(Future> pluginInfo) + throws InterruptedException, ExecutionException { + assertThat(pluginInfo.get().get().getPluginName(), is("superPlugin")); + assertThat(pluginInfo.get().get().getOriginalURI(), is("superPlugin")); + assertThat(pluginInfo.get().get().isTalkable(), is(true)); + assertThat(pluginInfo.get().get().getVersion(), is("42")); + assertThat(pluginInfo.get().get().getLongVersion(), is("1.2.3")); + assertThat(pluginInfo.get().get().isStarted(), is(true)); + } + + public class LoadPlugin { + + public class OfficialPlugins { + + @Test + public void fromFreenet() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = + fcpClient.loadPlugin().officialFromFreenet("superPlugin").execute(); + connectAndAssert(() -> createMatcherForOfficialSource("freenet")); + assertThat(lines, not(contains(startsWith("Store=")))); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + @Test + public void persistentFromFreenet() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = + fcpClient.loadPlugin().addToConfig().officialFromFreenet("superPlugin").execute(); + connectAndAssert(() -> createMatcherForOfficialSource("freenet")); + assertThat(lines, hasItem("Store=true")); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + @Test + public void fromHttps() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = + fcpClient.loadPlugin().officialFromHttps("superPlugin").execute(); + connectAndAssert(() -> createMatcherForOfficialSource("https")); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + private Matcher> createMatcherForOfficialSource(String officialSource) { + return matchesFcpMessage( + "LoadPlugin", + "Identifier=" + identifier, + "PluginURL=superPlugin", + "URLType=official", + "OfficialSource=" + officialSource, + "EndMessage" + ); + } + + } + + public class FromOtherSources { + + private static final String FILE_PATH = "/path/to/plugin.jar"; + private static final String URL = "http://server.com/plugin.jar"; + private static final String KEY = "KSK@plugin.jar"; + + @Test + public void fromFile() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = fcpClient.loadPlugin().fromFile(FILE_PATH).execute(); + connectAndAssert(() -> createMatcher("file", FILE_PATH)); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + @Test + public void fromUrl() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = fcpClient.loadPlugin().fromUrl(URL).execute(); + connectAndAssert(() -> createMatcher("url", URL)); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + @Test + public void fromFreenet() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = fcpClient.loadPlugin().fromFreenet(KEY).execute(); + connectAndAssert(() -> createMatcher("freenet", KEY)); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + private Matcher> createMatcher(String urlType, String url) { + return matchesFcpMessage( + "LoadPlugin", + "Identifier=" + identifier, + "PluginURL=" + url, + "URLType=" + urlType, + "EndMessage" + ); + } + + } + + public class Failed { + + @Test + public void failedLoad() throws ExecutionException, InterruptedException, IOException { + Future> pluginInfo = + fcpClient.loadPlugin().officialFromFreenet("superPlugin").execute(); + connectNode(); + List lines = fcpServer.collectUntil(is("EndMessage")); + String identifier = extractIdentifier(lines); + fcpServer.writeLine( + "ProtocolError", + "Identifier=" + identifier, + "EndMessage" + ); + assertThat(pluginInfo.get().isPresent(), is(false)); + } + + } + + } + + public class ReloadPlugin { + + private static final String CLASS_NAME = "foo.plugin.Plugin"; + + @Test + public void reloadingPluginWorks() throws InterruptedException, ExecutionException, IOException { + Future> pluginInfo = fcpClient.reloadPlugin().plugin(CLASS_NAME).execute(); + connectAndAssert(() -> matchesFcpMessage( + "ReloadPlugin", + "Identifier=" + identifier, + "PluginName=" + CLASS_NAME, + "EndMessage" + )); + replyWithPluginInfo(); + verifyPluginInfo(pluginInfo); + } + + } + + } + }