🔥 Remove unnecessary imports
[Sone.git] / src / test / java / net / pterodactylus / sone / core / WebOfTrustUpdaterTest.java
1 package net.pterodactylus.sone.core;
2
3 import static java.lang.Thread.sleep;
4 import static java.util.concurrent.TimeUnit.SECONDS;
5 import static org.hamcrest.MatcherAssert.assertThat;
6 import static org.hamcrest.Matchers.containsString;
7 import static org.hamcrest.Matchers.is;
8 import static org.hamcrest.Matchers.not;
9 import static org.mockito.Mockito.*;
10
11 import java.util.concurrent.CountDownLatch;
12
13 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.AddContextJob;
14 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.RemoveContextJob;
15 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.SetPropertyJob;
16 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.WebOfTrustContextUpdateJob;
17 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.WebOfTrustUpdateJob;
18 import net.pterodactylus.sone.freenet.plugin.PluginException;
19 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
20 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
21
22 import org.junit.Test;
23 import org.mockito.invocation.InvocationOnMock;
24 import org.mockito.stubbing.Answer;
25
26 /**
27  * Unit test for {@link WebOfTrustUpdaterImpl} and its subclasses.
28  */
29 public class WebOfTrustUpdaterTest {
30
31         private static final String CONTEXT = "test-context";
32         private static final String PROPERTY_NAME = "test-property";
33         private final WebOfTrustConnector webOfTrustConnector = mock(WebOfTrustConnector.class);
34         private final WebOfTrustUpdaterImpl webOfTrustUpdater = new WebOfTrustUpdaterImpl(webOfTrustConnector);
35         private final OwnIdentity ownIdentity = when(mock(OwnIdentity.class).getId()).thenReturn("own-identity-id").getMock();
36         private final WebOfTrustUpdateJob successfulWebOfTrustUpdateJob = createWebOfTrustUpdateJob(true);
37         private final WebOfTrustUpdateJob failingWebOfTrustUpdateJob = createWebOfTrustUpdateJob(false);
38         private final WebOfTrustContextUpdateJob contextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
39         private final AddContextJob addContextJob = webOfTrustUpdater.new AddContextJob(ownIdentity, CONTEXT);
40         private final RemoveContextJob removeContextJob = webOfTrustUpdater.new RemoveContextJob(ownIdentity, CONTEXT);
41
42         private WebOfTrustUpdateJob createWebOfTrustUpdateJob(final boolean success) {
43                 return webOfTrustUpdater.new WebOfTrustUpdateJob() {
44                         @Override
45                         public void run() {
46                                 super.run();
47                                 try {
48                                         sleep(100);
49                                 } catch (InterruptedException ie1) {
50                                         throw new RuntimeException(ie1);
51                                 }
52                                 finish(success);
53                         }
54                 };
55         }
56
57         @Test
58         public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsSuccess() throws InterruptedException {
59                 new Thread(successfulWebOfTrustUpdateJob).start();
60                 assertThat(successfulWebOfTrustUpdateJob.waitForCompletion(), is(true));
61         }
62
63         @Test
64         public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsFailure() throws InterruptedException {
65                 new Thread(failingWebOfTrustUpdateJob).start();
66                 assertThat(failingWebOfTrustUpdateJob.waitForCompletion(), is(false));
67         }
68
69         @Test
70         public void webOfTrustContextUpdateJobsAreEqualIfTheirClassOwnIdentityAndContextAreEqual() {
71                 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
72                 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(true));
73                 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(true));
74                 assertThat(contextUpdateJob.hashCode(), is(secondContextUpdateJob.hashCode()));
75         }
76
77         @Test
78         public void webOfTrustContextUpdatesJobsAreNotEqualIfTheirClassDiffers() {
79                 assertThat(contextUpdateJob.equals(addContextJob), is(false));
80         }
81
82         @Test
83         public void webOfTrustContextUpdateJobToStringContainsIdentityAndContext() {
84                 assertThat(contextUpdateJob.toString(), containsString(ownIdentity.toString()));
85                 assertThat(contextUpdateJob.toString(), containsString(CONTEXT));
86         }
87
88         @Test
89         public void webOfTrustContextUpdateJobsAreNotEqualIfTheIdentitiesDiffer() {
90                 OwnIdentity ownIdentity = mock(OwnIdentity.class);
91                 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
92                 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(false));
93                 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(false));
94         }
95
96         @Test
97         public void webOfTrustContextUpdateJobsAreNotEqualIfTheirContextsDiffer() {
98                 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT + CONTEXT);
99                 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(false));
100                 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(false));
101         }
102
103         @Test
104         public void webOfTrustContextUpdateJobsAreNotEqualToNull() {
105                 assertThat(contextUpdateJob.equals(null), is(false));
106         }
107
108         @Test
109         public void addContextJobAddsTheContext() throws PluginException {
110                 addContextJob.run();
111                 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
112                 verify(ownIdentity).addContext(eq(CONTEXT));
113                 assertThat(addContextJob.waitForCompletion(), is(true));
114         }
115
116         @Test
117         public void exceptionWhileAddingAContextIsExposed() throws PluginException {
118                 doThrow(PluginException.class).when(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
119                 addContextJob.run();
120                 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
121                 verify(ownIdentity, never()).addContext(eq(CONTEXT));
122                 assertThat(addContextJob.waitForCompletion(), is(false));
123         }
124
125         @Test
126         public void removeContextJobRemovesTheContext() throws PluginException {
127                 removeContextJob.run();
128                 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
129                 verify(ownIdentity).removeContext(eq(CONTEXT));
130                 assertThat(removeContextJob.waitForCompletion(), is(true));
131         }
132
133         @Test
134         public void exceptionWhileRemovingAContextIsExposed() throws PluginException {
135                 doThrow(PluginException.class).when(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
136                 removeContextJob.run();
137                 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
138                 verify(ownIdentity, never()).removeContext(eq(CONTEXT));
139                 assertThat(removeContextJob.waitForCompletion(), is(false));
140         }
141
142         @Test
143         public void settingAPropertySetsTheProperty() throws PluginException {
144                 String propertyName = "property-name";
145                 String propertyValue = "property-value";
146                 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
147                 setPropertyJob.run();
148                 verify(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
149                 verify(ownIdentity).setProperty(eq(propertyName), eq(propertyValue));
150                 assertThat(setPropertyJob.waitForCompletion(), is(true));
151         }
152
153         @Test
154         public void settingAPropertyToNullRemovesTheProperty() throws PluginException {
155                 String propertyName = "property-name";
156                 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, null);
157                 setPropertyJob.run();
158                 verify(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(propertyName));
159                 verify(ownIdentity).removeProperty(eq(propertyName));
160                 assertThat(setPropertyJob.waitForCompletion(), is(true));
161         }
162
163         @Test
164         public void pluginExceptionWhileSettingAPropertyIsHandled() throws PluginException {
165                 String propertyName = "property-name";
166                 String propertyValue = "property-value";
167                 doThrow(PluginException.class).when(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
168                 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
169                 setPropertyJob.run();
170                 verify(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
171                 verify(ownIdentity, never()).setProperty(eq(propertyName), eq(propertyValue));
172                 assertThat(setPropertyJob.waitForCompletion(), is(false));
173         }
174
175         @Test
176         public void setPropertyJobsWithSameClassPropertyAndValueAreEqual() {
177                 String propertyName = "property-name";
178                 String propertyValue = "property-value";
179                 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
180                 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
181                 assertThat(firstSetPropertyJob, is(secondSetPropertyJob));
182                 assertThat(secondSetPropertyJob, is(firstSetPropertyJob));
183                 assertThat(firstSetPropertyJob.hashCode(), is(secondSetPropertyJob.hashCode()));
184         }
185
186         @Test
187         public void setPropertyJobsWithDifferentClassesAreNotEqual() {
188                 String propertyName = "property-name";
189                 String propertyValue = "property-value";
190                 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
191                 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue) {
192                 };
193                 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
194         }
195
196         @Test
197         public void nullIsNotASetProjectJobEither() {
198                 String propertyName = "property-name";
199                 String propertyValue = "property-value";
200                 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
201                 assertThat(setPropertyJob, not(is((Object) null)));
202         }
203
204         @Test
205         public void setPropertyJobsWithDifferentPropertiesAreNotEqual() {
206                 String propertyName = "property-name";
207                 String propertyValue = "property-value";
208                 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
209                 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName + "2", propertyValue);
210                 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
211         }
212
213         @Test
214         public void setPropertyJobsWithDifferentOwnIdentitiesAreNotEqual() {
215                 OwnIdentity otherOwnIdentity = mock(OwnIdentity.class);
216                 String propertyName = "property-name";
217                 String propertyValue = "property-value";
218                 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
219                 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(otherOwnIdentity, propertyName, propertyValue);
220                 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
221         }
222
223         @Test
224         public void webOfTrustUpdaterStopsWhenItShould() {
225                 webOfTrustUpdater.stop();
226                 webOfTrustUpdater.serviceRun();
227         }
228
229         @Test
230         public void webOfTrustUpdaterStopsAfterItWasStarted() {
231                 webOfTrustUpdater.start();
232                 webOfTrustUpdater.stop();
233         }
234
235         @Test
236         public void removePropertyRemovesProperty() throws InterruptedException, PluginException {
237                 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
238                 doAnswer(new Answer<Void>() {
239                         @Override
240                         public Void answer(InvocationOnMock invocation) throws Throwable {
241                                 wotCallTriggered.countDown();
242                                 return null;
243                         }
244                 }).when(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
245                 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
246                 webOfTrustUpdater.start();
247                 assertThat(wotCallTriggered.await(1, SECONDS), is(true));
248         }
249
250         @Test
251         public void multipleCallsToSetPropertyAreCollapsed() throws InterruptedException, PluginException {
252                 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
253                 doAnswer(new Answer<Void>() {
254                         @Override
255                         public Void answer(InvocationOnMock invocation) throws Throwable {
256                                 wotCallTriggered.countDown();
257                                 return null;
258                         }
259                 }).when(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
260                 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
261                 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
262                 webOfTrustUpdater.start();
263                 assertThat(wotCallTriggered.await(1, SECONDS), is(true));
264                 verify(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
265         }
266
267         @Test
268         public void addContextWaitWaitsForTheContextToBeAdded() {
269                 webOfTrustUpdater.start();
270                 assertThat(webOfTrustUpdater.addContextWait(ownIdentity, CONTEXT), is(true));
271                 verify(ownIdentity).addContext(eq(CONTEXT));
272         }
273
274         @Test
275         public void removeContextRemovesAContext() throws InterruptedException, PluginException {
276                 webOfTrustUpdater.start();
277                 final CountDownLatch removeContextTrigger = new CountDownLatch(1);
278                 doAnswer(new Answer<Void>() {
279                         @Override
280                         public Void answer(InvocationOnMock invocation) throws Throwable {
281                                 removeContextTrigger.countDown();
282                                 return null;
283                         }
284                 }).when(ownIdentity).removeContext(eq(CONTEXT));
285                 webOfTrustUpdater.removeContext(ownIdentity, CONTEXT);
286                 removeContextTrigger.await(1, SECONDS);
287                 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
288                 verify(ownIdentity).removeContext(eq(CONTEXT));
289         }
290
291         @Test
292         public void removeContextRequestsAreCoalesced() throws InterruptedException, PluginException {
293                 final CountDownLatch contextRemovedTrigger = new CountDownLatch(1);
294                 doAnswer(new Answer<Void>() {
295                         @Override
296                         public Void answer(InvocationOnMock invocation) throws Throwable {
297                                 contextRemovedTrigger.countDown();
298                                 return null;
299                         }
300                 }).when(ownIdentity).removeContext(eq(CONTEXT));
301                 for (int i = 1; i <= 2; i++) {
302                         /* this is so fucking volatile. */
303                         if (i > 1) {
304                                 sleep(200);
305                         }
306                         new Thread(new Runnable() {
307                                 public void run() {
308                                         webOfTrustUpdater.removeContext(ownIdentity, CONTEXT);
309                                 }
310                         }).start();
311                 }
312                 webOfTrustUpdater.start();
313                 assertThat(contextRemovedTrigger.await(1, SECONDS), is(true));
314                 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
315                 verify(ownIdentity).removeContext(eq(CONTEXT));
316         }
317
318 }