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.Mockito.*;
11 import java.util.concurrent.CountDownLatch;
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;
22 import org.junit.Test;
23 import org.mockito.invocation.InvocationOnMock;
24 import org.mockito.stubbing.Answer;
27 * Unit test for {@link WebOfTrustUpdaterImpl} and its subclasses.
29 public class WebOfTrustUpdaterTest {
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);
42 private WebOfTrustUpdateJob createWebOfTrustUpdateJob(final boolean success) {
43 return webOfTrustUpdater.new WebOfTrustUpdateJob() {
49 } catch (InterruptedException ie1) {
50 throw new RuntimeException(ie1);
58 public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsSuccess() throws InterruptedException {
59 new Thread(successfulWebOfTrustUpdateJob).start();
60 assertThat(successfulWebOfTrustUpdateJob.waitForCompletion(), is(true));
64 public void webOfTrustUpdateJobWaitsUntilFinishedHasBeenCalledAndReturnsFailure() throws InterruptedException {
65 new Thread(failingWebOfTrustUpdateJob).start();
66 assertThat(failingWebOfTrustUpdateJob.waitForCompletion(), is(false));
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()));
78 public void webOfTrustContextUpdatesJobsAreNotEqualIfTheirClassDiffers() {
79 assertThat(contextUpdateJob.equals(addContextJob), is(false));
83 public void webOfTrustContextUpdateJobToStringContainsIdentityAndContext() {
84 assertThat(contextUpdateJob.toString(), containsString(ownIdentity.toString()));
85 assertThat(contextUpdateJob.toString(), containsString(CONTEXT));
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));
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));
104 public void webOfTrustContextUpdateJobsAreNotEqualToNull() {
105 assertThat(contextUpdateJob.equals(null), is(false));
109 public void addContextJobAddsTheContext() throws PluginException {
111 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
112 verify(ownIdentity).addContext(eq(CONTEXT));
113 assertThat(addContextJob.waitForCompletion(), is(true));
117 public void exceptionWhileAddingAContextIsExposed() throws PluginException {
118 doThrow(PluginException.class).when(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
120 verify(webOfTrustConnector).addContext(eq(ownIdentity), eq(CONTEXT));
121 verify(ownIdentity, never()).addContext(eq(CONTEXT));
122 assertThat(addContextJob.waitForCompletion(), is(false));
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));
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));
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));
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));
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));
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()));
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) {
193 assertThat(firstSetPropertyJob, not(is(secondSetPropertyJob)));
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)));
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)));
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)));
224 public void webOfTrustUpdaterStopsWhenItShould() {
225 webOfTrustUpdater.stop();
226 webOfTrustUpdater.serviceRun();
230 public void webOfTrustUpdaterStopsAfterItWasStarted() {
231 webOfTrustUpdater.start();
232 webOfTrustUpdater.stop();
236 public void removePropertyRemovesProperty() throws InterruptedException, PluginException {
237 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
238 doAnswer(new Answer<Void>() {
240 public Void answer(InvocationOnMock invocation) throws Throwable {
241 wotCallTriggered.countDown();
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));
251 public void multipleCallsToSetPropertyAreCollapsed() throws InterruptedException, PluginException {
252 final CountDownLatch wotCallTriggered = new CountDownLatch(1);
253 doAnswer(new Answer<Void>() {
255 public Void answer(InvocationOnMock invocation) throws Throwable {
256 wotCallTriggered.countDown();
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));
268 public void addContextWaitWaitsForTheContextToBeAdded() {
269 webOfTrustUpdater.start();
270 assertThat(webOfTrustUpdater.addContextWait(ownIdentity, CONTEXT), is(true));
271 verify(ownIdentity).addContext(eq(CONTEXT));
275 public void removeContextRemovesAContext() throws InterruptedException, PluginException {
276 webOfTrustUpdater.start();
277 final CountDownLatch removeContextTrigger = new CountDownLatch(1);
278 doAnswer(new Answer<Void>() {
280 public Void answer(InvocationOnMock invocation) throws Throwable {
281 removeContextTrigger.countDown();
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));
292 public void removeContextRequestsAreCoalesced() throws InterruptedException, PluginException {
293 final CountDownLatch contextRemovedTrigger = new CountDownLatch(1);
294 doAnswer(new Answer<Void>() {
296 public Void answer(InvocationOnMock invocation) throws Throwable {
297 contextRemovedTrigger.countDown();
300 }).when(ownIdentity).removeContext(eq(CONTEXT));
301 for (int i = 1; i <= 2; i++) {
302 /* this is so fucking volatile. */
306 new Thread(new Runnable() {
308 webOfTrustUpdater.removeContext(ownIdentity, CONTEXT);
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));