🎨 Replace UpdateFoundEvent with Kotlin version
[Sone.git] / src / test / java / net / pterodactylus / sone / core / ConfigurationSoneParserTest.java
index daf2cf9..4edc1b7 100644 (file)
@@ -1,36 +1,53 @@
 package net.pterodactylus.sone.core;
 
-import static com.google.common.base.Optional.fromNullable;
 import static com.google.common.base.Optional.of;
-import static java.lang.System.currentTimeMillis;
-import static java.util.UUID.randomUUID;
-import static net.pterodactylus.sone.Matchers.isPost;
+import static net.pterodactylus.sone.test.Matchers.isAlbum;
+import static net.pterodactylus.sone.test.Matchers.isImage;
+import static net.pterodactylus.sone.test.Matchers.isPost;
+import static net.pterodactylus.sone.test.Matchers.isPostReply;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.emptyIterable;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.Map;
+import java.util.Set;
 
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidAlbumFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidImageFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidParentAlbumFound;
 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
+import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
+import net.pterodactylus.sone.data.Album;
 import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
 import net.pterodactylus.sone.data.Profile;
 import net.pterodactylus.sone.data.Profile.Field;
 import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.database.AlbumBuilder;
+import net.pterodactylus.sone.database.AlbumBuilderFactory;
+import net.pterodactylus.sone.database.ImageBuilder;
+import net.pterodactylus.sone.database.ImageBuilderFactory;
 import net.pterodactylus.sone.database.PostBuilder;
 import net.pterodactylus.sone.database.PostBuilderFactory;
+import net.pterodactylus.sone.database.PostReplyBuilder;
+import net.pterodactylus.sone.database.PostReplyBuilderFactory;
+import net.pterodactylus.sone.test.TestAlbumBuilder;
+import net.pterodactylus.sone.test.TestImageBuilder;
+import net.pterodactylus.sone.test.TestPostBuilder;
+import net.pterodactylus.sone.test.TestPostReplyBuilder;
+import net.pterodactylus.sone.test.TestValue;
 import net.pterodactylus.util.config.Configuration;
-import net.pterodactylus.util.config.ConfigurationException;
-import net.pterodactylus.util.config.Value;
 
 import com.google.common.base.Optional;
 import org.hamcrest.Matchers;
@@ -40,8 +57,6 @@ import org.mockito.stubbing.Answer;
 
 /**
  * Unit test for {@link ConfigurationSoneParser}.
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David â€˜Bombe’ Roden</a>
  */
 public class ConfigurationSoneParserTest {
 
@@ -71,9 +86,9 @@ public class ConfigurationSoneParserTest {
 
        private void setupEmptyProfile() {
                when(configuration.getStringValue(anyString())).thenReturn(
-                               new TestValue<String>(null));
+                               TestValue.<String>from(null));
                when(configuration.getIntValue(anyString())).thenReturn(
-                               new TestValue<Integer>(null));
+                               TestValue.<Integer>from(null));
        }
 
        @Test
@@ -111,12 +126,12 @@ public class ConfigurationSoneParserTest {
 
        private void setupString(String nodeName, String value) {
                when(configuration.getStringValue(eq(nodeName))).thenReturn(
-                               new TestValue<String>(value));
+                               TestValue.from(value));
        }
 
        private void setupInteger(String nodeName, Integer value) {
                when(configuration.getIntValue(eq(nodeName))).thenReturn(
-                               new TestValue<Integer>(value));
+                               TestValue.from(value));
        }
 
        @Test
@@ -163,7 +178,7 @@ public class ConfigurationSoneParserTest {
 
        private void setupLong(String nodeName, Long value) {
                when(configuration.getLongValue(eq(nodeName))).thenReturn(
-                               new TestValue<Long>(value));
+                               TestValue.from(value));
        }
 
        @Test(expected = InvalidPostFound.class)
@@ -200,93 +215,308 @@ public class ConfigurationSoneParserTest {
                setupPost("1", null, 0L, null, null);
        }
 
