7029048be88268b32c2b0c92047dbb4760e4679b
[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, getInputStream("<xml>This is not valid XML.</invalid>"));
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, soneXmlBuilder.get());
93                 assertThat(sone, notNullValue());
94                 assertThat(sone.isPresent(), is(true));
95                 assertThat(sone.get().getTime(), is(1000L));
96                 assertThat(sone.get().getClient(), notNullValue());
97                 assertThat(sone.get().getClient().getName(), is("Test-Client"));
98                 assertThat(sone.get().getClient().getVersion(), is("1.0"));
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(2000));
104                 assertThat(sone.get().getProfile().getBirthMonth(), is(9));
105                 assertThat(sone.get().getProfile().getBirthDay(), is(13));
106                 assertThat(sone.get().getProfile().getAvatar(), is("avatar-id"));
107         }
108
109         public InputStream getInputStream(String content) throws UnsupportedEncodingException {
110                 return new ByteArrayInputStream(content.getBytes("UTF-8"));
111         }
112
113         private static class SoneXmlBuilder {
114
115                 private Optional<Long> time = of(1000L);
116                 private Optional<String> protocolVersion = of("0");
117                 private Optional<String> clientInformation = of("<name>Test-Client</name><version>1.0</version>");
118                 private Optional<String> profile = of(Joiner.on("").join(
119                                 "<first-name>First</first-name>",
120                                 "<middle-name>M.</middle-name>",
121                                 "<last-name>Last</last-name>",
122                                 "<birth-year>2000</birth-year>",
123                                 "<birth-month>9</birth-month>",
124                                 "<birth-day>13</birth-day>",
125                                 "<avatar>avatar-id</avatar>",
126                                 "<fields>",
127                                 "<field><field-name>Custom Field</field-name><field-value>Custom Value</field-value></field>",
128                                 "</fields>"
129                 ));
130                 private Optional<String> posts = of("<post><id>post-id</id><time>1</time><recipient>recipient</recipient><text>Hello!</text></post>");
131                 private Optional<String> replies = of("<reply><id>reply-id</id><post-id>post-id</post-id><time>2</time><text>Reply!</text></reply>");
132
133                 public SoneXmlBuilder removeTime() {
134                         time = absent();
135                         return this;
136                 }
137
138                 public SoneXmlBuilder setProtocolVersion(String protocolVersion) {
139                         this.protocolVersion = fromNullable(protocolVersion);
140                         return this;
141                 }
142
143                 public SoneXmlBuilder removeProtocolVersion() {
144                         this.protocolVersion = absent();
145                         return this;
146                 }
147
148                 public SoneXmlBuilder setClientInformation(String name, String version) {
149                         clientInformation = of("<name>" + name + "</name><version>" + version + "</version>");
150                         return this;
151                 }
152
153                 public SoneXmlBuilder removeClientInformation() {
154                         clientInformation = absent();
155                         return this;
156                 }
157
158                 public SoneXmlBuilder removeProfile() {
159                         profile = absent();
160                         return this;
161                 }
162
163                 public SoneXmlBuilder removePost() {
164                         posts = absent();
165                         return this;
166                 }
167
168                 public SoneXmlBuilder removeReply() {
169                         replies = absent();
170                         return this;
171                 }
172
173                 public InputStream get() {
174                         StringBuilder content = new StringBuilder();
175                         content.append("<sone>");
176                         if (time.isPresent()) {
177                                 content.append(createXmlElement("time", String.valueOf(time.get())));
178                         }
179                         if (protocolVersion.isPresent()) {
180                                 content.append(createXmlElement("protocol-version", protocolVersion.get()));
181                         }
182                         if (clientInformation.isPresent()) {
183                                 content.append(createXmlElement("client", clientInformation.get()));
184                         }
185                         if (profile.isPresent()) {
186                                 content.append(createXmlElement("profile", profile.get()));
187                         }
188                         if (posts.isPresent()) {
189                                 content.append(createXmlElement("posts", posts.get()));
190                         }
191                         content.append("</sone>");
192                         try {
193                                 String xmlString = content.toString();
194                                 return new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
195                         } catch (UnsupportedEncodingException e) {
196                                 /* ignore. */
197                         }
198                         return null;
199                 }
200
201                 private String createXmlElement(String xmlElement, String content) {
202                         return format("<%s>%s</%1$s>", xmlElement, content);
203                 }
204
205         }
206
207 }