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