1 package net.pterodactylus.sone.core
3 import com.google.common.base.Optional.*
5 import freenet.keys.InsertableClientSSK.*
6 import net.pterodactylus.sone.data.*
7 import net.pterodactylus.sone.database.memory.*
8 import net.pterodactylus.sone.freenet.wot.*
9 import net.pterodactylus.sone.test.*
10 import net.pterodactylus.util.config.*
11 import org.hamcrest.MatcherAssert.*
12 import org.hamcrest.Matchers.*
13 import org.mockito.Mockito.*
14 import java.lang.System.*
15 import java.util.concurrent.TimeUnit.*
19 * Unit test for [SoneParser].
21 class SoneParserTest {
23 private val database = MemoryDatabase(Configuration(MapConfigurationBackend()))
24 private val soneParser = SoneParser(database)
25 private val sone = mock<Sone>()
29 setupSone(this.sone, Identity::class.java)
30 database.storeSone(sone)
33 private fun setupSone(sone: Sone, identityClass: Class<out Identity>) {
34 val identity = mock(identityClass)
35 val clientSSK = createRandom(DummyRandomSource(), "WoT")
36 whenever(identity.requestUri).thenReturn(clientSSK.uri.toString())
37 whenever(identity.id).thenReturn("identity")
38 whenever(sone.id).thenReturn("identity")
39 whenever(sone.identity).thenReturn(identity)
40 whenever(sone.requestUri).thenAnswer { clientSSK.uri.setKeyType("USK").setDocName("Sone") }
41 whenever(sone.time).thenReturn(currentTimeMillis() - DAYS.toMillis(1))
45 fun `parsing a sone fails when document is not xml`() {
46 val inputStream = javaClass.getResourceAsStream("sone-parser-not-xml.xml")
47 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
51 fun `parsing a sone fails when document has negative protocol version`() {
52 val inputStream = javaClass.getResourceAsStream("sone-parser-negative-protocol-version.xml")
53 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
57 fun `parsing a sone fails when protocol version is too large`() {
58 val inputStream = javaClass.getResourceAsStream("sone-parser-too-large-protocol-version.xml")
59 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
63 fun `parsing a sone fails when there is no time`() {
64 val inputStream = javaClass.getResourceAsStream("sone-parser-no-time.xml")
65 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
69 fun `parsing a sone fails when time is not numeric`() {
70 val inputStream = javaClass.getResourceAsStream("sone-parser-time-not-numeric.xml")
71 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
75 fun `parsing a sone fails when profile is missing`() {
76 val inputStream = javaClass.getResourceAsStream("sone-parser-no-profile.xml")
77 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
81 fun `parsing a sone fails when profile field is missing afield name`() {
82 val inputStream = javaClass.getResourceAsStream("sone-parser-profile-missing-field-name.xml")
83 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
87 fun `parsing a sone fails when profile field name is empty`() {
88 val inputStream = javaClass.getResourceAsStream("sone-parser-profile-empty-field-name.xml")
89 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
93 fun `parsing a sone fails when profile field name is not unique`() {
94 val inputStream = javaClass.getResourceAsStream("sone-parser-profile-duplicate-field-name.xml")
95 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
99 fun `parsing a sone succeeds without payload`() {
100 val inputStream = javaClass.getResourceAsStream("sone-parser-no-payload.xml")
101 assertThat(soneParser.parseSone(sone, inputStream)!!.time, equalTo(1407197508000L))
105 fun `parsing a local sone succeeds without payload`() {
106 val inputStream = javaClass.getResourceAsStream("sone-parser-no-payload.xml")
107 val localSone = mock<Sone>()
108 setupSone(localSone, OwnIdentity::class.java)
109 whenever(localSone.isLocal).thenReturn(true)
110 val parsedSone = soneParser.parseSone(localSone, inputStream)
111 assertThat(parsedSone!!.time, equalTo(1407197508000L))
112 assertThat(parsedSone.isLocal, equalTo(true))
116 fun `parsing a sone succeeds without protocol version`() {
117 val inputStream = javaClass.getResourceAsStream("sone-parser-missing-protocol-version.xml")
118 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
122 fun `parsing a sone fails with missing client name`() {
123 val inputStream = javaClass.getResourceAsStream("sone-parser-missing-client-name.xml")
124 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
128 fun `parsing a sone fails with missing client version`() {
129 val inputStream = javaClass.getResourceAsStream("sone-parser-missing-client-version.xml")
130 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
134 fun `parsing a sone succeeds with client info`() {
135 val inputStream = javaClass.getResourceAsStream("sone-parser-with-client-info.xml")
136 assertThat(soneParser.parseSone(sone, inputStream)!!.client, equalTo(Client("some-client", "some-version")))
140 fun `parsing a sone succeeds with profile`() {
141 val inputStream = javaClass.getResourceAsStream("sone-parser-with-profile.xml")
142 val profile = soneParser.parseSone(sone, inputStream)!!.profile
143 assertThat(profile.firstName, equalTo("first"))
144 assertThat(profile.middleName, equalTo("middle"))
145 assertThat(profile.lastName, equalTo("last"))
146 assertThat(profile.birthDay, equalTo(18))
147 assertThat(profile.birthMonth, equalTo(12))
148 assertThat(profile.birthYear, equalTo(1976))
152 fun `parsing a sone succeeds without profile fields`() {
153 val inputStream = javaClass.getResourceAsStream("sone-parser-without-fields.xml")
154 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
158 fun `parsing a sone fails without post id`() {
159 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-id.xml")
160 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
164 fun `parsing a sone fails without post time`() {
165 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-time.xml")
166 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
170 fun `parsing a sone fails without post text`() {
171 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-text.xml")
172 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
176 fun `parsing a sone fails with invalid post time`() {
177 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-post-time.xml")
178 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
182 fun `parsing a sone succeeds with valid post time`() {
183 val inputStream = javaClass.getResourceAsStream("sone-parser-with-valid-post-time.xml")
184 val posts = soneParser.parseSone(sone, inputStream)!!.posts
185 assertThat(posts, hasSize(1))
186 assertThat(posts[0].sone.id, equalTo(sone.id))
187 assertThat(posts[0].id, equalTo("3de12680-afef-11e9-a124-e713cf8912fe"))
188 assertThat(posts[0].time, equalTo(1407197508000L))
189 assertThat(posts[0].recipientId, equalTo(absent()))
190 assertThat(posts[0].text, equalTo("text"))
194 fun `parsing a sone succeeds with recipient`() {
195 val inputStream = javaClass.getResourceAsStream("sone-parser-with-recipient.xml")
196 val posts = soneParser.parseSone(sone, inputStream)!!.posts
197 assertThat(posts, hasSize(1))
198 assertThat(posts[0].sone.id, equalTo(sone.id))
199 assertThat(posts[0].id, equalTo("3de12680-afef-11e9-a124-e713cf8912fe"))
200 assertThat(posts[0].time, equalTo(1407197508000L))
201 assertThat(posts[0].recipientId, equalTo(of("1234567890123456789012345678901234567890123")))
202 assertThat(posts[0].text, equalTo("text"))
206 fun `parsing a sone succeeds with invalid recipient`() {
207 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-recipient.xml")
208 val posts = soneParser.parseSone(sone, inputStream)!!.posts
209 assertThat(posts, hasSize(1))
210 assertThat(posts[0].sone.id, equalTo(sone.id))
211 assertThat(posts[0].id, equalTo("3de12680-afef-11e9-a124-e713cf8912fe"))
212 assertThat(posts[0].time, equalTo(1407197508000L))
213 assertThat(posts[0].recipientId, equalTo(absent()))
214 assertThat(posts[0].text, equalTo("text"))
218 fun `parsing a sone fails without post reply id`() {
219 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-reply-id.xml")
220 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
224 fun `parsing a sone fails without post reply post id`() {
225 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-reply-post-id.xml")
226 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
230 fun `parsing a sone fails without post reply time`() {
231 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-reply-time.xml")
232 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
236 fun `parsing a sone fails without post reply text`() {
237 val inputStream = javaClass.getResourceAsStream("sone-parser-without-post-reply-text.xml")
238 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
242 fun `parsing a sone fails with invalid post reply time`() {
243 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-post-reply-time.xml")
244 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
248 fun `parsing a sone succeeds with valid post reply time`() {
249 val inputStream = javaClass.getResourceAsStream("sone-parser-with-valid-post-reply-time.xml")
250 val postReplies = soneParser.parseSone(sone, inputStream)!!.replies
251 assertThat(postReplies, hasSize(1))
252 val postReply = postReplies.first()
253 assertThat(postReply.id, equalTo("5ccba7f4-aff0-11e9-b176-a7b9db60ce98"))
254 assertThat(postReply.postId, equalTo("3de12680-afef-11e9-a124-e713cf8912fe"))
255 assertThat(postReply.sone.id, equalTo("identity"))
256 assertThat(postReply.time, equalTo(1407197508000L))
257 assertThat(postReply.text, equalTo("reply-text"))
261 fun `parsing a sone succeeds without liked post ids`() {
262 val inputStream = javaClass.getResourceAsStream("sone-parser-without-liked-post-ids.xml")
263 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
267 fun `parsing a sone succeeds with liked post ids`() {
268 val inputStream = javaClass.getResourceAsStream("sone-parser-with-liked-post-ids.xml")
269 assertThat(soneParser.parseSone(sone, inputStream)!!.likedPostIds, equalTo(setOf("liked-post-id")))
273 fun `parsing a sone succeeds without liked post reply ids`() {
274 val inputStream = javaClass.getResourceAsStream("sone-parser-without-liked-post-reply-ids.xml")
275 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
279 fun `parsing a sone succeeds with liked post reply ids`() {
280 val inputStream = javaClass.getResourceAsStream("sone-parser-with-liked-post-reply-ids.xml")
281 assertThat(soneParser.parseSone(sone, inputStream)!!.likedReplyIds, equalTo(setOf("liked-post-reply-id")))
285 fun `parsing a sone succeeds without albums`() {
286 val inputStream = javaClass.getResourceAsStream("sone-parser-without-albums.xml")
287 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
291 fun `parsing a sone fails without album id`() {
292 val inputStream = javaClass.getResourceAsStream("sone-parser-without-album-id.xml")
293 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
297 fun `parsing a sone fails without album title`() {
298 val inputStream = javaClass.getResourceAsStream("sone-parser-without-album-title.xml")
299 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
303 fun `parsing a sone succeeds with nested albums`() {
304 val inputStream = javaClass.getResourceAsStream("sone-parser-with-multiple-albums.xml")
305 val parsedSone = soneParser.parseSone(sone, inputStream)
306 assertThat(parsedSone, notNullValue())
307 assertThat(parsedSone!!.rootAlbum.albums, hasSize(1))
308 val album = parsedSone.rootAlbum.albums[0]
309 assertThat(album.id, equalTo("album-id-1"))
310 assertThat(album.title, equalTo("album-title"))
311 assertThat(album.description, equalTo("album-description"))
312 assertThat(album.albums, hasSize(1))
313 val nestedAlbum = album.albums[0]
314 assertThat(nestedAlbum.id, equalTo("album-id-2"))
315 assertThat(nestedAlbum.title, equalTo("album-title-2"))
316 assertThat(nestedAlbum.description, equalTo("album-description-2"))
317 assertThat(nestedAlbum.albums, hasSize(0))
321 fun `parsing a sone fails with invalid parent album id`() {
322 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-parent-album-id.xml")
323 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
327 fun `parsing a sone succeeds without images`() {
328 val inputStream = javaClass.getResourceAsStream("sone-parser-without-images.xml")
329 assertThat(soneParser.parseSone(sone, inputStream), notNullValue())
333 fun `parsing a sone fails without image id`() {
334 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-id.xml")
335 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
339 fun `parsing a sone fails without image time`() {
340 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-time.xml")
341 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
345 fun `parsing a sone fails without image key`() {
346 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-key.xml")
347 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
351 fun `parsing a sone fails without image title`() {
352 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-title.xml")
353 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
357 fun `parsing a sone fails without image width`() {
358 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-width.xml")
359 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
363 fun `parsing a sone fails without image height`() {
364 val inputStream = javaClass.getResourceAsStream("sone-parser-without-image-height.xml")
365 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
369 fun `parsing a sone fails with invalid image width`() {
370 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-image-width.xml")
371 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
375 fun `parsing a sone fails with invalid image height`() {
376 val inputStream = javaClass.getResourceAsStream("sone-parser-with-invalid-image-height.xml")
377 assertThat(soneParser.parseSone(sone, inputStream), nullValue())
381 fun `parsing a sone succeeds with image`() {
382 val inputStream = javaClass.getResourceAsStream("sone-parser-with-image.xml")
383 val sone = soneParser.parseSone(this.sone, inputStream)
384 assertThat(sone, notNullValue())
385 assertThat(sone!!.rootAlbum.albums, hasSize(1))
386 assertThat(sone.rootAlbum.albums[0].images, hasSize(1))
387 val image = sone.rootAlbum.albums[0].images[0]
388 assertThat(image.id, equalTo("image-id"))
389 assertThat(image.creationTime, equalTo(1407197508000L))
390 assertThat(image.key, equalTo("KSK@GPLv3.txt"))
391 assertThat(image.title, equalTo("image-title"))
392 assertThat(image.description, equalTo("image-description"))
393 assertThat(image.width, equalTo(1920))
394 assertThat(image.height, equalTo(1080))
395 assertThat(sone.profile.avatar, equalTo("image-id"))