Add tests for parsing a post.
[Sone.git] / src / test / java / net / pterodactylus / sone / fcp / AbstractSoneCommandTest.java
1 /*
2  * Sone - AbstractSoneCommandTest.java - Copyright © 2013 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.fcp;
19
20 import static com.google.common.base.Optional.of;
21 import static java.util.Arrays.asList;
22 import static java.util.UUID.randomUUID;
23 import static net.pterodactylus.sone.fcp.AbstractSoneCommand.encodeSone;
24 import static net.pterodactylus.sone.fcp.AbstractSoneCommand.encodeString;
25 import static net.pterodactylus.sone.template.SoneAccessor.getNiceName;
26 import static org.hamcrest.CoreMatchers.is;
27 import static org.hamcrest.CoreMatchers.notNullValue;
28 import static org.hamcrest.CoreMatchers.nullValue;
29 import static org.hamcrest.MatcherAssert.assertThat;
30 import static org.mockito.Matchers.eq;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.when;
33
34 import java.util.List;
35
36 import net.pterodactylus.sone.core.Core;
37 import net.pterodactylus.sone.data.Post;
38 import net.pterodactylus.sone.data.PostReply;
39 import net.pterodactylus.sone.data.Profile;
40 import net.pterodactylus.sone.data.Sone;
41 import net.pterodactylus.sone.database.Database;
42 import net.pterodactylus.sone.freenet.SimpleFieldSetBuilder;
43 import net.pterodactylus.sone.freenet.fcp.FcpException;
44
45 import freenet.node.FSParseException;
46 import freenet.support.SimpleFieldSet;
47 import freenet.support.api.Bucket;
48
49 import com.google.common.base.Optional;
50 import org.junit.Test;
51 import org.mockito.Matchers;
52
53 /**
54  * Unit test for {@link AbstractSoneCommand}.
55  *
56  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
57  */
58 public class AbstractSoneCommandTest {
59
60         private final Core core = mock(Core.class);
61         private final Database database = mock(Database.class);
62         private final AbstractSoneCommand abstractSoneCommand = new AbstractSoneCommand(core) {
63                 @Override
64                 public Response execute(SimpleFieldSet parameters, Bucket data, AccessType accessType) throws FcpException {
65                         return null;
66                 }
67         };
68
69         public AbstractSoneCommandTest() {
70                 when(core.getDatabase()).thenReturn(database);
71         }
72
73         @Test
74         public void testStringEncoding() {
75                 String testString = prepareStringToBeEncoded();
76
77                 String encodedString = encodeString(testString);
78                 assertThat(encodedString, notNullValue());
79                 assertThat(encodedString.length(), is(testString.length() + 3));
80         }
81
82         private String prepareStringToBeEncoded() {
83                 StringBuilder testString = new StringBuilder();
84                 for (int i = 0; i < 4000; ++i) {
85                         testString.append((char) i);
86                 }
87                 return testString.toString();
88         }
89
90         @Test
91         public void testEncodingASone() throws FSParseException {
92                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
93                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", Optional.<Sone>absent());
94                 assertThat(soneFieldSet, notNullValue());
95                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
96                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
97                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
98                 assertThat(soneFieldSet.get("Prefix.Followed"), nullValue());
99                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
100                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
101                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
102         }
103
104         @Test
105         public void testEncodingAFollowedSone() throws FSParseException {
106                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
107                 Sone localSone = prepareLocalSoneThatFollowsEverybody();
108                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", of(localSone));
109                 assertThat(soneFieldSet, notNullValue());
110                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
111                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
112                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
113                 assertThat(soneFieldSet.get("Prefix.Followed"), is("true"));
114                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
115                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
116                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
117         }
118
119         @Test
120         public void testEncodingANotFollowedSone() throws FSParseException {
121                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
122                 Sone localSone = prepareLocalSoneThatFollowsNobody();
123                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", of(localSone));
124                 assertThat(soneFieldSet, notNullValue());
125                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
126                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
127                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
128                 assertThat(soneFieldSet.get("Prefix.Followed"), is("false"));
129                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
130                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
131                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
132         }
133
134         private Sone prepareLocalSoneThatFollowsEverybody() {
135                 Sone sone = mock(Sone.class);
136                 when(sone.hasFriend(Matchers.<String>any())).thenReturn(true);
137                 return sone;
138         }
139
140         private Sone prepareLocalSoneThatFollowsNobody() {
141                 Sone sone = mock(Sone.class);
142                 when(sone.hasFriend(Matchers.<String>any())).thenReturn(false);
143                 return sone;
144         }
145
146         @Test
147         public void testEncodingMultipleSones() throws FSParseException {
148                 List<Sone> sones = prepareMultipleSones();
149                 SimpleFieldSet sonesFieldSet = AbstractSoneCommand.encodeSones(sones, "Prefix.");
150                 assertThat(sonesFieldSet, notNullValue());
151                 assertThat(sonesFieldSet.getInt("Prefix.Count"), is(sones.size()));
152                 assertThat(sonesFieldSet.get("Prefix.0.ID"), is(sones.get(0).getId()));
153                 assertThat(sonesFieldSet.get("Prefix.0.Name"), is(sones.get(0).getName()));
154                 assertThat(sonesFieldSet.get("Prefix.0.NiceName"), is(getNiceName(sones.get(0))));
155                 assertThat(sonesFieldSet.getLong("Prefix.0.Time"), is(sones.get(0).getTime()));
156                 assertThat(sonesFieldSet.get("Prefix.1.ID"), is(sones.get(1).getId()));
157                 assertThat(sonesFieldSet.get("Prefix.1.Name"), is(sones.get(1).getName()));
158                 assertThat(sonesFieldSet.get("Prefix.1.NiceName"), is(getNiceName(sones.get(1))));
159                 assertThat(sonesFieldSet.getLong("Prefix.1.Time"), is(sones.get(1).getTime()));
160                 assertThat(sonesFieldSet.get("Prefix.2.ID"), is(sones.get(2).getId()));
161                 assertThat(sonesFieldSet.get("Prefix.2.Name"), is(sones.get(2).getName()));
162                 assertThat(sonesFieldSet.get("Prefix.2.NiceName"), is(getNiceName(sones.get(2))));
163                 assertThat(sonesFieldSet.getLong("Prefix.2.Time"), is(sones.get(2).getTime()));
164         }
165
166         private List<Sone> prepareMultipleSones() {
167                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
168                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
169                 Sone sone3 = createSone("-1Q6LhHvx91C1mSjOS3zznRSNUC4OxoHUbhIgBAyW1U", "Test3", "Gamma", "C.", "Third", (long) (Math.random() * Long.MAX_VALUE));
170                 return asList(sone1, sone2, sone3);
171         }
172
173         private Sone createSone(String id, String name, String firstName, String middleName, String lastName, long time) {
174                 Sone sone = mock(Sone.class);
175                 when(sone.getId()).thenReturn(id);
176                 when(sone.getName()).thenReturn(name);
177                 when(sone.getProfile()).thenReturn(prepareProfile(sone, firstName, middleName, lastName));
178                 when(sone.getTime()).thenReturn(time);
179                 return sone;
180         }
181
182         private Sone createLocalSone(String id, String name, String firstName, String middleName, String lastName, long time) {
183                 Sone sone = mock(Sone.class);
184                 when(sone.getId()).thenReturn(id);
185                 when(sone.getName()).thenReturn(name);
186                 when(sone.getProfile()).thenReturn(prepareProfile(sone, firstName, middleName, lastName));
187                 when(sone.getTime()).thenReturn(time);
188                 when(sone.isLocal()).thenReturn(true);
189                 return sone;
190         }
191
192         private Profile prepareProfile(Sone sone, String firstName, String middleName, String lastName) {
193                 Profile profile = new Profile(sone).modify().setFirstName(firstName).setMiddleName(middleName).setLastName(lastName).update();
194                 profile.setField(profile.addField("Test1"), "Value1");
195                 return profile;
196         }
197
198         @Test
199         public void testEncodingReplies() throws FSParseException {
200                 List<PostReply> postReplies = preparePostReplies();
201                 SimpleFieldSet postRepliesFieldSet = AbstractSoneCommand.encodeReplies(postReplies, "Prefix.");
202                 assertThat(postRepliesFieldSet, notNullValue());
203                 assertThat(postRepliesFieldSet.getInt("Prefix.Replies.Count"), is(postReplies.size()));
204                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.ID"), is(postReplies.get(0).getId()));
205                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.Sone"), is(postReplies.get(0).getSone().getId()));
206                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.0.Time"), is(postReplies.get(0).getTime()));
207                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.Text"), is(postReplies.get(0).getText()));
208                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.ID"), is(postReplies.get(1).getId()));
209                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.Sone"), is(postReplies.get(1).getSone().getId()));
210                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.1.Time"), is(postReplies.get(1).getTime()));
211                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.Text"), is(postReplies.get(1).getText()));
212                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.ID"), is(postReplies.get(2).getId()));
213                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.Sone"), is(postReplies.get(2).getSone().getId()));
214                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.2.Time"), is(postReplies.get(2).getTime()));
215                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.Text"), is(postReplies.get(2).getText()));
216         }
217
218         private List<PostReply> preparePostReplies() {
219                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
220                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
221                 Sone sone3 = createSone("-1Q6LhHvx91C1mSjOS3zznRSNUC4OxoHUbhIgBAyW1U", "Test3", "Gamma", "C.", "Third", (long) (Math.random() * Long.MAX_VALUE));
222                 PostReply postReply1 = createPostReply(sone1, "Text 1");
223                 PostReply postReply2 = createPostReply(sone2, "Text 2");
224                 PostReply postReply3 = createPostReply(sone3, "Text 3");
225                 return asList(postReply1, postReply2, postReply3);
226         }
227
228         private PostReply createPostReply(Sone sone, String text) {
229                 PostReply postReply = mock(PostReply.class);
230                 when(postReply.getId()).thenReturn(randomUUID().toString());
231                 when(postReply.getSone()).thenReturn(sone);
232                 when(postReply.getTime()).thenReturn((long) (Math.random() * Long.MAX_VALUE));
233                 when(postReply.getText()).thenReturn(text);
234                 return postReply;
235         }
236
237         @Test
238         public void testEncodingLikes() throws FSParseException {
239                 List<Sone> likes = prepareMultipleSones();
240                 SimpleFieldSet likesFieldSet = AbstractSoneCommand.encodeLikes(likes, "Prefix.");
241                 assertThat(likesFieldSet, notNullValue());
242                 assertThat(likesFieldSet.getInt("Prefix.Count"), is(likes.size()));
243                 assertThat(likesFieldSet.get("Prefix.0.ID"), is(likes.get(0).getId()));
244                 assertThat(likesFieldSet.get("Prefix.1.ID"), is(likes.get(1).getId()));
245                 assertThat(likesFieldSet.get("Prefix.2.ID"), is(likes.get(2).getId()));
246         }
247
248         @Test
249         public void testParsingAMandatorySone() throws FcpException {
250                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
251                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
252                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
253                 Sone parsedSone = abstractSoneCommand.getMandatorySone(soneFieldSet, "Sone");
254                 assertThat(parsedSone, notNullValue());
255                 assertThat(parsedSone, is(sone));
256         }
257
258         @Test(expected = FcpException.class)
259         public void testParsingANonExistingMandatorySoneCausesAnError() throws FcpException {
260                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
261                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
262                 abstractSoneCommand.getMandatorySone(soneFieldSet, "Sone");
263         }
264
265         @Test(expected = FcpException.class)
266         public void testParsingAMandatorySoneFromANonExistingFieldCausesAnError() throws FcpException {
267                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
268                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
269                 abstractSoneCommand.getMandatorySone(soneFieldSet, "RealSone");
270         }
271
272         @Test
273         public void testParsingAMandatoryLocalSone() throws FcpException {
274                 Sone sone = createLocalSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
275                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
276                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
277                 Sone parsedSone = abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "Sone");
278                 assertThat(parsedSone, notNullValue());
279                 assertThat(parsedSone, is(sone));
280                 assertThat(parsedSone.isLocal(), is(true));
281         }
282
283         @Test(expected = FcpException.class)
284         public void testParsingANonLocalSoneAsMandatoryLocalSoneCausesAnError() throws FcpException {
285                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
286                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
287                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
288                 abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "Sone");
289         }
290
291         @Test(expected = FcpException.class)
292         public void testParsingAMandatoryLocalSoneFromANonExistingFieldCausesAnError() throws FcpException {
293                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
294                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
295                 abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "RealSone");
296         }
297
298         @Test
299         public void testParsingAnExistingOptionalSone() throws FcpException {
300                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
301                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
302                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
303                 Optional<Sone> parsedSone = abstractSoneCommand.getOptionalSone(soneFieldSet, "Sone");
304                 assertThat(parsedSone, notNullValue());
305                 assertThat(parsedSone.isPresent(), is(true));
306                 assertThat(parsedSone.get(), is(sone));
307         }
308
309         @Test
310         public void testParsingANonExistingOptionalSone() throws FcpException {
311                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
312                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
313                 Optional<Sone> parsedSone = abstractSoneCommand.getOptionalSone(soneFieldSet, "Sone");
314                 assertThat(parsedSone, notNullValue());
315                 assertThat(parsedSone.isPresent(), is(false));
316         }
317
318         @Test(expected = FcpException.class)
319         public void testParsingAnOptionalSoneFromANonExistingFieldCausesAnError() throws FcpException {
320                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
321                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
322                 abstractSoneCommand.getOptionalSone(soneFieldSet, "RealSone");
323         }
324
325         @Test
326         public void testParsingAPost() throws FcpException {
327                 Post post = createPost();
328                 when(database.getPost(eq(post.getId()))).thenReturn(of(post));
329                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().put("Post", post.getId()).get();
330                 Post parsedPost = abstractSoneCommand.getPost(postFieldSet, "Post");
331                 assertThat(parsedPost, notNullValue());
332                 assertThat(parsedPost, is(post));
333         }
334
335         private Post createPost() {
336                 Post post = mock(Post.class);
337                 when(post.getId()).thenReturn(randomUUID().toString());
338                 return post;
339         }
340
341         @Test(expected = FcpException.class)
342         public void testThatTryingToParseANonExistingPostCausesAnError() throws FcpException {
343                 Post post = createPost();
344                 when(database.getPost(Matchers.<String>any())).thenReturn(Optional.<Post>absent());
345                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().put("Post", post.getId()).get();
346                 abstractSoneCommand.getPost(postFieldSet, "Post");
347         }
348
349         @Test(expected = FcpException.class)
350         public void testThatTryingToParseAPostFromANonExistingFieldCausesAnError() throws FcpException {
351                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().get();
352                 abstractSoneCommand.getPost(postFieldSet, "Post");
353         }
354
355 }