Start moving parsing a Sone from a configuration to a specialized parser.
[Sone.git] / src / test / java / net / pterodactylus / sone / core / ConfigurationSoneParserTest.java
1 package net.pterodactylus.sone.core;
2
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 org.hamcrest.MatcherAssert.assertThat;
9 import static org.hamcrest.Matchers.contains;
10 import static org.hamcrest.Matchers.emptyIterable;
11 import static org.hamcrest.Matchers.hasSize;
12 import static org.hamcrest.Matchers.is;
13 import static org.hamcrest.Matchers.notNullValue;
14 import static org.hamcrest.Matchers.nullValue;
15 import static org.mockito.Matchers.anyString;
16 import static org.mockito.Matchers.eq;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.when;
19
20 import java.util.Collection;
21 import java.util.List;
22 import java.util.concurrent.atomic.AtomicReference;
23
24 import net.pterodactylus.sone.core.ConfigurationSoneParser.InvalidPostFound;
25 import net.pterodactylus.sone.data.Post;
26 import net.pterodactylus.sone.data.Profile;
27 import net.pterodactylus.sone.data.Profile.Field;
28 import net.pterodactylus.sone.data.Sone;
29 import net.pterodactylus.sone.database.PostBuilder;
30 import net.pterodactylus.sone.database.PostBuilderFactory;
31 import net.pterodactylus.util.config.Configuration;
32 import net.pterodactylus.util.config.ConfigurationException;
33 import net.pterodactylus.util.config.Value;
34
35 import com.google.common.base.Optional;
36 import org.hamcrest.Matchers;
37 import org.junit.Test;
38 import org.mockito.invocation.InvocationOnMock;
39 import org.mockito.stubbing.Answer;
40
41 /**
42  * Unit test for {@link ConfigurationSoneParser}.
43  *
44  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
45  */
46 public class ConfigurationSoneParserTest {
47
48         private final Configuration configuration = mock(Configuration.class);
49         private final Sone sone = mock(Sone.class);
50         private final ConfigurationSoneParser configurationSoneParser;
51
52         public ConfigurationSoneParserTest() {
53                 when(sone.getId()).thenReturn("1");
54                 configurationSoneParser =
55                                 new ConfigurationSoneParser(configuration, sone);
56         }
57
58         @Test
59         public void emptyProfileIsLoadedCorrectly() {
60                 setupEmptyProfile();
61                 Profile profile = configurationSoneParser.parseProfile();
62                 assertThat(profile, notNullValue());
63                 assertThat(profile.getFirstName(), nullValue());
64                 assertThat(profile.getMiddleName(), nullValue());
65                 assertThat(profile.getLastName(), nullValue());
66                 assertThat(profile.getBirthDay(), nullValue());
67                 assertThat(profile.getBirthMonth(), nullValue());
68                 assertThat(profile.getBirthYear(), nullValue());
69                 assertThat(profile.getFields(), emptyIterable());
70         }
71
72         private void setupEmptyProfile() {
73                 when(configuration.getStringValue(anyString())).thenReturn(
74                                 new TestValue<String>(null));
75                 when(configuration.getIntValue(anyString())).thenReturn(
76                                 new TestValue<Integer>(null));
77         }
78
79         @Test
80         public void filledProfileWithFieldsIsParsedCorrectly() {
81                 setupFilledProfile();
82                 Profile profile = configurationSoneParser.parseProfile();
83                 assertThat(profile, notNullValue());
84                 assertThat(profile.getFirstName(), is("First"));
85                 assertThat(profile.getMiddleName(), is("M."));
86                 assertThat(profile.getLastName(), is("Last"));
87                 assertThat(profile.getBirthDay(), is(18));
88                 assertThat(profile.getBirthMonth(), is(12));
89                 assertThat(profile.getBirthYear(), is(1976));
90                 final List<Field> fields = profile.getFields();
91                 assertThat(fields, hasSize(2));
92                 assertThat(fields.get(0).getName(), is("Field1"));
93                 assertThat(fields.get(0).getValue(), is("Value1"));
94                 assertThat(fields.get(1).getName(), is("Field2"));
95                 assertThat(fields.get(1).getValue(), is("Value2"));
96         }
97
98         private void setupFilledProfile() {
99                 setupString("Sone/1/Profile/FirstName", "First");
100                 setupString("Sone/1/Profile/MiddleName", "M.");
101                 setupString("Sone/1/Profile/LastName", "Last");
102                 setupInteger("Sone/1/Profile/BirthDay", 18);
103                 setupInteger("Sone/1/Profile/BirthMonth", 12);
104                 setupInteger("Sone/1/Profile/BirthYear", 1976);
105                 setupString("Sone/1/Profile/Fields/0/Name", "Field1");
106                 setupString("Sone/1/Profile/Fields/0/Value", "Value1");
107                 setupString("Sone/1/Profile/Fields/1/Name", "Field2");
108                 setupString("Sone/1/Profile/Fields/1/Value", "Value2");
109                 setupString("Sone/1/Profile/Fields/2/Name", null);
110         }
111
112         private void setupString(String nodeName, String value) {
113                 when(configuration.getStringValue(eq(nodeName))).thenReturn(
114                                 new TestValue<String>(value));
115         }
116
117         private void setupInteger(String nodeName, Integer value) {
118                 when(configuration.getIntValue(eq(nodeName))).thenReturn(
119                                 new TestValue<Integer>(value));
120         }
121
122         @Test
123         public void postsAreParsedCorrectly() {
124                 setupCompletePosts();
125                 PostBuilderFactory postBuilderFactory = createPostBuilderFactory();
126                 Collection<Post> posts =
127                                 configurationSoneParser.parsePosts(postBuilderFactory);
128                 assertThat(posts,
129                                 Matchers.<Post>containsInAnyOrder(
130                                                 isPost("P0", 1000L, "T0", Optional.<String>absent()),
131                                                 isPost("P1", 1001L, "T1",
132                                                                 of("1234567890123456789012345678901234567890123"))));
133         }
134
135         private PostBuilderFactory createPostBuilderFactory() {
136                 PostBuilderFactory postBuilderFactory =
137                                 mock(PostBuilderFactory.class);
138                 when(postBuilderFactory.newPostBuilder()).thenAnswer(
139                                 new Answer<PostBuilder>() {
140                                         @Override
141                                         public PostBuilder answer(InvocationOnMock invocation)
142                                         throws Throwable {
143                                                 return new TestPostBuilder();
144                                         }
145                                 });
146                 return postBuilderFactory;
147         }
148
149         private void setupCompletePosts() {
150                 setupPost("0", "P0", 1000L, "T0", null);
151                 setupPost("1", "P1", 1001L, "T1",
152                                 "1234567890123456789012345678901234567890123");
153                 setupPost("2", null, 0L, null, null);
154         }
155
156         private void setupPost(String postNumber, String postId, long time,
157                         String text, String recipientId) {
158                 setupString("Sone/1/Posts/" + postNumber + "/ID", postId);
159                 setupLong("Sone/1/Posts/" + postNumber + "/Time", time);
160                 setupString("Sone/1/Posts/" + postNumber + "/Text", text);
161                 setupString("Sone/1/Posts/" + postNumber + "/Recipient", recipientId);
162         }
163
164         private void setupLong(String nodeName, Long value) {
165                 when(configuration.getLongValue(eq(nodeName))).thenReturn(
166                                 new TestValue<Long>(value));
167         }
168
169         @Test(expected = InvalidPostFound.class)
170         public void postWithoutTimeIsRecognized() {
171                 setupPostWithoutTime();
172                 configurationSoneParser.parsePosts(createPostBuilderFactory());
173         }
174
175         private void setupPostWithoutTime() {
176                 setupPost("0", "P0", 0L, "T0", null);
177         }
178
179         @Test(expected = InvalidPostFound.class)
180         public void postWithoutTextIsRecognized() {
181                 setupPostWithoutText();
182                 configurationSoneParser.parsePosts(createPostBuilderFactory());
183         }
184
185         private void setupPostWithoutText() {
186                 setupPost("0", "P0", 1000L, null, null);
187         }
188
189         @Test
190         public void postWithInvalidRecipientIdIsRecognized() {
191                 setupPostWithInvalidRecipientId();
192                 Collection<Post> posts = configurationSoneParser.parsePosts(
193                                 createPostBuilderFactory());
194                 assertThat(posts, contains(
195                                 isPost("P0", 1000L, "T0", Optional.<String>absent())));
196         }
197
198         private void setupPostWithInvalidRecipientId() {
199                 setupPost("0", "P0", 1000L, "T0", "123");
200                 setupPost("1", null, 0L, null, null);
201         }
202
203
204         private static class TestValue<T> implements Value<T> {
205
206                 private final AtomicReference<T> value = new AtomicReference<T>();
207
208                 public TestValue(T originalValue) {
209                         value.set(originalValue);
210                 }
211
212                 @Override
213                 public T getValue() throws ConfigurationException {
214                         return value.get();
215                 }
216
217                 @Override
218                 public T getValue(T defaultValue) {
219                         final T realValue = value.get();
220                         return (realValue != null) ? realValue : defaultValue;
221                 }
222
223                 @Override
224                 public void setValue(T newValue) throws ConfigurationException {
225                         value.set(newValue);
226                 }
227
228         }
229
230         private static class TestPostBuilder implements PostBuilder {
231
232                 private final Post post = mock(Post.class);
233                 private String recipientId = null;
234
235                 @Override
236                 public PostBuilder copyPost(Post post) throws NullPointerException {
237                         return this;
238                 }
239
240                 @Override
241                 public PostBuilder from(String senderId) {
242                         final Sone sone = mock(Sone.class);
243                         when(sone.getId()).thenReturn(senderId);
244                         when(post.getSone()).thenReturn(sone);
245                         return this;
246                 }
247
248                 @Override
249                 public PostBuilder randomId() {
250                         when(post.getId()).thenReturn(randomUUID().toString());
251                         return this;
252                 }
253
254                 @Override
255                 public PostBuilder withId(String id) {
256                         when(post.getId()).thenReturn(id);
257                         return this;
258                 }
259
260                 @Override
261                 public PostBuilder currentTime() {
262                         when(post.getTime()).thenReturn(currentTimeMillis());
263                         return this;
264                 }
265
266                 @Override
267                 public PostBuilder withTime(long time) {
268                         when(post.getTime()).thenReturn(time);
269                         return this;
270                 }
271
272                 @Override
273                 public PostBuilder withText(String text) {
274                         when(post.getText()).thenReturn(text);
275                         return this;
276                 }
277
278                 @Override
279                 public PostBuilder to(String recipientId) {
280                         this.recipientId = recipientId;
281                         return this;
282                 }
283
284                 @Override
285                 public Post build() throws IllegalStateException {
286                         when(post.getRecipientId()).thenReturn(fromNullable(recipientId));
287                         return post;
288                 }
289
290         }
291
292 }