Create Guava optional utility collection
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / fcp / SoneCommandTest.kt
1 package net.pterodactylus.sone.fcp
2
3 import com.google.common.base.Optional
4 import com.google.common.base.Optional.absent
5 import freenet.support.SimpleFieldSet
6 import net.pterodactylus.sone.core.Core
7 import net.pterodactylus.sone.data.Post
8 import net.pterodactylus.sone.data.PostReply
9 import net.pterodactylus.sone.data.Profile
10 import net.pterodactylus.sone.data.Sone
11 import net.pterodactylus.sone.freenet.fcp.FcpException
12 import net.pterodactylus.sone.template.SoneAccessor
13 import net.pterodactylus.sone.test.OneByOneMatcher
14 import net.pterodactylus.sone.test.mock
15 import net.pterodactylus.sone.test.whenever
16 import net.pterodactylus.sone.utils.asOptional
17 import org.junit.Before
18 import org.junit.Rule
19 import org.junit.rules.ExpectedException
20 import org.mockito.ArgumentMatchers.anyString
21
22 /**
23  * Base class for Sone FCP command tests.
24  */
25 abstract class SoneCommandTest {
26
27         @Rule @JvmField val expectedException = ExpectedException.none()!!
28
29         protected val core = mock<Core>()
30         protected val command: AbstractSoneCommand by lazy { createCommand(core) }
31
32         protected val parameters = SimpleFieldSet(true)
33         protected val localSone = mock<Sone>().apply {
34                 whenever(isLocal).thenReturn(true)
35         }
36         protected val remoteSone = mock<Sone>()
37
38         protected abstract fun createCommand(core: Core): AbstractSoneCommand
39
40         @Before
41         fun setupCore() {
42                 whenever(core.getSone(anyString())).thenReturn(absent())
43                 whenever(core.getPost(anyString())).thenReturn(absent())
44                 whenever(core.getPostReply(anyString())).thenReturn(absent())
45         }
46
47         protected fun createSone(id: String, name: String, firstName: String, lastName: String, time: Long) = mock<Sone>().apply {
48                 whenever(this.id).thenReturn(id)
49                 whenever(this.name).thenReturn(name)
50                 whenever(profile).thenReturn(Profile(this).apply {
51                         this.firstName = firstName
52                         this.lastName = lastName
53                 })
54                 whenever(this.time).thenReturn(time)
55         }
56
57         protected fun createPost(id: String, sone: Sone, recipientId: String?, time: Long, text: String) = mock<Post>().apply {
58                 whenever(this.id).thenReturn(id)
59                 whenever(this.sone).thenReturn(sone)
60                 whenever(this.recipientId).thenReturn(recipientId.asOptional())
61                 whenever(this.time).thenReturn(time)
62                 whenever(this.text).thenReturn(text)
63         }
64
65         protected fun createReply(id: String, sone: Sone, post: Post, time: Long, text: String) = mock<PostReply>().apply {
66                 whenever(this.id).thenReturn(id)
67                 whenever(this.sone).thenReturn(sone)
68                 whenever(this.post).thenReturn(post.asOptional())
69                 whenever(this.time).thenReturn(time)
70                 whenever(this.text).thenReturn(text)
71         }
72
73         protected fun executeCommandAndExpectFcpException() {
74                 expectedException.expect(FcpException::class.java)
75                 command.execute(parameters)
76         }
77
78         protected fun requestWithoutAnyParameterResultsInFcpException() {
79                 expectedException.expect(FcpException::class.java)
80                 command.execute(parameters)
81         }
82
83         protected fun requestWithEmptySoneParameterResultsInFcpException() {
84                 parameters += "Sone" to null
85                 executeCommandAndExpectFcpException()
86         }
87
88         protected fun requestWithInvalidSoneParameterResultsInFcpException() {
89                 parameters += "Sone" to "InvalidSoneId"
90                 executeCommandAndExpectFcpException()
91         }
92
93         fun requestWithValidRemoteSoneParameterResultsInFcpException() {
94                 parameters += "Sone" to "RemoteSoneId"
95                 whenever(core.getSone("RemoteSoneId")).thenReturn(Optional.of(remoteSone))
96                 executeCommandAndExpectFcpException()
97         }
98
99         protected operator fun SimpleFieldSet.plusAssign(keyValue: Pair<String, String?>) = putSingle(keyValue.first, keyValue.second)
100         protected fun SimpleFieldSet.parsePost(prefix: String) = parseFromSimpleFieldSet(prefix, "ID", "Sone", "Recipient", "Time", "Text")
101         protected fun SimpleFieldSet.parseReply(prefix: String) = parseFromSimpleFieldSet(prefix, "ID", "Sone", "Time", "Text")
102         protected fun SimpleFieldSet.parseSone(prefix: String) = parseFromSimpleFieldSet(prefix, "ID", "Name", "NiceName", "LastUpdated", "Followed") +
103                         (0 until this["${prefix}Field.Count"].toInt()).map {
104                                 ("Field." + this["${prefix}Field.$it.Name"]) to this["${prefix}Field.$it.Value"]
105                         }
106
107         private fun SimpleFieldSet.parseFromSimpleFieldSet(prefix: String, vararg fields: String) = listOf(*fields)
108                         .map { it to (get(prefix + it) as String?) }
109                         .toMap()
110
111         protected fun matchesPost(post: Post) = OneByOneMatcher<Map<String, String?>>().apply {
112                 expect("ID", post.id) { it["ID"] }
113                 expect("Sone", post.sone.id) { it["Sone"] }
114                 expect("recipient", post.recipientId.orNull()) { it["Recipient"] }
115                 expect("time", post.time.toString()) { it["Time"] }
116                 expect("text", post.text.replace("\\", "\\\\").replace("\r", "\\r").replace("\n", "\\n")) { it["Text"] }
117         }
118
119         protected fun matchesReply(reply: PostReply) = OneByOneMatcher<Map<String, String?>>().apply {
120                 expect("ID", reply.id) { it["ID"] }
121                 expect("Sone", reply.sone.id) { it["Sone"] }
122                 expect("time", reply.time.toString()) { it["Time"] }
123                 expect("text", reply.text.replace("\\", "\\\\").replace("\r", "\\r").replace("\n", "\\n")) { it["Text"] }
124         }
125
126         protected fun matchesSone(sone: Sone) = OneByOneMatcher<Map<String, String?>>().apply {
127                 expect("ID", sone.id) { it["ID"] }
128                 expect("name", sone.name) { it["Name"] }
129                 expect("last updated", sone.time.toString()) { it["LastUpdated"] }
130                 expect("nice name", SoneAccessor.getNiceName(sone)) { it["NiceName"] }
131                 sone.profile.fields.forEach { field ->
132                         expect("field: ${field.name}", field.value) { it["Field.${field.name}"] }
133                 }
134         }
135
136 }