Return an optional from the Sone parser.
[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 org.hamcrest.CoreMatchers.is;
8 import static org.hamcrest.CoreMatchers.notNullValue;
9 import static org.hamcrest.MatcherAssert.assertThat;
10 import static org.mockito.Matchers.anyString;
11 import static org.mockito.Mockito.mock;
12 import static org.mockito.Mockito.when;
13
14 import java.io.ByteArrayInputStream;
15 import java.io.InputStream;
16 import java.io.UnsupportedEncodingException;
17
18 import net.pterodactylus.sone.data.Client;
19 import net.pterodactylus.sone.data.Image;
20 import net.pterodactylus.sone.data.Sone;
21 import net.pterodactylus.sone.database.Database;
22 import net.pterodactylus.sone.database.SoneBuilder.SoneCreated;
23 import net.pterodactylus.sone.database.memory.MemoryDatabase;
24
25 import com.google.common.base.Joiner;
26 import com.google.common.base.Optional;
27 import org.junit.Test;
28
29 /**
30  * Unit test for {@link SoneParser}.
31  *
32  * @author <a href="mailto:d.roden@xplosion.de">David Roden</a>
33  */
34 public class SoneParserTest {
35
36         private final Core core = mock(Core.class);
37         private final Database database = new MemoryDatabase(null);
38         private final Sone originalSone = database.newSoneBuilder().by("test").using(new Client("TestClient", "1.0")).build(Optional.<SoneCreated>absent());
39         private final SoneXmlBuilder soneXmlBuilder = new SoneXmlBuilder();
40         private final SoneParser soneParser = new SoneParser();
41
42         public SoneParserTest() {
43                 Optional<Image> image = mock(Optional.class);
44                 when(core.getImage(anyString())).thenReturn(image);
45         }
46
47         @Test
48         public void verifyThatAnInvalidXmlDocumentIsNotParsed() throws UnsupportedEncodingException {
49                 Optional<Sone> sone = soneParser.parseSone(database, originalSone, getInputStream("<xml>This is not valid XML.</invalid>"));
50                 assertThat(sone, notNullValue());
51                 assertThat(sone.isPresent(), is(false));
52         }
53
54         @Test
55         public void verifyThatANegativeProtocolVersionCausesAnError() {
56                 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("-1").get());
57                 assertThat(sone, notNullValue());
58                 assertThat(sone.isPresent(), is(false));
59         }
60
61         @Test
62         public void verifyThatATooLargeProtocolVersionCausesAnError() {
63                 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.setProtocolVersion("1").get());
64                 assertThat(sone, notNullValue());
65                 assertThat(sone.isPresent(), is(false));
66         }
67
68         @Test
69         public void verifyThatAMissingClientCausesTheOriginalClientToBeUsed() {
70                 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.removeClientInformation().get());
71                 assertThat(sone, notNullValue());
72                 assertThat(sone.isPresent(), is(true));
73                 assertThat(sone.get().getClient(), notNullValue());
74                 assertThat(sone.get().getClient(), is(originalSone.getClient()));
75         }
76
77         @Test
78         public void verifyThatTheCreatedSoneMeetsAllExpectations() {
79                 Optional<Sone> sone = soneParser.parseSone(database, originalSone, soneXmlBuilder.get());
80                 assertThat(sone, notNullValue());
81                 assertThat(sone.isPresent(), is(true));
82                 assertThat(sone.get().getTime(), is(1000L));
83                 assertThat(sone.get().getClient(), notNullValue());
84                 assertThat(sone.get().getClient().getName(), is("Test-Client"));
85                 assertThat(sone.get().getClient().getVersion(), is("1.0"));
86                 assertThat(sone.get().getProfile(), notNullValue());
87                 assertThat(sone.get().getProfile().getFirstName(), is("First"));
88                 assertThat(sone.get().getProfile().getMiddleName(), is("M."));
89                 assertThat(sone.get().getProfile().getLastName(), is("Last"));
90                 assertThat(sone.get().getProfile().getBirthYear(), is(2000));
91                 assertThat(sone.get().getProfile().getBirthMonth(), is(9));
92                 assertThat(sone.get().getProfile().getBirthDay(), is(13));
93                 assertThat(sone.get().getProfile().getAvatar(), is("avatar-id"));
94         }
95
96         public InputStream getInputStream(String content) throws UnsupportedEncodingException {
97                 return new ByteArrayInputStream(content.getBytes("UTF-8"));
98         }
99
100         private static class SoneXmlBuilder {
101
102                 private Optional<Long> time = of(1000L);
103                 private Optional<String> protocolVersion = of("0");
104                 private Optional<String> clientInformation = of("<name>Test-Client</name><version>1.0</version>");
105                 private Optional<String> profile = of(Joiner.on("").join(
106                                 "<first-name>First</first-name>",
107                                 "<middle-name>M.</middle-name>",
108                                 "<last-name>Last</last-name>",
109                                 "<birth-year>2000</birth-year>",
110                                 "<birth-month>9</birth-month>",
111                                 "<birth-day>13</birth-day>",
112                                 "<avatar>avatar-id</avatar>",
113                                 "<fields>",
114                                 "<field><field-name>Custom Field</field-name><field-value>Custom Value</field-value></field>",
115                                 "</fields>"
116                 ));
117                 private Optional<String> posts = of("<post><id>post-id</id><time>1</time><recipient>recipient</recipient><text>Hello!</text></post>");
118                 private Optional<String> replies = of("<reply><id>reply-id</id><post-id>post-id</post-id><time>2</time><text>Reply!</text></reply>");
119
120                 public SoneXmlBuilder removeTime() {
121                         time = absent();
122                         return this;
123                 }
124
125                 public SoneXmlBuilder setProtocolVersion(String protocolVersion) {
126                         this.protocolVersion = fromNullable(protocolVersion);
127                         return this;
128                 }
129
130                 public SoneXmlBuilder removeProtocolVersion() {
131                         this.protocolVersion = absent();
132                         return this;
133                 }
134
135                 public SoneXmlBuilder setClientInformation(String name, String version) {
136                         clientInformation = of("<name>" + name + "</name><version>" + version + "</version>");
137                         return this;
138                 }
139
140                 public SoneXmlBuilder removeClientInformation() {
141                         clientInformation = absent();
142                         return this;
143                 }
144
145                 public SoneXmlBuilder removeProfile() {
146                         profile = absent();
147                         return this;
148                 }
149
150                 public SoneXmlBuilder removePost() {
151                         posts = absent();
152                         return this;
153                 }
154
155                 public SoneXmlBuilder removeReply() {
156                         replies = absent();
157                         return this;
158                 }
159
160                 public InputStream get() {
161                         StringBuilder content = new StringBuilder();
162                         content.append("<sone>");
163                         if (time.isPresent()) {
164                                 content.append(createXmlElement("time", String.valueOf(time.get())));
165                         }
166                         if (protocolVersion.isPresent()) {
167                                 content.append(createXmlElement("protocol-version", protocolVersion.get()));
168                         }
169                         if (clientInformation.isPresent()) {
170                                 content.append(createXmlElement("client", clientInformation.get()));
171                         }
172                         if (profile.isPresent()) {
173                                 content.append(createXmlElement("profile", profile.get()));
174                         }
175                         if (posts.isPresent()) {
176                                 content.append(createXmlElement("posts", posts.get()));
177                         }
178                         content.append("</sone>");
179                         try {
180                                 String xmlString = content.toString();
181                                 System.out.println(xmlString);
182                                 return new ByteArrayInputStream(xmlString.getBytes("UTF-8"));
183                         } catch (UnsupportedEncodingException e) {
184                                 /* ignore. */
185                         }
186                         return null;
187                 }
188
189                 private String createXmlElement(String xmlElement, String content) {
190                         return format("<%s>%s</%1$s>", xmlElement, content);
191                 }
192
193         }
194
195 }