1 package net.pterodactylus.sone.core;
3 import static com.google.common.base.Optional.fromNullable;
4 import static com.google.common.base.Optional.of;
5 import static java.lang.System.currentTimeMillis;
6 import static java.util.UUID.randomUUID;
7 import static net.pterodactylus.sone.Matchers.isPost;
8 import static net.pterodactylus.sone.Matchers.isPostReply;
9 import static org.hamcrest.MatcherAssert.assertThat;
10 import static org.hamcrest.Matchers.contains;
11 import static org.hamcrest.Matchers.containsInAnyOrder;
12 import static org.hamcrest.Matchers.emptyIterable;
13 import static org.hamcrest.Matchers.hasSize;
14 import static org.hamcrest.Matchers.is;
15 import static org.hamcrest.Matchers.notNullValue;
16 import static org.hamcrest.Matchers.nullValue;
17 import static org.mockito.Matchers.anyString;
18 import static org.mockito.Matchers.eq;
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.when;
22 import java.util.Collection;
23 import java.util.List;
25 import java.util.concurrent.atomic.AtomicReference;
27 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
28 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
29 import net.pterodactylus.sone.data.Post;
30 import net.pterodactylus.sone.data.PostReply;
31 import net.pterodactylus.sone.data.Profile;
32 import net.pterodactylus.sone.data.Profile.Field;
33 import net.pterodactylus.sone.data.Sone;
34 import net.pterodactylus.sone.database.PostBuilder;
35 import net.pterodactylus.sone.database.PostBuilderFactory;
36 import net.pterodactylus.sone.database.PostReplyBuilder;
37 import net.pterodactylus.sone.database.PostReplyBuilderFactory;
38 import net.pterodactylus.util.config.Configuration;
39 import net.pterodactylus.util.config.ConfigurationException;
40 import net.pterodactylus.util.config.Value;
42 import com.google.common.base.Optional;
43 import org.hamcrest.Matchers;
44 import org.junit.Test;
45 import org.mockito.invocation.InvocationOnMock;
46 import org.mockito.stubbing.Answer;
49 * Unit test for {@link ConfigurationSoneParser}.
51 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
53 public class ConfigurationSoneParserTest {
55 private final Configuration configuration = mock(Configuration.class);
56 private final Sone sone = mock(Sone.class);
57 private final ConfigurationSoneParser configurationSoneParser;
59 public ConfigurationSoneParserTest() {
60 when(sone.getId()).thenReturn("1");
61 configurationSoneParser =
62 new ConfigurationSoneParser(configuration, sone);
66 public void emptyProfileIsLoadedCorrectly() {
68 Profile profile = configurationSoneParser.parseProfile();
69 assertThat(profile, notNullValue());
70 assertThat(profile.getFirstName(), nullValue());
71 assertThat(profile.getMiddleName(), nullValue());
72 assertThat(profile.getLastName(), nullValue());
73 assertThat(profile.getBirthDay(), nullValue());
74 assertThat(profile.getBirthMonth(), nullValue());
75 assertThat(profile.getBirthYear(), nullValue());
76 assertThat(profile.getFields(), emptyIterable());
79 private void setupEmptyProfile() {
80 when(configuration.getStringValue(anyString())).thenReturn(
81 new TestValue<String>(null));
82 when(configuration.getIntValue(anyString())).thenReturn(
83 new TestValue<Integer>(null));
87 public void filledProfileWithFieldsIsParsedCorrectly() {
89 Profile profile = configurationSoneParser.parseProfile();
90 assertThat(profile, notNullValue());
91 assertThat(profile.getFirstName(), is("First"));
92 assertThat(profile.getMiddleName(), is("M."));
93 assertThat(profile.getLastName(), is("Last"));
94 assertThat(profile.getBirthDay(), is(18));
95 assertThat(profile.getBirthMonth(), is(12));
96 assertThat(profile.getBirthYear(), is(1976));
97 final List<Field> fields = profile.getFields();
98 assertThat(fields, hasSize(2));
99 assertThat(fields.get(0).getName(), is("Field1"));
100 assertThat(fields.get(0).getValue(), is("Value1"));
101 assertThat(fields.get(1).getName(), is("Field2"));
102 assertThat(fields.get(1).getValue(), is("Value2"));
105 private void setupFilledProfile() {
106 setupString("Sone/1/Profile/FirstName", "First");
107 setupString("Sone/1/Profile/MiddleName", "M.");
108 setupString("Sone/1/Profile/LastName", "Last");
109 setupInteger("Sone/1/Profile/BirthDay", 18);
110 setupInteger("Sone/1/Profile/BirthMonth", 12);
111 setupInteger("Sone/1/Profile/BirthYear", 1976);
112 setupString("Sone/1/Profile/Fields/0/Name", "Field1");
113 setupString("Sone/1/Profile/Fields/0/Value", "Value1");
114 setupString("Sone/1/Profile/Fields/1/Name", "Field2");
115 setupString("Sone/1/Profile/Fields/1/Value", "Value2");
116 setupString("Sone/1/Profile/Fields/2/Name", null);
119 private void setupString(String nodeName, String value) {
120 when(configuration.getStringValue(eq(nodeName))).thenReturn(
121 new TestValue<String>(value));
124 private void setupInteger(String nodeName, Integer value) {
125 when(configuration.getIntValue(eq(nodeName))).thenReturn(
126 new TestValue<Integer>(value));
130 public void postsAreParsedCorrectly() {
131 setupCompletePosts();
132 PostBuilderFactory postBuilderFactory = createPostBuilderFactory();
133 Collection<Post> posts =
134 configurationSoneParser.parsePosts(postBuilderFactory);
136 Matchers.<Post>containsInAnyOrder(
137 isPost("P0", 1000L, "T0", Optional.<String>absent()),
138 isPost("P1", 1001L, "T1",
139 of("1234567890123456789012345678901234567890123"))));
142 private PostBuilderFactory createPostBuilderFactory() {
143 PostBuilderFactory postBuilderFactory =
144 mock(PostBuilderFactory.class);
145 when(postBuilderFactory.newPostBuilder()).thenAnswer(
146 new Answer<PostBuilder>() {
148 public PostBuilder answer(InvocationOnMock invocation)
150 return new TestPostBuilder();
153 return postBuilderFactory;
156 private void setupCompletePosts() {
157 setupPost("0", "P0", 1000L, "T0", null);
158 setupPost("1", "P1", 1001L, "T1",
159 "1234567890123456789012345678901234567890123");
160 setupPost("2", null, 0L, null, null);
163 private void setupPost(String postNumber, String postId, long time,
164 String text, String recipientId) {
165 setupString("Sone/1/Posts/" + postNumber + "/ID", postId);
166 setupLong("Sone/1/Posts/" + postNumber + "/Time", time);
167 setupString("Sone/1/Posts/" + postNumber + "/Text", text);
168 setupString("Sone/1/Posts/" + postNumber + "/Recipient", recipientId);
171 private void setupLong(String nodeName, Long value) {
172 when(configuration.getLongValue(eq(nodeName))).thenReturn(
173 new TestValue<Long>(value));
176 @Test(expected = InvalidPostFound.class)
177 public void postWithoutTimeIsRecognized() {
178 setupPostWithoutTime();
179 configurationSoneParser.parsePosts(createPostBuilderFactory());
182 private void setupPostWithoutTime() {
183 setupPost("0", "P0", 0L, "T0", null);
186 @Test(expected = InvalidPostFound.class)
187 public void postWithoutTextIsRecognized() {
188 setupPostWithoutText();
189 configurationSoneParser.parsePosts(createPostBuilderFactory());
192 private void setupPostWithoutText() {
193 setupPost("0", "P0", 1000L, null, null);
197 public void postWithInvalidRecipientIdIsRecognized() {
198 setupPostWithInvalidRecipientId();
199 Collection<Post> posts = configurationSoneParser.parsePosts(
200 createPostBuilderFactory());
201 assertThat(posts, contains(
202 isPost("P0", 1000L, "T0", Optional.<String>absent())));
205 private void setupPostWithInvalidRecipientId() {
206 setupPost("0", "P0", 1000L, "T0", "123");
207 setupPost("1", null, 0L, null, null);
211 public void postRepliesAreParsedCorrectly() {
213 PostReplyBuilderFactory postReplyBuilderFactory =
214 new PostReplyBuilderFactory() {
216 public PostReplyBuilder newPostReplyBuilder() {
217 return new TestPostReplyBuilder();
220 Collection<PostReply> postReplies =
221 configurationSoneParser.parsePostReplies(
222 postReplyBuilderFactory);
223 assertThat(postReplies, hasSize(2));
224 assertThat(postReplies,
225 containsInAnyOrder(isPostReply("R0", "P0", 1000L, "T0"),
226 isPostReply("R1", "P1", 1001L, "T1")));
229 private void setupPostReplies() {
230 setupPostReply("0", "R0", "P0", 1000L, "T0");
231 setupPostReply("1", "R1", "P1", 1001L, "T1");
232 setupPostReply("2", null, null, 0L, null);
235 private void setupPostReply(String postReplyNumber, String postReplyId,
236 String postId, long time, String text) {
237 setupString("Sone/1/Replies/" + postReplyNumber + "/ID", postReplyId);
238 setupString("Sone/1/Replies/" + postReplyNumber + "/Post/ID", postId);
239 setupLong("Sone/1/Replies/" + postReplyNumber + "/Time", time);
240 setupString("Sone/1/Replies/" + postReplyNumber + "/Text", text);
243 @Test(expected = InvalidPostReplyFound.class)
244 public void missingPostIdIsRecognized() {
245 setupPostReplyWithMissingPostId();
246 configurationSoneParser.parsePostReplies(null);
249 private void setupPostReplyWithMissingPostId() {
250 setupPostReply("0", "R0", null, 1000L, "T0");
253 @Test(expected = InvalidPostReplyFound.class)
254 public void missingPostReplyTimeIsRecognized() {
255 setupPostReplyWithMissingPostReplyTime();
256 configurationSoneParser.parsePostReplies(null);
259 private void setupPostReplyWithMissingPostReplyTime() {
260 setupPostReply("0", "R0", "P0", 0L, "T0");
263 @Test(expected = InvalidPostReplyFound.class)
264 public void missingPostReplyTextIsRecognized() {
265 setupPostReplyWithMissingPostReplyText();
266 configurationSoneParser.parsePostReplies(null);
269 private void setupPostReplyWithMissingPostReplyText() {
270 setupPostReply("0", "R0", "P0", 1000L, null);
274 public void likedPostIdsParsedCorrectly() {
276 Set<String> likedPostIds =
277 configurationSoneParser.parseLikedPostIds();
278 assertThat(likedPostIds, containsInAnyOrder("P1", "P2", "P3"));
281 private void setupLikedPostIds() {
282 setupString("Sone/1/Likes/Post/0/ID", "P1");
283 setupString("Sone/1/Likes/Post/1/ID", "P2");
284 setupString("Sone/1/Likes/Post/2/ID", "P3");
285 setupString("Sone/1/Likes/Post/3/ID", null);
289 public void likedPostReplyIdsAreParsedCorrectly() {
290 setupLikedPostReplyIds();
291 Set<String> likedPostReplyIds =
292 configurationSoneParser.parseLikedPostReplyIds();
293 assertThat(likedPostReplyIds, containsInAnyOrder("R1", "R2", "R3"));
296 private void setupLikedPostReplyIds() {
297 setupString("Sone/1/Likes/Reply/0/ID", "R1");
298 setupString("Sone/1/Likes/Reply/1/ID", "R2");
299 setupString("Sone/1/Likes/Reply/2/ID", "R3");
300 setupString("Sone/1/Likes/Reply/3/ID", null);
304 public void friendsAreParsedCorrectly() {
306 Set<String> friends = configurationSoneParser.parseFriends();
307 assertThat(friends, containsInAnyOrder("F1", "F2", "F3"));
310 private void setupFriends() {
311 setupString("Sone/1/Friends/0/ID", "F1");
312 setupString("Sone/1/Friends/1/ID", "F2");
313 setupString("Sone/1/Friends/2/ID", "F3");
314 setupString("Sone/1/Friends/3/ID", null);
317 private static class TestValue<T> implements Value<T> {
319 private final AtomicReference<T> value = new AtomicReference<T>();
321 public TestValue(T originalValue) {
322 value.set(originalValue);
326 public T getValue() throws ConfigurationException {
331 public T getValue(T defaultValue) {
332 final T realValue = value.get();
333 return (realValue != null) ? realValue : defaultValue;
337 public void setValue(T newValue) throws ConfigurationException {
343 private static class TestPostBuilder implements PostBuilder {
345 private final Post post = mock(Post.class);
346 private String recipientId = null;
349 public PostBuilder copyPost(Post post) throws NullPointerException {
354 public PostBuilder from(String senderId) {
355 final Sone sone = mock(Sone.class);
356 when(sone.getId()).thenReturn(senderId);
357 when(post.getSone()).thenReturn(sone);
362 public PostBuilder randomId() {
363 when(post.getId()).thenReturn(randomUUID().toString());
368 public PostBuilder withId(String id) {
369 when(post.getId()).thenReturn(id);
374 public PostBuilder currentTime() {
375 when(post.getTime()).thenReturn(currentTimeMillis());
380 public PostBuilder withTime(long time) {
381 when(post.getTime()).thenReturn(time);
386 public PostBuilder withText(String text) {
387 when(post.getText()).thenReturn(text);
392 public PostBuilder to(String recipientId) {
393 this.recipientId = recipientId;
398 public Post build() throws IllegalStateException {
399 when(post.getRecipientId()).thenReturn(fromNullable(recipientId));
405 private static class TestPostReplyBuilder implements PostReplyBuilder {
407 private final PostReply postReply = mock(PostReply.class);
410 public PostReplyBuilder to(String postId) {
411 when(postReply.getPostId()).thenReturn(postId);
416 public PostReply build() throws IllegalStateException {
421 public PostReplyBuilder randomId() {
422 when(postReply.getId()).thenReturn(randomUUID().toString());
427 public PostReplyBuilder withId(String id) {
428 when(postReply.getId()).thenReturn(id);
433 public PostReplyBuilder from(String senderId) {
434 Sone sone = mock(Sone.class);
435 when(sone.getId()).thenReturn(senderId);
436 when(postReply.getSone()).thenReturn(sone);
441 public PostReplyBuilder currentTime() {
442 when(postReply.getTime()).thenReturn(currentTimeMillis());
447 public PostReplyBuilder withTime(long time) {
448 when(postReply.getTime()).thenReturn(time);
453 public PostReplyBuilder withText(String text) {
454 when(postReply.getText()).thenReturn(text);