1 package net.pterodactylus.sone.core;
3 import static freenet.keys.InsertableClientSSK.createRandom;
4 import static java.lang.System.currentTimeMillis;
5 import static java.util.concurrent.TimeUnit.DAYS;
6 import static net.pterodactylus.sone.data.Sone.SoneStatus.downloading;
7 import static net.pterodactylus.sone.data.Sone.SoneStatus.idle;
8 import static net.pterodactylus.sone.data.Sone.SoneStatus.unknown;
9 import static net.pterodactylus.sone.web.AllPagesTestKt.getBaseInjector;
10 import static org.hamcrest.MatcherAssert.assertThat;
11 import static org.hamcrest.Matchers.is;
12 import static org.hamcrest.Matchers.notNullValue;
13 import static org.mockito.ArgumentCaptor.forClass;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.ArgumentMatchers.eq;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.never;
18 import static org.mockito.Mockito.times;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
22 import java.io.IOException;
23 import java.io.InputStream;
25 import net.pterodactylus.sone.data.Sone;
26 import net.pterodactylus.sone.data.Sone.SoneStatus;
27 import net.pterodactylus.sone.freenet.wot.Identity;
28 import net.pterodactylus.sone.test.GuiceKt;
30 import freenet.client.ClientMetadata;
31 import freenet.client.FetchResult;
32 import freenet.client.async.USKCallback;
33 import freenet.crypt.DummyRandomSource;
34 import freenet.keys.FreenetURI;
35 import freenet.keys.InsertableClientSSK;
36 import freenet.support.api.Bucket;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.mockito.ArgumentCaptor;
43 * Unit test for {@link SoneDownloaderImpl} and its subclasses.
45 public class SoneDownloaderTest {
47 private final FreenetInterface freenetInterface = mock(FreenetInterface.class);
48 private final SoneParser soneParser = mock(SoneParser.class);
49 private final UpdatedSoneProcessor updatedSoneProcessor = mock(UpdatedSoneProcessor.class);
50 private final SoneDownloaderImpl soneDownloader = new SoneDownloaderImpl(updatedSoneProcessor, freenetInterface, soneParser);
51 private final InsertableClientSSK clientSSK = createRandom(new DummyRandomSource(), "WoT");
52 private final FreenetURI requestUri = clientSSK.getURI().setKeyType("USK").setDocName("Sone");
53 private final FreenetURI finalRequestUri = requestUri.setMetaString(new String[] { "sone.xml" });
54 private final Sone sone = mock(Sone.class);
55 private final Sone parsedSone = mock(Sone.class);
58 public void setupSone() {
59 Identity identity = mock(Identity.class);
60 when(identity.getRequestUri()).thenReturn(clientSSK.getURI().toString());
61 when(identity.getId()).thenReturn("identity");
62 when(sone.getId()).thenReturn("identity");
63 when(sone.getIdentity()).thenReturn(identity);
64 when(sone.getRequestUri()).thenReturn(requestUri);
65 when(sone.getTime()).thenReturn(currentTimeMillis() - DAYS.toMillis(1));
68 private void setupSoneAsUnknown() {
69 when(sone.getTime()).thenReturn(0L);
73 public void addingASoneWillRegisterItsKey() {
74 soneDownloader.addSone(sone);
75 verify(freenetInterface).registerActiveUsk(eq(sone.getRequestUri()), any(
77 verify(freenetInterface, never()).unregisterUsk(sone);
81 public void addingASoneTwiceWillAlsoDeregisterItsKey() {
82 soneDownloader.addSone(sone);
83 soneDownloader.addSone(sone);
84 verify(freenetInterface, times(2)).registerActiveUsk(eq(
85 sone.getRequestUri()), any(USKCallback.class));
86 verify(freenetInterface).unregisterUsk(sone);
91 public void stoppingTheSoneDownloaderUnregistersTheSone() {
92 soneDownloader.addSone(sone);
93 soneDownloader.stop();
94 verify(freenetInterface).unregisterUsk(sone);
98 public void notBeingAbleToFetchAnUnknownSoneDoesNotUpdateCore() {
100 soneDownloader.fetchSoneAsSskAction(sone).run();
101 verify(freenetInterface).fetchUri(finalRequestUri.sskForUSK());
102 verifyThatSoneStatusWasChangedToDownloadingAndBackTo(unknown);
103 verify(updatedSoneProcessor, never()).updateSone(any(Sone.class));
106 private void verifyThatSoneStatusWasChangedToDownloadingAndBackTo(SoneStatus soneStatus) {
107 ArgumentCaptor<SoneStatus> soneStatuses = forClass(SoneStatus.class);
108 verify(sone, times(2)).setStatus(soneStatuses.capture());
109 assertThat(soneStatuses.getAllValues().get(0), is(downloading));
110 assertThat(soneStatuses.getAllValues().get(1), is(soneStatus));
114 public void notBeingAbleToFetchAKnownSoneDoesNotUpdateCore() {
115 soneDownloader.fetchSoneAsSskAction(sone).run();
116 verify(freenetInterface).fetchUri(finalRequestUri.sskForUSK());
117 verifyThatSoneStatusWasChangedToDownloadingAndBackTo(idle);
118 verify(updatedSoneProcessor, never()).updateSone(any(Sone.class));
121 @Test(expected = NullPointerException.class)
122 public void exceptionWhileFetchingSoneDoesNotProcessUpdatedSone() {
123 when(freenetInterface.fetchUri(any(FreenetURI.class))).thenThrow(NullPointerException.class);
125 soneDownloader.fetchSoneAsSskAction(sone).run();
127 verify(updatedSoneProcessor, never()).updateSone(any(Sone.class));
132 public void onlyFetchingASoneWillNotUpdateTheCore() throws IOException, SoneException {
134 soneDownloader.fetchSone(sone, sone.getRequestUri(), true);
135 verify(updatedSoneProcessor, never()).updateSone(any(Sone.class));
136 verifyThatSoneStatusWasChangedToDownloadingAndBackTo(idle);
140 public void fetchingACompleteSoneNotifiesTheUpdatedSoneProcessor() throws IOException, SoneException {
142 soneDownloader.fetchSone(sone, sone.getRequestUri(), false);
143 verify(updatedSoneProcessor).updateSone(parsedSone);
144 verifyThatSoneStatusWasChangedToDownloadingAndBackTo(idle);
147 private void setupParsedSone() throws IOException, SoneException {
148 InputStream inputStream = mock(InputStream.class);
149 ClientMetadata clientMetadata = new ClientMetadata("application/xml");
150 Bucket bucket = mock(Bucket.class);
151 when(bucket.getInputStream()).thenReturn(inputStream);
152 FetchResult fetchResult = new FetchResult(clientMetadata, bucket);
153 Fetched fetched = new Fetched(finalRequestUri, fetchResult);
154 when(freenetInterface.fetchUri(eq(finalRequestUri))).thenReturn(fetched);
155 when(soneParser.parseSone(sone, inputStream)).thenReturn(parsedSone);
159 public void soneDownloaderCanBeCreatedByDependencyInjection() {
160 assertThat(getBaseInjector().createChildInjector(
161 GuiceKt.supply(UpdatedSoneProcessor.class).byInstance(mock(UpdatedSoneProcessor.class)),
162 GuiceKt.supply(SoneParser.class).byInstance(mock(SoneParser.class))
163 ).getInstance(SoneDownloader.class), notNullValue());