2ebc42867001ab1ebd0e57f68e085bb3b8a29b0c
[Sone.git] / src / test / java / net / pterodactylus / sone / core / FreenetInterfaceTest.java
1 package net.pterodactylus.sone.core;
2
3 import static freenet.client.FetchException.FetchExceptionMode.ALL_DATA_NOT_FOUND;
4 import static freenet.keys.InsertableClientSSK.createRandom;
5 import static freenet.node.RequestStarter.INTERACTIVE_PRIORITY_CLASS;
6 import static freenet.node.RequestStarter.PREFETCH_PRIORITY_CLASS;
7 import static net.pterodactylus.sone.test.Matchers.delivers;
8 import static net.pterodactylus.sone.test.TestUtil.setFinalField;
9 import static org.hamcrest.MatcherAssert.assertThat;
10 import static org.hamcrest.Matchers.is;
11 import static org.hamcrest.Matchers.notNullValue;
12 import static org.hamcrest.Matchers.nullValue;
13 import static org.mockito.ArgumentCaptor.forClass;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.ArgumentMatchers.anyBoolean;
16 import static org.mockito.ArgumentMatchers.anyLong;
17 import static org.mockito.ArgumentMatchers.anyShort;
18 import static org.mockito.ArgumentMatchers.eq;
19 import static org.mockito.Mockito.doNothing;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.verifyNoMoreInteractions;
25 import static org.mockito.Mockito.when;
26 import static org.mockito.Mockito.withSettings;
27
28 import java.io.IOException;
29 import java.net.MalformedURLException;
30 import java.util.HashMap;
31
32 import net.pterodactylus.sone.core.FreenetInterface.BackgroundFetchCallback;
33 import net.pterodactylus.sone.core.FreenetInterface.Callback;
34 import net.pterodactylus.sone.core.FreenetInterface.Fetched;
35 import net.pterodactylus.sone.core.FreenetInterface.InsertToken;
36 import net.pterodactylus.sone.core.FreenetInterface.InsertTokenSupplier;
37 import net.pterodactylus.sone.core.event.ImageInsertAbortedEvent;
38 import net.pterodactylus.sone.core.event.ImageInsertFailedEvent;
39 import net.pterodactylus.sone.core.event.ImageInsertFinishedEvent;
40 import net.pterodactylus.sone.core.event.ImageInsertStartedEvent;
41 import net.pterodactylus.sone.data.Image;
42 import net.pterodactylus.sone.data.Sone;
43 import net.pterodactylus.sone.data.TemporaryImage;
44 import net.pterodactylus.sone.data.impl.ImageImpl;
45 import net.pterodactylus.sone.test.TestUtil;
46
47 import freenet.client.ClientMetadata;
48 import freenet.client.FetchContext;
49 import freenet.client.FetchException;
50 import freenet.client.FetchException.FetchExceptionMode;
51 import freenet.client.FetchResult;
52 import freenet.client.HighLevelSimpleClient;
53 import freenet.client.InsertBlock;
54 import freenet.client.InsertContext;
55 import freenet.client.InsertException;
56 import freenet.client.InsertException.InsertExceptionMode;
57 import freenet.client.Metadata;
58 import freenet.client.async.ClientContext;
59 import freenet.client.async.ClientGetCallback;
60 import freenet.client.async.ClientGetter;
61 import freenet.client.async.ClientPutter;
62 import freenet.client.async.SnoopMetadata;
63 import freenet.client.async.USKCallback;
64 import freenet.client.async.USKManager;
65 import freenet.crypt.DummyRandomSource;
66 import freenet.crypt.RandomSource;
67 import freenet.keys.FreenetURI;
68 import freenet.keys.InsertableClientSSK;
69 import freenet.keys.USK;
70 import freenet.node.Node;
71 import freenet.node.NodeClientCore;
72 import freenet.node.RequestClient;
73 import freenet.support.Base64;
74 import freenet.support.api.Bucket;
75 import freenet.support.io.ArrayBucket;
76 import freenet.support.io.ResumeFailedException;
77
78 import com.google.common.eventbus.EventBus;
79 import org.junit.Before;
80 import org.junit.Test;
81 import org.mockito.ArgumentCaptor;
82 import org.mockito.ArgumentMatchers;
83
84 /**
85  * Unit test for {@link FreenetInterface}.
86  *
87  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
88  */
89 public class FreenetInterfaceTest {
90
91         private final EventBus eventBus = mock(EventBus.class);
92         private final Node node = mock(Node.class);
93         private final NodeClientCore nodeClientCore = mock(NodeClientCore.class);
94         private final HighLevelSimpleClient highLevelSimpleClient = mock(HighLevelSimpleClient.class, withSettings().extraInterfaces(RequestClient.class));
95         private final RandomSource randomSource = new DummyRandomSource();
96         private final USKManager uskManager = mock(USKManager.class);
97         private FreenetInterface freenetInterface;
98         private final Sone sone = mock(Sone.class);
99         private final ArgumentCaptor<USKCallback> callbackCaptor = forClass(USKCallback.class);
100         private final Image image = mock(Image.class);
101         private InsertToken insertToken;
102         private final Bucket bucket = mock(Bucket.class);
103         private final ArgumentCaptor<ClientGetCallback> clientGetCallback = forClass(ClientGetCallback.class);
104         private final FreenetURI uri = new FreenetURI("KSK@pgl.png");
105         private final FetchResult fetchResult = mock(FetchResult.class);
106         private final BackgroundFetchCallback backgroundFetchCallback = mock(BackgroundFetchCallback.class);
107         private final ClientGetter clientGetter = mock(ClientGetter.class);
108
109         public FreenetInterfaceTest() throws MalformedURLException {
110         }
111
112         @Before
113         public void setupHighLevelSimpleClient() throws Exception {
114                 when(highLevelSimpleClient.getFetchContext()).thenReturn(mock(FetchContext.class));
115                 when(highLevelSimpleClient.fetch(eq(uri), anyLong(), any(ClientGetCallback.class), any(FetchContext.class), anyShort())).thenReturn( clientGetter);
116         }
117
118         @Before
119         public void setupFreenetInterface() {
120                 when(nodeClientCore.makeClient(anyShort(), anyBoolean(), anyBoolean())).thenReturn(highLevelSimpleClient);
121                 setFinalField(node, "clientCore", nodeClientCore);
122                 setFinalField(node, "random", randomSource);
123                 setFinalField(nodeClientCore, "uskManager", uskManager);
124                 setFinalField(nodeClientCore, "clientContext", mock(ClientContext.class));
125                 freenetInterface = new FreenetInterface(eventBus, node);
126                 insertToken = freenetInterface.new InsertToken(image);
127                 insertToken.setBucket(bucket);
128         }
129
130         @Before
131         public void setupSone() {
132                 InsertableClientSSK insertSsk = createRandom(randomSource, "test-0");
133                 when(sone.getId()).thenReturn(Base64.encode(insertSsk.getURI().getRoutingKey()));
134                 when(sone.getRequestUri()).thenReturn(insertSsk.getURI().uskForSSK());
135         }
136
137         @Before
138         public void setupCallbackCaptorAndUskManager() {
139                 doNothing().when(uskManager).subscribe(any(USK.class), callbackCaptor.capture(), anyBoolean(), any(RequestClient.class));
140         }
141
142         @Test
143         public void canFetchUri() throws MalformedURLException, FetchException {
144                 FreenetURI freenetUri = new FreenetURI("KSK@GPLv3.txt");
145                 FetchResult fetchResult = createFetchResult();
146                 when(highLevelSimpleClient.fetch(freenetUri)).thenReturn(fetchResult);
147                 Fetched fetched = freenetInterface.fetchUri(freenetUri);
148                 assertThat(fetched, notNullValue());
149                 assertThat(fetched.getFetchResult(), is(fetchResult));
150                 assertThat(fetched.getFreenetUri(), is(freenetUri));
151         }
152
153         @Test
154         public void fetchFollowsRedirect() throws MalformedURLException, FetchException {
155                 FreenetURI freenetUri = new FreenetURI("KSK@GPLv2.txt");
156                 FreenetURI newFreenetUri = new FreenetURI("KSK@GPLv3.txt");
157                 FetchResult fetchResult = createFetchResult();
158                 FetchException fetchException = new FetchException(FetchExceptionMode.PERMANENT_REDIRECT, newFreenetUri);
159                 when(highLevelSimpleClient.fetch(freenetUri)).thenThrow(fetchException);
160                 when(highLevelSimpleClient.fetch(newFreenetUri)).thenReturn(fetchResult);
161                 Fetched fetched = freenetInterface.fetchUri(freenetUri);
162                 assertThat(fetched.getFetchResult(), is(fetchResult));
163                 assertThat(fetched.getFreenetUri(), is(newFreenetUri));
164         }
165
166         @Test
167         public void fetchReturnsNullOnFetchExceptions() throws MalformedURLException, FetchException {
168                 FreenetURI freenetUri = new FreenetURI("KSK@GPLv2.txt");
169                 FetchException fetchException = new FetchException(ALL_DATA_NOT_FOUND);
170                 when(highLevelSimpleClient.fetch(freenetUri)).thenThrow(fetchException);
171                 Fetched fetched = freenetInterface.fetchUri(freenetUri);
172                 assertThat(fetched, nullValue());
173         }
174
175         private FetchResult createFetchResult() {
176                 ClientMetadata clientMetadata = new ClientMetadata("text/plain");
177                 Bucket bucket = new ArrayBucket("Some Data.".getBytes());
178                 return new FetchResult(clientMetadata, bucket);
179         }
180
181         @Test
182         public void insertingAnImage() throws SoneException, InsertException, IOException {
183                 TemporaryImage temporaryImage = new TemporaryImage("image-id");
184                 temporaryImage.setMimeType("image/png");
185                 byte[] imageData = new byte[] { 1, 2, 3, 4 };
186                 temporaryImage.setImageData(imageData);
187                 Image image = new ImageImpl("image-id");
188                 InsertToken insertToken = freenetInterface.new InsertToken(image);
189                 InsertContext insertContext = mock(InsertContext.class);
190                 when(highLevelSimpleClient.getInsertContext(anyBoolean())).thenReturn(insertContext);
191                 ClientPutter clientPutter = mock(ClientPutter.class);
192                 ArgumentCaptor<InsertBlock> insertBlockCaptor = forClass(InsertBlock.class);
193                 when(highLevelSimpleClient.insert(insertBlockCaptor.capture(), eq((String) null), eq(false), eq(insertContext), eq(insertToken), anyShort())).thenReturn(clientPutter);
194                 freenetInterface.insertImage(temporaryImage, image, insertToken);
195                 assertThat(insertBlockCaptor.getValue().getData().getInputStream(), delivers(new byte[] { 1, 2, 3, 4 }));
196                 assertThat(TestUtil.<ClientPutter>getPrivateField(insertToken, "clientPutter"), is(clientPutter));
197                 verify(eventBus).post(any(ImageInsertStartedEvent.class));
198         }
199
200         @Test(expected = SoneInsertException.class)
201         public void insertExceptionCausesASoneException() throws InsertException, SoneException, IOException {
202                 TemporaryImage temporaryImage = new TemporaryImage("image-id");
203                 temporaryImage.setMimeType("image/png");
204                 byte[] imageData = new byte[] { 1, 2, 3, 4 };
205                 temporaryImage.setImageData(imageData);
206                 Image image = new ImageImpl("image-id");
207                 InsertToken insertToken = freenetInterface.new InsertToken(image);
208                 InsertContext insertContext = mock(InsertContext.class);
209                 when(highLevelSimpleClient.getInsertContext(anyBoolean())).thenReturn(insertContext);
210                 ArgumentCaptor<InsertBlock> insertBlockCaptor = forClass(InsertBlock.class);
211                 when(highLevelSimpleClient.insert(insertBlockCaptor.capture(), eq((String) null), eq(false), eq(insertContext), eq(insertToken), anyShort())).thenThrow(InsertException.class);
212                 freenetInterface.insertImage(temporaryImage, image, insertToken);
213         }
214
215         @Test
216         public void insertingADirectory() throws InsertException, SoneException {
217                 FreenetURI freenetUri = mock(FreenetURI.class);
218                 HashMap<String, Object> manifestEntries = new HashMap<String, Object>();
219                 String defaultFile = "index.html";
220                 FreenetURI resultingUri = mock(FreenetURI.class);
221                 when(highLevelSimpleClient.insertManifest(eq(freenetUri), eq(manifestEntries), eq(defaultFile))).thenReturn(resultingUri);
222                 assertThat(freenetInterface.insertDirectory(freenetUri, manifestEntries, defaultFile), is(resultingUri));
223         }
224
225         @Test(expected = SoneException.class)
226         public void insertExceptionIsForwardedAsSoneException() throws InsertException, SoneException {
227                 when(highLevelSimpleClient.insertManifest(ArgumentMatchers.<FreenetURI>any(), ArgumentMatchers.<HashMap<String, Object>>any(), ArgumentMatchers.<String>any())).thenThrow(InsertException.class);
228                 freenetInterface.insertDirectory(null, null, null);
229         }
230
231         @Test
232         public void soneWithWrongRequestUriWillNotBeSubscribed() throws MalformedURLException {
233                 when(sone.getRequestUri()).thenReturn(new FreenetURI("KSK@GPLv3.txt"));
234                 freenetInterface.registerUsk(new FreenetURI("KSK@GPLv3.txt"), null);
235                 verify(uskManager, never()).subscribe(any(USK.class), any(USKCallback.class), anyBoolean(), any(RequestClient.class));
236         }
237
238         @Test
239         public void registeringAUsk() {
240                 FreenetURI freenetUri = createRandom(randomSource, "test-0").getURI().uskForSSK();
241                 Callback callback = mock(Callback.class);
242                 freenetInterface.registerUsk(freenetUri, callback);
243                 verify(uskManager).subscribe(any(USK.class), any(USKCallback.class), anyBoolean(), eq((RequestClient) highLevelSimpleClient));
244         }
245
246         @Test
247         public void registeringANonUskKeyWillNotBeSubscribed() throws MalformedURLException {
248                 FreenetURI freenetUri = new FreenetURI("KSK@GPLv3.txt");
249                 Callback callback = mock(Callback.class);
250                 freenetInterface.registerUsk(freenetUri, callback);
251                 verify(uskManager, never()).subscribe(any(USK.class), any(USKCallback.class), anyBoolean(), eq((RequestClient) highLevelSimpleClient));
252         }
253
254         @Test
255         public void registeringAnActiveUskWillSubscribeToItCorrectly() {
256                 FreenetURI freenetUri = createRandom(randomSource, "test-0").getURI().uskForSSK();
257                 final USKCallback uskCallback = mock(USKCallback.class);
258                 freenetInterface.registerActiveUsk(freenetUri, uskCallback);
259                 verify(uskManager).subscribe(any(USK.class), eq(uskCallback), eq(true), any(RequestClient.class));
260         }
261
262         @Test
263         public void registeringAnInactiveUskWillSubscribeToItCorrectly() {
264                 FreenetURI freenetUri = createRandom(randomSource, "test-0").getURI().uskForSSK();
265                 final USKCallback uskCallback = mock(USKCallback.class);
266                 freenetInterface.registerPassiveUsk(freenetUri, uskCallback);
267                 verify(uskManager).subscribe(any(USK.class), eq(uskCallback), eq(false), any(RequestClient.class));
268         }
269
270         @Test
271         public void registeringAnActiveNonUskWillNotSubscribeToAUsk()
272         throws MalformedURLException {
273                 FreenetURI freenetUri = createRandom(randomSource, "test-0").getURI();
274                 freenetInterface.registerActiveUsk(freenetUri, null);
275                 verify(uskManager, never()).subscribe(any(USK.class),
276                                 any(USKCallback.class), anyBoolean(),
277                                 eq((RequestClient) highLevelSimpleClient));
278         }
279
280         @Test
281         public void registeringAnInactiveNonUskWillNotSubscribeToAUsk()
282         throws MalformedURLException {
283                 FreenetURI freenetUri = createRandom(randomSource, "test-0").getURI();
284                 freenetInterface.registerPassiveUsk(freenetUri, null);
285                 verify(uskManager, never()).subscribe(any(USK.class),
286                                 any(USKCallback.class), anyBoolean(),
287                                 eq((RequestClient) highLevelSimpleClient));
288         }
289
290         @Test
291         public void unregisteringANotRegisteredUskDoesNothing() {
292                 FreenetURI freenetURI = createRandom(randomSource, "test-0").getURI().uskForSSK();
293                 freenetInterface.unregisterUsk(freenetURI);
294                 verify(uskManager, never()).unsubscribe(any(USK.class), any(USKCallback.class));
295         }
296
297         @Test
298         public void unregisteringARegisteredUsk() {
299                 FreenetURI freenetURI = createRandom(randomSource, "test-0").getURI().uskForSSK();
300                 Callback callback = mock(Callback.class);
301                 freenetInterface.registerUsk(freenetURI, callback);
302                 freenetInterface.unregisterUsk(freenetURI);
303                 verify(uskManager).unsubscribe(any(USK.class), any(USKCallback.class));
304         }
305
306         @Test
307         public void unregisteringANotRegisteredSoneDoesNothing() {
308                 freenetInterface.unregisterUsk(sone);
309                 verify(uskManager, never()).unsubscribe(any(USK.class), any(USKCallback.class));
310         }
311
312         @Test
313         public void unregisteringARegisteredSoneUnregistersTheSone()
314         throws MalformedURLException {
315                 freenetInterface.registerActiveUsk(sone.getRequestUri(), mock(USKCallback.class));
316                 freenetInterface.unregisterUsk(sone);
317                 verify(uskManager).unsubscribe(any(USK.class), any(USKCallback.class));
318         }
319
320         @Test
321         public void unregisteringASoneWithAWrongRequestKeyWillNotUnsubscribe() throws MalformedURLException {
322                 when(sone.getRequestUri()).thenReturn(new FreenetURI("KSK@GPLv3.txt"));
323                 freenetInterface.registerUsk(sone.getRequestUri(), null);
324                 freenetInterface.unregisterUsk(sone);
325                 verify(uskManager, never()).unsubscribe(any(USK.class), any(USKCallback.class));
326         }
327
328         @Test
329         public void callbackForNormalUskUsesDifferentPriorities() {
330                 Callback callback = mock(Callback.class);
331                 FreenetURI soneUri = createRandom(randomSource, "test-0").getURI().uskForSSK();
332                 freenetInterface.registerUsk(soneUri, callback);
333                 assertThat(callbackCaptor.getValue().getPollingPriorityNormal(), is(PREFETCH_PRIORITY_CLASS));
334                 assertThat(callbackCaptor.getValue().getPollingPriorityProgress(), is(INTERACTIVE_PRIORITY_CLASS));
335         }
336
337         @Test
338         public void callbackForNormalUskForwardsImportantParameters() throws MalformedURLException {
339                 Callback callback = mock(Callback.class);
340                 FreenetURI uri = createRandom(randomSource, "test-0").getURI().uskForSSK();
341                 freenetInterface.registerUsk(uri, callback);
342                 USK key = mock(USK.class);
343                 when(key.getURI()).thenReturn(uri);
344                 callbackCaptor.getValue().onFoundEdition(3, key, null, false, (short) 0, null, true, true);
345                 verify(callback).editionFound(eq(uri), eq(3L), eq(true), eq(true));
346         }
347
348         @Test
349         public void fetchedRetainsUriAndFetchResult() {
350                 FreenetURI freenetUri = mock(FreenetURI.class);
351                 FetchResult fetchResult = mock(FetchResult.class);
352                 Fetched fetched = new Fetched(freenetUri, fetchResult);
353                 assertThat(fetched.getFreenetUri(), is(freenetUri));
354                 assertThat(fetched.getFetchResult(), is(fetchResult));
355         }
356
357         @Test
358         public void cancellingAnInsertWillFireImageInsertAbortedEvent() {
359                 ClientPutter clientPutter = mock(ClientPutter.class);
360                 insertToken.setClientPutter(clientPutter);
361                 ArgumentCaptor<ImageInsertStartedEvent> imageInsertStartedEvent = forClass(ImageInsertStartedEvent.class);
362                 verify(eventBus).post(imageInsertStartedEvent.capture());
363                 assertThat(imageInsertStartedEvent.getValue().image(), is(image));
364                 insertToken.cancel();
365                 ArgumentCaptor<ImageInsertAbortedEvent> imageInsertAbortedEvent = forClass(ImageInsertAbortedEvent.class);
366                 verify(eventBus, times(2)).post(imageInsertAbortedEvent.capture());
367                 verify(bucket).free();
368                 assertThat(imageInsertAbortedEvent.getValue().image(), is(image));
369         }
370
371         @Test
372         public void failureWithoutExceptionSendsFailedEvent() {
373                 insertToken.onFailure(null, null);
374                 ArgumentCaptor<ImageInsertFailedEvent> imageInsertFailedEvent = forClass(ImageInsertFailedEvent.class);
375                 verify(eventBus).post(imageInsertFailedEvent.capture());
376                 verify(bucket).free();
377                 assertThat(imageInsertFailedEvent.getValue().image(), is(image));
378                 assertThat(imageInsertFailedEvent.getValue().cause(), nullValue());
379         }
380
381         @Test
382         public void failureSendsFailedEventWithException() {
383                 InsertException insertException = new InsertException(InsertExceptionMode.INTERNAL_ERROR, "Internal error", null);
384                 insertToken.onFailure(insertException, null);
385                 ArgumentCaptor<ImageInsertFailedEvent> imageInsertFailedEvent = forClass(ImageInsertFailedEvent.class);
386                 verify(eventBus).post(imageInsertFailedEvent.capture());
387                 verify(bucket).free();
388                 assertThat(imageInsertFailedEvent.getValue().image(), is(image));
389                 assertThat(imageInsertFailedEvent.getValue().cause(), is((Throwable) insertException));
390         }
391
392         @Test
393         public void failureBecauseCancelledByUserSendsAbortedEvent() {
394                 InsertException insertException = new InsertException(InsertExceptionMode.CANCELLED, null);
395                 insertToken.onFailure(insertException, null);
396                 ArgumentCaptor<ImageInsertAbortedEvent> imageInsertAbortedEvent = forClass(ImageInsertAbortedEvent.class);
397                 verify(eventBus).post(imageInsertAbortedEvent.capture());
398                 verify(bucket).free();
399                 assertThat(imageInsertAbortedEvent.getValue().image(), is(image));
400         }
401
402         @Test
403         public void ignoredMethodsDoNotThrowExceptions() throws ResumeFailedException {
404                 insertToken.onResume(null);
405                 insertToken.onFetchable(null);
406                 insertToken.onGeneratedMetadata(null, null);
407         }
408
409         @Test
410         public void generatedUriIsPostedOnSuccess() {
411                 FreenetURI generatedUri = mock(FreenetURI.class);
412                 insertToken.onGeneratedURI(generatedUri, null);
413                 insertToken.onSuccess(null);
414                 ArgumentCaptor<ImageInsertFinishedEvent> imageInsertFinishedEvent = forClass(ImageInsertFinishedEvent.class);
415                 verify(eventBus).post(imageInsertFinishedEvent.capture());
416                 verify(bucket).free();
417                 assertThat(imageInsertFinishedEvent.getValue().image(), is(image));
418                 assertThat(imageInsertFinishedEvent.getValue().resultingUri(), is(generatedUri));
419         }
420
421         @Test
422         public void insertTokenSupplierSuppliesInsertTokens() {
423                 InsertTokenSupplier insertTokenSupplier = freenetInterface.new InsertTokenSupplier();
424                 assertThat(insertTokenSupplier.apply(image), notNullValue());
425         }
426
427         @Test
428         public void backgroundFetchCanBeStarted() throws Exception {
429                 freenetInterface.startFetch(uri, backgroundFetchCallback);
430                 verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), any(ClientGetCallback.class), any(FetchContext.class), anyShort());
431         }
432
433         @Test
434         public void backgroundFetchRegistersSnoopAndRestartsTheRequest() throws Exception {
435                 freenetInterface.startFetch(uri, backgroundFetchCallback);
436                 verify(clientGetter).setMetaSnoop(any(SnoopMetadata.class));
437                 verify(clientGetter).restart(eq(uri), anyBoolean(), any(ClientContext.class));
438         }
439
440         @Test
441         public void requestIsNotCancelledForImageMimeType() {
442                 verifySnoopCancelsRequestForMimeType("image/png", false);
443                 verify(backgroundFetchCallback, never()).failed(uri);
444         }
445
446         @Test
447         public void requestIsCancelledForNullMimeType() {
448                 verifySnoopCancelsRequestForMimeType(null, true);
449                 verify(backgroundFetchCallback, never()).shouldCancel(eq(uri), ArgumentMatchers.<String>any(), anyLong());
450                 verify(backgroundFetchCallback).failed(uri);
451         }
452
453         @Test
454         public void requestIsCancelledForVideoMimeType() {
455                 verifySnoopCancelsRequestForMimeType("video/mkv", true);
456                 verify(backgroundFetchCallback).failed(uri);
457         }
458
459         @Test
460         public void requestIsCancelledForAudioMimeType() {
461                 verifySnoopCancelsRequestForMimeType("audio/mpeg", true);
462                 verify(backgroundFetchCallback).failed(uri);
463         }
464
465         @Test
466         public void requestIsCancelledForTextMimeType() {
467                 verifySnoopCancelsRequestForMimeType("text/plain", true);
468                 verify(backgroundFetchCallback).failed(uri);
469         }
470
471         private void verifySnoopCancelsRequestForMimeType(String mimeType, boolean cancel) {
472                 when(backgroundFetchCallback.shouldCancel(eq(uri), eq(mimeType), anyLong())).thenReturn(cancel);
473                 freenetInterface.startFetch(uri, backgroundFetchCallback);
474                 ArgumentCaptor<SnoopMetadata> snoopMetadata = forClass(SnoopMetadata.class);
475                 verify(clientGetter).setMetaSnoop(snoopMetadata.capture());
476                 Metadata metadata = mock(Metadata.class);
477                 when(metadata.getMIMEType()).thenReturn(mimeType);
478                 assertThat(snoopMetadata.getValue().snoopMetadata(metadata, mock(ClientContext.class)), is(cancel));
479         }
480
481         @Test
482         public void callbackOfBackgroundFetchIsNotifiedOnSuccess() throws Exception {
483                 freenetInterface.startFetch(uri, backgroundFetchCallback);
484                 verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
485                 when(fetchResult.getMimeType()).thenReturn("image/png");
486                 when(fetchResult.asByteArray()).thenReturn(new byte[] { 1, 2, 3, 4, 5 });
487                 clientGetCallback.getValue().onSuccess(fetchResult, mock(ClientGetter.class));
488                 verify(backgroundFetchCallback).loaded(uri, "image/png", new byte[] { 1, 2, 3, 4, 5 });
489                 verifyNoMoreInteractions(backgroundFetchCallback);
490         }
491
492         @Test
493         public void callbackOfBackgroundFetchIsNotifiedOnFailure() throws Exception {
494                 freenetInterface.startFetch(uri, backgroundFetchCallback);
495                 verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
496                 when(fetchResult.getMimeType()).thenReturn("image/png");
497                 when(fetchResult.asByteArray()).thenReturn(new byte[] { 1, 2, 3, 4, 5 });
498                 clientGetCallback.getValue().onFailure(new FetchException(ALL_DATA_NOT_FOUND), mock(ClientGetter.class));
499                 verify(backgroundFetchCallback).failed(uri);
500                 verifyNoMoreInteractions(backgroundFetchCallback);
501         }
502
503         @Test
504         public void callbackOfBackgroundFetchIsNotifiedAsFailureIfBucketCanNotBeLoaded() throws Exception {
505                 freenetInterface.startFetch(uri, backgroundFetchCallback);
506                 verify(highLevelSimpleClient).fetch(eq(uri), anyLong(), clientGetCallback.capture(), any(FetchContext.class), anyShort());
507                 when(fetchResult.getMimeType()).thenReturn("image/png");
508                 when(fetchResult.asByteArray()).thenThrow(IOException.class);
509                 clientGetCallback.getValue().onSuccess(fetchResult, mock(ClientGetter.class));
510                 verify(backgroundFetchCallback).failed(uri);
511                 verifyNoMoreInteractions(backgroundFetchCallback);
512         }
513
514 }