1 package net.pterodactylus.sone.core;
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.ArgumentMatchers.eq;
10 import static org.mockito.Mockito.doAnswer;
11 import static org.mockito.Mockito.doThrow;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.never;
14 import static org.mockito.Mockito.verify;
15 import static org.mockito.Mockito.when;
17 import java.util.concurrent.CountDownLatch;
19 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.AddContextJob;
20 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.RemoveContextJob;
21 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.SetPropertyJob;
22 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.SetTrustJob;
23 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.WebOfTrustContextUpdateJob;
24 import net.pterodactylus.sone.core.WebOfTrustUpdaterImpl.WebOfTrustUpdateJob;
25 import net.pterodactylus.sone.freenet.plugin.PluginException;
26 import net.pterodactylus.sone.freenet.wot.Identity;
27 import net.pterodactylus.sone.freenet.wot.OwnIdentity;
28 import net.pterodactylus.sone.freenet.wot.Trust;
29 import net.pterodactylus.sone.freenet.wot.WebOfTrustConnector;
30 import net.pterodactylus.sone.freenet.wot.WebOfTrustException;
32 import org.junit.Test;
33 import org.mockito.invocation.InvocationOnMock;
34 import org.mockito.stubbing.Answer;
37 * Unit test for {@link WebOfTrustUpdaterImpl} and its subclasses.
39 public class WebOfTrustUpdaterTest {
41 private static final String CONTEXT = "test-context";
42 private static final Integer SCORE = 50;
43 private static final Integer OTHER_SCORE = 25;
44 private static final String TRUST_COMMENT = "set in a test";
45 private static final String PROPERTY_NAME = "test-property";
46 private final WebOfTrustConnector webOfTrustConnector = mock(WebOfTrustConnector.class);
47 private final WebOfTrustUpdaterImpl webOfTrustUpdater = new WebOfTrustUpdaterImpl(webOfTrustConnector);
48 private final OwnIdentity ownIdentity = when(mock(OwnIdentity.class).getId()).thenReturn("own-identity-id").getMock();
49 private final WebOfTrustUpdateJob successfulWebOfTrustUpdateJob = createWebOfTrustUpdateJob(true);
50 private final WebOfTrustUpdateJob failingWebOfTrustUpdateJob = createWebOfTrustUpdateJob(false);
51 private final WebOfTrustContextUpdateJob contextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
52 private final AddContextJob addContextJob = webOfTrustUpdater.new AddContextJob(ownIdentity, CONTEXT);
53 private final RemoveContextJob removeContextJob = webOfTrustUpdater.new RemoveContextJob(ownIdentity, CONTEXT);
54 private final Identity trustee = when(mock(Identity.class).getId()).thenReturn("trustee-id").getMock();
56 private WebOfTrustUpdateJob createWebOfTrustUpdateJob(final boolean success) {
57 return webOfTrustUpdater.new WebOfTrustUpdateJob() {
63 } catch (InterruptedException ie1) {
64 throw new RuntimeException(ie1);
72 public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsSuccess() throws InterruptedException {
73 new Thread(successfulWebOfTrustUpdateJob).start();
74 assertThat(successfulWebOfTrustUpdateJob.waitForCompletion(), is(true));
78 public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsFailure() throws InterruptedException {
79 new Thread(failingWebOfTrustUpdateJob).start();
80 assertThat(failingWebOfTrustUpdateJob.waitForCompletion(), is(false));
84 public void webOfTrustContextUpdateJobsAreEqualIfTheirClassOwnIdentityAndContextAreEqual() {
85 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
86 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(true));
87 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(true));
88 assertThat(contextUpdateJob.hashCode(), is(secondContextUpdateJob.hashCode()));
92 public void webOfTrustContextUpdatesJobsAreNotEqualIfTheirClassDiffers() {
93 assertThat(contextUpdateJob.equals(addContextJob), is(false));
97 public void webOfTrustContextUpdateJobToStringContainsIdentityAndContext() {
98 assertThat(contextUpdateJob.toString(), containsString(ownIdentity.toString()));
99 assertThat(contextUpdateJob.toString(), containsString(CONTEXT));
103 public void webOfTrustContextUpdateJobsAreNotEqualIfTheIdentitiesDiffer() {
104 OwnIdentity ownIdentity = mock(OwnIdentity.class);
105 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT);
106 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(false));
107 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(false));
111 public void webOfTrustContextUpdateJobsAreNotEqualIfTheirContextsDiffer() {
112 WebOfTrustContextUpdateJob secondContextUpdateJob = webOfTrustUpdater.new WebOfTrustContextUpdateJob(ownIdentity, CONTEXT + CONTEXT);
113 assertThat(contextUpdateJob.equals(secondContextUpdateJob), is(false));
114 assertThat(secondContextUpdateJob.equals(contextUpdateJob), is(false));
118 public void webOfTrustContextUpdateJobsAreNotEqualToNull() {
119 assertThat(contextUpdateJob.equals(null), is(false));
123 public void addContextJobAddsTheContext() throws PluginException {
125 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
126 verify(ownIdentity).addContext(eq(CONTEXT));
127 assertThat(addContextJob.waitForCompletion(), is(true));
131 public void exceptionWhileAddingAContextIsExposed() throws PluginException {
132 doThrow(PluginException.class).when(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
134 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
135 verify(ownIdentity, never()).addContext(eq(CONTEXT));
136 assertThat(addContextJob.waitForCompletion(), is(false));
140 public void removeContextJobRemovesTheContext() throws PluginException {
141 removeContextJob.run();
142 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
143 verify(ownIdentity).removeContext(eq(CONTEXT));
144 assertThat(removeContextJob.waitForCompletion(), is(true));
148 public void exceptionWhileRemovingAContextIsExposed() throws PluginException {
149 doThrow(PluginException.class).when(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
150 removeContextJob.run();
151 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
152 verify(ownIdentity, never()).removeContext(eq(CONTEXT));
153 assertThat(removeContextJob.waitForCompletion(), is(false));
157 public void settingAPropertySetsTheProperty() throws PluginException {
158 String propertyName = "property-name";
159 String propertyValue = "property-value";
160 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
161 setPropertyJob.run();
162 verify(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
163 verify(ownIdentity).setProperty(eq(propertyName), eq(propertyValue));
164 assertThat(setPropertyJob.waitForCompletion(), is(true));
168 public void settingAPropertyToNullRemovesTheProperty() throws PluginException {
169 String propertyName = "property-name";
170 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, null);
171 setPropertyJob.run();
172 verify(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(propertyName));
173 verify(ownIdentity).removeProperty(eq(propertyName));
174 assertThat(setPropertyJob.waitForCompletion(), is(true));
178 public void pluginExceptionWhileSettingAPropertyIsHandled() throws PluginException {
179 String propertyName = "property-name";
180 String propertyValue = "property-value";
181 doThrow(PluginException.class).when(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
182 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
183 setPropertyJob.run();
184 verify(webOfTrustConnector).setProperty(eq(ownIdentity), eq(propertyName), eq(propertyValue));
185 verify(ownIdentity, never()).setProperty(eq(propertyName), eq(propertyValue));
186 assertThat(setPropertyJob.waitForCompletion(), is(false));
190 public void setPropertyJobsWithSameClassPropertyAndValueAreEqual() {
191 String propertyName = "property-name";
192 String propertyValue = "property-value";
193 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
194 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
195 assertThat(firstSetPropertyJob, is(secondSetPropertyJob));
196 assertThat(secondSetPropertyJob, is(firstSetPropertyJob));
197 assertThat(firstSetPropertyJob.hashCode(), is(secondSetPropertyJob.hashCode()));
201 public void setPropertyJobsWithDifferentClassesAreNotEqual() {
202 String propertyName = "property-name";
203 String propertyValue = "property-value";
204 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
205 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue) {
207 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
211 public void nullIsNotASetProjectJobEither() {
212 String propertyName = "property-name";
213 String propertyValue = "property-value";
214 SetPropertyJob setPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
215 assertThat(setPropertyJob, not(is((Object) null)));
219 public void setPropertyJobsWithDifferentPropertiesAreNotEqual() {
220 String propertyName = "property-name";
221 String propertyValue = "property-value";
222 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
223 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName + "2", propertyValue);
224 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
228 public void setPropertyJobsWithDifferentOwnIdentitiesAreNotEqual() {
229 OwnIdentity otherOwnIdentity = mock(OwnIdentity.class);
230 String propertyName = "property-name";
231 String propertyValue = "property-value";
232 SetPropertyJob firstSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(ownIdentity, propertyName, propertyValue);
233 SetPropertyJob secondSetPropertyJob = webOfTrustUpdater.new SetPropertyJob(otherOwnIdentity, propertyName, propertyValue);
234 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
238 public void setTrustJobSetsTrust() throws PluginException {
239 SetTrustJob setTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
241 verify(webOfTrustConnector).setTrust(eq(ownIdentity), eq(trustee), eq(SCORE), eq(TRUST_COMMENT));
242 verify(trustee).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
243 assertThat(setTrustJob.waitForCompletion(), is(true));
247 public void settingNullTrustRemovesTrust() throws WebOfTrustException {
248 SetTrustJob setTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, null, TRUST_COMMENT);
250 verify(webOfTrustConnector).removeTrust(eq(ownIdentity), eq(trustee));
251 verify(trustee).removeTrust(eq(ownIdentity));
252 assertThat(setTrustJob.waitForCompletion(), is(true));
256 public void exceptionWhileSettingTrustIsCaught() throws PluginException {
257 doThrow(PluginException.class).when(webOfTrustConnector).setTrust(eq(ownIdentity), eq(trustee), eq(SCORE), eq(TRUST_COMMENT));
258 SetTrustJob setTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
260 verify(webOfTrustConnector).setTrust(eq(ownIdentity), eq(trustee), eq(SCORE), eq(TRUST_COMMENT));
261 verify(trustee, never()).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
262 assertThat(setTrustJob.waitForCompletion(), is(false));
266 public void setTrustJobsWithDifferentClassesAreNotEqual() {
267 SetTrustJob firstSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
268 SetTrustJob secondSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT) {
270 assertThat(firstSetTrustJob, not(is(secondSetTrustJob)));
271 assertThat(secondSetTrustJob, not(is(firstSetTrustJob)));
275 public void setTrustJobsWithDifferentTrustersAreNotEqual() {
276 SetTrustJob firstSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
277 SetTrustJob secondSetTrustJob = webOfTrustUpdater.new SetTrustJob(mock(OwnIdentity.class), trustee, SCORE, TRUST_COMMENT);
278 assertThat(firstSetTrustJob, not(is(secondSetTrustJob)));
279 assertThat(secondSetTrustJob, not(is(firstSetTrustJob)));
283 public void setTrustJobsWithDifferentTrusteesAreNotEqual() {
284 SetTrustJob firstSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
285 SetTrustJob secondSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, mock(Identity.class), SCORE, TRUST_COMMENT);
286 assertThat(firstSetTrustJob, not(is(secondSetTrustJob)));
287 assertThat(secondSetTrustJob, not(is(firstSetTrustJob)));
291 public void setTrustJobsWithDifferentScoreAreEqual() {
292 SetTrustJob firstSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
293 SetTrustJob secondSetTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, OTHER_SCORE, TRUST_COMMENT);
294 assertThat(firstSetTrustJob, is(secondSetTrustJob));
295 assertThat(secondSetTrustJob, is(firstSetTrustJob));
296 assertThat(firstSetTrustJob.hashCode(), is(secondSetTrustJob.hashCode()));
300 public void setTrustJobDoesNotEqualNull() {
301 SetTrustJob setTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
302 assertThat(setTrustJob, not(is((Object) null)));
306 public void toStringOfSetTrustJobContainsIdsOfTrusterAndTrustee() {
307 SetTrustJob setTrustJob = webOfTrustUpdater.new SetTrustJob(ownIdentity, trustee, SCORE, TRUST_COMMENT);
308 assertThat(setTrustJob.toString(), containsString(ownIdentity.getId()));
309 assertThat(setTrustJob.toString(), containsString(trustee.getId()));
313 public void webOfTrustUpdaterStopsWhenItShould() {
314 webOfTrustUpdater.stop();
315 webOfTrustUpdater.serviceRun();
319 public void webOfTrustUpdaterStopsAfterItWasStarted() {
320 webOfTrustUpdater.start();
321 webOfTrustUpdater.stop();
325 public void removePropertyRemovesProperty() throws InterruptedException, PluginException {
326 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
327 doAnswer(new Answer<Void>() {
329 public Void answer(InvocationOnMock invocation) throws Throwable {
330 wotCallTriggered.countDown();
333 }).when(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
334 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
335 webOfTrustUpdater.start();
336 assertThat(wotCallTriggered.await(1, SECONDS), is(true));
340 public void multipleCallsToSetPropertyAreCollapsed() throws InterruptedException, PluginException {
341 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
342 doAnswer(new Answer<Void>() {
344 public Void answer(InvocationOnMock invocation) throws Throwable {
345 wotCallTriggered.countDown();
348 }).when(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
349 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
350 webOfTrustUpdater.removeProperty(ownIdentity, PROPERTY_NAME);
351 webOfTrustUpdater.start();
352 assertThat(wotCallTriggered.await(1, SECONDS), is(true));
353 verify(webOfTrustConnector).removeProperty(eq(ownIdentity), eq(PROPERTY_NAME));
357 public void addContextWaitWaitsForTheContextToBeAdded() {
358 webOfTrustUpdater.start();
359 assertThat(webOfTrustUpdater.addContextWait(ownIdentity, CONTEXT), is(true));
360 verify(ownIdentity).addContext(eq(CONTEXT));
364 public void removeContextRemovesAContext() throws InterruptedException, PluginException {
365 webOfTrustUpdater.start();
366 final CountDownLatch removeContextTrigger = new CountDownLatch(1);
367 doAnswer(new Answer<Void>() {
369 public Void answer(InvocationOnMock invocation) throws Throwable {
370 removeContextTrigger.countDown();
373 }).when(ownIdentity).removeContext(eq(CONTEXT));
374 webOfTrustUpdater.removeContext(ownIdentity, CONTEXT);
375 removeContextTrigger.await(1, SECONDS);
376 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
377 verify(ownIdentity).removeContext(eq(CONTEXT));
381 public void removeContextRequestsAreCoalesced() throws InterruptedException, PluginException {
382 final CountDownLatch contextRemovedTrigger = new CountDownLatch(1);
383 doAnswer(new Answer<Void>() {
385 public Void answer(InvocationOnMock invocation) throws Throwable {
386 contextRemovedTrigger.countDown();
389 }).when(ownIdentity).removeContext(eq(CONTEXT));
390 for (int i = 1; i <= 2; i++) {
391 /* this is so fucking volatile. */
395 new Thread(new Runnable() {
397 webOfTrustUpdater.removeContext(ownIdentity, CONTEXT);
401 webOfTrustUpdater.start();
402 assertThat(contextRemovedTrigger.await(1, SECONDS), is(true));
403 verify(webOfTrustConnector).removeContext(eq(ownIdentity), eq(CONTEXT));
404 verify(ownIdentity).removeContext(eq(CONTEXT));
408 public void setTrustSetsTrust() throws InterruptedException, PluginException {
409 final CountDownLatch trustSetTrigger = new CountDownLatch(1);
410 doAnswer(new Answer<Void>() {
412 public Void answer(InvocationOnMock invocation) throws Throwable {
413 trustSetTrigger.countDown();
416 }).when(trustee).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
417 webOfTrustUpdater.start();
418 webOfTrustUpdater.setTrust(ownIdentity, trustee, SCORE, TRUST_COMMENT);
419 assertThat(trustSetTrigger.await(1, SECONDS), is(true));
420 verify(trustee).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
421 verify(webOfTrustConnector).setTrust(eq(ownIdentity), eq(trustee), eq(SCORE), eq(TRUST_COMMENT));
425 public void setTrustRequestsAreCoalesced() throws InterruptedException, PluginException {
426 final CountDownLatch trustSetTrigger = new CountDownLatch(1);
427 doAnswer(new Answer<Void>() {
429 public Void answer(InvocationOnMock invocation) throws Throwable {
430 trustSetTrigger.countDown();
433 }).when(trustee).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
434 for (int i = 1; i <= 2; i++) {
435 /* this is so fucking volatile. */
439 new Thread(new Runnable() {
441 webOfTrustUpdater.setTrust(ownIdentity, trustee, SCORE, TRUST_COMMENT);
445 webOfTrustUpdater.start();
446 assertThat(trustSetTrigger.await(1, SECONDS), is(true));
447 verify(trustee).setTrust(eq(ownIdentity), eq(new Trust(SCORE, null, 0)));
448 verify(webOfTrustConnector).setTrust(eq(ownIdentity), eq(trustee), eq(SCORE), eq(TRUST_COMMENT));