🔥 Remove unnecessary imports
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / core / ConfigurationSoneParserTest.kt
1 package net.pterodactylus.sone.core
2
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.*
11 import org.junit.*
12 import org.junit.rules.*
13 import org.mockito.ArgumentMatchers.*
14 import org.mockito.ArgumentMatchers.eq
15
16 /**
17  * Unit test for [ConfigurationSoneParser].
18  */
19 class ConfigurationSoneParserTest {
20
21         @Rule
22         @JvmField
23         val expectedException = ExpectedException.none()!!
24
25         private val configuration = mock<Configuration>()
26         private val sone = mock<Sone>().apply {
27                 whenever(this.id).thenReturn("1")
28         }
29         private val configurationSoneParser = ConfigurationSoneParser(configuration, sone)
30
31         @Test
32         fun emptyProfileIsLoadedCorrectly() {
33                 setupEmptyProfile()
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())
43         }
44
45         private fun setupEmptyProfile() {
46                 whenever(configuration.getStringValue(anyString())).thenReturn(TestValue.from(null))
47                 whenever(configuration.getIntValue(anyString())).thenReturn(TestValue.from(null))
48         }
49
50         @Test
51         fun filledProfileWithFieldsIsParsedCorrectly() {
52                 setupFilledProfile()
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"))
67         }
68
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")
81         }
82
83         private fun setupString(nodeName: String, value: String? = null) {
84                 whenever(configuration.getStringValue(eq(nodeName))).thenReturn(TestValue.from(value))
85         }
86
87         private fun setupInteger(nodeName: String, value: Int?) {
88                 whenever(configuration.getIntValue(eq(nodeName))).thenReturn(TestValue.from(value))
89         }
90
91         @Test
92         fun postsAreParsedCorrectly() {
93                 setupCompletePosts()
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")
99                 ))
100         }
101
102         private fun createPostBuilderFactory(): PostBuilderFactory {
103                 val postBuilderFactory = mock<PostBuilderFactory>()
104                 whenever(postBuilderFactory.newPostBuilder()).thenAnswer { TestPostBuilder() }
105                 return postBuilderFactory
106         }
107
108         private fun setupCompletePosts() {
109                 setupPost("0", "P0", 1000L, "T0")
110                 setupPost("1", "P1", 1001L, "T1", "1234567890123456789012345678901234567890123")
111                 setupPost("2")
112         }
113
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)
119         }
120
121         private fun setupLong(nodeName: String, value: Long?) {
122                 whenever(configuration.getLongValue(eq(nodeName))).thenReturn(TestValue.from(value))
123         }
124
125         @Test
126         fun postWithoutTimeIsRecognized() {
127                 setupPostWithoutTime()
128                 expectedException.expect<InvalidPostFound>()
129                 configurationSoneParser.parsePosts(createPostBuilderFactory())
130         }
131
132         private fun setupPostWithoutTime() {
133                 setupPost("0", "P0", 0L, "T0")
134         }
135
136         @Test
137         fun postWithoutTextIsRecognized() {
138                 setupPostWithoutText()
139                 expectedException.expect<InvalidPostFound>()
140                 configurationSoneParser.parsePosts(createPostBuilderFactory())
141         }
142
143         private fun setupPostWithoutText() {
144                 setupPost("0", "P0", 1000L)
145         }
146
147         @Test
148         fun postWithInvalidRecipientIdIsRecognized() {
149                 setupPostWithInvalidRecipientId()
150                 val posts = configurationSoneParser.parsePosts(createPostBuilderFactory())
151                 assertThat(posts, contains(isPost("P0", 1000L, "T0", null)))
152         }
153
154         private fun setupPostWithInvalidRecipientId() {
155                 setupPost("0", "P0", 1000L, "T0", "123")
156                 setupPost("1")
157         }
158
159         @Test
160         fun postRepliesAreParsedCorrectly() {
161                 setupPostReplies()
162                 val postReplyBuilderFactory = object : PostReplyBuilderFactory {
163                         override fun newPostReplyBuilder(): PostReplyBuilder {
164                                 return TestPostReplyBuilder()
165                         }
166                 }
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")
172                 ))
173         }
174
175         private fun setupPostReplies() {
176                 setupPostReply("0", "R0", "P0", 1000L, "T0")
177                 setupPostReply("1", "R1", "P1", 1001L, "T1")
178                 setupPostReply("2")
179         }
180
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)
186         }
187
188         @Test
189         fun missingPostIdIsRecognized() {
190                 setupPostReplyWithMissingPostId()
191                 expectedException.expect<InvalidPostReplyFound>()
192                 configurationSoneParser.parsePostReplies(null)
193         }
194
195         private fun setupPostReplyWithMissingPostId() {
196                 setupPostReply("0", "R0", null, 1000L, "T0")
197         }
198
199         @Test
200         fun missingPostReplyTimeIsRecognized() {
201                 setupPostReplyWithMissingPostReplyTime()
202                 expectedException.expect<InvalidPostReplyFound>()
203                 configurationSoneParser.parsePostReplies(null)
204         }
205
206         private fun setupPostReplyWithMissingPostReplyTime() {
207                 setupPostReply("0", "R0", "P0", 0L, "T0")
208         }
209
210         @Test
211         fun missingPostReplyTextIsRecognized() {
212                 setupPostReplyWithMissingPostReplyText()
213                 expectedException.expect<InvalidPostReplyFound>()
214                 configurationSoneParser.parsePostReplies(null)
215         }
216
217         private fun setupPostReplyWithMissingPostReplyText() {
218                 setupPostReply("0", "R0", "P0", 1000L)
219         }
220
221         @Test
222         fun likedPostIdsParsedCorrectly() {
223                 setupLikedPostIds()
224                 val likedPostIds = configurationSoneParser.parseLikedPostIds()
225                 assertThat(likedPostIds, containsInAnyOrder("P1", "P2", "P3"))
226         }
227
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")
233         }
234
235         @Test
236         fun likedPostReplyIdsAreParsedCorrectly() {
237                 setupLikedPostReplyIds()
238                 val likedPostReplyIds = configurationSoneParser.parseLikedPostReplyIds()
239                 assertThat(likedPostReplyIds, containsInAnyOrder("R1", "R2", "R3"))
240         }
241
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")
247         }
248
249         @Test
250         fun friendsAreParsedCorrectly() {
251                 setupFriends()
252                 val friends = configurationSoneParser.parseFriends()
253                 assertThat(friends, containsInAnyOrder("F1", "F2", "F3"))
254         }
255
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")
261         }
262
263         @Test
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>())
281         }
282
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")
287                 setupAlbum(3)
288         }
289
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)
297         }
298
299         private fun createAlbumBuilderFactory(): AlbumBuilderFactory {
300                 val albumBuilderFactory = mock<AlbumBuilderFactory>()
301                 whenever(albumBuilderFactory.newAlbumBuilder()).thenAnswer { TestAlbumBuilder() }
302                 return albumBuilderFactory
303         }
304
305         @Test
306         fun albumWithInvalidTitleIsRecognized() {
307                 setupAlbum(0, "A1", null, null, "D1", "I1")
308                 expectedException.expect<InvalidAlbumFound>()
309                 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
310         }
311
312         @Test
313         fun albumWithInvalidDescriptionIsRecognized() {
314                 setupAlbum(0, "A1", null, "T1", null, "I1")
315                 expectedException.expect<InvalidAlbumFound>()
316                 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
317         }
318
319         @Test
320         fun albumWithInvalidParentIsRecognized() {
321                 setupAlbum(0, "A1", "A0", "T1", "D1", "I1")
322                 expectedException.expect<InvalidParentAlbumFound>()
323                 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
324         }
325
326         @Test
327         fun imagesAreParsedCorrectly() {
328                 setupTopLevelAlbums()
329                 configurationSoneParser.parseTopLevelAlbums(createAlbumBuilderFactory())
330                 setupImages()
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)))
336         }
337
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)
343         }
344
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)
355         }
356
357         private fun createImageBuilderFactory(): ImageBuilderFactory {
358                 val imageBuilderFactory = mock<ImageBuilderFactory>()
359                 whenever(imageBuilderFactory.newImageBuilder()).thenAnswer { TestImageBuilder() }
360                 return imageBuilderFactory
361         }
362
363         @Test
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())
370         }
371
372         @Test
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())
379         }
380
381         @Test
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())
388         }
389
390         @Test
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())
397         }
398
399         @Test
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())
406         }
407
408         @Test
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())
415         }
416
417         @Test
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())
424         }
425
426         @Test
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())
433         }
434
435 }