Use XML file to test a complete Sone.
[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.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;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.InputStream;
17 import java.io.UnsupportedEncodingException;
18 import java.util.logging.Logger;
19
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;
26
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Optional;
29 import org.junit.Test;
30
31 /**
32  * Unit test for {@link SoneParser}.
33  *
34  * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
35  */
36 public class SoneParserTest {
37
38         static {
39                 Logger.getLogger("").setLevel(OFF);
40         }
41
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();
47
48         public SoneParserTest() {
49                 Optional<Image> image = mock(Optional.class);
50                 when(core.getImage(anyString())).thenReturn(image);
51         }
52
53         @Test
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));
58         }
59
60         @Test
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));
65         }
66
67         @Test
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));
72         }
73
74         @Test
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));
79         }
80
81         @Test
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()));
88         }
89
90         @Test
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"));
107         }
108
109         public InputStream getInputStream(String content) throws UnsupportedEncodingException {
110                 return new ByteArrayInputStream(content.getBytes("UTF-8"));
111         }
112
113         private InputStream getXml(String name) {
114                 return getClass().getResourceAsStream(format("/sone-parser/%s.xml", name));
115         }
116
117         private static class SoneXmlBuilder {
118
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>",
130                                 "<fields>",
131                                 "<field><field-name>Custom Field</field-name><field-value>Custom Value</field-value></field>",
132                                 "</fields>"
133                 ));
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>");
136
137                 public SoneXmlBuilder removeTime() {
138                         time = absent();
139                         return this;
140                 }
141
142                 public SoneXmlBuilder setProtocolVersion(String protocolVersion) {
143                         this.protocolVersion = fromNullable(protocolVersion);
144                         return this;
145                 }
146
147                 public SoneXmlBuilder removeProtocolVersion() {
148                         this.protocolVersion = absent();
149                         return this;
150                 }
151
152                 public SoneXmlBuilder setClientInformation(String name, String version) {
153                         clientInformation = of("<name>" + name + "</name><version>" + version + "</version>");
154                         return this;
155                 }
156
157                 public SoneXmlBuilder removeClientInformation() {
158                         clientInformation = absent();
159                         return this;
160                 }
161
162                 public SoneXmlBuilder removeProfile() {
163                         profile = absent();
164                         return this;
165                 }
166
167                 public SoneXmlBuilder removePost() {
168                         posts = absent();
169                         return this;
170                 }
171
172                 public SoneXmlBuilder removeReply() {
173                         replies = absent();
174                         return this;
175                 }
176
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())));
182                         }
183                         if (protocolVersion.isPresent()) {
184                                 content.append(createXmlElement("protocol-version", protocolVersion.get()));
185                         }
186                         if (clientInformation.isPresent()) {
187                                 content.append(createXmlElement("client", clientInformation.get()));
188                         }
189                         if (profile.isPresent()) {
190                                 content.append(createXmlElement("profile", profile.get()));
191                         }
192                         if (posts.isPresent()) {
193                                 content.append(createXmlElement("posts", posts.get()));
194                         }
195                         content.append("</sone>");
196                         try {
197                                 String xmlString = content.toString();
198                                 return new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
199                         } catch (UnsupportedEncodingException e) {
200                                 /* ignore. */
201                         }
202                         return null;
203                 }
204
205                 private String createXmlElement(String xmlElement, String content) {
206                         return format("<%s>%s</%1$s>", xmlElement, content);
207                 }
208
209         }
210
211 }