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;
24 import java.util.concurrent.atomic.AtomicReference;
26 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
27 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostReplyFound;
28 import net.pterodactylus.sone.data.Post;
29 import net.pterodactylus.sone.data.PostReply;
30 import net.pterodactylus.sone.data.Profile;
31 import net.pterodactylus.sone.data.Profile.Field;
32 import net.pterodactylus.sone.data.Sone;
33 import net.pterodactylus.sone.database.PostBuilder;
34 import net.pterodactylus.sone.database.PostBuilderFactory;
35 import net.pterodactylus.sone.database.PostReplyBuilder;
36 import net.pterodactylus.sone.database.PostReplyBuilderFactory;
37 import net.pterodactylus.util.config.Configuration;
38 import net.pterodactylus.util.config.ConfigurationException;
39 import net.pterodactylus.util.config.Value;
41 import com.google.common.base.Optional;
42 import org.hamcrest.Matchers;
43 import org.junit.Test;
44 import org.mockito.invocation.InvocationOnMock;
45 import org.mockito.stubbing.Answer;
48 * Unit test for {@link ConfigurationSoneParser}.
50 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
52 public class ConfigurationSoneParserTest {
54 private final Configuration configuration = mock(Configuration.class);
55 private final Sone sone = mock(Sone.class);
56 private final ConfigurationSoneParser configurationSoneParser;
58 public ConfigurationSoneParserTest() {
59 when(sone.getId()).thenReturn("1");
60 configurationSoneParser =
61 new ConfigurationSoneParser(configuration, sone);
65 public void emptyProfileIsLoadedCorrectly() {
67 Profile profile = configurationSoneParser.parseProfile();
68 assertThat(profile, notNullValue());
69 assertThat(profile.getFirstName(), nullValue());
70 assertThat(profile.getMiddleName(), nullValue());
71 assertThat(profile.getLastName(), nullValue());
72 assertThat(profile.getBirthDay(), nullValue());
73 assertThat(profile.getBirthMonth(), nullValue());
74 assertThat(profile.getBirthYear(), nullValue());
75 assertThat(profile.getFields(), emptyIterable());
78 private void setupEmptyProfile() {
79 when(configuration.getStringValue(anyString())).thenReturn(
80 new TestValue<String>(null));
81 when(configuration.getIntValue(anyString())).thenReturn(
82 new TestValue<Integer>(null));
86 public void filledProfileWithFieldsIsParsedCorrectly() {
88 Profile profile = configurationSoneParser.parseProfile();
89 assertThat(profile, notNullValue());
90 assertThat(profile.getFirstName(), is("First"));
91 assertThat(profile.getMiddleName(), is("M."));
92 assertThat(profile.getLastName(), is("Last"));
93 assertThat(profile.getBirthDay(), is(18));
94 assertThat(profile.getBirthMonth(), is(12));
95 assertThat(profile.getBirthYear(), is(1976));
96 final List<Field> fields = profile.getFields();
97 assertThat(fields, hasSize(2));
98 assertThat(fields.get(0).getName(), is("Field1"));
99 assertThat(fields.get(0).getValue(), is("Value1"));
100 assertThat(fields.get(1).getName(), is("Field2"));
101 assertThat(fields.get(1).getValue(), is("Value2"));
104 private void setupFilledProfile() {
105 setupString("Sone/1/Profile/FirstName", "First");
106 setupString("Sone/1/Profile/MiddleName", "M.");
107 setupString("Sone/1/Profile/LastName", "Last");
108 setupInteger("Sone/1/Profile/BirthDay", 18);
109 setupInteger("Sone/1/Profile/BirthMonth", 12);
110 setupInteger("Sone/1/Profile/BirthYear", 1976);
111 setupString("Sone/1/Profile/Fields/0/Name", "Field1");
112 setupString("Sone/1/Profile/Fields/0/Value", "Value1");
113 setupString("Sone/1/Profile/Fields/1/Name", "Field2");
114 setupString("Sone/1/Profile/Fields/1/Value", "Value2");
115 setupString("Sone/1/Profile/Fields/2/Name", null);
118 private void setupString(String nodeName, String value) {
119 when(configuration.getStringValue(eq(nodeName))).thenReturn(
120 new TestValue<String>(value));
123 private void setupInteger(String nodeName, Integer value) {
124 when(configuration.getIntValue(eq(nodeName))).thenReturn(
125 new TestValue<Integer>(value));
129 public void postsAreParsedCorrectly() {
130 setupCompletePosts();
131 PostBuilderFactory postBuilderFactory = createPostBuilderFactory();
132 Collection<Post> posts =
133 configurationSoneParser.parsePosts(postBuilderFactory);
135 Matchers.<Post>containsInAnyOrder(
136 isPost("P0", 1000L, "T0", Optional.<String>absent()),
137 isPost("P1", 1001L, "T1",
138 of("1234567890123456789012345678901234567890123"))));
141 private PostBuilderFactory createPostBuilderFactory() {
142 PostBuilderFactory postBuilderFactory =
143 mock(PostBuilderFactory.class);
144 when(postBuilderFactory.newPostBuilder()).thenAnswer(
145 new Answer<PostBuilder>() {
147 public PostBuilder answer(InvocationOnMock invocation)
149 return new TestPostBuilder();
152 return postBuilderFactory;
155 private void setupCompletePosts() {
156 setupPost("0", "P0", 1000L, "T0", null);
157 setupPost("1", "P1", 1001L, "T1",
158 "1234567890123456789012345678901234567890123");
159 setupPost("2", null, 0L, null, null);
162 private void setupPost(String postNumber, String postId, long time,
163 String text, String recipientId) {
164 setupString("Sone/1/Posts/" + postNumber + "/ID", postId);
165 setupLong("Sone/1/Posts/" + postNumber + "/Time", time);
166 setupString("Sone/1/Posts/" + postNumber + "/Text", text);
167 setupString("Sone/1/Posts/" + postNumber + "/Recipient", recipientId);
170 private void setupLong(String nodeName, Long value) {
171 when(configuration.getLongValue(eq(nodeName))).thenReturn(
172 new TestValue<Long>(value));
175 @Test(expected = InvalidPostFound.class)
176 public void postWithoutTimeIsRecognized() {
177 setupPostWithoutTime();
178 configurationSoneParser.parsePosts(createPostBuilderFactory());
181 private void setupPostWithoutTime() {
182 setupPost("0", "P0", 0L, "T0", null);
185 @Test(expected = InvalidPostFound.class)
186 public void postWithoutTextIsRecognized() {
187 setupPostWithoutText();
188 configurationSoneParser.parsePosts(createPostBuilderFactory());
191 private void setupPostWithoutText() {
192 setupPost("0", "P0", 1000L, null, null);
196 public void postWithInvalidRecipientIdIsRecognized() {
197 setupPostWithInvalidRecipientId();
198 Collection<Post> posts = configurationSoneParser.parsePosts(
199 createPostBuilderFactory());
200 assertThat(posts, contains(
201 isPost("P0", 1000L, "T0", Optional.<String>absent())));
204 private void setupPostWithInvalidRecipientId() {
205 setupPost("0", "P0", 1000L, "T0", "123");
206 setupPost("1", null, 0L, null, null);
210 public void postRepliesAreParsedCorrectly() {
212 PostReplyBuilderFactory postReplyBuilderFactory =
213 new PostReplyBuilderFactory() {
215 public PostReplyBuilder newPostReplyBuilder() {
216 return new TestPostReplyBuilder();
219 Collection<PostReply> postReplies =
220 configurationSoneParser.parsePostReplies(
221 postReplyBuilderFactory);
222 assertThat(postReplies, hasSize(2));
223 assertThat(postReplies,
224 containsInAnyOrder(isPostReply("R0", "P0", 1000L, "T0"),
225 isPostReply("R1", "P1", 1001L, "T1")));
228 private void setupPostReplies() {
229 setupPostReply("0", "R0", "P0", 1000L, "T0");
230 setupPostReply("1", "R1", "P1", 1001L, "T1");
231 setupPostReply("2", null, null, 0L, null);
234 private void setupPostReply(String postReplyNumber, String postReplyId,
235 String postId, long time, String text) {
236 setupString("Sone/1/Replies/" + postReplyNumber + "/ID", postReplyId);
237 setupString("Sone/1/Replies/" + postReplyNumber + "/Post/ID", postId);
238 setupLong("Sone/1/Replies/" + postReplyNumber + "/Time", time);
239 setupString("Sone/1/Replies/" + postReplyNumber + "/Text", text);
242 @Test(expected = InvalidPostReplyFound.class)
243 public void missingPostIdIsRecognized() {
244 setupPostReplyWithMissingPostId();
245 configurationSoneParser.parsePostReplies(null);
248 private void setupPostReplyWithMissingPostId() {
249 setupPostReply("0", "R0", null, 1000L, "T0");
252 @Test(expected = InvalidPostReplyFound.class)
253 public void missingPostReplyTimeIsRecognized() {
254 setupPostReplyWithMissingPostReplyTime();
255 configurationSoneParser.parsePostReplies(null);
258 private void setupPostReplyWithMissingPostReplyTime() {
259 setupPostReply("0", "R0", "P0", 0L, "T0");
262 @Test(expected = InvalidPostReplyFound.class)
263 public void missingPostReplyTextIsRecognized() {
264 setupPostReplyWithMissingPostReplyText();
265 configurationSoneParser.parsePostReplies(null);
268 private void setupPostReplyWithMissingPostReplyText() {
269 setupPostReply("0", "R0", "P0", 1000L, null);
272 private static class TestValue<T> implements Value<T> {
274 private final AtomicReference<T> value = new AtomicReference<T>();
276 public TestValue(T originalValue) {
277 value.set(originalValue);
281 public T getValue() throws ConfigurationException {
286 public T getValue(T defaultValue) {
287 final T realValue = value.get();
288 return (realValue != null) ? realValue : defaultValue;
292 public void setValue(T newValue) throws ConfigurationException {
298 private static class TestPostBuilder implements PostBuilder {
300 private final Post post = mock(Post.class);
301 private String recipientId = null;
304 public PostBuilder copyPost(Post post) throws NullPointerException {
309 public PostBuilder from(String senderId) {
310 final Sone sone = mock(Sone.class);
311 when(sone.getId()).thenReturn(senderId);
312 when(post.getSone()).thenReturn(sone);
317 public PostBuilder randomId() {
318 when(post.getId()).thenReturn(randomUUID().toString());
323 public PostBuilder withId(String id) {
324 when(post.getId()).thenReturn(id);
329 public PostBuilder currentTime() {
330 when(post.getTime()).thenReturn(currentTimeMillis());
335 public PostBuilder withTime(long time) {
336 when(post.getTime()).thenReturn(time);
341 public PostBuilder withText(String text) {
342 when(post.getText()).thenReturn(text);
347 public PostBuilder to(String recipientId) {
348 this.recipientId = recipientId;
353 public Post build() throws IllegalStateException {
354 when(post.getRecipientId()).thenReturn(fromNullable(recipientId));
360 private static class TestPostReplyBuilder implements PostReplyBuilder {
362 private final PostReply postReply = mock(PostReply.class);
365 public PostReplyBuilder to(String postId) {
366 when(postReply.getPostId()).thenReturn(postId);
371 public PostReply build() throws IllegalStateException {
376 public PostReplyBuilder randomId() {
377 when(postReply.getId()).thenReturn(randomUUID().toString());
382 public PostReplyBuilder withId(String id) {
383 when(postReply.getId()).thenReturn(id);
388 public PostReplyBuilder from(String senderId) {
389 Sone sone = mock(Sone.class);
390 when(sone.getId()).thenReturn(senderId);
391 when(postReply.getSone()).thenReturn(sone);
396 public PostReplyBuilder currentTime() {
397 when(postReply.getTime()).thenReturn(currentTimeMillis());
402 public PostReplyBuilder withTime(long time) {
403 when(postReply.getTime()).thenReturn(time);
408 public PostReplyBuilder withText(String text) {
409 when(postReply.getText()).thenReturn(text);