16fa99ef5eee11b17618757c92ca2d9fb359fa2f
[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.InvalidProtocolVersion;
21 import net.pterodactylus.sone.core.SoneParser.InvalidXml;
22 import net.pterodactylus.sone.core.SoneParser.MalformedXml;
23 import net.pterodactylus.sone.data.Client;
24 import net.pterodactylus.sone.data.Image;
25 import net.pterodactylus.sone.data.Post;
26 import net.pterodactylus.sone.data.PostReply;
27 import net.pterodactylus.sone.data.Profile.Field;
28 import net.pterodactylus.sone.data.Sone;
29 import net.pterodactylus.sone.database.Database;
30 import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
31 import net.pterodactylus.sone.database.memory.MemoryDatabase;
32
33 import com.google.common.base.Optional;
34 import org.hamcrest.Description;
35 import org.hamcrest.Matcher;
36 import org.hamcrest.TypeSafeMatcher;
37 import org.junit.Test;
38
39 /**
40  * Unit test for {@link SoneParser}.
41  *
42  * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
43  */
44 public class SoneParserTest {
45
46         static {
47                 Logger.getLogger("").setLevel(OFF);
48         }
49
50         private final Core core = mock(Core.class);
51         private final Database database = new MemoryDatabase(null);
52         private final Sone originalSone = database.newSoneBuilder().by("test").using(new Client("TestClient", "1.0")).build(Optional.<SoneCreated>absent());
53         private final SoneParser soneParser = new SoneParser();
54
55         public SoneParserTest() {
56                 Optional<Image> image = mock(Optional.class);
57                 when(core.getImage(anyString())).thenReturn(image);
58         }
59
60         @Test(expected = InvalidXml.class)
61         public void verifyThatAnInvalidXmlDocumentIsNotParsed() {
62                 soneParser.parseSone(database, originalSone, getXml("invalid-xml"));
63         }
64
65         @Test(expected = InvalidProtocolVersion.class)
66         public void verifyThatANegativeProtocolVersionCausesAnError() {
67                 soneParser.parseSone(database, originalSone, getXml("negative-protocol-version"));
68         }
69
70         @Test(expected = InvalidProtocolVersion.class)
71         public void verifyThatATooLargeProtocolVersionCausesAnError() {
72                 soneParser.parseSone(database, originalSone, getXml("too-large-protocol-version"));
73         }
74
75         @Test(expected = MalformedXml.class)
76         public void verifyThatAMissingTimeCausesAnError() {
77                 soneParser.parseSone(database, originalSone, getXml("missing-time"));
78         }
79
80         @Test
81         public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
82                 Sone sone = soneParser.parseSone(database, originalSone, getXml("missing-client"));
83                 assertThat(sone, notNullValue());
84                 assertThat(sone.getClient(), notNullValue());
85                 assertThat(sone.getClient(), is(originalSone.getClient()));
86         }
87
88         @Test
89         public void verifyThatAnInvalidClientCausesTheOriginalClientToBeUsed() {
90                 Sone sone = soneParser.parseSone(database, originalSone, getXml("invalid-client"));
91                 assertThat(sone, notNullValue());
92                 assertThat(sone.getClient(), notNullValue());
93                 assertThat(sone.getClient(), is(originalSone.getClient()));
94         }
95
96         @Test(expected = MalformedXml.class)
97         public void verifyThatAMissingProfileCausesAnError() {
98                 soneParser.parseSone(database, originalSone, getXml("missing-profile"));
99         }
100
101         @Test
102         public void verifyThatAnEmptyProfileIsParsedWithoutError() {
103                 Sone sone = soneParser.parseSone(database, originalSone, getXml("empty-profile"));
104                 assertThat(sone.getProfile().getFirstName(), nullValue());
105                 assertThat(sone.getProfile().getMiddleName(), nullValue());
106                 assertThat(sone.getProfile().getLastName(), nullValue());
107                 assertThat(sone.getProfile().getBirthYear(), nullValue());
108                 assertThat(sone.getProfile().getBirthMonth(), nullValue());
109                 assertThat(sone.getProfile().getBirthDay(), nullValue());
110                 assertThat(sone.getProfile().getAvatar(), nullValue());
111                 assertThat(sone.getProfile().getFields(), empty());
112         }
113
114         @Test
115         public void verifyThatTheCreatedSoneMeetsAllExpectations() {
116                 Sone sone = soneParser.parseSone(database, originalSone, getXml("complete"));
117                 assertThat(sone, notNullValue());
118                 assertThat(sone.getTime(), is(1382419919000L));
119                 assertThat(sone.getClient(), notNullValue());
120                 assertThat(sone.getClient().getName(), is("Sone"));
121                 assertThat(sone.getClient().getVersion(), is("0.8.7"));
122                 assertThat(sone.getProfile(), notNullValue());
123                 assertThat(sone.getProfile().getFirstName(), is("First"));
124                 assertThat(sone.getProfile().getMiddleName(), is("M."));
125                 assertThat(sone.getProfile().getLastName(), is("Last"));
126                 assertThat(sone.getProfile().getBirthYear(), is(2013));
127                 assertThat(sone.getProfile().getBirthMonth(), is(10));
128                 assertThat(sone.getProfile().getBirthDay(), is(22));
129                 assertThat(sone.getProfile().getAvatar(), is("96431abe-3add-11e3-8a46-67047503bf6d"));
130                 assertThat(sone.getProfile().getFields(), contains(
131                                 fieldMatcher("Field1", "Value1"),
132                                 fieldMatcher("Field2", "Value2")
133                 ));
134                 assertThat(sone.getPosts(), contains(
135                                 postMatcher("d8c9586e-3adb-11e3-bb31-171fc040e645", "0rpD4gL8mszav2trndhIdKIxvKUCNAe2kjA3dLV8CVU", 1382420181000L, "Hello, User!"),
136                                 postMatcher("bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", null, 1382420140000L, "Hello, World!")
137                 ));
138                 assertThat(sone.getReplies(), containsInAnyOrder(
139                                 postReplyMatcher("f09fa448-3adb-11e3-a783-ab54a11aacc4", "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", 1382420224000L, "Talking to myself."),
140                                 postReplyMatcher("0a376440-3adc-11e3-8f45-c7cc157436a5", "11ebe86e-3adc-11e3-b7b9-7f2c88018a33", 1382420271000L, "Talking to somebody I can't see.")
141                 ));
142                 assertThat(sone.getLikedPostIds(), containsInAnyOrder(
143                                 "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3",
144                                 "305d85e6-3adc-11e3-be45-8b53dd91f0af"
145                 ));
146                 assertThat(sone.getLikedReplyIds(), containsInAnyOrder(
147                                 "f09fa448-3adb-11e3-a783-ab54a11aacc4",
148                                 "3ba28960-3adc-11e3-93c7-6713d170f44c"
149                 ));
150         }
151
152         private Matcher<PostReply> postReplyMatcher(final String id, final String postId, final long time, final String text) {
153                 return new TypeSafeMatcher<PostReply>() {
154                         @Override
155                         protected boolean matchesSafely(PostReply postReply) {
156                                 return postReply.getId().equals(id) && postReply.getPostId().equals(postId) && (postReply.getTime() == time) && postReply.getText().equals(text);
157                         }
158
159                         @Override
160                         public void describeTo(Description description) {
161                                 description.appendText("PostReply(")
162                                                 .appendValue(id).appendText(", ")
163                                                 .appendValue(postId).appendText(", ")
164                                                 .appendValue(time).appendText(", ")
165                                                 .appendValue(text).appendText(")");
166                         }
167
168                         @Override
169                         protected void describeMismatchSafely(PostReply postReply, Description mismatchDescription) {
170                                 mismatchDescription.appendText("PostReply(")
171                                                 .appendValue(postReply.getId()).appendText(", ")
172                                                 .appendValue(postReply.getPostId()).appendText(", ")
173                                                 .appendValue(postReply.getTime()).appendText(", ")
174                                                 .appendValue(postReply.getText()).appendText(")");
175                         }
176                 };
177         }
178
179         private Matcher<Post> postMatcher(final String id, final String recipient, final long time, final String text) {
180                 return new TypeSafeMatcher<Post>() {
181                         @Override
182                         protected boolean matchesSafely(Post post) {
183                                 return post.getId().equals(id) && equal(post.getRecipientId().orNull(), recipient) && (post.getTime() == time) && post.getText().equals(text);
184                         }
185
186                         @Override
187                         public void describeTo(Description description) {
188                                 description.appendText("Post(")
189                                                 .appendValue(id).appendText(", ")
190                                                 .appendValue(recipient).appendText(", ")
191                                                 .appendValue(time).appendText(", ")
192                                                 .appendValue(text).appendText(")");
193                         }
194
195                         @Override
196                         protected void describeMismatchSafely(Post post, Description mismatchDescription) {
197                                 mismatchDescription.appendText("Post(")
198                                                 .appendValue(post.getId()).appendText(", ")
199                                                 .appendValue(post.getRecipientId().orNull()).appendText(", ")
200                                                 .appendValue(post.getTime()).appendText(", ")
201                                                 .appendValue(post.getText()).appendText(")");
202                         }
203                 };
204         }
205
206         private Matcher<Field> fieldMatcher(final String name, final String value) {
207                 return new TypeSafeMatcher<Field>() {
208                         @Override
209                         protected boolean matchesSafely(Field field) {
210                                 return field.getName().equals(name) && field.getValue().equals(value);
211                         }
212
213                         @Override
214                         public void describeTo(Description description) {
215                                 description.appendText("field named ").appendValue(name).appendText(" with value ").appendValue(value);
216                         }
217
218                         @Override
219                         protected void describeMismatchSafely(Field field, Description mismatchDescription) {
220                                 mismatchDescription.appendText("field named ").appendValue(field.getName()).appendText(" with value ").appendValue(field.getValue());
221                         }
222                 };
223         }
224
225         private InputStream getXml(String name) {
226                 return getClass().getResourceAsStream(format("/sone-parser/%s.xml", name));
227         }
228
229 }