1 package net.pterodactylus.sone.core;
3 import static com.google.common.base.Optional.of;
4 import static net.pterodactylus.sone.Matchers.isAlbum;
5 import static net.pterodactylus.sone.Matchers.isImage;
6 import static net.pterodactylus.sone.Matchers.isPost;
7 import static net.pterodactylus.sone.Matchers.isPostReply;
8 import static org.hamcrest.MatcherAssert.assertThat;
9 import static org.hamcrest.Matchers.contains;
10 import static org.hamcrest.Matchers.containsInAnyOrder;
11 import static org.hamcrest.Matchers.emptyIterable;
12 import static org.hamcrest.Matchers.hasSize;
13 import static org.hamcrest.Matchers.is;
14 import static org.hamcrest.Matchers.notNullValue;
15 import static org.hamcrest.Matchers.nullValue;
16 import static org.mockito.ArgumentMatchers.anyString;
17 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.when;
21 import java.util.Collection;
22 import java.util.List;
26 import net.pterodactylus.sone.TestAlbumBuilder;
27 import net.pterodactylus.sone.TestImageBuilder;
28 import net.pterodactylus.sone.TestPostBuilder;
29 import net.pterodactylus.sone.TestPostReplyBuilder;
30 import net.pterodactylus.sone.TestValue;
31 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
32 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
33 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
34 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
35 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
36 import net.pterodactylus.sone.data.Album;
37 import net.pterodactylus.sone.data.Post;
38 import net.pterodactylus.sone.data.PostReply;
39 import net.pterodactylus.sone.data.Profile;
40 import net.pterodactylus.sone.data.Profile.Field;
41 import net.pterodactylus.sone.data.Sone;
42 import net.pterodactylus.sone.database.AlbumBuilder;
43 import net.pterodactylus.sone.database.AlbumBuilderFactory;
44 import net.pterodactylus.sone.database.ImageBuilder;
45 import net.pterodactylus.sone.database.ImageBuilderFactory;
46 import net.pterodactylus.sone.database.PostBuilder;
47 import net.pterodactylus.sone.database.PostBuilderFactory;
48 import net.pterodactylus.sone.database.PostReplyBuilder;
49 import net.pterodactylus.sone.database.PostReplyBuilderFactory;
50 import net.pterodactylus.util.config.Configuration;
52 import com.google.common.base.Optional;
53 import org.hamcrest.Matchers;
54 import org.junit.Test;
55 import org.mockito.invocation.InvocationOnMock;
56 import org.mockito.stubbing.Answer;
59 * Unit test for {@link ConfigurationSoneParser}.
61 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
63 public class ConfigurationSoneParserTest {
65 private final Configuration configuration = mock(Configuration.class);
66 private final Sone sone = mock(Sone.class);
67 private final ConfigurationSoneParser configurationSoneParser;
69 public ConfigurationSoneParserTest() {
70 when(sone.getId()).thenReturn("1");
71 configurationSoneParser =
72 new ConfigurationSoneParser(configuration, sone);
76 public void emptyProfileIsLoadedCorrectly() {
78 Profile profile = configurationSoneParser.parseProfile();
79 assertThat(profile, notNullValue());
80 assertThat(profile.getFirstName(), nullValue());
81 assertThat(profile.getMiddleName(), nullValue());
82 assertThat(profile.getLastName(), nullValue());
83 assertThat(profile.getBirthDay(), nullValue());
84 assertThat(profile.getBirthMonth(), nullValue());
85 assertThat(profile.getBirthYear(), nullValue());
86 assertThat(profile.getFields(), emptyIterable());
89 private void setupEmptyProfile() {
90 when(configuration.getStringValue(anyString())).thenReturn(
91 TestValue.<String>from(null));
92 when(configuration.getIntValue(anyString())).thenReturn(
93 TestValue.<Integer>from(null));
97 public void filledProfileWithFieldsIsParsedCorrectly() {
99 Profile profile = configurationSoneParser.parseProfile();
100 assertThat(profile, notNullValue());
101 assertThat(profile.getFirstName(), is("First"));
102 assertThat(profile.getMiddleName(), is("M."));
103 assertThat(profile.getLastName(), is("Last"));
104 assertThat(profile.getBirthDay(), is(18));
105 assertThat(profile.getBirthMonth(), is(12));
106 assertThat(profile.getBirthYear(), is(1976));
107 final List<Field> fields = profile.getFields();
108 assertThat(fields, hasSize(2));
109 assertThat(fields.get(0).getName(), is("Field1"));
110 assertThat(fields.get(0).getValue(), is("Value1"));
111 assertThat(fields.get(1).getName(), is("Field2"));
112 assertThat(fields.get(1).getValue(), is("Value2"));
115 private void setupFilledProfile() {
116 setupString("Sone/1/Profile/FirstName", "First");
117 setupString("Sone/1/Profile/MiddleName", "M.");
118 setupString("Sone/1/Profile/LastName", "Last");
119 setupInteger("Sone/1/Profile/BirthDay", 18);
120 setupInteger("Sone/1/Profile/BirthMonth", 12);
121 setupInteger("Sone/1/Profile/BirthYear", 1976);
122 setupString("Sone/1/Profile/Fields/0/Name", "Field1");
123 setupString("Sone/1/Profile/Fields/0/Value", "Value1");
124 setupString("Sone/1/Profile/Fields/1/Name", "Field2");
125 setupString("Sone/1/Profile/Fields/1/Value", "Value2");
126 setupString("Sone/1/Profile/Fields/2/Name", null);
129 private void setupString(String nodeName, String value) {
130 when(configuration.getStringValue(eq(nodeName))).thenReturn(
131 TestValue.from(value));
134 private void setupInteger(String nodeName, Integer value) {
135 when(configuration.getIntValue(eq(nodeName))).thenReturn(
136 TestValue.from(value));
140 public void postsAreParsedCorrectly() {
141 setupCompletePosts();
142 PostBuilderFactory postBuilderFactory = createPostBuilderFactory();
143 Collection<Post> posts =
144 configurationSoneParser.parsePosts(postBuilderFactory);
146 Matchers.<Post>containsInAnyOrder(
147 isPost("P0", 1000L, "T0", Optional.<String>absent()),
148 isPost("P1", 1001L, "T1",
149 of("1234567890123456789012345678901234567890123"))));
152 private PostBuilderFactory createPostBuilderFactory() {
153 PostBuilderFactory postBuilderFactory =
154 mock(PostBuilderFactory.class);
155 when(postBuilderFactory.newPostBuilder()).thenAnswer(
156 new Answer<PostBuilder>() {
158 public PostBuilder answer(InvocationOnMock invocation)
160 return new TestPostBuilder();
163 return postBuilderFactory;
166 private void setupCompletePosts() {
167 setupPost("0", "P0", 1000L, "T0", null);
168 setupPost("1", "P1", 1001L, "T1",
169 "1234567890123456789012345678901234567890123");
170 setupPost("2", null, 0L, null, null);
173 private void setupPost(String postNumber, String postId, long time,
174 String text, String recipientId) {
175 setupString("Sone/1/Posts/" + postNumber + "/ID", postId);
176 setupLong("Sone/1/Posts/" + postNumber + "/Time", time);
177 setupString("Sone/1/Posts/" + postNumber + "/Text", text);
178 setupString("Sone/1/Posts/" + postNumber + "/Recipient", recipientId);
181 private void setupLong(String nodeName, Long value) {
182 when(configuration.getLongValue(eq(nodeName))).thenReturn(
183 TestValue.from(value));
186 @Test(expected = InvalidPostFound.class)
187 public void postWithoutTimeIsRecognized() {
188 setupPostWithoutTime();
189 configurationSoneParser.parsePosts(createPostBuilderFactory());
192 private void setupPostWithoutTime() {
193 setupPost("0", "P0", 0L, "T0", null);
196 @Test(expected = InvalidPostFound.class)
197 public void postWithoutTextIsRecognized() {
198 setupPostWithoutText();
199 configurationSoneParser.parsePosts(createPostBuilderFactory());
202 private void setupPostWithoutText() {
203 setupPost("0", "P0", 1000L, null, null);
207 public void postWithInvalidRecipientIdIsRecognized() {
208 setupPostWithInvalidRecipientId();
209 Collection<Post> posts = configurationSoneParser.parsePosts(
210 createPostBuilderFactory());
211 assertThat(posts, contains(
212 isPost("P0", 1000L, "T0", Optional.<String>absent())));
215 private void setupPostWithInvalidRecipientId() {
216 setupPost("0", "P0", 1000L, "T0", "123");
217 setupPost("1", null, 0L, null, null);
221 public void postRepliesAreParsedCorrectly() {
223 PostReplyBuilderFactory postReplyBuilderFactory =
224 new PostReplyBuilderFactory() {
226 public PostReplyBuilder newPostReplyBuilder() {
227 return new TestPostReplyBuilder();
230 Collection<PostReply> postReplies =
231 configurationSoneParser.parsePostReplies(
232 postReplyBuilderFactory);
233 assertThat(postReplies, hasSize(2));
234 assertThat(postReplies,
235 containsInAnyOrder(isPostReply("R0", "P0", 1000L, "T0"),
236 isPostReply("R1", "P1", 1001L, "T1")));
239 private void setupPostReplies() {
240 setupPostReply("0", "R0", "P0", 1000L, "T0");
241 setupPostReply("1", "R1", "P1", 1001L, "T1");
242 setupPostReply("2", null, null, 0L, null);
245 private void setupPostReply(String postReplyNumber, String postReplyId,
246 String postId, long time, String text) {
247 setupString("Sone/1/Replies/" + postReplyNumber + "/ID", postReplyId);
248 setupString("Sone/1/Replies/" + postReplyNumber + "/Post/ID", postId);
249 setupLong("Sone/1/Replies/" + postReplyNumber + "/Time", time);
250 setupString("Sone/1/Replies/" + postReplyNumber + "/Text", text);
253 @Test(expected = InvalidPostReplyFound.class)
254 public void missingPostIdIsRecognized() {
255 setupPostReplyWithMissingPostId();
256 configurationSoneParser.parsePostReplies(null);
259 private void setupPostReplyWithMissingPostId() {
260 setupPostReply("0", "R0", null, 1000L, "T0");
263 @Test(expected = InvalidPostReplyFound.class)
264 public void missingPostReplyTimeIsRecognized() {
265 setupPostReplyWithMissingPostReplyTime();
266 configurationSoneParser.parsePostReplies(null);
269 private void setupPostReplyWithMissingPostReplyTime() {
270 setupPostReply("0", "R0", "P0", 0L, "T0");
273 @Test(expected = InvalidPostReplyFound.class)
274 public void missingPostReplyTextIsRecognized() {
275 setupPostReplyWithMissingPostReplyText();
276 configurationSoneParser.parsePostReplies(null);
279 private void setupPostReplyWithMissingPostReplyText() {
280 setupPostReply("0", "R0", "P0", 1000L, null);
284 public void likedPostIdsParsedCorrectly() {
286 Set<String> likedPostIds =
287 configurationSoneParser.parseLikedPostIds();
288 assertThat(likedPostIds, containsInAnyOrder("P1", "P2", "P3"));
291 private void setupLikedPostIds() {
292 setupString("Sone/1/Likes/Post/0/ID", "P1");
293 setupString("Sone/1/Likes/Post/1/ID", "P2");
294 setupString("Sone/1/Likes/Post/2/ID", "P3");
295 setupString("Sone/1/Likes/Post/3/ID", null);
299 public void likedPostReplyIdsAreParsedCorrectly() {
300 setupLikedPostReplyIds();
301 Set<String> likedPostReplyIds =
302 configurationSoneParser.parseLikedPostReplyIds();
303 assertThat(likedPostReplyIds, containsInAnyOrder("R1", "R2", "R3"));
306 private void setupLikedPostReplyIds() {
307 setupString("Sone/1/Likes/Reply/0/ID", "R1");
308 setupString("Sone/1/Likes/Reply/1/ID", "R2");
309 setupString("Sone/1/Likes/Reply/2/ID", "R3");
310 setupString("Sone/1/Likes/Reply/3/ID", null);
314 public void friendsAreParsedCorrectly() {
316 Set<String> friends = configurationSoneParser.parseFriends();
317 assertThat(friends, containsInAnyOrder("F1", "F2", "F3"));
320 private void setupFriends() {
321 setupString("Sone/1/Friends/0/ID", "F1");
322 setupString("Sone/1/Friends/1/ID", "F2");
323 setupString("Sone/1/Friends/2/ID", "F3");
324 setupString("Sone/1/Friends/3/ID", null);
328 public void topLevelAlbumsAreParsedCorrectly() {
329 setupTopLevelAlbums();
330 AlbumBuilderFactory albumBuilderFactory = createAlbumBuilderFactory();
331 List<Album> topLevelAlbums =
332 configurationSoneParser.parseTopLevelAlbums(
333 albumBuilderFactory);
334 assertThat(topLevelAlbums, hasSize(2));
335 Album firstAlbum = topLevelAlbums.get(0);
336 assertThat(firstAlbum, isAlbum("A1", null, "T1", "D1"));
337 assertThat(firstAlbum.getAlbums(), emptyIterable());
338 assertThat(firstAlbum.getImages(), emptyIterable());
339 Album secondAlbum = topLevelAlbums.get(1);
340 assertThat(secondAlbum, isAlbum("A2", null, "T2", "D2"));
341 assertThat(secondAlbum.getAlbums(), hasSize(1));
342 assertThat(secondAlbum.getImages(), emptyIterable());
343 Album thirdAlbum = secondAlbum.getAlbums().get(0);
344 assertThat(thirdAlbum, isAlbum("A3", "A2", "T3", "D3"));
345 assertThat(thirdAlbum.getAlbums(), emptyIterable());
346 assertThat(thirdAlbum.getImages(), emptyIterable());
349 private void setupTopLevelAlbums() {
350 setupAlbum(0, "A1", null, "T1", "D1", "I1");
351 setupAlbum(1, "A2", null, "T2", "D2", null);
352 setupAlbum(2, "A3", "A2", "T3", "D3", "I3");
353 setupAlbum(3, null, null, null, null, null);
356 private void setupAlbum(int albumNumber, String albumId,
357 String parentAlbumId,
358 String title, String description, String imageId) {
359 final String albumPrefix = "Sone/1/Albums/" + albumNumber;
360 setupString(albumPrefix + "/ID", albumId);
361 setupString(albumPrefix + "/Title", title);
362 setupString(albumPrefix + "/Description", description);
363 setupString(albumPrefix + "/Parent", parentAlbumId);
364 setupString(albumPrefix + "/AlbumImage", imageId);
367 private AlbumBuilderFactory createAlbumBuilderFactory() {
368 AlbumBuilderFactory albumBuilderFactory =
369 mock(AlbumBuilderFactory.class);
370 when(albumBuilderFactory.newAlbumBuilder()).thenAnswer(
371 new Answer<AlbumBuilder>() {
373 public AlbumBuilder answer(InvocationOnMock invocation) {
374 return new TestAlbumBuilder();
377 return albumBuilderFactory;
380 @Test(expected = InvalidAlbumFound.class)
381 public void albumWithInvalidTitleIsRecognized() {
382 setupAlbum(0, "A1", null, null, "D1", "I1");
383 configurationSoneParser.parseTopLevelAlbums(
384 createAlbumBuilderFactory());
387 @Test(expected = InvalidAlbumFound.class)
388 public void albumWithInvalidDescriptionIsRecognized() {
389 setupAlbum(0, "A1", null, "T1", null, "I1");
390 configurationSoneParser.parseTopLevelAlbums(
391 createAlbumBuilderFactory());
394 @Test(expected = InvalidParentAlbumFound.class)
395 public void albumWithInvalidParentIsRecognized() {
396 setupAlbum(0, "A1", "A0", "T1", "D1", "I1");
397 configurationSoneParser.parseTopLevelAlbums(
398 createAlbumBuilderFactory());
402 public void imagesAreParsedCorrectly() {
403 setupTopLevelAlbums();
404 configurationSoneParser.parseTopLevelAlbums(
405 createAlbumBuilderFactory());
407 configurationSoneParser.parseImages(createImageBuilderFactory());
408 Map<String, Album> albums = configurationSoneParser.getAlbums();
409 assertThat(albums.get("A1").getImages(),
410 contains(isImage("I1", 1000L, "K1", "T1", "D1", 16, 9)));
411 assertThat(albums.get("A2").getImages(), contains(
412 isImage("I2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2)));
413 assertThat(albums.get("A3").getImages(), contains(
414 isImage("I3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3)));
417 private void setupImages() {
418 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, 9);
419 setupImage(1, "I2", "A2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2);
420 setupImage(2, "I3", "A3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3);
421 setupImage(3, null, null, 0L, null, null, null, 0, 0);
424 private void setupImage(int imageNumber, String id,
425 String parentAlbumId, Long creationTime, String key, String title,
426 String description, Integer width, Integer height) {
427 final String imagePrefix = "Sone/1/Images/" + imageNumber;
428 setupString(imagePrefix + "/ID", id);
429 setupString(imagePrefix + "/Album", parentAlbumId);
430 setupLong(imagePrefix + "/CreationTime", creationTime);
431 setupString(imagePrefix + "/Key", key);
432 setupString(imagePrefix + "/Title", title);
433 setupString(imagePrefix + "/Description", description);
434 setupInteger(imagePrefix + "/Width", width);
435 setupInteger(imagePrefix + "/Height", height);
438 private ImageBuilderFactory createImageBuilderFactory() {
439 ImageBuilderFactory imageBuilderFactory =
440 mock(ImageBuilderFactory.class);
441 when(imageBuilderFactory.newImageBuilder()).thenAnswer(
442 new Answer<ImageBuilder>() {
444 public ImageBuilder answer(InvocationOnMock invocation)
446 return new TestImageBuilder();
449 return imageBuilderFactory;
452 @Test(expected = InvalidImageFound.class)
453 public void missingAlbumIdIsRecognized() {
454 setupTopLevelAlbums();
455 configurationSoneParser.parseTopLevelAlbums(
456 createAlbumBuilderFactory());
457 setupImage(0, "I1", null, 1000L, "K1", "T1", "D1", 16, 9);
458 configurationSoneParser.parseImages(createImageBuilderFactory());
461 @Test(expected = InvalidParentAlbumFound.class)
462 public void invalidAlbumIdIsRecognized() {
463 setupTopLevelAlbums();
464 configurationSoneParser.parseTopLevelAlbums(
465 createAlbumBuilderFactory());
466 setupImage(0, "I1", "A4", 1000L, "K1", "T1", "D1", 16, 9);
467 configurationSoneParser.parseImages(createImageBuilderFactory());
470 @Test(expected = InvalidImageFound.class)
471 public void missingCreationTimeIsRecognized() {
472 setupTopLevelAlbums();
473 configurationSoneParser.parseTopLevelAlbums(
474 createAlbumBuilderFactory());
475 setupImage(0, "I1", "A1", null, "K1", "T1", "D1", 16, 9);
476 configurationSoneParser.parseImages(createImageBuilderFactory());
479 @Test(expected = InvalidImageFound.class)
480 public void missingKeyIsRecognized() {
481 setupTopLevelAlbums();
482 configurationSoneParser.parseTopLevelAlbums(
483 createAlbumBuilderFactory());
484 setupImage(0, "I1", "A1", 1000L, null, "T1", "D1", 16, 9);
485 configurationSoneParser.parseImages(createImageBuilderFactory());
488 @Test(expected = InvalidImageFound.class)
489 public void missingTitleIsRecognized() {
490 setupTopLevelAlbums();
491 configurationSoneParser.parseTopLevelAlbums(
492 createAlbumBuilderFactory());
493 setupImage(0, "I1", "A1", 1000L, "K1", null, "D1", 16, 9);
494 configurationSoneParser.parseImages(createImageBuilderFactory());
497 @Test(expected = InvalidImageFound.class)
498 public void missingDescriptionIsRecognized() {
499 setupTopLevelAlbums();
500 configurationSoneParser.parseTopLevelAlbums(
501 createAlbumBuilderFactory());
502 setupImage(0, "I1", "A1", 1000L, "K1", "T1", null, 16, 9);
503 configurationSoneParser.parseImages(createImageBuilderFactory());
506 @Test(expected = InvalidImageFound.class)
507 public void missingWidthIsRecognized() {
508 setupTopLevelAlbums();
509 configurationSoneParser.parseTopLevelAlbums(
510 createAlbumBuilderFactory());
511 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", null, 9);
512 configurationSoneParser.parseImages(createImageBuilderFactory());
515 @Test(expected = InvalidImageFound.class)
516 public void missingHeightIsRecognized() {
517 setupTopLevelAlbums();
518 configurationSoneParser.parseTopLevelAlbums(
519 createAlbumBuilderFactory());
520 setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, null);
521 configurationSoneParser.parseImages(createImageBuilderFactory());