+       @Test
+       public void postRepliesAreParsedCorrectly() {
+               setupPostReplies();
+               PostReplyBuilderFactory postReplyBuilderFactory =
+                               new PostReplyBuilderFactory() {
+                                       @Override
+                                       public PostReplyBuilder newPostReplyBuilder() {
+                                               return new TestPostReplyBuilder();
+                                       }
+                               };
+               Collection<PostReply> postReplies =
+                               configurationSoneParser.parsePostReplies(
+                                               postReplyBuilderFactory);
+               assertThat(postReplies, hasSize(2));
+               assertThat(postReplies,
+                               containsInAnyOrder(isPostReply("R0", "P0", 1000L, "T0"),
+                                               isPostReply("R1", "P1", 1001L, "T1")));
+       }
 
-       private static class TestValue<T> implements Value<T> {
+       private void setupPostReplies() {
+               setupPostReply("0", "R0", "P0", 1000L, "T0");
+               setupPostReply("1", "R1", "P1", 1001L, "T1");
+               setupPostReply("2", null, null, 0L, null);
+       }
 
-               private final AtomicReference<T> value = new AtomicReference<T>();
+       private void setupPostReply(String postReplyNumber, String postReplyId,
+                       String postId, long time, String text) {
+               setupString("Sone/1/Replies/" + postReplyNumber + "/ID", postReplyId);
+               setupString("Sone/1/Replies/" + postReplyNumber + "/Post/ID", postId);
+               setupLong("Sone/1/Replies/" + postReplyNumber + "/Time", time);
+               setupString("Sone/1/Replies/" + postReplyNumber + "/Text", text);
+       }
 
-               public TestValue(T originalValue) {
-                       value.set(originalValue);
-               }
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostIdIsRecognized() {
+               setupPostReplyWithMissingPostId();
+               configurationSoneParser.parsePostReplies(null);
+       }
 
-               @Override
-               public T getValue() throws ConfigurationException {
-                       return value.get();
-               }
+       private void setupPostReplyWithMissingPostId() {
+               setupPostReply("0", "R0", null, 1000L, "T0");
+       }
 
-               @Override
-               public T getValue(T defaultValue) {
-                       final T realValue = value.get();
-                       return (realValue != null) ? realValue : defaultValue;
-               }
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostReplyTimeIsRecognized() {
+               setupPostReplyWithMissingPostReplyTime();
+               configurationSoneParser.parsePostReplies(null);
+       }
 
-               @Override
-               public void setValue(T newValue) throws ConfigurationException {
-                       value.set(newValue);
-               }
+       private void setupPostReplyWithMissingPostReplyTime() {
+               setupPostReply("0", "R0", "P0", 0L, "T0");
+       }
 
+       @Test(expected = InvalidPostReplyFound.class)
+       public void missingPostReplyTextIsRecognized() {
+               setupPostReplyWithMissingPostReplyText();
+               configurationSoneParser.parsePostReplies(null);
        }
 
-       private static class TestPostBuilder implements PostBuilder {
+       private void setupPostReplyWithMissingPostReplyText() {
+               setupPostReply("0", "R0", "P0", 1000L, null);
+       }
 
-               private final Post post = mock(Post.class);
-               private String recipientId = null;
+       @Test
+       public void likedPostIdsParsedCorrectly() {
+               setupLikedPostIds();
+               Set<String> likedPostIds =
+                               configurationSoneParser.parseLikedPostIds();
+               assertThat(likedPostIds, containsInAnyOrder("P1", "P2", "P3"));
+       }
 
-               @Override
-               public PostBuilder copyPost(Post post) throws NullPointerException {
-                       return this;
-               }
+       private void setupLikedPostIds() {
+               setupString("Sone/1/Likes/Post/0/ID", "P1");
+               setupString("Sone/1/Likes/Post/1/ID", "P2");
+               setupString("Sone/1/Likes/Post/2/ID", "P3");
+               setupString("Sone/1/Likes/Post/3/ID", null);
+       }
 
-               @Override
-               public PostBuilder from(String senderId) {
-                       final Sone sone = mock(Sone.class);
-                       when(sone.getId()).thenReturn(senderId);
-                       when(post.getSone()).thenReturn(sone);
-                       return this;
-               }
+       @Test
+       public void likedPostReplyIdsAreParsedCorrectly() {
+               setupLikedPostReplyIds();
+               Set<String> likedPostReplyIds =
+                               configurationSoneParser.parseLikedPostReplyIds();
+               assertThat(likedPostReplyIds, containsInAnyOrder("R1", "R2", "R3"));
+       }
 
-               @Override
-               public PostBuilder randomId() {
-                       when(post.getId()).thenReturn(randomUUID().toString());
-                       return this;
-               }
+       private void setupLikedPostReplyIds() {
+               setupString("Sone/1/Likes/Reply/0/ID", "R1");
+               setupString("Sone/1/Likes/Reply/1/ID", "R2");
+               setupString("Sone/1/Likes/Reply/2/ID", "R3");
+               setupString("Sone/1/Likes/Reply/3/ID", null);
+       }
 
-               @Override
-               public PostBuilder withId(String id) {
-                       when(post.getId()).thenReturn(id);
-                       return this;
-               }
+       @Test
+       public void friendsAreParsedCorrectly() {
+               setupFriends();
+               Set<String> friends = configurationSoneParser.parseFriends();
+               assertThat(friends, containsInAnyOrder("F1", "F2", "F3"));
+       }
 
-               @Override
-               public PostBuilder currentTime() {
-                       when(post.getTime()).thenReturn(currentTimeMillis());
-                       return this;
-               }
+       private void setupFriends() {
+               setupString("Sone/1/Friends/0/ID", "F1");
+               setupString("Sone/1/Friends/1/ID", "F2");
+               setupString("Sone/1/Friends/2/ID", "F3");
+               setupString("Sone/1/Friends/3/ID", null);
+       }
 
-               @Override
-               public PostBuilder withTime(long time) {
-                       when(post.getTime()).thenReturn(time);
-                       return this;
-               }
+       @Test
+       public void topLevelAlbumsAreParsedCorrectly() {
+               setupTopLevelAlbums();
+               AlbumBuilderFactory albumBuilderFactory = createAlbumBuilderFactory();
+               List<Album> topLevelAlbums =
+                               configurationSoneParser.parseTopLevelAlbums(
+                                               albumBuilderFactory);
+               assertThat(topLevelAlbums, hasSize(2));
+               Album firstAlbum = topLevelAlbums.get(0);
+               assertThat(firstAlbum, isAlbum("A1", null, "T1", "D1"));
+               assertThat(firstAlbum.getAlbums(), emptyIterable());
+               assertThat(firstAlbum.getImages(), emptyIterable());
+               Album secondAlbum = topLevelAlbums.get(1);
+               assertThat(secondAlbum, isAlbum("A2", null, "T2", "D2"));
+               assertThat(secondAlbum.getAlbums(), hasSize(1));
+               assertThat(secondAlbum.getImages(), emptyIterable());
+               Album thirdAlbum = secondAlbum.getAlbums().get(0);
+               assertThat(thirdAlbum, isAlbum("A3", "A2", "T3", "D3"));
+               assertThat(thirdAlbum.getAlbums(), emptyIterable());
+               assertThat(thirdAlbum.getImages(), emptyIterable());
+       }
 
-               @Override
-               public PostBuilder withText(String text) {
-                       when(post.getText()).thenReturn(text);
-                       return this;
-               }
+       private void setupTopLevelAlbums() {
+               setupAlbum(0, "A1", null, "T1", "D1", "I1");
+               setupAlbum(1, "A2", null, "T2", "D2", null);
+               setupAlbum(2, "A3", "A2", "T3", "D3", "I3");
+               setupAlbum(3, null, null, null, null, null);
+       }
 
-               @Override
-               public PostBuilder to(String recipientId) {
-                       this.recipientId = recipientId;
-                       return this;
-               }
+       private void setupAlbum(int albumNumber, String albumId,
+                       String parentAlbumId,
+                       String title, String description, String imageId) {
+               final String albumPrefix = "Sone/1/Albums/" + albumNumber;
+               setupString(albumPrefix + "/ID", albumId);
+               setupString(albumPrefix + "/Title", title);
+               setupString(albumPrefix + "/Description", description);
+               setupString(albumPrefix + "/Parent", parentAlbumId);
+               setupString(albumPrefix + "/AlbumImage", imageId);
+       }
+
+       private AlbumBuilderFactory createAlbumBuilderFactory() {
+               AlbumBuilderFactory albumBuilderFactory =
+                               mock(AlbumBuilderFactory.class);
+               when(albumBuilderFactory.newAlbumBuilder()).thenAnswer(
+                               new Answer<AlbumBuilder>() {
+                                       @Override
+                                       public AlbumBuilder answer(InvocationOnMock invocation) {
+                                               return new TestAlbumBuilder();
+                                       }
+                               });
+               return albumBuilderFactory;
+       }
+
+       @Test(expected = InvalidAlbumFound.class)
+       public void albumWithInvalidTitleIsRecognized() {
+               setupAlbum(0, "A1", null, null, "D1", "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
 
-               @Override
-               public Post build() throws IllegalStateException {
-                       when(post.getRecipientId()).thenReturn(fromNullable(recipientId));
-                       return post;
-               }
+       @Test(expected = InvalidAlbumFound.class)
+       public void albumWithInvalidDescriptionIsRecognized() {
+               setupAlbum(0, "A1", null, "T1", null, "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
+
+       @Test(expected = InvalidParentAlbumFound.class)
+       public void albumWithInvalidParentIsRecognized() {
+               setupAlbum(0, "A1", "A0", "T1", "D1", "I1");
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+       }
+
+       @Test
+       public void imagesAreParsedCorrectly() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImages();
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+               Map<String, Album> albums = configurationSoneParser.getAlbums();
+               assertThat(albums.get("A1").getImages(),
+                               contains(isImage("I1", 1000L, "K1", "T1", "D1", 16, 9)));
+               assertThat(albums.get("A2").getImages(), contains(
+                               isImage("I2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2)));
+               assertThat(albums.get("A3").getImages(), contains(
+                               isImage("I3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3)));
+       }
+
+       private void setupImages() {
+               setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, 9);
+               setupImage(1, "I2", "A2", 2000L, "K2", "T2", "D2", 16 * 2, 9 * 2);
+               setupImage(2, "I3", "A3", 3000L, "K3", "T3", "D3", 16 * 3, 9 * 3);
+               setupImage(3, null, null, 0L, null, null, null, 0, 0);
+       }
+
+       private void setupImage(int imageNumber, String id,
+                       String parentAlbumId, Long creationTime, String key, String title,
+                       String description, Integer width, Integer height) {
+               final String imagePrefix = "Sone/1/Images/" + imageNumber;
+               setupString(imagePrefix + "/ID", id);
+               setupString(imagePrefix + "/Album", parentAlbumId);
+               setupLong(imagePrefix + "/CreationTime", creationTime);
+               setupString(imagePrefix + "/Key", key);
+               setupString(imagePrefix + "/Title", title);
+               setupString(imagePrefix + "/Description", description);
+               setupInteger(imagePrefix + "/Width", width);
+               setupInteger(imagePrefix + "/Height", height);
+       }
+
+       private ImageBuilderFactory createImageBuilderFactory() {
+               ImageBuilderFactory imageBuilderFactory =
+                               mock(ImageBuilderFactory.class);
+               when(imageBuilderFactory.newImageBuilder()).thenAnswer(
+                               new Answer<ImageBuilder>() {
+                                       @Override
+                                       public ImageBuilder answer(InvocationOnMock invocation)
+                                       throws Throwable {
+                                               return new TestImageBuilder();
+                                       }
+                               });
+               return imageBuilderFactory;
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingAlbumIdIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", null, 1000L, "K1", "T1", "D1", 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidParentAlbumFound.class)
+       public void invalidAlbumIdIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A4", 1000L, "K1", "T1", "D1", 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingCreationTimeIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", null, "K1", "T1", "D1", 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingKeyIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", 1000L, null, "T1", "D1", 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingTitleIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", 1000L, "K1", null, "D1", 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingDescriptionIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", 1000L, "K1", "T1", null, 16, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
+
+       @Test(expected = InvalidImageFound.class)
+       public void missingWidthIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", null, 9);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
+       }
 
+       @Test(expected = InvalidImageFound.class)
+       public void missingHeightIsRecognized() {
+               setupTopLevelAlbums();
+               configurationSoneParser.parseTopLevelAlbums(
+                               createAlbumBuilderFactory());
+               setupImage(0, "I1", "A1", 1000L, "K1", "T1", "D1", 16, null);
+               configurationSoneParser.parseImages(createImageBuilderFactory());
        }
 
 }