1 package net.pterodactylus.sone.core;
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.CoreMatchers.nullValue;
9 import static org.hamcrest.MatcherAssert.assertThat;
10 import static org.hamcrest.Matchers.containsInAnyOrder;
11 import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
12 import static org.mockito.Matchers.anyString;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.when;
16 import java.io.InputStream;
17 import java.io.UnsupportedEncodingException;
18 import java.util.logging.Logger;
20 import net.pterodactylus.sone.data.Client;
21 import net.pterodactylus.sone.data.Image;
22 import net.pterodactylus.sone.data.Post;
23 import net.pterodactylus.sone.data.PostReply;
24 import net.pterodactylus.sone.data.Profile.Field;
25 import net.pterodactylus.sone.data.Sone;
26 import net.pterodactylus.sone.database.Database;
27 import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
28 import net.pterodactylus.sone.database.memory.MemoryDatabase;
30 import com.google.common.base.Optional;
31 import org.hamcrest.Description;
32 import org.hamcrest.Matcher;
33 import org.hamcrest.TypeSafeMatcher;
34 import org.junit.Test;
37 * Unit test for {@link SoneParser}.
39 * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
41 public class SoneParserTest {
44 Logger.getLogger("").setLevel(OFF);
47 private final Core core = mock(Core.class);
48 private final Database database = new MemoryDatabase(null);
49 private final Sone originalSone = database.newSoneBuilder().by("test").using(new Client("TestClient", "1.0")).build(Optional.<SoneCreated>absent());
50 private final SoneParser soneParser = new SoneParser();
52 public SoneParserTest() {
53 Optional<Image> image = mock(Optional.class);
54 when(core.getImage(anyString())).thenReturn(image);
58 public void verifyThatAnInvalidXmlDocumentIsNotParsed() {
59 soneParser.parseSone(database, originalSone, getXml("invalid-xml"));
63 public void verifyThatANegativeProtocolVersionCausesAnError() {
64 soneParser.parseSone(database, originalSone, getXml("negative-protocol-version"));
68 public void verifyThatATooLargeProtocolVersionCausesAnError() {
69 soneParser.parseSone(database, originalSone, getXml("too-large-protocol-version"));
73 public void verifyThatAMissingTimeCausesAnError() {
74 soneParser.parseSone(database, originalSone, getXml("missing-time"));
78 public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
79 Sone sone = soneParser.parseSone(database, originalSone, getXml("missing-client"));
80 assertThat(sone, notNullValue());
81 assertThat(sone.getClient(), notNullValue());
82 assertThat(sone.getClient(), is(originalSone.getClient()));
86 public void verifyThatAnInvalidClientCausesTheOriginalClientToBeUsed() {
87 Sone sone = soneParser.parseSone(database, originalSone, getXml("invalid-client"));
88 assertThat(sone, notNullValue());
89 assertThat(sone.getClient(), notNullValue());
90 assertThat(sone.getClient(), is(originalSone.getClient()));
94 public void verifyThatTheCreatedSoneMeetsAllExpectations() {
95 Sone sone = soneParser.parseSone(database, originalSone, getXml("complete"));
96 assertThat(sone, notNullValue());
97 assertThat(sone.getTime(), is(1382419919000L));
98 assertThat(sone.getClient(), notNullValue());
99 assertThat(sone.getClient().getName(), is("Sone"));
100 assertThat(sone.getClient().getVersion(), is("0.8.7"));
101 assertThat(sone.getProfile(), notNullValue());
102 assertThat(sone.getProfile().getFirstName(), is("First"));
103 assertThat(sone.getProfile().getMiddleName(), is("M."));
104 assertThat(sone.getProfile().getLastName(), is("Last"));
105 assertThat(sone.getProfile().getBirthYear(), is(2013));
106 assertThat(sone.getProfile().getBirthMonth(), is(10));
107 assertThat(sone.getProfile().getBirthDay(), is(22));
108 assertThat(sone.getProfile().getAvatar(), is("96431abe-3add-11e3-8a46-67047503bf6d"));
109 assertThat(sone.getProfile().getFields(), contains(
110 fieldMatcher("Field1", "Value1"),
111 fieldMatcher("Field2", "Value2")
113 assertThat(sone.getPosts(), contains(
114 postMatcher("d8c9586e-3adb-11e3-bb31-171fc040e645", "0rpD4gL8mszav2trndhIdKIxvKUCNAe2kjA3dLV8CVU", 1382420181000L, "Hello, User!"),
115 postMatcher("bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", null, 1382420140000L, "Hello, World!")
117 assertThat(sone.getReplies(), containsInAnyOrder(
118 postReplyMatcher("f09fa448-3adb-11e3-a783-ab54a11aacc4", "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3", 1382420224000L, "Talking to myself."),
119 postReplyMatcher("0a376440-3adc-11e3-8f45-c7cc157436a5", "11ebe86e-3adc-11e3-b7b9-7f2c88018a33", 1382420271000L, "Talking to somebody I can't see.")
121 assertThat(sone.getLikedPostIds(), containsInAnyOrder(
122 "bbb7ebf0-3adb-11e3-8a0b-630cd8f21cf3",
123 "305d85e6-3adc-11e3-be45-8b53dd91f0af"
125 assertThat(sone.getLikedReplyIds(), containsInAnyOrder(
126 "f09fa448-3adb-11e3-a783-ab54a11aacc4",
127 "3ba28960-3adc-11e3-93c7-6713d170f44c"
131 private Matcher<PostReply> postReplyMatcher(final String id, final String postId, final long time, final String text) {
132 return new TypeSafeMatcher<PostReply>() {
134 protected boolean matchesSafely(PostReply postReply) {
135 return postReply.getId().equals(id) && postReply.getPostId().equals(postId) && (postReply.getTime() == time) && postReply.getText().equals(text);
139 public void describeTo(Description description) {
140 description.appendText("PostReply(")
141 .appendValue(id).appendText(", ")
142 .appendValue(postId).appendText(", ")
143 .appendValue(time).appendText(", ")
144 .appendValue(text).appendText(")");
148 protected void describeMismatchSafely(PostReply postReply, Description mismatchDescription) {
149 mismatchDescription.appendText("PostReply(")
150 .appendValue(postReply.getId()).appendText(", ")
151 .appendValue(postReply.getPostId()).appendText(", ")
152 .appendValue(postReply.getTime()).appendText(", ")
153 .appendValue(postReply.getText()).appendText(")");
158 private Matcher<Post> postMatcher(final String id, final String recipient, final long time, final String text) {
159 return new TypeSafeMatcher<Post>() {
161 protected boolean matchesSafely(Post post) {
162 return post.getId().equals(id) && equal(post.getRecipientId().orNull(), recipient) && (post.getTime() == time) && post.getText().equals(text);
166 public void describeTo(Description description) {
167 description.appendText("Post(")
168 .appendValue(id).appendText(", ")
169 .appendValue(recipient).appendText(", ")
170 .appendValue(time).appendText(", ")
171 .appendValue(text).appendText(")");
175 protected void describeMismatchSafely(Post post, Description mismatchDescription) {
176 mismatchDescription.appendText("Post(")
177 .appendValue(post.getId()).appendText(", ")
178 .appendValue(post.getRecipientId().orNull()).appendText(", ")
179 .appendValue(post.getTime()).appendText(", ")
180 .appendValue(post.getText()).appendText(")");
185 private Matcher<Field> fieldMatcher(final String name, final String value) {
186 return new TypeSafeMatcher<Field>() {
188 protected boolean matchesSafely(Field field) {
189 return field.getName().equals(name) && field.getValue().equals(value);
193 public void describeTo(Description description) {
194 description.appendText("field named ").appendValue(name).appendText(" with value ").appendValue(value);
198 protected void describeMismatchSafely(Field field, Description mismatchDescription) {
199 mismatchDescription.appendText("field named ").appendValue(field.getName()).appendText(" with value ").appendValue(field.getValue());
204 private InputStream getXml(String name) {
205 return getClass().getResourceAsStream(format("/sone-parser/%s.xml", name));