🔥 Remove unused import
[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.Optional.of;
4 import static freenet.keys.InsertableClientSSK.createRandom;
5 import static java.lang.System.currentTimeMillis;
6 import static java.util.UUID.randomUUID;
7 import static java.util.concurrent.TimeUnit.DAYS;
8 import static org.hamcrest.MatcherAssert.assertThat;
9 import static org.hamcrest.Matchers.hasSize;
10 import static org.hamcrest.Matchers.is;
11 import static org.hamcrest.Matchers.not;
12 import static org.hamcrest.Matchers.notNullValue;
13 import static org.hamcrest.Matchers.nullValue;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.ArgumentMatchers.anyLong;
16 import static org.mockito.ArgumentMatchers.anyString;
17 import static org.mockito.Mockito.doAnswer;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.when;
20
21 import java.io.InputStream;
22 import java.net.MalformedURLException;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29
30 import net.pterodactylus.sone.data.Album;
31 import net.pterodactylus.sone.data.Album.Modifier;
32 import net.pterodactylus.sone.data.Client;
33 import net.pterodactylus.sone.data.Image;
34 import net.pterodactylus.sone.data.Post;
35 import net.pterodactylus.sone.data.PostReply;
36 import net.pterodactylus.sone.data.Profile;
37 import net.pterodactylus.sone.data.Sone;
38 import net.pterodactylus.sone.database.AlbumBuilder;
39 import net.pterodactylus.sone.database.Database;
40 import net.pterodactylus.sone.database.ImageBuilder;
41 import net.pterodactylus.sone.database.PostBuilder;
42 import net.pterodactylus.sone.database.PostReplyBuilder;
43 import net.pterodactylus.sone.database.SoneBuilder;
44 import net.pterodactylus.sone.database.memory.MemorySoneBuilder;
45 import net.pterodactylus.sone.freenet.wot.Identity;
46 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
47
48 import freenet.crypt.DummyRandomSource;
49 import freenet.keys.FreenetURI;
50 import freenet.keys.InsertableClientSSK;
51
52 import com.google.common.base.Optional;
53 import com.google.common.collect.ArrayListMultimap;
54 import com.google.common.collect.ImmutableSet;
55 import com.google.common.collect.ListMultimap;
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.mockito.invocation.InvocationOnMock;
59 import org.mockito.stubbing.Answer;
60
61 /**
62  * Unit test for {@link SoneParser}.
63  */
64 public class SoneParserTest {
65
66         private final Database database = mock(Database.class);
67         private final SoneParser soneParser = new SoneParser(database);
68         private final Sone sone = mock(Sone.class);
69         private FreenetURI requestUri = mock(FreenetURI.class);
70         private final PostBuilder postBuilder = mock(PostBuilder.class);
71         private final List<Post> createdPosts = new ArrayList<>();
72         private Post post = mock(Post.class);
73         private final PostReplyBuilder postReplyBuilder = mock(PostReplyBuilder.class);
74         private final Set<PostReply> createdPostReplies = new HashSet<>();
75         private PostReply postReply = mock(PostReply.class);
76         private final AlbumBuilder albumBuilder = mock(AlbumBuilder.class);
77         private final ListMultimap<Album, Album>
78                         nestedAlbums = ArrayListMultimap.create();
79         private final ListMultimap<Album, Image> albumImages = ArrayListMultimap.create();
80         private Album album = mock(Album.class);
81         private final Map<String, Album> albums = new HashMap<>();
82         private final ImageBuilder imageBuilder = mock(ImageBuilder.class);
83         private Image image = mock(Image.class);
84         private final Map<String, Image> images = new HashMap<>();
85
86         @Before
87         public void setupSone() {
88                 setupSone(this.sone, Identity.class);
89         }
90
91         private void setupSone(Sone sone, Class<? extends Identity> identityClass) {
92                 Identity identity = mock(identityClass);
93                 InsertableClientSSK clientSSK =
94                                 createRandom(new DummyRandomSource(), "WoT");
95                 when(identity.getRequestUri()).thenReturn(clientSSK.getURI().toString());
96                 when(identity.getId()).thenReturn("identity");
97                 when(sone.getId()).thenReturn("identity");
98                 when(sone.getIdentity()).thenReturn(identity);
99                 requestUri = clientSSK.getURI().setKeyType("USK").setDocName("Sone");
100                 when(sone.getRequestUri()).thenAnswer(new Answer<FreenetURI>() {
101                         @Override
102                         public FreenetURI answer(InvocationOnMock invocation)
103                         throws Throwable {
104                                 return requestUri;
105                         }
106                 });
107                 when(sone.getTime())
108                                 .thenReturn(currentTimeMillis() - DAYS.toMillis(1));
109         }
110
111         @Before
112         public void setupSoneBuilder() {
113                 when(database.newSoneBuilder()).thenAnswer(new Answer<SoneBuilder>() {
114                         @Override
115                         public SoneBuilder answer(InvocationOnMock invocation) {
116                                 return new MemorySoneBuilder(null);
117                         }
118                 });
119         }
120
121         @Before
122         public void setupPost() {
123                 when(post.getRecipientId()).thenReturn(Optional.<String>absent());
124         }
125
126         @Before
127         public void setupPostBuilder() {
128                 when(postBuilder.withId(anyString())).thenAnswer(new Answer<PostBuilder>() {
129                         @Override
130                         public PostBuilder answer(InvocationOnMock invocation) throws Throwable {
131                                 when(post.getId()).thenReturn((String) invocation.getArguments()[0]);
132                                 return postBuilder;
133                         }
134                 });
135                 when(postBuilder.from(anyString())).thenAnswer(new Answer<PostBuilder>() {
136                         @Override
137                         public PostBuilder answer(InvocationOnMock invocation) throws Throwable {
138                                 final Sone sone = mock(Sone.class);
139                                 when(sone.getId()).thenReturn((String) invocation.getArguments()[0]);
140                                 when(post.getSone()).thenReturn(sone);
141                                 return postBuilder;
142                         }
143                 });
144                 when(postBuilder.withTime(anyLong())).thenAnswer(new Answer<PostBuilder>() {
145                         @Override
146                         public PostBuilder answer(InvocationOnMock invocation) throws Throwable {
147                                 when(post.getTime()).thenReturn((Long) invocation.getArguments()[0]);
148                                 return postBuilder;
149                         }
150                 });
151                 when(postBuilder.withText(anyString())).thenAnswer(new Answer<PostBuilder>() {
152                         @Override
153                         public PostBuilder answer(InvocationOnMock invocation) throws Throwable {
154                                 when(post.getText()).thenReturn((String) invocation.getArguments()[0]);
155                                 return postBuilder;
156                         }
157                 });
158                 when(postBuilder.to(anyString())).thenAnswer(new Answer<PostBuilder>() {
159                         @Override
160                         public PostBuilder answer(InvocationOnMock invocation) throws Throwable {
161                                 when(post.getRecipientId()).thenReturn(of((String) invocation.getArguments()[0]));
162                                 return postBuilder;
163                         }
164                 });
165                 when(postBuilder.build()).thenAnswer(new Answer<Post>() {
166                         @Override
167                         public Post answer(InvocationOnMock invocation) throws Throwable {
168                                 Post post = SoneParserTest.this.post;
169                                 SoneParserTest.this.post = mock(Post.class);
170                                 setupPost();
171                                 createdPosts.add(post);
172                                 return post;
173                         }
174                 });
175                 when(database.newPostBuilder()).thenReturn(postBuilder);
176         }
177
178         @Before
179         public void setupPostReplyBuilder() {
180                 when(postReplyBuilder.withId(anyString())).thenAnswer(new Answer<PostReplyBuilder>() {
181                         @Override
182                         public PostReplyBuilder answer(InvocationOnMock invocation) throws Throwable {
183                                 when(postReply.getId()).thenReturn((String) invocation.getArguments()[0]);
184                                 return postReplyBuilder;
185                         }
186                 });
187                 when(postReplyBuilder.from(anyString())).thenAnswer(
188                                 new Answer<PostReplyBuilder>() {
189                                         @Override
190                                         public PostReplyBuilder answer(
191                                                         InvocationOnMock invocation) throws Throwable {
192                                                 Sone sone = when(mock(Sone.class).getId()).thenReturn(
193                                                                 (String) invocation.getArguments()[0])
194                                                                 .getMock();
195                                                 when(postReply.getSone()).thenReturn(sone);
196                                                 return postReplyBuilder;
197                                         }
198                                 });
199                 when(postReplyBuilder.to(anyString())).thenAnswer(
200                                 new Answer<PostReplyBuilder>() {
201                                         @Override
202                                         public PostReplyBuilder answer(
203                                                         InvocationOnMock invocation) throws Throwable {
204                                                 when(postReply.getPostId()).thenReturn(
205                                                                 (String) invocation.getArguments()[0]);
206                                                 Post post = when(mock(Post.class).getId()).thenReturn(
207                                                                 (String) invocation.getArguments()[0])
208                                                                 .getMock();
209                                                 when(postReply.getPost()).thenReturn(of(post));
210                                                 return postReplyBuilder;
211                                         }
212                                 });
213                 when(postReplyBuilder.withTime(anyLong())).thenAnswer(
214                                 new Answer<PostReplyBuilder>() {
215                                         @Override
216                                         public PostReplyBuilder answer(
217                                                         InvocationOnMock invocation) throws Throwable {
218                                                 when(postReply.getTime()).thenReturn(
219                                                                 (Long) invocation.getArguments()[0]);
220                                                 return postReplyBuilder;
221                                         }
222                                 });
223                 when(postReplyBuilder.withText(anyString())).thenAnswer(new Answer<PostReplyBuilder>() {
224                         @Override
225                         public PostReplyBuilder answer(InvocationOnMock invocation) throws Throwable {
226                                 when(postReply.getText()).thenReturn((String) invocation.getArguments()[0]);
227                                 return postReplyBuilder;
228                         }
229                 });
230                 when(postReplyBuilder.build()).thenAnswer(new Answer<PostReply>() {
231                         @Override
232                         public PostReply answer(InvocationOnMock invocation) throws Throwable {
233                                 PostReply postReply = SoneParserTest.this.postReply;
234                                 createdPostReplies.add(postReply);
235                                 SoneParserTest.this.postReply = mock(PostReply.class);
236                                 return postReply;
237                         }
238                 });
239                 when(database.newPostReplyBuilder()).thenReturn(postReplyBuilder);
240         }
241
242         @Before
243         public void setupAlbum() {
244                 final Album album = SoneParserTest.this.album;
245                 doAnswer(new Answer<Void>() {
246                         @Override
247                         public Void answer(InvocationOnMock invocation) {
248                                 nestedAlbums.put(album, (Album) invocation.getArguments()[0]);
249                                 return null;
250                         }
251                 }).when(album).addAlbum(any(Album.class));
252                 doAnswer(new Answer<Void>() {
253                         @Override
254                         public Void answer(InvocationOnMock invocation) {
255                                 albumImages.put(album, (Image) invocation.getArguments()[0]);
256                                 return null;
257                         }
258                 }).when(album).addImage(any(Image.class));
259                 when(album.getAlbums()).thenAnswer(new Answer<List<Album>>() {
260                         @Override
261                         public List<Album> answer(InvocationOnMock invocation) {
262                                 return nestedAlbums.get(album);
263                         }
264                 });
265                 when(album.getImages()).thenAnswer(new Answer<List<Image>>() {
266                         @Override
267                         public List<Image> answer(InvocationOnMock invocation) {
268                                 return albumImages.get(album);
269                         }
270                 });
271                 final Modifier albumModifier = new Modifier() {
272                         private String title = album.getTitle();
273                         private String description = album.getDescription();
274
275                         @Override
276                         public Modifier setTitle(String title) {
277                                 this.title = title;
278                                 return this;
279                         }
280
281                         @Override
282                         public Modifier setDescription(String description) {
283                                 this.description = description;
284                                 return this;
285                         }
286
287                         @Override
288                         public Album update() throws IllegalStateException {
289                                 when(album.getTitle()).thenReturn(title);
290                                 when(album.getDescription()).thenReturn(description);
291                                 return album;
292                         }
293                 };
294                 when(album.modify()).thenReturn(albumModifier);
295         }
296
297         @Before
298         public void setupAlbumBuilder() {
299                 when(albumBuilder.withId(anyString())).thenAnswer(new Answer<AlbumBuilder>() {
300                         @Override
301                         public AlbumBuilder answer(InvocationOnMock invocation) {
302                                 when(album.getId()).thenReturn((String) invocation.getArguments()[0]);
303                                 return albumBuilder;
304                         }
305                 });
306                 when(albumBuilder.randomId()).thenAnswer(new Answer<AlbumBuilder>() {
307                         @Override
308                         public AlbumBuilder answer(InvocationOnMock invocation) {
309                                 when(album.getId()).thenReturn(randomUUID().toString());
310                                 return albumBuilder;
311                         }
312                 });
313                 when(albumBuilder.by(any(Sone.class))).thenAnswer(new Answer<AlbumBuilder>() {
314                         @Override
315                         public AlbumBuilder answer(InvocationOnMock invocation) {
316                                 when(album.getSone()).thenReturn((Sone) invocation.getArguments()[0]);
317                                 return albumBuilder;
318                         }
319                 });
320                 when(albumBuilder.build()).thenAnswer(new Answer<Album>() {
321                         @Override
322                         public Album answer(InvocationOnMock invocation) {
323                                 Album album = SoneParserTest.this.album;
324                                 albums.put(album.getId(), album);
325                                 SoneParserTest.this.album = mock(Album.class);
326                                 setupAlbum();
327                                 return album;
328                         }
329                 });
330                 when(database.newAlbumBuilder()).thenReturn(albumBuilder);
331         }
332
333         @Before
334         public void setupAlbums() {
335                 when(database.getAlbum(anyString())).thenAnswer(new Answer<Album>() {
336                         @Override
337                         public Album answer(InvocationOnMock invocation)
338                         throws Throwable {
339                                 return albums.get(invocation.getArguments()[0]);
340                         }
341                 });
342         }
343
344         @Before
345         public void setupImage() {
346                 final Image image = SoneParserTest.this.image;
347                 Image.Modifier modifier = new Image.Modifier() {
348                         private Sone sone = image.getSone();
349                         private long creationTime = image.getCreationTime();
350                         private String key = image.getKey();
351                         private String title = image.getTitle();
352                         private String description = image.getDescription();
353                         private int width = image.getWidth();
354                         private int height = image.getHeight();
355
356                         @Override
357                         public Image.Modifier setSone(Sone sone) {
358                                 this.sone = sone;
359                                 return this;
360                         }
361
362                         @Override
363                         public Image.Modifier setCreationTime(long creationTime) {
364                                 this.creationTime = creationTime;
365                                 return this;
366                         }
367
368                         @Override
369                         public Image.Modifier setKey(String key) {
370                                 this.key = key;
371                                 return this;
372                         }
373
374                         @Override
375                         public Image.Modifier setTitle(String title) {
376                                 this.title = title;
377                                 return this;
378                         }
379
380                         @Override
381                         public Image.Modifier setDescription(String description) {
382                                 this.description = description;
383                                 return this;
384                         }
385
386                         @Override
387                         public Image.Modifier setWidth(int width) {
388                                 this.width = width;
389                                 return this;
390                         }
391
392                         @Override
393                         public Image.Modifier setHeight(int height) {
394                                 this.height = height;
395                                 return this;
396                         }
397
398                         @Override
399                         public Image update() throws IllegalStateException {
400                                 when(image.getSone()).thenReturn(sone);
401                                 when(image.getCreationTime()).thenReturn(creationTime);
402                                 when(image.getKey()).thenReturn(key);
403                                 when(image.getTitle()).thenReturn(title);
404                                 when(image.getDescription()).thenReturn(description);
405                                 when(image.getWidth()).thenReturn(width);
406                                 when(image.getHeight()).thenReturn(height);
407                                 return image;
408                         }
409                 };
410                 when(image.getSone()).thenReturn(sone);
411                 when(image.modify()).thenReturn(modifier);
412         }
413
414         @Before
415         public void setupImageBuilder() {
416                 when(imageBuilder.randomId()).thenAnswer(new Answer<ImageBuilder>() {
417                         @Override
418                         public ImageBuilder answer(InvocationOnMock invocation) {
419                                 when(image.getId()).thenReturn(randomUUID().toString());
420                                 return imageBuilder;
421                         }
422                 });
423                 when(imageBuilder.withId(anyString())).thenAnswer(new Answer<ImageBuilder>() {
424                         @Override
425                         public ImageBuilder answer(InvocationOnMock invocation) {
426                                 when(image.getId()).thenReturn(
427                                                 (String) invocation.getArguments()[0]);
428                                 return imageBuilder;
429                         }
430                 });
431                 when(imageBuilder.build()).thenAnswer(new Answer<Image>() {
432                         @Override
433                         public Image answer(InvocationOnMock invocation) {
434                                 Image image = SoneParserTest.this.image;
435                                 images.put(image.getId(), image);
436                                 SoneParserTest.this.image = mock(Image.class);
437                                 setupImage();
438                                 return image;
439                         }
440                 });
441                 when(database.newImageBuilder()).thenReturn(imageBuilder);
442         }
443
444         @Before
445         public void setupImages() {
446                 when(database.getImage(anyString())).thenAnswer(new Answer<Image>() {
447                         @Override
448                         public Image answer(InvocationOnMock invocation)
449                         throws Throwable {
450                                 return images.get(invocation.getArguments()[0]);
451                         }
452                 });
453         }
454         @Test
455         public void parsingASoneFailsWhenDocumentIsNotXml() throws SoneException {
456                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-not-xml.xml");
457                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
458         }
459
460         @Test
461         public void parsingASoneFailsWhenDocumentHasNegativeProtocolVersion() throws SoneException {
462                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-negative-protocol-version.xml");
463                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
464         }
465
466         @Test
467         public void parsingASoneFailsWhenProtocolVersionIsTooLarge() throws SoneException {
468                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-too-large-protocol-version.xml");
469                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
470         }
471
472         @Test
473         public void parsingASoneFailsWhenThereIsNoTime() throws SoneException {
474                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-no-time.xml");
475                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
476         }
477
478         @Test
479         public void parsingASoneFailsWhenTimeIsNotNumeric() throws SoneException {
480                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-time-not-numeric.xml");
481                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
482         }
483
484         @Test
485         public void parsingASoneFailsWhenProfileIsMissing() throws SoneException {
486                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-no-profile.xml");
487                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
488         }
489
490         @Test
491         public void parsingASoneFailsWhenProfileFieldIsMissingAFieldName() throws SoneException {
492                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-profile-missing-field-name.xml");
493                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
494         }
495
496         @Test
497         public void parsingASoneFailsWhenProfileFieldNameIsEmpty() throws SoneException {
498                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-profile-empty-field-name.xml");
499                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
500         }
501
502         @Test
503         public void parsingASoneFailsWhenProfileFieldNameIsNotUnique() throws SoneException {
504                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-profile-duplicate-field-name.xml");
505                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
506         }
507
508         @Test
509         public void parsingASoneSucceedsWithoutPayload() throws SoneException {
510                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-no-payload.xml");
511                 assertThat(soneParser.parseSone(sone, inputStream).getTime(), is(
512                                 1407197508000L));
513         }
514
515         @Test
516         public void parsingALocalSoneSucceedsWithoutPayload() throws SoneException {
517                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-no-payload.xml");
518                 Sone localSone = mock(Sone.class);
519                 setupSone(localSone, OwnIdentity.class);
520                 when(localSone.isLocal()).thenReturn(true);
521                 Sone parsedSone = soneParser.parseSone(localSone, inputStream);
522                 assertThat(parsedSone.getTime(), is(1407197508000L));
523                 assertThat(parsedSone.isLocal(), is(true));
524         }
525
526         @Test
527         public void parsingASoneSucceedsWithoutProtocolVersion() throws SoneException {
528                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-missing-protocol-version.xml");
529                 assertThat(soneParser.parseSone(sone, inputStream), not(
530                                 nullValue()));
531         }
532
533         @Test
534         public void parsingASoneFailsWithMissingClientName() throws SoneException {
535                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-missing-client-name.xml");
536                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
537         }
538
539         @Test
540         public void parsingASoneFailsWithMissingClientVersion() throws SoneException {
541                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-missing-client-version.xml");
542                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
543         }
544
545         @Test
546         public void parsingASoneSucceedsWithClientInfo() throws SoneException {
547                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-client-info.xml");
548                 assertThat(soneParser.parseSone(sone, inputStream).getClient(), is(new Client("some-client", "some-version")));
549         }
550
551         @Test
552         public void parsingASoneSucceedsWithProfile() throws SoneException,
553         MalformedURLException {
554                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-profile.xml");
555                 final Profile profile = soneParser.parseSone(sone, inputStream).getProfile();
556                 assertThat(profile.getFirstName(), is("first"));
557                 assertThat(profile.getMiddleName(), is("middle"));
558                 assertThat(profile.getLastName(), is("last"));
559                 assertThat(profile.getBirthDay(), is(18));
560                 assertThat(profile.getBirthMonth(), is(12));
561                 assertThat(profile.getBirthYear(), is(1976));
562         }
563
564         @Test
565         public void parsingASoneSucceedsWithoutProfileFields() throws SoneException, MalformedURLException {
566                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-fields.xml");
567                 assertThat(soneParser.parseSone(sone, inputStream), notNullValue());
568         }
569
570         @Test
571         public void parsingASoneFailsWithoutPostId() throws SoneException, MalformedURLException {
572                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-id.xml");
573                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
574         }
575
576         @Test
577         public void parsingASoneFailsWithoutPostTime() throws SoneException, MalformedURLException {
578                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-time.xml");
579                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
580         }
581
582         @Test
583         public void parsingASoneFailsWithoutPostText() throws SoneException, MalformedURLException {
584                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-text.xml");
585                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
586         }
587
588         @Test
589         public void parsingASoneFailsWithInvalidPostTime() throws SoneException, MalformedURLException {
590                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-post-time.xml");
591                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
592         }
593
594         @Test
595         public void parsingASoneSucceedsWithValidPostTime() throws SoneException, MalformedURLException {
596                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-valid-post-time.xml");
597                 final List<Post> posts = soneParser.parseSone(sone, inputStream).getPosts();
598                 assertThat(posts, is(createdPosts));
599                 assertThat(posts.get(0).getSone().getId(), is(sone.getId()));
600                 assertThat(posts.get(0).getId(), is("post-id"));
601                 assertThat(posts.get(0).getTime(), is(1407197508000L));
602                 assertThat(posts.get(0).getRecipientId(), is(Optional.<String>absent()));
603                 assertThat(posts.get(0).getText(), is("text"));
604         }
605
606         @Test
607         public void parsingASoneSucceedsWithRecipient() throws SoneException, MalformedURLException {
608                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-recipient.xml");
609                 final List<Post> posts = soneParser.parseSone(sone, inputStream).getPosts();
610                 assertThat(posts, is(createdPosts));
611                 assertThat(posts.get(0).getSone().getId(), is(sone.getId()));
612                 assertThat(posts.get(0).getId(), is("post-id"));
613                 assertThat(posts.get(0).getTime(), is(1407197508000L));
614                 assertThat(posts.get(0).getRecipientId(), is(of(
615                                 "1234567890123456789012345678901234567890123")));
616                 assertThat(posts.get(0).getText(), is("text"));
617         }
618
619         @Test
620         public void parsingASoneSucceedsWithInvalidRecipient() throws SoneException, MalformedURLException {
621                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-recipient.xml");
622                 final List<Post> posts = soneParser.parseSone(sone, inputStream).getPosts();
623                 assertThat(posts, is(createdPosts));
624                 assertThat(posts.get(0).getSone().getId(), is(sone.getId()));
625                 assertThat(posts.get(0).getId(), is("post-id"));
626                 assertThat(posts.get(0).getTime(), is(1407197508000L));
627                 assertThat(posts.get(0).getRecipientId(), is(Optional.<String>absent()));
628                 assertThat(posts.get(0).getText(), is("text"));
629         }
630
631         @Test
632         public void parsingASoneFailsWithoutPostReplyId() throws SoneException, MalformedURLException {
633                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-reply-id.xml");
634                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
635         }
636
637         @Test
638         public void parsingASoneFailsWithoutPostReplyPostId() throws SoneException, MalformedURLException {
639                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-reply-post-id.xml");
640                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
641         }
642
643         @Test
644         public void parsingASoneFailsWithoutPostReplyTime() throws SoneException, MalformedURLException {
645                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-reply-time.xml");
646                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
647         }
648
649         @Test
650         public void parsingASoneFailsWithoutPostReplyText() throws SoneException, MalformedURLException {
651                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-post-reply-text.xml");
652                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
653         }
654
655         @Test
656         public void parsingASoneFailsWithInvalidPostReplyTime() throws SoneException, MalformedURLException {
657                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-post-reply-time.xml");
658                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
659         }
660
661         @Test
662         public void parsingASoneSucceedsWithValidPostReplyTime() throws SoneException, MalformedURLException {
663                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-valid-post-reply-time.xml");
664                 final Set<PostReply> postReplies = soneParser.parseSone(sone, inputStream).getReplies();
665                 assertThat(postReplies, is(createdPostReplies));
666                 PostReply postReply = createdPostReplies.iterator().next();
667                 assertThat(postReply.getId(), is("reply-id"));
668                 assertThat(postReply.getPostId(), is("post-id"));
669                 assertThat(postReply.getPost().get().getId(), is("post-id"));
670                 assertThat(postReply.getSone().getId(), is("identity"));
671                 assertThat(postReply.getTime(), is(1407197508000L));
672                 assertThat(postReply.getText(), is("reply-text"));
673         }
674
675         @Test
676         public void parsingASoneSucceedsWithoutLikedPostIds() throws SoneException, MalformedURLException {
677                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-liked-post-ids.xml");
678                 assertThat(soneParser.parseSone(sone, inputStream), not(
679                                 nullValue()));
680         }
681
682         @Test
683         public void parsingASoneSucceedsWithLikedPostIds() throws SoneException, MalformedURLException {
684                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-liked-post-ids.xml");
685                 assertThat(soneParser.parseSone(sone, inputStream).getLikedPostIds(), is(
686                                 (Set<String>) ImmutableSet.of("liked-post-id")));
687         }
688
689         @Test
690         public void parsingASoneSucceedsWithoutLikedPostReplyIds() throws SoneException, MalformedURLException {
691                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-liked-post-reply-ids.xml");
692                 assertThat(soneParser.parseSone(sone, inputStream), not(
693                                 nullValue()));
694         }
695
696         @Test
697         public void parsingASoneSucceedsWithLikedPostReplyIds() throws SoneException, MalformedURLException {
698                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-liked-post-reply-ids.xml");
699                 assertThat(soneParser.parseSone(sone, inputStream).getLikedReplyIds(), is(
700                                 (Set<String>) ImmutableSet.of("liked-post-reply-id")));
701         }
702
703         @Test
704         public void parsingASoneSucceedsWithoutAlbums() throws SoneException, MalformedURLException {
705                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-albums.xml");
706                 assertThat(soneParser.parseSone(sone, inputStream), not(
707                                 nullValue()));
708         }
709
710         @Test
711         public void parsingASoneFailsWithoutAlbumId() throws SoneException, MalformedURLException {
712                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-album-id.xml");
713                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
714         }
715
716         @Test
717         public void parsingASoneFailsWithoutAlbumTitle() throws SoneException, MalformedURLException {
718                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-album-title.xml");
719                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
720         }
721
722         @Test
723         public void parsingASoneSucceedsWithNestedAlbums() throws SoneException, MalformedURLException {
724                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-multiple-albums.xml");
725                 final Sone parsedSone = soneParser.parseSone(sone, inputStream);
726                 assertThat(parsedSone, not(nullValue()));
727                 assertThat(parsedSone.getRootAlbum().getAlbums(), hasSize(1));
728                 Album album = parsedSone.getRootAlbum().getAlbums().get(0);
729                 assertThat(album.getId(), is("album-id-1"));
730                 assertThat(album.getTitle(), is("album-title"));
731                 assertThat(album.getDescription(), is("album-description"));
732                 assertThat(album.getAlbums(), hasSize(1));
733                 Album nestedAlbum = album.getAlbums().get(0);
734                 assertThat(nestedAlbum.getId(), is("album-id-2"));
735                 assertThat(nestedAlbum.getTitle(), is("album-title-2"));
736                 assertThat(nestedAlbum.getDescription(), is("album-description-2"));
737                 assertThat(nestedAlbum.getAlbums(), hasSize(0));
738         }
739
740         @Test
741         public void parsingASoneFailsWithInvalidParentAlbumId() throws SoneException, MalformedURLException {
742                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-parent-album-id.xml");
743                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
744         }
745
746         @Test
747         public void parsingASoneSucceedsWithoutImages() throws SoneException, MalformedURLException {
748                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-images.xml");
749                 assertThat(soneParser.parseSone(sone, inputStream), not(
750                                 nullValue()));
751         }
752
753         @Test
754         public void parsingASoneFailsWithoutImageId() throws SoneException, MalformedURLException {
755                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-id.xml");
756                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
757         }
758
759         @Test
760         public void parsingASoneFailsWithoutImageTime() throws SoneException, MalformedURLException {
761                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-time.xml");
762                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
763         }
764
765         @Test
766         public void parsingASoneFailsWithoutImageKey() throws SoneException, MalformedURLException {
767                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-key.xml");
768                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
769         }
770
771         @Test
772         public void parsingASoneFailsWithoutImageTitle() throws SoneException, MalformedURLException {
773                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-title.xml");
774                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
775         }
776
777         @Test
778         public void parsingASoneFailsWithoutImageWidth() throws SoneException, MalformedURLException {
779                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-width.xml");
780                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
781         }
782
783         @Test
784         public void parsingASoneFailsWithoutImageHeight() throws SoneException, MalformedURLException {
785                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-without-image-height.xml");
786                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
787         }
788
789         @Test
790         public void parsingASoneFailsWithInvalidImageWidth() throws SoneException, MalformedURLException {
791                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-image-width.xml");
792                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
793         }
794
795         @Test
796         public void parsingASoneFailsWithInvalidImageHeight() throws SoneException, MalformedURLException {
797                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-invalid-image-height.xml");
798                 assertThat(soneParser.parseSone(sone, inputStream), nullValue());
799         }
800
801         @Test
802         public void parsingASoneSucceedsWithImage() throws SoneException, MalformedURLException {
803                 InputStream inputStream = getClass().getResourceAsStream("sone-parser-with-image.xml");
804                 final Sone sone = soneParser.parseSone(this.sone, inputStream);
805                 assertThat(sone, not(nullValue()));
806                 assertThat(sone.getRootAlbum().getAlbums(), hasSize(1));
807                 assertThat(sone.getRootAlbum().getAlbums().get(0).getImages(), hasSize(1));
808                 Image image = sone.getRootAlbum().getAlbums().get(0).getImages().get(0);
809                 assertThat(image.getId(), is("image-id"));
810                 assertThat(image.getCreationTime(), is(1407197508000L));
811                 assertThat(image.getKey(), is("KSK@GPLv3.txt"));
812                 assertThat(image.getTitle(), is("image-title"));
813                 assertThat(image.getDescription(), is("image-description"));
814                 assertThat(image.getWidth(), is(1920));
815                 assertThat(image.getHeight(), is(1080));
816                 assertThat(sone.getProfile().getAvatar(), is("image-id"));
817         }
818
819
820 }