1 package net.pterodactylus.sone.core;
3 import static com.google.common.base.Optional.absent;
4 import static com.google.common.base.Optional.fromNullable;
5 import static com.google.common.base.Optional.of;
6 import static java.lang.String.format;
7 import static java.util.logging.Level.OFF;
8 import static org.hamcrest.CoreMatchers.is;
9 import static org.hamcrest.CoreMatchers.notNullValue;
10 import static org.hamcrest.MatcherAssert.assertThat;
11 import static org.mockito.Matchers.anyString;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.when;
15 import java.io.ByteArrayInputStream;
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.Sone;
23 import net.pterodactylus.sone.database.Database;
24 import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
25 import net.pterodactylus.sone.database.memory.MemoryDatabase;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Optional;
29 import org.junit.Test;
32 * Unit test for {@link SoneParser}.
34 * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
36 public class SoneParserTest {
39 Logger.getLogger("").setLevel(OFF);
42 private final Core core = mock(Core.class);
43 private final Database database = new MemoryDatabase(null);
44 private final Sone originalSone = database.newSoneBuilder().by("test").using(new Client("TestClient", "1.0")).build(Optional.<SoneCreated>absent());
45 private final SoneXmlBuilder soneXmlBuilder = new SoneXmlBuilder();
46 private final SoneParser soneParser = new SoneParser();
48 public SoneParserTest() {
49 Optional<Image> image = mock(Optional.class);
50 when(core.getImage(anyString())).thenReturn(image);
54 public void verifyThatAnInvalidXmlDocumentIsNotParsed() throws UnsupportedEncodingException {
55 Optional<Sone> sone = soneParser.parseSone(database, originalSone, getXml("invalid-xml"));
56 assertThat(sone, notNullValue());
57 assertThat(sone.isPresent(), is(false));
61 public void verifyThatANegativeProtocolVersionCausesAnError() {
62 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("-1").get());
63 assertThat(sone, notNullValue());
64 assertThat(sone.isPresent(), is(false));
68 public void verifyThatATooLargeProtocolVersionCausesAnError() {
69 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("1").get());
70 assertThat(sone, notNullValue());
71 assertThat(sone.isPresent(), is(false));
75 public void verifyThatAMissingTimeCausesAnError() {
76 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.removeTime().get());
77 assertThat(sone, notNullValue());
78 assertThat(sone.isPresent(), is(false));
82 public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
83 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.removeClientInformation().get());
84 assertThat(sone, notNullValue());
85 assertThat(sone.isPresent(), is(true));
86 assertThat(sone.get().getClient(), notNullValue());
87 assertThat(sone.get().getClient(), is(originalSone.getClient()));
91 public void verifyThatTheCreatedSoneMeetsAllExpectations() {
92 Optional<Sone> sone = soneParser.parseSone(database, originalSone, getXml("complete"));
93 assertThat(sone, notNullValue());
94 assertThat(sone.isPresent(), is(true));
95 assertThat(sone.get().getTime(), is(1382419919000L));
96 assertThat(sone.get().getClient(), notNullValue());
97 assertThat(sone.get().getClient().getName(), is("Sone"));
98 assertThat(sone.get().getClient().getVersion(), is("0.8.7"));
99 assertThat(sone.get().getProfile(), notNullValue());
100 assertThat(sone.get().getProfile().getFirstName(), is("First"));
101 assertThat(sone.get().getProfile().getMiddleName(), is("M."));
102 assertThat(sone.get().getProfile().getLastName(), is("Last"));
103 assertThat(sone.get().getProfile().getBirthYear(), is(2013));
104 assertThat(sone.get().getProfile().getBirthMonth(), is(10));
105 assertThat(sone.get().getProfile().getBirthDay(), is(22));
106 assertThat(sone.get().getProfile().getAvatar(), is("96431abe-3add-11e3-8a46-67047503bf6d"));
109 public InputStream getInputStream(String content) throws UnsupportedEncodingException {
110 return new ByteArrayInputStream(content.getBytes("UTF-8"));
113 private InputStream getXml(String name) {
114 return getClass().getResourceAsStream(format("/sone-parser/%s.xml", name));
117 private static class SoneXmlBuilder {
119 private Optional<Long> time = of(1000L);
120 private Optional<String> protocolVersion = of("0");
121 private Optional<String> clientInformation = of("<name>Test-Client</name><version>1.0</version>");
122 private Optional<String> profile = of(Joiner.on("").join(
123 "<first-name>First</first-name>",
124 "<middle-name>M.</middle-name>",
125 "<last-name>Last</last-name>",
126 "<birth-year>2000</birth-year>",
127 "<birth-month>9</birth-month>",
128 "<birth-day>13</birth-day>",
129 "<avatar>avatar-id</avatar>",
131 "<field><field-name>Custom Field</field-name><field-value>Custom Value</field-value></field>",
134 private Optional<String> posts = of("<post><id>post-id</id><time>1</time><recipient>recipient</recipient><text>Hello!</text></post>");
135 private Optional<String> replies = of("<reply><id>reply-id</id><post-id>post-id</post-id><time>2</time><text>Reply!</text></reply>");
137 public SoneXmlBuilder removeTime() {
142 public SoneXmlBuilder setProtocolVersion(String protocolVersion) {
143 this.protocolVersion = fromNullable(protocolVersion);
147 public SoneXmlBuilder removeProtocolVersion() {
148 this.protocolVersion = absent();
152 public SoneXmlBuilder setClientInformation(String name, String version) {
153 clientInformation = of("<name>" + name + "</name><version>" + version + "</version>");
157 public SoneXmlBuilder removeClientInformation() {
158 clientInformation = absent();
162 public SoneXmlBuilder removeProfile() {
167 public SoneXmlBuilder removePost() {
172 public SoneXmlBuilder removeReply() {
177 public InputStream get() {
178 StringBuilder content = new StringBuilder();
179 content.append("<sone>");
180 if (time.isPresent()) {
181 content.append(createXmlElement("time", String.valueOf(time.get())));
183 if (protocolVersion.isPresent()) {
184 content.append(createXmlElement("protocol-version", protocolVersion.get()));
186 if (clientInformation.isPresent()) {
187 content.append(createXmlElement("client", clientInformation.get()));
189 if (profile.isPresent()) {
190 content.append(createXmlElement("profile", profile.get()));
192 if (posts.isPresent()) {
193 content.append(createXmlElement("posts", posts.get()));
195 content.append("</sone>");
197 String xmlString = content.toString();
198 return new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
199 } catch (UnsupportedEncodingException e) {
205 private String createXmlElement(String xmlElement, String content) {
206 return format("<%s>%s</%1$s>", xmlElement, content);