1 package net.pterodactylus.sone.core
3 import net.pterodactylus.sone.core.ConfigurationSoneParser.*
4 import net.pterodactylus.sone.data.*
5 import net.pterodactylus.sone.database.*
6 import net.pterodactylus.sone.test.*
7 import net.pterodactylus.sone.test.Matchers.*
8 import net.pterodactylus.util.config.*
9 import org.hamcrest.MatcherAssert.*
10 import org.hamcrest.Matchers.*
12 import org.junit.rules.*
13 import org.mockito.ArgumentMatchers.*
14 import org.mockito.ArgumentMatchers.eq
17 * Unit test for [ConfigurationSoneParser].
19 class ConfigurationSoneParserTest {
23 val expectedException = ExpectedException.none()!!
25 private val configuration = mock<Configuration>()
26 private val sone = mock<Sone>().apply {
27 whenever(this.id).thenReturn("1")
29 private val configurationSoneParser = ConfigurationSoneParser(configuration, sone)
32 fun emptyProfileIsLoadedCorrectly() {
34 val profile = configurationSoneParser.parseProfile()
35 assertThat(profile, notNullValue())
36 assertThat(profile.firstName, nullValue())
37 assertThat(profile.middleName, nullValue())
38 assertThat(profile.lastName, nullValue())
39 assertThat(profile.birthDay, nullValue())
40 assertThat(profile.birthMonth, nullValue())
41 assertThat(profile.birthYear, nullValue())
42 assertThat(profile.fields, emptyIterable())
45 private fun setupEmptyProfile() {
46 whenever(configuration.getStringValue(anyString())).thenReturn(TestValue.from(null))
47 whenever(configuration.getIntValue(anyString())).thenReturn(TestValue.from(null))
51 fun filledProfileWithFieldsIsParsedCorrectly() {
53 val profile = configurationSoneParser.parseProfile()
54 assertThat(profile, notNullValue())
55 assertThat(profile.firstName, equalTo("First"))
56 assertThat(profile.middleName, equalTo("M."))
57 assertThat(profile.lastName, equalTo("Last"))
58 assertThat(profile.birthDay, equalTo(18))
59 assertThat(profile.birthMonth, equalTo(12))
60 assertThat(profile.birthYear, equalTo(1976))
61 val fields = profile.fields
62 assertThat(fields, hasSize<Any>(2))
63 assertThat(fields[0].name, equalTo("Field1"))
64 assertThat(fields[0].value, equalTo("Value1"))
65 assertThat(fields[1].name, equalTo("Field2"))
66 assertThat(fields[1].value, equalTo("Value2"))
69 private fun setupFilledProfile() {
70 setupString("Sone/1/Profile/FirstName", "First")
71 setupString("Sone/1/Profile/MiddleName", "M.")
72 setupString("Sone/1/Profile/LastName", "Last")
73 setupInteger("Sone/1/Profile/BirthDay", 18)
74 setupInteger("Sone/1/Profile/BirthMonth", 12)
75 setupInteger("Sone/1/Profile/BirthYear", 1976)
76 setupString("Sone/1/Profile/Fields/0/Name", "Field1")
77 setupString("Sone/1/Profile/Fields/0/Value", "Value1")
78 setupString("Sone/1/Profile/Fields/1/Name", "Field2")
79 setupString("Sone/1/Profile/Fields/1/Value", "Value2")
80 setupString("Sone/1/Profile/Fields/2/Name")
83 private fun setupString(nodeName: String, value: String? = null) {
84 whenever(configuration.getStringValue(eq(nodeName))).thenReturn(TestValue.from(value))
87 private fun setupInteger(nodeName: String, value: Int?) {
88 whenever(configuration.getIntValue(eq(nodeName))).thenReturn(TestValue.from(value))
92 fun postsAreParsedCorrectly() {
94 val postBuilderFactory = createPostBuilderFactory()
95 val posts = configurationSoneParser.parsePosts(postBuilderFactory)
96 assertThat(posts, containsInAnyOrder(
97 isPost("P0", 1000L, "T0", null),
98 isPost("P1", 1001L, "T1", "1234567890123456789012345678901234567890123")
102 private fun createPostBuilderFactory(): PostBuilderFactory {
103 val postBuilderFactory = mock<PostBuilderFactory>()
104 whenever(postBuilderFactory.newPostBuilder()).thenAnswer { TestPostBuilder() }
105 return postBuilderFactory
108 private fun setupCompletePosts() {
109 setupPost("0", "P0", 1000L, "T0")
110 setupPost("1", "P1", 1001L, "T1", "1234567890123456789012345678901234567890123")
114 private fun setupPost(postNumber: String, postId: String? = null, time: Long = 0, text: String? = null, recipientId: String? = null) {
115 setupString("Sone/1/Posts/$postNumber/ID", postId)
116 setupLong("Sone/1/Posts/$postNumber/Time", time)
117 setupString("Sone/1/Posts/$postNumber/Text", text)
118 setupString("Sone/1/Posts/$postNumber/Recipient", recipientId)
121 private fun setupLong(nodeName: String, value: Long?) {
122 whenever(configuration.getLongValue(eq(nodeName))).thenReturn(TestValue.from(value))
126 fun postWithoutTimeIsRecognized() {
127 setupPostWithoutTime()
128 expectedException.expect<InvalidPostFound>()
129 configurationSoneParser.parsePosts(createPostBuilderFactory())
132 private fun setupPostWithoutTime() {
133 setupPost("0", "P0", 0L, "T0")
137 fun postWithoutTextIsRecognized() {
138 setupPostWithoutText()
139 expectedException.expect<InvalidPostFound>()
140 configurationSoneParser.parsePosts(createPostBuilderFactory())
143 private fun setupPostWithoutText() {
144 setupPost("0", "P0", 1000L)
148 fun postWithInvalidRecipientIdIsRecognized() {
149 setupPostWithInvalidRecipientId()
150 val posts = configurationSoneParser.parsePosts(createPostBuilderFactory())
151 assertThat(posts, contains(isPost("P0", 1000L, "T0", null)))
154 private fun setupPostWithInvalidRecipientId() {
155 setupPost("0", "P0", 1000L, "T0", "123")
160 fun postRepliesAreParsedCorrectly() {
162 val postReplyBuilderFactory = object : PostReplyBuilderFactory {
163 override fun newPostReplyBuilder(): PostReplyBuilder {
164 return TestPostReplyBuilder()
167 val postReplies = configurationSoneParser.parsePostReplies(postReplyBuilderFactory)
168 assertThat(postReplies, hasSize(2))
169 assertThat(postReplies, containsInAnyOrder(
170 isPostReply("R0", "P0", 1000L, "T0"),
171 isPostReply("R1", "P1", 1001L, "T1")
175 private fun setupPostReplies() {
176 setupPostReply("0", "R0", "P0", 1000L, "T0")
177 setupPostReply("1", "R1", "P1", 1001L, "T1")
181 private fun setupPostReply(postReplyNumber: String, postReplyId: String? = null, postId: String? = null, time: Long = 0, text: String? = null) {
182 setupString("Sone/1/Replies/$postReplyNumber/ID", postReplyId)
183 setupString("Sone/1/Replies/$postReplyNumber/Post/ID", postId)
184 setupLong("Sone/1/Replies/$postReplyNumber/Time", time)
185 setupString("Sone/1/Replies/$postReplyNumber/Text", text)
189 fun missingPostIdIsRecognized() {
190 setupPostReplyWithMissingPostId()
191 expectedException.expect<InvalidPostReplyFound>()
192 configurationSoneParser.parsePostReplies(null)
195 private fun setupPostReplyWithMissingPostId() {
196 setupPostReply("0", "R0", null, 1000L, "T0")
200 fun missingPostReplyTimeIsRecognized() {
201 setupPostReplyWithMissingPostReplyTime()
202 expectedException.expect<InvalidPostReplyFound>()
203 configurationSoneParser.parsePostReplies(null)
206 private fun setupPostReplyWithMissingPostReplyTime() {
207 setupPostReply("0", "R0", "P0", 0L, "T0")
211 fun missingPostReplyTextIsRecognized() {
212 setupPostReplyWithMissingPostReplyText()
213 expectedException.expect<InvalidPostReplyFound>()
214 configurationSoneParser.parsePostReplies(null)
217 private fun setupPostReplyWithMissingPostReplyText() {
218 setupPostReply("0", "R0", "P0", 1000L)
222 fun likedPostIdsParsedCorrectly() {
224 val likedPostIds = configurationSoneParser.parseLikedPostIds()
225 assertThat(likedPostIds, containsInAnyOrder("P1", "P2", "P3"))
228 private fun setupLikedPostIds() {
229 setupString("Sone/1/Likes/Post/0/ID", "P1")
230 setupString("Sone/1/Likes/Post/1/ID", "P2")
231 setupString("Sone/1/Likes/Post/2/ID", "P3")
232 setupString("Sone/1/Likes/Post/3/ID")
236 fun likedPostReplyIdsAreParsedCorrectly() {
237 setupLikedPostReplyIds()
238 val likedPostReplyIds = configurationSoneParser.parseLikedPostReplyIds()
239 assertThat(likedPostReplyIds, containsInAnyOrder("R1", "R2", "R3"))
242 private fun setupLikedPostReplyIds() {
243 setupString("Sone/1/Likes/Reply/0/ID", "R1")
244 setupString("Sone/1/Likes/Reply/1/ID", "R2")
245 setupString("Sone/1/Likes/Reply/2/ID", "R3")
246 setupString("Sone/1/Likes/Reply/3/ID")
250 fun friendsAreParsedCorrectly() {
252 val friends = configurationSoneParser.parseFriends()
253 assertThat(friends, containsInAnyOrder("F1", "F2", "F3"))
256 private fun setupFriends() {
257 setupString("Sone/1/Friends/0/ID", "F1")
258 setupString("Sone/1/Friends/1/ID", "F2")
259 setupString("Sone/1/Friends/2/ID", "F3")
260 setupString("Sone/1/Friends/3/ID")
264 fun topLevelAlbumsAreParsedCorrectly() {
265 setupTopLevelAlbums()
266 val albumBuilderFactory = createAlbumBuilderFactory()
267 val topLevelAlbums = configurationSoneParser.parseTopLevelAlbums(albumBuilderFactory)
268 assertThat(topLevelAlbums, hasSize<Any>(2))
269 val firstAlbum = topLevelAlbums[0]
270 assertThat(firstAlbum, isAlbum("A1", null, "T1", "D1"))
271 assertThat(firstAlbum.albums, emptyIterable<Any>())
272 assertThat<List<Image>>(firstAlbum.images, emptyIterable<Any>())
273 val secondAlbum = topLevelAlbums[1]
274 assertThat(secondAlbum, isAlbum("A2", null, "T2", "D2"))
275 assertThat(secondAlbum.albums, hasSize<Any>(1))
276 assertThat<List<Image>>(secondAlbum.images, emptyIterable<Any>())
277 val thirdAlbum = secondAlbum.albums[0]
278 assertThat(thirdAlbum, isAlbum("A3", "A2", "T3", "D3"))
279 assertThat(thirdAlbum.albums, emptyIterable<Any>())
280 assertThat<List<Image>>(thirdAlbum.images, emptyIterable<Any>())
283 private fun setupTopLevelAlbums() {
284 setupAlbum(0, "A1", null, "T1", "D1", "I1")
285 setupAlbum(1, "A2", null, "T2", "D2")
286 setupAlbum(2, "A3", "A2", "T3", "D3", "I3")
290 private fun setupAlbum(albumNumber: Int, albumId: String? = null, parentAlbumId: String? = null, title: String? = null, description: String? = null, imageId: String? =null) {
291 val albumPrefix = "Sone/1/Albums/$albumNumber"
292 setupString("$albumPrefix/ID", albumId)
293 setupString("$albumPrefix/Title", title)
294 setupString("$albumPrefix/Description", description)
295 setupString("$albumPrefix/Parent", parentAlbumId)
296 setupString("$albumPrefix/AlbumImage", imageId)
299 private fun createAlbumBuilderFactory(): AlbumBuilderFactory {
300 val albumBuilderFactory = mock<AlbumBuilderFactory>()
301 whenever(albumBuilderFactory.newAlbumBuilder()).thenAnswer { TestAlbumBuilder() }
302 return albumBuilderFactory
306 fun albumWithInvalidTitleIsRecognized() {
307 setupAlbum(0, "A1", null, null, "D1", "I1")
308 expectedException.expect<InvalidAlbumFound>()
309 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
313 fun albumWithInvalidDescriptionIsRecognized() {
314 setupAlbum(0, "A1", null, "T1", null, "I1")
315 expectedException.expect<InvalidAlbumFound>()
316 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
320 fun albumWithInvalidParentIsRecognized() {
321 setupAlbum(0, "A1", "A0", "T1", "D1", "I1")
322 expectedException.expect<InvalidParentAlbumFound>()
323 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
327 fun imagesAreParsedCorrectly() {
328 setupTopLevelAlbums()
329 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
331 configurationSoneParser.parseImages(createImageBuilderFactory())
332 val albums = configurationSoneParser.albums
333 assertThat<List<Image>>(albums["A1"]!!.images, contains<Image>(isImage("I1", 1000L, "K1", "T1", "D1", 16, 9)))
334 assertThat<List<Image>>(albums["A2"]!!.images, contains<Image>(isImage("I2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2)))
335 assertThat<List<Image>>(albums["A3"]!!.images, contains<Image>(isImage("I3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3)))
338 private fun setupImages() {
339 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, 9)
340 setupImage(1, "I2", "A2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2)
341 setupImage(2, "I3", "A3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3)
342 setupImage(3, null, null, 0L, null, null, null, 0, 0)
345 private fun setupImage(imageNumber: Int, id: String?, parentAlbumId: String?, creationTime: Long?, key: String?, title: String?, description: String?, width: Int?, height: Int?) {
346 val imagePrefix = "Sone/1/Images/$imageNumber"
347 setupString("$imagePrefix/ID", id)
348 setupString("$imagePrefix/Album", parentAlbumId)
349 setupLong("$imagePrefix/CreationTime", creationTime)
350 setupString("$imagePrefix/Key", key)
351 setupString("$imagePrefix/Title", title)
352 setupString("$imagePrefix/Description", description)
353 setupInteger("$imagePrefix/Width", width)
354 setupInteger("$imagePrefix/Height", height)
357 private fun createImageBuilderFactory(): ImageBuilderFactory {
358 val imageBuilderFactory = mock<ImageBuilderFactory>()
359 whenever(imageBuilderFactory.newImageBuilder()).thenAnswer { TestImageBuilder() }
360 return imageBuilderFactory
364 fun missingAlbumIdIsRecognized() {
365 setupTopLevelAlbums()
366 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
367 setupImage(0, "I1", null, 1000L, "K1", "T1", "D1", 16, 9)
368 expectedException.expect<InvalidImageFound>()
369 configurationSoneParser.parseImages(createImageBuilderFactory())
373 fun invalidAlbumIdIsRecognized() {
374 setupTopLevelAlbums()
375 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
376 setupImage(0, "I1", "A4", 1000L, "K1", "T1", "D1", 16, 9)
377 expectedException.expect<InvalidParentAlbumFound>()
378 configurationSoneParser.parseImages(createImageBuilderFactory())
382 fun missingCreationTimeIsRecognized() {
383 setupTopLevelAlbums()
384 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
385 setupImage(0, "I1", "A1", null, "K1", "T1", "D1", 16, 9)
386 expectedException.expect<InvalidImageFound>()
387 configurationSoneParser.parseImages(createImageBuilderFactory())
391 fun missingKeyIsRecognized() {
392 setupTopLevelAlbums()
393 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
394 setupImage(0, "I1", "A1", 1000L, null, "T1", "D1", 16, 9)
395 expectedException.expect<InvalidImageFound>()
396 configurationSoneParser.parseImages(createImageBuilderFactory())
400 fun missingTitleIsRecognized() {
401 setupTopLevelAlbums()
402 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
403 setupImage(0, "I1", "A1", 1000L, "K1", null, "D1", 16, 9)
404 expectedException.expect<InvalidImageFound>()
405 configurationSoneParser.parseImages(createImageBuilderFactory())
409 fun missingDescriptionIsRecognized() {
410 setupTopLevelAlbums()
411 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
412 setupImage(0, "I1", "A1", 1000L, "K1", "T1", null, 16, 9)
413 expectedException.expect<InvalidImageFound>()
414 configurationSoneParser.parseImages(createImageBuilderFactory())
418 fun missingWidthIsRecognized() {
419 setupTopLevelAlbums()
420 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
421 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", null, 9)
422 expectedException.expect<InvalidImageFound>()
423 configurationSoneParser.parseImages(createImageBuilderFactory())
427 fun missingHeightIsRecognized() {
428 setupTopLevelAlbums()
429 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
430 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, null)
431 expectedException.expect<InvalidImageFound>()
432 configurationSoneParser.parseImages(createImageBuilderFactory())