From 0747ce52deab6ed6e4c3118959cf76827c2ce495 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sun, 8 Jan 2017 13:54:42 +0100 Subject: [PATCH] Add some more tests for FCP interface and refactor --- .../net/pterodactylus/sone/fcp/FcpInterface.java | 50 ++++++------- .../net/pterodactylus/sone/fcp/FcpInterfaceTest.kt | 82 ++++++++++++++++++++++ 2 files changed, 105 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java b/src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java index 440cb4c..36e18e6 100644 --- a/src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java +++ b/src/main/java/net/pterodactylus/sone/fcp/FcpInterface.java @@ -153,41 +153,37 @@ public class FcpInterface { */ public void handle(PluginReplySender pluginReplySender, SimpleFieldSet parameters, Bucket data, int accessType) { if (!active.get()) { - try { - sendReply(pluginReplySender, null, new ErrorResponse(400, "FCP Interface deactivated")); - } catch (PluginNotFoundException pnfe1) { - logger.log(Level.FINE, "Could not set error to plugin.", pnfe1); - } + sendErrorReply(pluginReplySender, null, 503, "FCP Interface deactivated"); return; } AbstractSoneCommand command = commands.get(parameters.get("Message")); if ((accessType == FredPluginFCP.ACCESS_FCP_RESTRICTED) && (((fullAccessRequired.get() == FullAccessRequired.WRITING) && command.requiresWriteAccess()) || (fullAccessRequired.get() == FullAccessRequired.ALWAYS))) { - try { - sendReply(pluginReplySender, null, new ErrorResponse(401, "Not authorized")); - } catch (PluginNotFoundException pnfe1) { - logger.log(Level.FINE, "Could not set error to plugin.", pnfe1); - } + sendErrorReply(pluginReplySender, null, 401, "Not authorized"); return; } + if (command == null) { + sendErrorReply(pluginReplySender, null, 404, "Unrecognized Message: " + parameters.get("Message")); + return; + } + String identifier = parameters.get("Identifier"); + if ((identifier == null) || (identifier.length() == 0)) { + sendErrorReply(pluginReplySender, null, 400, "Missing Identifier."); + return; + } + try { + Response response = command.execute(parameters, data, AccessType.values()[accessType]); + sendReply(pluginReplySender, identifier, response); + } catch (Exception e1) { + logger.log(Level.WARNING, "Could not process FCP command “%s”.", command); + sendErrorReply(pluginReplySender, identifier, 500, "Error executing command: " + e1.getMessage()); + } + } + + private void sendErrorReply(PluginReplySender pluginReplySender, String identifier, int errorCode, String message) { try { - if (command == null) { - sendReply(pluginReplySender, null, new ErrorResponse("Unrecognized Message: " + parameters.get("Message"))); - return; - } - String identifier = parameters.get("Identifier"); - if ((identifier == null) || (identifier.length() == 0)) { - sendReply(pluginReplySender, null, new ErrorResponse("Missing Identifier.")); - return; - } - try { - Response response = command.execute(parameters, data, AccessType.values()[accessType]); - sendReply(pluginReplySender, identifier, response); - } catch (Exception e1) { - logger.log(Level.WARNING, "Could not process FCP command “%s”.", command); - sendReply(pluginReplySender, identifier, new ErrorResponse("Error executing command: " + e1.getMessage())); - } + sendReply(pluginReplySender, identifier, new ErrorResponse(errorCode, message)); } catch (PluginNotFoundException pnfe1) { - logger.log(Level.WARNING, "Could not find destination plugin: " + pluginReplySender); + logger.log(Level.FINE, "Could not send error to plugin.", pnfe1); } } diff --git a/src/test/java/net/pterodactylus/sone/fcp/FcpInterfaceTest.kt b/src/test/java/net/pterodactylus/sone/fcp/FcpInterfaceTest.kt index 1ec9473..9e9df16 100644 --- a/src/test/java/net/pterodactylus/sone/fcp/FcpInterfaceTest.kt +++ b/src/test/java/net/pterodactylus/sone/fcp/FcpInterfaceTest.kt @@ -1,5 +1,10 @@ +@file:Suppress("DEPRECATION") + package net.pterodactylus.sone.fcp +import freenet.pluginmanager.PluginNotFoundException +import freenet.pluginmanager.PluginReplySender +import freenet.support.SimpleFieldSet import net.pterodactylus.sone.core.Core import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.ALWAYS @@ -8,10 +13,17 @@ import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired.WRITING import net.pterodactylus.sone.fcp.event.FcpInterfaceActivatedEvent import net.pterodactylus.sone.fcp.event.FcpInterfaceDeactivatedEvent import net.pterodactylus.sone.fcp.event.FullAccessRequiredChanged +import net.pterodactylus.sone.freenet.fcp.Command.AccessType.FULL_FCP +import net.pterodactylus.sone.freenet.fcp.Command.AccessType.RESTRICTED_FCP +import net.pterodactylus.sone.main.SonePlugin +import net.pterodactylus.sone.test.capture import net.pterodactylus.sone.test.mock +import net.pterodactylus.sone.test.whenever import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.Test +import org.mockito.ArgumentMatchers +import org.mockito.Mockito.verify /** * Unit test for [FcpInterface] and its subclasses. @@ -20,6 +32,9 @@ class FcpInterfaceTest { private val core = mock() private val fcpInterface = FcpInterface(core) + private val pluginReplySender = mock() + private val parameters = SimpleFieldSet(true) + private val replyParameters = capture() @Test fun `fcp interface can be activated`() { @@ -53,4 +68,71 @@ class FcpInterfaceTest { setAndVerifyAccessRequired(ALWAYS) } + @Test + fun `sending command to inactive fcp interface results in 400 error reply`() { + fcpInterface.fcpInterfaceDeactivated(FcpInterfaceDeactivatedEvent()) + fcpInterface.handle(pluginReplySender, parameters, null, 0) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Error")) + assertThat(replyParameters.value["ErrorCode"], equalTo("503")) + } + + @Test + fun `exception while sending reply does not result in exception`() { + fcpInterface.fcpInterfaceDeactivated(FcpInterfaceDeactivatedEvent()) + whenever(pluginReplySender.send(ArgumentMatchers.any())).thenThrow(PluginNotFoundException::class.java) + fcpInterface.handle(pluginReplySender, parameters, null, 0) + } + + @Test + fun `sending command over restricted fcp connection results in 401 error reply`() { + fcpInterface.fcpInterfaceActivated(FcpInterfaceActivatedEvent()) + fcpInterface.handle(pluginReplySender, parameters, null, RESTRICTED_FCP.ordinal) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Error")) + assertThat(replyParameters.value["ErrorCode"], equalTo("401")) + } + + @Test + fun `sending unknown command over full access connection results in 404 error reply`() { + fcpInterface.fcpInterfaceActivated(FcpInterfaceActivatedEvent()) + fcpInterface.handle(pluginReplySender, parameters, null, FULL_FCP.ordinal) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Error")) + assertThat(replyParameters.value["ErrorCode"], equalTo("404")) + } + + @Test + fun `sending version command without identifier results in 400 error code`() { + fcpInterface.fcpInterfaceActivated(FcpInterfaceActivatedEvent()) + parameters.putSingle("Message", "Version") + fcpInterface.handle(pluginReplySender, parameters, null, FULL_FCP.ordinal) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Error")) + assertThat(replyParameters.value["ErrorCode"], equalTo("400")) + } + + @Test + fun `sending version command with empty identifier results in 400 error code`() { + fcpInterface.fcpInterfaceActivated(FcpInterfaceActivatedEvent()) + parameters.putSingle("Message", "Version") + parameters.putSingle("Identifier", "") + fcpInterface.handle(pluginReplySender, parameters, null, FULL_FCP.ordinal) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Error")) + assertThat(replyParameters.value["ErrorCode"], equalTo("400")) + } + + @Test + fun `sending version command with identifier results in version reply`() { + fcpInterface.fcpInterfaceActivated(FcpInterfaceActivatedEvent()) + parameters.putSingle("Message", "Version") + parameters.putSingle("Identifier", "Test") + fcpInterface.handle(pluginReplySender, parameters, null, FULL_FCP.ordinal) + verify(pluginReplySender).send(replyParameters.capture()) + assertThat(replyParameters.value["Message"], equalTo("Version")) + assertThat(replyParameters.value["Version"], equalTo(SonePlugin.getPluginVersion())) + assertThat(replyParameters.value["ProtocolVersion"], equalTo("1")) + } + } -- 2.7.4