Add method that verifies multiple posts with replies.
[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.fromNullable;
21 import static com.google.common.base.Optional.of;
22 import static com.google.common.collect.FluentIterable.from;
23 import static java.util.Arrays.asList;
24 import static java.util.UUID.randomUUID;
25 import static net.pterodactylus.sone.data.Reply.FUTURE_REPLY_FILTER;
26 import static net.pterodactylus.sone.fcp.AbstractSoneCommand.encodeSone;
27 import static net.pterodactylus.sone.fcp.AbstractSoneCommand.encodeString;
28 import static net.pterodactylus.sone.template.SoneAccessor.getNiceName;
29 import static org.hamcrest.CoreMatchers.is;
30 import static org.hamcrest.CoreMatchers.notNullValue;
31 import static org.hamcrest.CoreMatchers.nullValue;
32 import static org.hamcrest.MatcherAssert.assertThat;
33 import static org.mockito.Matchers.eq;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.when;
36
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.List;
40
41 import net.pterodactylus.sone.core.Core;
42 import net.pterodactylus.sone.data.Post;
43 import net.pterodactylus.sone.data.PostReply;
44 import net.pterodactylus.sone.data.Profile;
45 import net.pterodactylus.sone.data.Sone;
46 import net.pterodactylus.sone.database.Database;
47 import net.pterodactylus.sone.freenet.SimpleFieldSetBuilder;
48 import net.pterodactylus.sone.freenet.fcp.FcpException;
49
50 import freenet.node.FSParseException;
51 import freenet.support.SimpleFieldSet;
52 import freenet.support.api.Bucket;
53
54 import com.google.common.base.Optional;
55 import org.junit.Test;
56 import org.mockito.Matchers;
57
58 /**
59  * Unit test for {@link AbstractSoneCommand}.
60  *
61  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
62  */
63 public class AbstractSoneCommandTest {
64
65         private final Core core = mock(Core.class);
66         private final Database database = mock(Database.class);
67         private final AbstractSoneCommand abstractSoneCommand = new AbstractSoneCommand(core) {
68                 @Override
69                 public Response execute(SimpleFieldSet parameters, Bucket data, AccessType accessType) throws FcpException {
70                         return null;
71                 }
72         };
73
74         public AbstractSoneCommandTest() {
75                 when(core.getDatabase()).thenReturn(database);
76         }
77
78         @Test
79         public void testStringEncoding() {
80                 String testString = prepareStringToBeEncoded();
81
82                 String encodedString = encodeString(testString);
83                 assertThat(encodedString, notNullValue());
84                 assertThat(encodedString.length(), is(testString.length() + 3));
85         }
86
87         private String prepareStringToBeEncoded() {
88                 StringBuilder testString = new StringBuilder();
89                 for (int i = 0; i < 4000; ++i) {
90                         testString.append((char) i);
91                 }
92                 return testString.toString();
93         }
94
95         @Test
96         public void testEncodingASone() throws FSParseException {
97                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
98                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", Optional.<Sone>absent());
99                 assertThat(soneFieldSet, notNullValue());
100                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
101                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
102                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
103                 assertThat(soneFieldSet.get("Prefix.Followed"), nullValue());
104                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
105                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
106                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
107         }
108
109         @Test
110         public void testEncodingAFollowedSone() throws FSParseException {
111                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
112                 Sone localSone = prepareLocalSoneThatFollowsEverybody();
113                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", of(localSone));
114                 assertThat(soneFieldSet, notNullValue());
115                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
116                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
117                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
118                 assertThat(soneFieldSet.get("Prefix.Followed"), is("true"));
119                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
120                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
121                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
122         }
123
124         @Test
125         public void testEncodingANotFollowedSone() throws FSParseException {
126                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
127                 Sone localSone = prepareLocalSoneThatFollowsNobody();
128                 SimpleFieldSet soneFieldSet = encodeSone(sone, "Prefix.", of(localSone));
129                 assertThat(soneFieldSet, notNullValue());
130                 assertThat(soneFieldSet.get("Prefix.Name"), is("test"));
131                 assertThat(soneFieldSet.get("Prefix.NiceName"), is("First M. Last"));
132                 assertThat(soneFieldSet.getLong("Prefix.LastUpdated"), is(sone.getTime()));
133                 assertThat(soneFieldSet.get("Prefix.Followed"), is("false"));
134                 assertThat(soneFieldSet.getInt("Prefix.Field.Count"), is(1));
135                 assertThat(soneFieldSet.get("Prefix.Field.0.Name"), is("Test1"));
136                 assertThat(soneFieldSet.get("Prefix.Field.0.Value"), is("Value1"));
137         }
138
139         private Sone prepareLocalSoneThatFollowsEverybody() {
140                 Sone sone = mock(Sone.class);
141                 when(sone.hasFriend(Matchers.<String>any())).thenReturn(true);
142                 return sone;
143         }
144
145         private Sone prepareLocalSoneThatFollowsNobody() {
146                 Sone sone = mock(Sone.class);
147                 when(sone.hasFriend(Matchers.<String>any())).thenReturn(false);
148                 return sone;
149         }
150
151         @Test
152         public void testEncodingMultipleSones() throws FSParseException {
153                 List<Sone> sones = prepareMultipleSones();
154                 SimpleFieldSet sonesFieldSet = AbstractSoneCommand.encodeSones(sones, "Prefix.");
155                 assertThat(sonesFieldSet, notNullValue());
156                 assertThat(sonesFieldSet.getInt("Prefix.Count"), is(sones.size()));
157                 assertThat(sonesFieldSet.get("Prefix.0.ID"), is(sones.get(0).getId()));
158                 assertThat(sonesFieldSet.get("Prefix.0.Name"), is(sones.get(0).getName()));
159                 assertThat(sonesFieldSet.get("Prefix.0.NiceName"), is(getNiceName(sones.get(0))));
160                 assertThat(sonesFieldSet.getLong("Prefix.0.Time"), is(sones.get(0).getTime()));
161                 assertThat(sonesFieldSet.get("Prefix.1.ID"), is(sones.get(1).getId()));
162                 assertThat(sonesFieldSet.get("Prefix.1.Name"), is(sones.get(1).getName()));
163                 assertThat(sonesFieldSet.get("Prefix.1.NiceName"), is(getNiceName(sones.get(1))));
164                 assertThat(sonesFieldSet.getLong("Prefix.1.Time"), is(sones.get(1).getTime()));
165                 assertThat(sonesFieldSet.get("Prefix.2.ID"), is(sones.get(2).getId()));
166                 assertThat(sonesFieldSet.get("Prefix.2.Name"), is(sones.get(2).getName()));
167                 assertThat(sonesFieldSet.get("Prefix.2.NiceName"), is(getNiceName(sones.get(2))));
168                 assertThat(sonesFieldSet.getLong("Prefix.2.Time"), is(sones.get(2).getTime()));
169         }
170
171         private List<Sone> prepareMultipleSones() {
172                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
173                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
174                 Sone sone3 = createSone("-1Q6LhHvx91C1mSjOS3zznRSNUC4OxoHUbhIgBAyW1U", "Test3", "Gamma", "C.", "Third", (long) (Math.random() * Long.MAX_VALUE));
175                 return asList(sone1, sone2, sone3);
176         }
177
178         private Sone createSone(String id, String name, String firstName, String middleName, String lastName, long time) {
179                 Sone sone = mock(Sone.class);
180                 when(sone.getId()).thenReturn(id);
181                 when(sone.getName()).thenReturn(name);
182                 when(sone.getProfile()).thenReturn(prepareProfile(sone, firstName, middleName, lastName));
183                 when(sone.getTime()).thenReturn(time);
184                 return sone;
185         }
186
187         private Sone createLocalSone(String id, String name, String firstName, String middleName, String lastName, long time) {
188                 Sone sone = mock(Sone.class);
189                 when(sone.getId()).thenReturn(id);
190                 when(sone.getName()).thenReturn(name);
191                 when(sone.getProfile()).thenReturn(prepareProfile(sone, firstName, middleName, lastName));
192                 when(sone.getTime()).thenReturn(time);
193                 when(sone.isLocal()).thenReturn(true);
194                 return sone;
195         }
196
197         private Profile prepareProfile(Sone sone, String firstName, String middleName, String lastName) {
198                 Profile profile = new Profile(sone).modify().setFirstName(firstName).setMiddleName(middleName).setLastName(lastName).update();
199                 profile.setField(profile.addField("Test1"), "Value1");
200                 return profile;
201         }
202
203         @Test
204         public void testEncodingReplies() throws FSParseException {
205                 List<PostReply> postReplies = preparePostReplies();
206                 SimpleFieldSet postRepliesFieldSet = AbstractSoneCommand.encodeReplies(postReplies, "Prefix.");
207                 assertThat(postRepliesFieldSet, notNullValue());
208                 assertThat(postRepliesFieldSet.getInt("Prefix.Replies.Count"), is(postReplies.size()));
209                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.ID"), is(postReplies.get(0).getId()));
210                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.Sone"), is(postReplies.get(0).getSone().getId()));
211                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.0.Time"), is(postReplies.get(0).getTime()));
212                 assertThat(postRepliesFieldSet.get("Prefix.Replies.0.Text"), is(postReplies.get(0).getText()));
213                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.ID"), is(postReplies.get(1).getId()));
214                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.Sone"), is(postReplies.get(1).getSone().getId()));
215                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.1.Time"), is(postReplies.get(1).getTime()));
216                 assertThat(postRepliesFieldSet.get("Prefix.Replies.1.Text"), is(postReplies.get(1).getText()));
217                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.ID"), is(postReplies.get(2).getId()));
218                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.Sone"), is(postReplies.get(2).getSone().getId()));
219                 assertThat(postRepliesFieldSet.getLong("Prefix.Replies.2.Time"), is(postReplies.get(2).getTime()));
220                 assertThat(postRepliesFieldSet.get("Prefix.Replies.2.Text"), is(postReplies.get(2).getText()));
221         }
222
223         private List<PostReply> preparePostReplies() {
224                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
225                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
226                 Sone sone3 = createSone("-1Q6LhHvx91C1mSjOS3zznRSNUC4OxoHUbhIgBAyW1U", "Test3", "Gamma", "C.", "Third", (long) (Math.random() * Long.MAX_VALUE));
227                 PostReply postReply1 = createPostReply(sone1, "Text 1");
228                 PostReply postReply2 = createPostReply(sone2, "Text 2");
229                 PostReply postReply3 = createPostReply(sone3, "Text 3");
230                 return asList(postReply1, postReply2, postReply3);
231         }
232
233         private PostReply createPostReply(Sone sone, String text) {
234                 PostReply postReply = mock(PostReply.class);
235                 when(postReply.getId()).thenReturn(randomUUID().toString());
236                 when(postReply.getSone()).thenReturn(sone);
237                 when(postReply.getTime()).thenReturn(System.currentTimeMillis());
238                 when(postReply.getText()).thenReturn(text);
239                 return postReply;
240         }
241
242         private PostReply createFuturePostReply(Sone sone, String text) {
243                 PostReply postReply = createPostReply(sone, text);
244                 when(postReply.getTime()).thenReturn(System.currentTimeMillis() + 86400000);
245                 return postReply;
246         }
247
248         @Test
249         public void testEncodingLikes() throws FSParseException {
250                 List<Sone> likes = prepareMultipleSones();
251                 SimpleFieldSet likesFieldSet = AbstractSoneCommand.encodeLikes(likes, "Prefix.");
252                 assertThat(likesFieldSet, notNullValue());
253                 assertThat(likesFieldSet.getInt("Prefix.Count"), is(likes.size()));
254                 assertThat(likesFieldSet.get("Prefix.0.ID"), is(likes.get(0).getId()));
255                 assertThat(likesFieldSet.get("Prefix.1.ID"), is(likes.get(1).getId()));
256                 assertThat(likesFieldSet.get("Prefix.2.ID"), is(likes.get(2).getId()));
257         }
258
259         @Test
260         public void testParsingAMandatorySone() throws FcpException {
261                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
262                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
263                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
264                 Sone parsedSone = abstractSoneCommand.getMandatorySone(soneFieldSet, "Sone");
265                 assertThat(parsedSone, notNullValue());
266                 assertThat(parsedSone, is(sone));
267         }
268
269         @Test(expected = FcpException.class)
270         public void testParsingANonExistingMandatorySoneCausesAnError() throws FcpException {
271                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
272                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
273                 abstractSoneCommand.getMandatorySone(soneFieldSet, "Sone");
274         }
275
276         @Test(expected = FcpException.class)
277         public void testParsingAMandatorySoneFromANonExistingFieldCausesAnError() throws FcpException {
278                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
279                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
280                 abstractSoneCommand.getMandatorySone(soneFieldSet, "RealSone");
281         }
282
283         @Test
284         public void testParsingAMandatoryLocalSone() throws FcpException {
285                 Sone sone = createLocalSone("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                 Sone parsedSone = abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "Sone");
289                 assertThat(parsedSone, notNullValue());
290                 assertThat(parsedSone, is(sone));
291                 assertThat(parsedSone.isLocal(), is(true));
292         }
293
294         @Test(expected = FcpException.class)
295         public void testParsingANonLocalSoneAsMandatoryLocalSoneCausesAnError() throws FcpException {
296                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
297                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
298                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
299                 abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "Sone");
300         }
301
302         @Test(expected = FcpException.class)
303         public void testParsingAMandatoryLocalSoneFromANonExistingFieldCausesAnError() throws FcpException {
304                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
305                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
306                 abstractSoneCommand.getMandatoryLocalSone(soneFieldSet, "RealSone");
307         }
308
309         @Test
310         public void testParsingAnExistingOptionalSone() throws FcpException {
311                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
312                 when(core.getSone(eq("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E"))).thenReturn(of(sone));
313                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
314                 Optional<Sone> parsedSone = abstractSoneCommand.getOptionalSone(soneFieldSet, "Sone");
315                 assertThat(parsedSone, notNullValue());
316                 assertThat(parsedSone.isPresent(), is(true));
317                 assertThat(parsedSone.get(), is(sone));
318         }
319
320         @Test
321         public void testParsingANonExistingOptionalSone() throws FcpException {
322                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
323                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
324                 Optional<Sone> parsedSone = abstractSoneCommand.getOptionalSone(soneFieldSet, "Sone");
325                 assertThat(parsedSone, notNullValue());
326                 assertThat(parsedSone.isPresent(), is(false));
327         }
328
329         @Test(expected = FcpException.class)
330         public void testParsingAnOptionalSoneFromANonExistingFieldCausesAnError() throws FcpException {
331                 when(core.getSone(Matchers.<String>any())).thenReturn(Optional.<Sone>absent());
332                 SimpleFieldSet soneFieldSet = new SimpleFieldSetBuilder().put("Sone", "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E").get();
333                 abstractSoneCommand.getOptionalSone(soneFieldSet, "RealSone");
334         }
335
336         @Test
337         public void testParsingAPost() throws FcpException {
338                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
339                 Post post = createPost(sone, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
340                 when(database.getPost(eq(post.getId()))).thenReturn(of(post));
341                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().put("Post", post.getId()).get();
342                 Post parsedPost = abstractSoneCommand.getPost(postFieldSet, "Post");
343                 assertThat(parsedPost, notNullValue());
344                 assertThat(parsedPost, is(post));
345         }
346
347         private Post createPost(Sone sone, String recipient, long time, String text) {
348                 Post post = mock(Post.class);
349                 when(post.getId()).thenReturn(randomUUID().toString());
350                 when(post.getSone()).thenReturn(sone);
351                 when(post.getRecipientId()).thenReturn(fromNullable(recipient));
352                 when(post.getTime()).thenReturn(time);
353                 when(post.getText()).thenReturn(text);
354                 return post;
355         }
356
357         @Test(expected = FcpException.class)
358         public void testThatTryingToParseANonExistingPostCausesAnError() throws FcpException {
359                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
360                 Post post = createPost(sone, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
361                 when(database.getPost(Matchers.<String>any())).thenReturn(Optional.<Post>absent());
362                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().put("Post", post.getId()).get();
363                 abstractSoneCommand.getPost(postFieldSet, "Post");
364         }
365
366         @Test(expected = FcpException.class)
367         public void testThatTryingToParseAPostFromANonExistingFieldCausesAnError() throws FcpException {
368                 SimpleFieldSet postFieldSet = new SimpleFieldSetBuilder().get();
369                 abstractSoneCommand.getPost(postFieldSet, "Post");
370         }
371
372         @Test
373         public void testParsingAReply() throws FcpException {
374                 PostReply reply = createPostReply();
375                 when(database.getPostReply(eq(reply.getId()))).thenReturn(of(reply));
376                 SimpleFieldSet replyFieldSet = new SimpleFieldSetBuilder().put("Reply", reply.getId()).get();
377                 PostReply parsedReply = abstractSoneCommand.getReply(replyFieldSet, "Reply");
378                 assertThat(parsedReply, notNullValue());
379                 assertThat(parsedReply, is(reply));
380         }
381
382         private PostReply createPostReply() {
383                 PostReply postReply = mock(PostReply.class);
384                 when(postReply.getId()).thenReturn(randomUUID().toString());
385                 return postReply;
386         }
387
388         @Test(expected = FcpException.class)
389         public void testParsingANonExistingReply() throws FcpException {
390                 PostReply reply = createPostReply();
391                 when(database.getPostReply(Matchers.<String>any())).thenReturn(Optional.<PostReply>absent());
392                 SimpleFieldSet replyFieldSet = new SimpleFieldSetBuilder().put("Reply", reply.getId()).get();
393                 abstractSoneCommand.getReply(replyFieldSet, "Reply");
394         }
395
396         @Test(expected = FcpException.class)
397         public void testParsingAReplyFromANonExistingField() throws FcpException {
398                 SimpleFieldSet replyFieldSet = new SimpleFieldSetBuilder().get();
399                 abstractSoneCommand.getReply(replyFieldSet, "Reply");
400         }
401
402         @Test
403         public void testEncodingAPostWithoutRecipientAndReplies() throws FSParseException {
404                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
405                 Post post = createPost(sone, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
406                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePost(post, "Post.");
407                 assertThat(postFieldSet, notNullValue());
408                 verifyPost(postFieldSet, "Post.", post);
409         }
410
411         private void verifyPost(SimpleFieldSet postFieldSet, String prefix, Post post) throws FSParseException {
412                 assertThat(postFieldSet.get(prefix + "ID"), is(post.getId()));
413                 assertThat(postFieldSet.get(prefix + "Sone"), is(post.getSone().getId()));
414                 assertThat(postFieldSet.get(prefix + "Recipient"), is(post.getRecipientId().orNull()));
415                 assertThat(postFieldSet.getLong(prefix + "Time"), is(post.getTime()));
416                 assertThat(postFieldSet.get(prefix + "Text"), is(post.getText()));
417         }
418
419         @Test
420         public void testEncodingAPostWithRecipientWithoutReplies() throws FSParseException {
421                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
422                 Post post = createPost(sone, "KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
423                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePost(post, "Post.");
424                 assertThat(postFieldSet, notNullValue());
425                 verifyPost(postFieldSet, "Post.", post);
426         }
427
428         @Test
429         public void testEncodingAPostWithoutRecipientWithReplies() throws FSParseException {
430                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
431                 Post post = createPost(sone, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
432                 PostReply postReply = createPostReply(sone, "Reply.");
433                 when(post.getReplies()).thenReturn(asList(postReply));
434                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostWithReplies(post, "Post.");
435                 assertThat(postFieldSet, notNullValue());
436                 verifyPost(postFieldSet, "Post.", post);
437                 verifyPostReplies(postFieldSet, "Post.", asList(postReply));
438         }
439
440         private void verifyPostReplies(SimpleFieldSet postFieldSet, String prefix, Collection<PostReply> postReplies) throws FSParseException {
441                 assertThat(postFieldSet.getInt(prefix + "Replies.Count"), is(from(postReplies).filter(FUTURE_REPLY_FILTER).size()));
442                 int postReplyIndex = 0;
443                 for (PostReply postReply : from(postReplies).filter(FUTURE_REPLY_FILTER)) {
444                         assertThat(postFieldSet.get(prefix + "Replies." + postReplyIndex + ".ID"), is(postReply.getId()));
445                         assertThat(postFieldSet.get(prefix + "Replies." + postReplyIndex + ".Sone"), is(postReply.getSone().getId()));
446                         assertThat(postFieldSet.getLong(prefix + "Replies." + postReplyIndex + ".Time"), is(postReply.getTime()));
447                         assertThat(postFieldSet.get(prefix + "Replies." + postReplyIndex + ".Text"), is(postReply.getText()));
448                         postReplyIndex++;
449                 }
450         }
451
452         @Test
453         public void testEncodingAPostWithoutRecipientWithFutureReplies() throws FSParseException {
454                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
455                 Post post = createPost(sone, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
456                 PostReply postReply = createFuturePostReply(sone, "Reply.");
457                 when(post.getReplies()).thenReturn(asList(postReply));
458                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostWithReplies(post, "Post.");
459                 assertThat(postFieldSet, notNullValue());
460                 verifyPost(postFieldSet, "Post.", post);
461                 verifyPostReplies(postFieldSet, "Post.", Collections.<PostReply>emptyList());
462         }
463
464         @Test
465         public void testEncodingAPostWithRecipientAndReplies() throws FSParseException {
466                 Sone sone = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test", "First", "M.", "Last", (long) (Math.random() * Long.MAX_VALUE));
467                 Post post = createPost(sone, "KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
468                 PostReply postReply = createPostReply(sone, "Reply.");
469                 when(post.getReplies()).thenReturn(asList(postReply));
470                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostWithReplies(post, "Post.");
471                 assertThat(postFieldSet, notNullValue());
472                 verifyPost(postFieldSet, "Post.", post);
473                 verifyPostReplies(postFieldSet, "Post.", asList(postReply));
474         }
475
476         @Test
477         public void testEncodingPostsWithoutRecipientAndReplies() throws FSParseException {
478                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
479                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
480                 Post post1 = createPost(sone1, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
481                 Post post2 = createPost(sone2, null, (long) (Math.random() * Long.MAX_VALUE), "Some other Text.");
482                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePosts(asList(post1, post2), "Posts.");
483                 assertThat(postFieldSet, notNullValue());
484                 verifyPosts(postFieldSet, "Posts.", asList(post1, post2));
485         }
486
487         private void verifyPosts(SimpleFieldSet postFieldSet, String prefix, Collection<Post> posts) throws FSParseException {
488                 assertThat(postFieldSet.getInt(prefix + "Count"), is(posts.size()));
489                 int postIndex = 0;
490                 for (Post post : posts) {
491                         verifyPost(postFieldSet, prefix + postIndex + ".", post);
492                         postIndex++;
493                 }
494         }
495
496         @Test
497         public void testEncodingPostsWithRecipientWithoutReplies() throws FSParseException {
498                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
499                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
500                 Post post1 = createPost(sone1, "KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
501                 Post post2 = createPost(sone2, "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", (long) (Math.random() * Long.MAX_VALUE), "Some other Text.");
502                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePosts(asList(post1, post2), "Posts.");
503                 assertThat(postFieldSet, notNullValue());
504                 verifyPosts(postFieldSet, "Posts.", asList(post1, post2));
505         }
506
507         @Test
508         public void testEncodingPostsWithoutRecipientWithReplies() throws FSParseException {
509                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
510                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
511                 Post post1 = createPost(sone1, null, (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
512                 Post post2 = createPost(sone2, null, (long) (Math.random() * Long.MAX_VALUE), "Some other Text.");
513                 PostReply postReply1 = createPostReply(sone2, "Reply from 2 to 1");
514                 PostReply postReply2 = createPostReply(sone1, "Reply from 1 to 2");
515                 when(post1.getReplies()).thenReturn(asList(postReply1));
516                 when(post2.getReplies()).thenReturn(asList(postReply2));
517                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostsWithReplies(asList(post1, post2), "Posts.");
518                 assertThat(postFieldSet, notNullValue());
519                 verifyPostsWithReplies(postFieldSet, "Posts.", asList(post1, post2));
520         }
521
522         private void verifyPostsWithReplies(SimpleFieldSet postFieldSet, String prefix, Collection<Post> posts) throws FSParseException {
523                 assertThat(postFieldSet.getInt(prefix + "Count"), is(posts.size()));
524                 int postIndex = 0;
525                 for (Post post : posts) {
526                         verifyPost(postFieldSet, prefix + postIndex + ".", post);
527                         verifyPostReplies(postFieldSet, prefix + postIndex + ".", post.getReplies());
528                         postIndex++;
529                 }
530         }
531
532         @Test
533         public void testEncodingPostsWithRecipientAndReplies() throws FSParseException {
534                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
535                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
536                 Post post1 = createPost(sone1, "KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
537                 Post post2 = createPost(sone2, "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", (long) (Math.random() * Long.MAX_VALUE), "Some other Text.");
538                 PostReply postReply1 = createPostReply(sone2, "Reply from 2 to 1");
539                 PostReply postReply2 = createPostReply(sone1, "Reply from 1 to 2");
540                 when(post1.getReplies()).thenReturn(asList(postReply1));
541                 when(post2.getReplies()).thenReturn(asList(postReply2));
542                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostsWithReplies(asList(post1, post2), "Posts.");
543                 assertThat(postFieldSet, notNullValue());
544                 verifyPostsWithReplies(postFieldSet, "Posts.", asList(post1, post2));
545         }
546
547         @Test
548         public void testEncodingPostsWithRecipientAndFutureReplies() throws FSParseException {
549                 Sone sone1 = createSone("jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", "Test1", "Alpha", "A.", "First", (long) (Math.random() * Long.MAX_VALUE));
550                 Sone sone2 = createSone("KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", "Test2", "Beta", "B.", "Second", (long) (Math.random() * Long.MAX_VALUE));
551                 Post post1 = createPost(sone1, "KpoohJSbZGltHHG-YsxKV8ojjS5gwScRv50kl3AkLXg", (long) (Math.random() * Long.MAX_VALUE), "Some Text.");
552                 Post post2 = createPost(sone2, "jXH8d-eFdm14R69WyaCgQoSjaY0jl-Ut6etlXjK0e6E", (long) (Math.random() * Long.MAX_VALUE), "Some other Text.");
553                 PostReply postReply1 = createPostReply(sone2, "Reply from 2 to 1");
554                 PostReply postReply2 = createFuturePostReply(sone1, "Reply from 1 to 2");
555                 when(post1.getReplies()).thenReturn(asList(postReply1));
556                 when(post2.getReplies()).thenReturn(asList(postReply2));
557                 SimpleFieldSet postFieldSet = abstractSoneCommand.encodePostsWithReplies(asList(post1, post2), "Posts.");
558                 assertThat(postFieldSet, notNullValue());
559                 verifyPostsWithReplies(postFieldSet, "Posts.", asList(post1, post2));
560         }
561
562 }