Add unit test for get sone command, fix some bugs
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 13 Jan 2017 22:22:54 +0000 (23:22 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 13 Jan 2017 22:22:54 +0000 (23:22 +0100)
a) Add a prefix for the sone being returned.
b) When asking for a local Sone, actually require it, too.
c) Fix the actual check for a local Sone.

src/main/java/net/pterodactylus/sone/fcp/AbstractSoneCommand.java
src/main/java/net/pterodactylus/sone/fcp/GetSoneCommand.java
src/test/kotlin/net/pterodactylus/sone/fcp/GetSoneCommandTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/fcp/SoneCommandTest.kt

index 3698b05..1c4fd2e 100644 (file)
@@ -162,7 +162,7 @@ public abstract class AbstractSoneCommand extends AbstractCommand {
                        throw new FcpException("Could not load Sone ID from “" + parameterName + "”.");
                }
                Optional<Sone> sone = core.getSone(soneId);
-               if ((mandatory && !sone.isPresent()) || (mandatory && sone.isPresent() && (localOnly && !sone.get().isLocal()))) {
+               if ((mandatory && !sone.isPresent()) || (sone.isPresent() && localOnly && !sone.get().isLocal())) {
                        throw new FcpException("Could not load Sone from “" + soneId + "”.");
                }
                return sone;
index d0bd5cc..9d0e0b7 100644 (file)
@@ -50,8 +50,8 @@ public class GetSoneCommand extends AbstractSoneCommand {
        @Override
        public Response execute(SimpleFieldSet parameters) throws FcpException {
                Sone sone = getSone(parameters, "Sone", false);
-               Optional<Sone> localSone = getSone(parameters, "LocalSone", false, false);
-               return new Response("Sone", encodeSone(sone, "", localSone));
+               Optional<Sone> localSone = getSone(parameters, "LocalSone", true, false);
+               return new Response("Sone", encodeSone(sone, "Sone.", localSone));
        }
 
 }
diff --git a/src/test/kotlin/net/pterodactylus/sone/fcp/GetSoneCommandTest.kt b/src/test/kotlin/net/pterodactylus/sone/fcp/GetSoneCommandTest.kt
new file mode 100644 (file)
index 0000000..710a5df
--- /dev/null
@@ -0,0 +1,93 @@
+package net.pterodactylus.sone.fcp
+
+import net.pterodactylus.sone.core.Core
+import net.pterodactylus.sone.freenet.fcp.FcpException
+import net.pterodactylus.sone.test.asOptional
+import net.pterodactylus.sone.test.whenever
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.equalTo
+import org.hamcrest.Matchers.nullValue
+import org.junit.Test
+
+/**
+ * Unit test for [GetSoneCommand].
+ */
+class GetSoneCommandTest : SoneCommandTest() {
+
+       private val sone = createSone("SoneId", "Sone", "Sone", "#1", 1000).apply {
+               profile.addField("Test").value = "true"
+               profile.addField("More Test").value = "also true"
+       }
+
+       override fun createCommand(core: Core) = GetSoneCommand(core)
+
+       @Test
+       fun `command does not require write access`() {
+               assertThat(command.requiresWriteAccess(), equalTo(false))
+       }
+
+       @Test
+       fun `request without any parameters results in fcp exception`() {
+               requestWithoutAnyParameterResultsInFcpException()
+       }
+
+       @Test
+       fun `request with empty Sone parameter results in fcp exception`() {
+               requestWithEmptySoneParameterResultsInFcpException()
+       }
+
+       @Test
+       fun `request with invalid Sone parameter results in fcp exception`() {
+               requestWithInvalidSoneParameterResultsInFcpException()
+       }
+
+       @Test
+       fun `request with valid Sone parameter results in response with Sone information`() {
+               whenever(core.getSone("SoneId")).thenReturn(sone.asOptional())
+               whenever(core.getSone(null)).thenReturn(null.asOptional())
+               parameters += "Sone" to "SoneId"
+               val replyParameters = command.execute(parameters).replyParameters
+               assertThat(replyParameters["Message"], equalTo("Sone"))
+               assertThat(replyParameters.parseSone("Sone."), matchesSone(sone))
+               assertThat(replyParameters["Sone.Followed"], nullValue())
+       }
+
+       @Test
+       fun `request with local sone parameter results in followed being true for friend sone`() {
+               whenever(core.getSone("SoneId")).thenReturn(sone.asOptional())
+               whenever(core.getSone("LocalSone")).thenReturn(localSone.asOptional())
+               whenever(localSone.id).thenReturn("LocalSone")
+               whenever(localSone.hasFriend("SoneId")).thenReturn(true)
+               parameters += "Sone" to "SoneId"
+               parameters += "LocalSone" to "LocalSone"
+               val replyParameters = command.execute(parameters).replyParameters
+               assertThat(replyParameters["Message"], equalTo("Sone"))
+               assertThat(replyParameters.parseSone("Sone."), matchesSone(sone))
+               assertThat(replyParameters["Sone.Followed"], equalTo("true"))
+       }
+       
+       @Test
+       fun `request with local sone parameter results in followed being false for non-friend sone`() {
+               whenever(core.getSone("SoneId")).thenReturn(sone.asOptional())
+               whenever(core.getSone("LocalSone")).thenReturn(localSone.asOptional())
+               whenever(localSone.id).thenReturn("LocalSone")
+               parameters += "Sone" to "SoneId"
+               parameters += "LocalSone" to "LocalSone"
+               val replyParameters = command.execute(parameters).replyParameters
+               assertThat(replyParameters["Message"], equalTo("Sone"))
+               assertThat(replyParameters.parseSone("Sone."), matchesSone(sone))
+               assertThat(replyParameters["Sone.Followed"], equalTo("false"))
+       }
+
+       @Test
+       fun `request with remote sone as local sone parameter results in fcp exception`() {
+               whenever(core.getSone("SoneId")).thenReturn(sone.asOptional())
+               whenever(core.getSone("RemoteSone")).thenReturn(remoteSone.asOptional())
+               whenever(localSone.id).thenReturn("RemoteSone")
+               parameters += "Sone" to "SoneId"
+               parameters += "LocalSone" to "RemoteSone"
+               expectedException.expect(FcpException::class.java)
+               command.execute(parameters)
+       }
+
+}
index 086bbb3..ddaecee 100644 (file)
@@ -10,6 +10,7 @@ import net.pterodactylus.sone.data.PostReply
 import net.pterodactylus.sone.data.Profile
 import net.pterodactylus.sone.data.Sone
 import net.pterodactylus.sone.freenet.fcp.FcpException
+import net.pterodactylus.sone.template.SoneAccessor
 import net.pterodactylus.sone.test.asOptional
 import net.pterodactylus.sone.test.mock
 import net.pterodactylus.sone.test.whenever
@@ -98,6 +99,10 @@ abstract class SoneCommandTest {
        protected operator fun SimpleFieldSet.plusAssign(keyValue: Pair<String, String?>) = putSingle(keyValue.first, keyValue.second)
        protected fun SimpleFieldSet.parsePost(prefix: String) = parseFromSimpleFieldSet(prefix, "ID", "Sone", "Recipient", "Time", "Text")
        protected fun SimpleFieldSet.parseReply(prefix: String) = parseFromSimpleFieldSet(prefix, "ID", "Sone", "Time", "Text")
+       protected fun SimpleFieldSet.parseSone(prefix: String) = parseFromSimpleFieldSet(prefix, "Name", "NiceName", "LastUpdated", "Followed") +
+                       (0 until this["${prefix}Field.Count"].toInt()).map {
+                               ("Field." + this["${prefix}Field.$it.Name"]) to this["${prefix}Field.$it.Value"]
+                       }
 
        private fun SimpleFieldSet.parseFromSimpleFieldSet(prefix: String, vararg fields: String) = listOf(*fields)
                        .map { it to (get(prefix + it) as String?) }
@@ -118,4 +123,13 @@ abstract class SoneCommandTest {
                expect("text", reply.text.replace("\\", "\\\\").replace("\r", "\\r").replace("\n", "\\n")) { it["Text"] }
        }
 
+       protected fun matchesSone(sone: Sone) = OneByOneMatcher<Map<String, String?>>().apply {
+               expect("name", sone.name) { it["Name"] }
+               expect("last updated", sone.time.toString()) { it["LastUpdated"] }
+               expect("nice name", SoneAccessor.getNiceName(sone)) { it["NiceName"] }
+               sone.profile.fields.forEach { field ->
+                       expect("field: ${field.name}", field.value) { it["Field.${field.name}"] }
+               }
+       }
+
 }