2 * Sone - SoneMentionDetectorTest.kt - Copyright © 2019 David ‘Bombe’ Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.text
20 import com.google.common.eventbus.*
21 import net.pterodactylus.sone.core.event.*
22 import net.pterodactylus.sone.data.*
23 import net.pterodactylus.sone.database.*
24 import net.pterodactylus.sone.test.*
25 import org.hamcrest.MatcherAssert.*
26 import org.hamcrest.Matchers.*
30 * Unit test for [SoneMentionDetector].
32 @Suppress("UnstableApiUsage")
33 class SoneMentionDetectorTest {
35 private val eventBus = EventBus()
36 private val soneProvider = TestSoneProvider()
37 private val postProvider = TestPostProvider()
38 private val soneTextParser = SoneTextParser(soneProvider, postProvider)
39 private val capturedFoundEvents = mutableListOf<MentionOfLocalSoneFoundEvent>()
40 private val capturedRemovedEvents = mutableListOf<MentionOfLocalSoneRemovedEvent>()
41 private val postReplyProvider = TestPostReplyProvider()
44 eventBus.register(SoneMentionDetector(eventBus, soneTextParser, postReplyProvider))
45 eventBus.register(object : Any() {
47 fun captureFoundEvent(mentionOfLocalSoneFoundEvent: MentionOfLocalSoneFoundEvent) {
48 capturedFoundEvents += mentionOfLocalSoneFoundEvent
52 fun captureRemovedEvent(event: MentionOfLocalSoneRemovedEvent) {
53 capturedRemovedEvents += event
59 fun `detector does not emit event on post that does not contain any sones`() {
60 val post = createPost()
61 eventBus.post(NewPostFoundEvent(post))
62 assertThat(capturedFoundEvents, emptyIterable())
66 fun `detector does not emit event on post that does contain two remote sones`() {
67 val post = createPost("text mentions sone://${remoteSone1.id} and sone://${remoteSone2.id}.")
68 eventBus.post(NewPostFoundEvent(post))
69 assertThat(capturedFoundEvents, emptyIterable())
73 fun `detector emits event on post that contains links to a remote and a local sone`() {
74 val post = createPost("text mentions sone://${localSone1.id} and sone://${remoteSone2.id}.")
75 eventBus.post(NewPostFoundEvent(post))
76 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
80 fun `detector emits one event on post that contains two links to the same local sone`() {
81 val post = createPost("text mentions sone://${localSone1.id} and sone://${localSone1.id}.")
82 eventBus.post(NewPostFoundEvent(post))
83 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
87 fun `detector emits one event on post that contains links to two local sones`() {
88 val post = createPost("text mentions sone://${localSone1.id} and sone://${localSone2.id}.")
89 eventBus.post(NewPostFoundEvent(post))
90 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
94 fun `detector does not emit event for post by local sone`() {
95 val post = createPost("text mentions sone://${localSone1.id} and sone://${localSone2.id}.", localSone1)
96 eventBus.post(NewPostFoundEvent(post))
97 assertThat(capturedFoundEvents, emptyIterable())
101 fun `detector does not emit event for reply that contains no sones`() {
102 val reply = emptyPostReply()
103 eventBus.post(NewPostReplyFoundEvent(reply))
104 assertThat(capturedFoundEvents, emptyIterable())
108 fun `detector does not emit event for reply that contains two links to remote sones`() {
109 val reply = emptyPostReply("text mentions sone://${remoteSone1.id} and sone://${remoteSone2.id}.")
110 eventBus.post(NewPostReplyFoundEvent(reply))
111 assertThat(capturedFoundEvents, emptyIterable())
115 fun `detector emits event on reply that contains links to a remote and a local sone`() {
116 val post = createPost()
117 val reply = emptyPostReply("text mentions sone://${remoteSone1.id} and sone://${localSone1.id}.", post)
118 eventBus.post(NewPostReplyFoundEvent(reply))
119 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
123 fun `detector emits one event on reply that contains two links to the same local sone`() {
124 val post = createPost()
125 val reply = emptyPostReply("text mentions sone://${localSone1.id} and sone://${localSone1.id}.", post)
126 eventBus.post(NewPostReplyFoundEvent(reply))
127 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
131 fun `detector emits one event on reply that contains two links to local sones`() {
132 val post = createPost()
133 val reply = emptyPostReply("text mentions sone://${localSone1.id} and sone://${localSone2.id}.", post)
134 eventBus.post(NewPostReplyFoundEvent(reply))
135 assertThat(capturedFoundEvents, contains(MentionOfLocalSoneFoundEvent(post)))
139 fun `detector does not emit event for reply by local sone`() {
140 val reply = emptyPostReply("text mentions sone://${localSone1.id} and sone://${localSone2.id}.", sone = localSone1)
141 eventBus.post(NewPostReplyFoundEvent(reply))
142 assertThat(capturedFoundEvents, emptyIterable())
146 fun `detector does not emit removed event when a post without mention is removed`() {
147 val post = createPost()
148 eventBus.post(PostRemovedEvent(post))
149 assertThat(capturedRemovedEvents, emptyIterable())
153 fun `detector does emit removed event when post with mention is removed`() {
154 val post = createPost("sone://${localSone1.id}")
155 eventBus.post(NewPostFoundEvent(post))
156 eventBus.post(PostRemovedEvent(post))
157 assertThat(capturedRemovedEvents, contains(MentionOfLocalSoneRemovedEvent(post)))
161 fun `detector does not emit removed event when a post without mention is marked as known`() {
162 val post = createPost()
163 eventBus.post(MarkPostKnownEvent(post))
164 assertThat(capturedRemovedEvents, emptyIterable())
168 fun `detector does emit removed event when post with mention is marked as known`() {
169 val post = createPost("sone://${localSone1.id}")
170 eventBus.post(NewPostFoundEvent(post))
171 eventBus.post(MarkPostKnownEvent(post))
172 assertThat(capturedRemovedEvents, contains(MentionOfLocalSoneRemovedEvent(post)))
176 fun `detector does emit removed event when reply with mention is removed and no more mentions in that post exist`() {
177 val post = createPost()
178 val reply = emptyPostReply("sone://${localSone1.id}", post)
179 postReplyProvider.postReplies[post.id] = listOf(reply)
180 eventBus.post(NewPostReplyFoundEvent(reply))
181 eventBus.post(PostReplyRemovedEvent(reply))
182 assertThat(capturedRemovedEvents, contains(MentionOfLocalSoneRemovedEvent(post)))
186 fun `detector does not emit removed event when reply with mention is removed and post mentions local sone`() {
187 val post = createPost("sone://${localSone1.id}")
188 val reply = emptyPostReply("sone://${localSone1.id}", post)
189 eventBus.post(NewPostReplyFoundEvent(reply))
190 eventBus.post(PostReplyRemovedEvent(reply))
191 assertThat(capturedRemovedEvents, emptyIterable())
195 fun `detector does emit removed event when reply with mention is removed and post mentions local sone but is known`() {
196 val post = createPost("sone://${localSone1.id}", known = true)
197 val reply = emptyPostReply("sone://${localSone1.id}", post)
198 eventBus.post(NewPostReplyFoundEvent(reply))
199 eventBus.post(PostReplyRemovedEvent(reply))
200 assertThat(capturedRemovedEvents, contains(MentionOfLocalSoneRemovedEvent(post)))
204 fun `detector does not emit removed event when reply with mention is removed and post has other replies with mentions`() {
205 val post = createPost()
206 val reply1 = emptyPostReply("sone://${localSone1.id}", post)
207 val reply2 = emptyPostReply("sone://${localSone1.id}", post)
208 postReplyProvider.postReplies[post.id] = listOf(reply1, reply2)
209 eventBus.post(NewPostReplyFoundEvent(reply1))
210 eventBus.post(PostReplyRemovedEvent(reply1))
211 assertThat(capturedRemovedEvents, emptyIterable())
215 fun `detector does emit removed event when reply with mention is removed and post has other replies with mentions which are known`() {
216 val post = createPost()
217 val reply1 = emptyPostReply("sone://${localSone1.id}", post)
218 val reply2 = emptyPostReply("sone://${localSone1.id}", post, known = true)
219 postReplyProvider.postReplies[post.id] = listOf(reply1, reply2)
220 eventBus.post(NewPostReplyFoundEvent(reply1))
221 eventBus.post(PostReplyRemovedEvent(reply1))
222 assertThat(capturedRemovedEvents, contains(MentionOfLocalSoneRemovedEvent(post)))
227 private class TestSoneProvider : SoneProvider {
229 override val sones: Collection<Sone> get() = remoteSones + localSones
230 override val localSones: Collection<Sone> get() = setOf(localSone1, localSone2)
231 override val remoteSones: Collection<Sone> get() = setOf(remoteSone1, remoteSone2)
232 override val soneLoader: (String) -> Sone? get() = this::getSone
233 override fun getSone(soneId: String): Sone? =
234 localSones.firstOrNull { it.id == soneId } ?: remoteSones.firstOrNull { it.id == soneId }
238 private class TestPostProvider : PostProvider {
240 override fun getPost(postId: String): Post? = null
241 override fun getPosts(soneId: String): Collection<Post> = emptyList()
242 override fun getDirectedPosts(recipientId: String): Collection<Post> = emptyList()
246 private class TestPostReplyProvider : PostReplyProvider {
248 val replies = mutableMapOf<String, PostReply>()
249 val postReplies = mutableMapOf<String, List<PostReply>>()
251 override fun getPostReply(id: String) = replies[id]
252 override fun getReplies(postId: String) = postReplies[postId] ?: emptyList()