Verify that an image with invalid dimensions causes an error.
[Sone.git] / src / test / java / net / pterodactylus / sone / core / SoneParserTest.java
1 package net.pterodactylus.sone.core;
2
3 import static com.google.common.base.Objects.equal;
4 import static java.lang.String.format;
5 import static java.util.logging.Level.OFF;
6 import static org.hamcrest.MatcherAssert.assertThat;
7 import static org.hamcrest.Matchers.containsInAnyOrder;
8 import static org.hamcrest.Matchers.empty;
9 import static org.hamcrest.Matchers.is;
10 import static org.hamcrest.Matchers.notNullValue;
11 import static org.hamcrest.Matchers.nullValue;
12 import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
13 import static org.mockito.Matchers.anyString;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.when;
16
17 import java.io.InputStream;
18 import java.util.logging.Logger;
19
20 import net.pterodactylus.sone.core.SoneParser.DuplicateField;
21 import net.pterodactylus.sone.core.SoneParser.InvalidParentAlbum;
22 import net.pterodactylus.sone.core.SoneParser.InvalidProtocolVersion;
23 import net.pterodactylus.sone.core.SoneParser.InvalidXml;
24 import net.pterodactylus.sone.core.SoneParser.MalformedDimension;
25 import net.pterodactylus.sone.core.SoneParser.MalformedTime;
26 import net.pterodactylus.sone.core.SoneParser.MalformedXml;
27 import net.pterodactylus.sone.data.Client;
28 import net.pterodactylus.sone.data.Image;
29 import net.pterodactylus.sone.data.Post;
30 import net.pterodactylus.sone.data.PostReply;
31 import net.pterodactylus.sone.data.Profile.Field;
32 import net.pterodactylus.sone.data.Sone;
33 import net.pterodactylus.sone.database.Database;
34 import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
35 import net.pterodactylus.sone.database.memory.MemoryDatabase;
36
37 import com.google.common.base.Optional;
38 import org.hamcrest.Description;
39 import org.hamcrest.Matcher;
40 import org.hamcrest.TypeSafeMatcher;
41 import org.junit.Test;
42
43 /**
44  * Unit test for {@link SoneParser}.
45  *
46  * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
47  */
48 public class SoneParserTest {
49
50         static {
51                 Logger.getLogger("").setLevel(OFF);
52         }
53
54         private final Core core = mock(Core.class);
55         private final Database database = new MemoryDatabase(null);
56         private final Sone originalSone = database.newSoneBuilder().by("test").using(new Client("TestClient", "1.0")).build(Optional.<SoneCreated>absent());
57         private final SoneParser soneParser = new SoneParser();
58
59         public SoneParserTest() {
60                 Optional<Image> image = mock(Optional.class);
61                 when(core.getImage(anyString())).thenReturn(image);
62         }
63
64         @Test(expected = InvalidXml.class)
65         public void verifyThatAnInvalidXmlDocumentIsNotParsed() {
66                 soneParser.parseSone(database, originalSone, getXml("invalid-xml"));
67         }
68
69         @Test(expected = InvalidProtocolVersion.class)
70         public void verifyThatANegativeProtocolVersionCausesAnError() {
71                 soneParser.parseSone(database, originalSone, getXml("negative-protocol-version"));
72         }
73
74         @Test(expected = InvalidProtocolVersion.class)
75         public void verifyThatATooLargeProtocolVersionCausesAnError() {
76                 soneParser.parseSone(database, originalSone, getXml("too-large-protocol-version"));
77         }
78
79         @Test(expected = MalformedXml.class)
80         public void verifyThatAMissingTimeCausesAnError() {
81                 soneParser.parseSone(database, originalSone, getXml("missing-time"));
82         }
83
84         @Test
85         public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
86                 Sone sone = soneParser.parseSone(database, originalSone, getXml("missing-client"));
87                 assertThat(sone, notNullValue());
88                 assertThat(sone.getClient(), notNullValue());
89                 assertThat(sone.getClient(), is(originalSone.getClient()));
90         }
91
92         @Test
93         public void verifyThatAnInvalidClientCausesTheOriginalClientToBeUsed() {
94                 Sone sone = soneParser.parseSone(database, originalSone, getXml("invalid-client"));
95                 assertThat(sone, notNullValue());
96                 assertThat(sone.getClient(), notNullValue());
97                 assertThat(sone.getClient(), is(originalSone.getClient()));
98         }
99
100         @Test(expected = MalformedXml.class)
101         public void verifyThatAMissingProfileCausesAnError() {
102                 soneParser.parseSone(database, originalSone, getXml("missing-profile"));
103         }
104
105         @Test(expected = MalformedXml.class)
106         public void verifyThatInvalidFieldsCauseAnError() {
107                 soneParser.parseSone(database, originalSone, getXml("invalid-field"));
108         }
109
110         @Test(expected = DuplicateField.class)
111         public void verifyThatDuplicateFieldsCauseAnError() {
112                 soneParser.parseSone(database, originalSone, getXml("duplicate-field"));
113         }
114
115         @Test
116         public void verifyThatMissingPostsDoNotCauseAnError() {
117                 soneParser.parseSone(database, originalSone, getXml("missing-posts"));
118         }
119
120         @Test(expected = MalformedXml.class)
121         public void verifyThatInvalidPostsCauseAnError() {
122                 soneParser.parseSone(database, originalSone, getXml("invalid-posts"));
123         }
124
125         @Test(expected = MalformedTime.class)
126         public void verifyThatAMalformedTimeCausesAnError() {
127                 soneParser.parseSone(database, originalSone, getXml("invalid-post-time"));
128         }
129
130         @Test
131         public void verifyThatMissingRepliesDoNotCauseAnError() {
132                 soneParser.parseSone(database, originalSone, getXml("missing-replies"));
133         }
134
135         @Test(expected = MalformedXml.class)
136         public void verifyThatInvalidRepliesCauseAnError() {
137                 soneParser.parseSone(database, originalSone, getXml("invalid-replies"));
138         }
139
140         @Test(expected = MalformedTime.class)
141         public void verifyThatAMalformedReplyTimeCausesAnError() {
142                 soneParser.parseSone(database, originalSone, getXml("invalid-reply-time"));
143         }
144
145         @Test
146         public void verifyThatAMissingPostLikesSectionDoesNotCauseAnError() {
147                 soneParser.parseSone(database, originalSone, getXml("missing-post-likes"));
148         }
149
150         @Test
151         public void verifyThatAMissingReplyLikesSectionDoesNotCauseAnError() {
152                 soneParser.parseSone(database, originalSone, getXml("missing-reply-likes"));
153         }
154
155         @Test
156         public void verifyThatMissingAlbumsSectionDoNotCauseAnError() {
157                 soneParser.parseSone(database, originalSone, getXml("missing-albums"));
158         }
159
160         @Test(expected = MalformedXml.class)
161         public void verifyThatAnInvalidAlbumCausesAnError() {
162                 soneParser.parseSone(database, originalSone, getXml("invalid-album"));
163         }
164
165         @Test(expected = InvalidParentAlbum.class)
166         public void verifyThatAnInvalidParentAlbumCausesAnError() {
167                 soneParser.parseSone(database, originalSone, getXml("invalid-parent-album"));
168         }
169
170         @Test(expected = MalformedXml.class)
171         public void verifyThatAnInvalidImageCausesAnError() {
172                 soneParser.parseSone(database, originalSone, getXml("invalid-image"));
173         }
174
175         @Test(expected = MalformedDimension.class)
176         public void verifyThatInvalidImageDimensionsCauseAnError() {
177                 soneParser.parseSone(database, originalSone, getXml("invalid-image-dimensions"));
178         }
179
180         @Test
181         public void verifyThatAnEmptyProfileIsParsedWithoutError() {
182                 Sone sone = soneParser.parseSone(database, originalSone, getXml("empty-profile"));
183                 assertThat(sone.getProfile().getFirstName(), nullValue());
184                 assertThat(sone.getProfile().getMiddleName(), nullValue());
185                 assertThat(sone.getProfile().getLastName(), nullValue());
186                 assertThat(sone.getProfile().getBirthYear(), nullValue());
187                 assertThat(sone.getProfile().getBirthMonth(), nullValue());
188                 assertThat(sone.getProfile().getBirthDay(), nullValue());
189                 assertThat(sone.getProfile().getAvatar(), nullValue());
190                 assertThat(sone.getProfile().getFields(), empty());
191         }
192
193         @Test
194         public void verifyThatTheCreatedSoneMeetsAllExpectations() {
195                 Sone sone = soneParser.parseSone(database, originalSone, getXml("complete"));
196                 assertThat(sone, notNullValue());
197                 assertThat(sone.getTime(), is(1382419919000L));
198                 assertThat(sone.getClient(), notNullValue());
199                 assertThat(sone.getClient().getName(), is("Sone"));
200                 assertThat(sone.getClient().getVersion(), is("0.8.7"));
201                 assertThat(sone.getProfile(), notNullValue());
202                 assertThat(sone.getProfile().getFirstName(), is("First"));
203                 assertThat(sone.getProfile().getMiddleName(), is("M."));
204                 assertThat(sone.getProfile().getLastName(), is("Last"));
205                 assertThat(sone.getProfile().getBirthYear(), is(2013));
206                 assertThat(sone.getProfile().getBirthMonth(), is(10));
207                 assertThat(sone.getProfile().getBirthDay(), is(22));
208                 assertThat(sone.getProfile().getAvatar(), is("96431abe-3add-11e3-8a46-67047503bf6d"));
209                 assertThat(sone.getProfile().getFields(), contains(
210                                 fieldMatcher("Field1", "Value1"),
211                                 fieldMatcher("Field2", "Value2")
212                 ));
213                 assertThat(sone.getPosts(), contains(
214                                 postMatcher("d8c9586e-3adb-11e3-bb31-171fc040e645", "0rpD4gL8mszav2trndhIdKIxvKUCNAe2kjA3dLV8CVU", 1382420181000L, "Hello, User!"),
215                                 postMatcher("bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", null, 1382420140000L, "Hello, World!")
216                 ));
217                 assertThat(sone.getReplies(), containsInAnyOrder(
218                                 postReplyMatcher("f09fa448-3adb-11e3-a783-ab54a11aacc4", "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", 1382420224000L, "Talking to myself."),
219                                 postReplyMatcher("0a376440-3adc-11e3-8f45-c7cc157436a5", "11ebe86e-3adc-11e3-b7b9-7f2c88018a33", 1382420271000L, "Talking to somebody I can't see.")
220                 ));
221                 assertThat(sone.getLikedPostIds(), containsInAnyOrder(
222                                 "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3",
223                                 "305d85e6-3adc-11e3-be45-8b53dd91f0af"
224                 ));
225                 assertThat(sone.getLikedReplyIds(), containsInAnyOrder(
226                                 "f09fa448-3adb-11e3-a783-ab54a11aacc4",
227                                 "3ba28960-3adc-11e3-93c7-6713d170f44c"
228                 ));
229         }
230
231         private Matcher<PostReply> postReplyMatcher(final String id, final String postId, final long time, final String text) {
232                 return new TypeSafeMatcher<PostReply>() {
233                         @Override
234                         protected boolean matchesSafely(PostReply postReply) {
235                                 return postReply.getId().equals(id) && postReply.getPostId().equals(postId) && (postReply.getTime() == time) && postReply.getText().equals(text);
236                         }
237
238                         @Override
239                         public void describeTo(Description description) {
240                                 description.appendText("PostReply(")
241                                                 .appendValue(id).appendText(", ")
242                                                 .appendValue(postId).appendText(", ")
243                                                 .appendValue(time).appendText(", ")
244                                                 .appendValue(text).appendText(")");
245                         }
246
247                         @Override
248                         protected void describeMismatchSafely(PostReply postReply, Description mismatchDescription) {
249                                 mismatchDescription.appendText("PostReply(")
250                                                 .appendValue(postReply.getId()).appendText(", ")
251                                                 .appendValue(postReply.getPostId()).appendText(", ")
252                                                 .appendValue(postReply.getTime()).appendText(", ")
253                                                 .appendValue(postReply.getText()).appendText(")");
254                         }
255                 };
256         }
257
258         private Matcher<Post> postMatcher(final String id, final String recipient, final long time, final String text) {
259                 return new TypeSafeMatcher<Post>() {
260                         @Override
261                         protected boolean matchesSafely(Post post) {
262                                 return post.getId().equals(id) && equal(post.getRecipientId().orNull(), recipient) && (post.getTime() == time) && post.getText().equals(text);
263                         }
264
265                         @Override
266                         public void describeTo(Description description) {
267                                 description.appendText("Post(")
268                                                 .appendValue(id).appendText(", ")
269                                                 .appendValue(recipient).appendText(", ")
270                                                 .appendValue(time).appendText(", ")
271                                                 .appendValue(text).appendText(")");
272                         }
273
274                         @Override
275                         protected void describeMismatchSafely(Post post, Description mismatchDescription) {
276                                 mismatchDescription.appendText("Post(")
277                                                 .appendValue(post.getId()).appendText(", ")
278                                                 .appendValue(post.getRecipientId().orNull()).appendText(", ")
279                                                 .appendValue(post.getTime()).appendText(", ")
280                                                 .appendValue(post.getText()).appendText(")");
281                         }
282                 };
283         }
284
285         private Matcher<Field> fieldMatcher(final String name, final String value) {
286                 return new TypeSafeMatcher<Field>() {
287                         @Override
288                         protected boolean matchesSafely(Field field) {
289                                 return field.getName().equals(name) && field.getValue().equals(value);
290                         }
291
292                         @Override
293                         public void describeTo(Description description) {
294                                 description.appendText("field named ").appendValue(name).appendText(" with value ").appendValue(value);
295                         }
296
297                         @Override
298                         protected void describeMismatchSafely(Field field, Description mismatchDescription) {
299                                 mismatchDescription.appendText("field named ").appendValue(field.getName()).appendText(" with value ").appendValue(field.getValue());
300                         }
301                 };
302         }
303
304         private InputStream getXml(String name) {
305                 return getClass().getResourceAsStream(format("/sone-parser/%s.xml", name));
306         }
307
308 }