@Override public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause) { for (DownloadListener listener : listenerList) { listener.taskEnd(task, cause, realCause); } }
@Override public void run() { for (DownloadTask task : completedTaskCollection) { task.getListener().taskEnd(task, EndCause.COMPLETED, null); } for (DownloadTask task : sameTaskConflictCollection) { task.getListener().taskEnd(task, EndCause.SAME_TASK_BUSY, null); } for (DownloadTask task : fileBusyCollection) { task.getListener().taskEnd(task, EndCause.FILE_BUSY, null); } } });
@Override public void run() { for (DownloadTask task : canceledCollection) { task.getListener().taskEnd(task, EndCause.CANCELED, null); } } });
@Override public void run() { for (DownloadTask task : errorCollection) { task.getListener().taskEnd(task, EndCause.ERROR, realCause); } } });
@Override public void run() { task.getListener().taskEnd(task, cause, realCause); } });
@Override public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause) { final DownloadListener[] listeners = getThreadSafeArray(task, realListenerMap); if (listeners == null) return; for (final DownloadListener realOne : listeners) { if (realOne == null) continue; realOne.taskEnd(task, cause, realCause); } if (autoRemoveListenerIdList.contains(task.getId())) { detachListener(task.getId()); } } };
private synchronized void processCalls() { if (skipProceedCallCount.get() > 0) return; if (runningAsyncSize() >= maxParallelRunningCount) return; if (readyAsyncCalls.isEmpty()) return; for (Iterator<DownloadCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) { DownloadCall call = i.next(); i.remove(); final DownloadTask task = call.task; if (isFileConflictAfterRun(task)) { OkDownload.with().callbackDispatcher().dispatch().taskEnd(task, EndCause.FILE_BUSY, null); continue; } runningAsyncCalls.add(call); getExecutorService().execute(call); if (runningAsyncSize() >= maxParallelRunningCount) return; } }
@Override public void taskEnd(@NonNull final DownloadTask task, @NonNull final EndCause cause, @Nullable final Exception realCause) { if (cause == EndCause.ERROR) { // only care about error. Util.d(TAG, "taskEnd: " + task.getId() + " " + cause + " " + realCause); } inspectTaskEnd(task, cause, realCause); if (task.isAutoCallbackToUIThread()) { uiHandler.post(new Runnable() { @Override public void run() { task.getListener().taskEnd(task, cause, realCause); } }); } else { task.getListener().taskEnd(task, cause, realCause); } }
@Test public void taskEnd_detachListener() { final DownloadListener listener1 = mock(DownloadListener.class); final ArrayList<DownloadListener> list = new ArrayList<>(); list.add(listener1); listenerManager.realListenerMap.put(1, list); final DownloadTask task = mockTask(1); final DownloadListener listener = listenerManager.hostListener; listenerManager.autoRemoveListenerIdList.add(1); listener.taskEnd(task, EndCause.CANCELED, null); assertThat(listenerManager.realListenerMap.size()).isZero(); }
@Test public void execute_urlIsEmpty() throws InterruptedException { when(task.getUrl()).thenReturn(""); call.execute(); final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); verify(call, never()).start(any(DownloadCache.class), any(BreakpointInfo.class)); ArgumentCaptor<IOException> captor = ArgumentCaptor.forClass(IOException.class); verify(listener).taskEnd(eq(task), eq(EndCause.ERROR), captor.capture()); IOException exception = captor.getValue(); assertThat(exception.getMessage()).isEqualTo("unexpected url: "); }
@Test public void cancel_notSameReferenceButSameId_readyAsync() { final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask runningSyncTask = mock(DownloadTask.class); final DownloadTask runningAsyncTask = mock(DownloadTask.class); final DownloadTask readyAsyncTask = mock(DownloadTask.class); when(runningSyncTask.getId()).thenReturn(1); when(runningAsyncTask.getId()).thenReturn(1); when(readyAsyncTask.getId()).thenReturn(1); final DownloadCall readyAsyncCall = spy(DownloadCall.create(readyAsyncTask, false, store)); readyAsyncCalls.add(readyAsyncCall); final DownloadTask sameIdTask = mock(DownloadTask.class); when(sameIdTask.getId()).thenReturn(1); dispatcher.cancel(sameIdTask); verify(listener).taskEnd(eq(readyAsyncTask), eq(CANCELED), nullable(Exception.class)); }
@Test public void cancel_runningSync() { final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask task = mock(DownloadTask.class); when(task.getId()).thenReturn(1); final DownloadCall call = spy(DownloadCall.create(task, false, store)); runningSyncCalls.add(call); dispatcher.cancel(task); verify(call).cancel(); verify(listener).taskEnd(eq(task), eq(CANCELED), nullable(Exception.class)); }
@Test public void cancel_runningAsync() throws IOException { mockOkDownload(); final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask task = mock(DownloadTask.class); when(task.getId()).thenReturn(1); final DownloadCall call = spy(DownloadCall.create(task, false, store)); runningAsyncCalls.add(call); dispatcher.cancel(task); verify(call).cancel(); verify(listener).taskEnd(eq(task), eq(CANCELED), nullable(Exception.class)); }
private void verifyTaskEnd(DownloadTask task, EndCause cause, Exception realCause) { verify(OkDownload.with().callbackDispatcher().dispatch()).taskEnd(task, cause, realCause); }
@Test public void cancel_readyAsyncCall() throws IOException { mockOkDownload(); final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask task = mock(DownloadTask.class); when(task.getId()).thenReturn(1); final DownloadCall call = spy(DownloadCall.create(task, false, store)); readyAsyncCalls.add(call); dispatcher.cancel(task); verify(call, never()).cancel(); verify(store, never()).onTaskEnd(eq(1), eq(CANCELED), nullable(Exception.class)); verify(listener).taskEnd(eq(task), eq(CANCELED), nullable(Exception.class)); assertThat(readyAsyncCalls.isEmpty()).isTrue(); }
@Test public void cancel_notSameReferenceButSameId_runningSync() { final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask runningSyncTask = mock(DownloadTask.class); final DownloadTask runningAsyncTask = mock(DownloadTask.class); final DownloadTask readyAsyncTask = mock(DownloadTask.class); when(runningSyncTask.getId()).thenReturn(1); when(runningAsyncTask.getId()).thenReturn(1); when(readyAsyncTask.getId()).thenReturn(1); final DownloadTask sameIdTask = mock(DownloadTask.class); when(sameIdTask.getId()).thenReturn(1); final DownloadCall runningSyncCall = spy( DownloadCall.create(runningSyncTask, false, store)); runningSyncCalls.add(runningSyncCall); dispatcher.cancel(sameIdTask); verify(runningSyncCall).cancel(); verify(listener).taskEnd(eq(runningSyncTask), eq(CANCELED), nullable(Exception.class)); }
@Test public void cancel_notSameReferenceButSameId_runningAsync() { final DownloadListener listener = OkDownload.with().callbackDispatcher().dispatch(); final DownloadTask runningSyncTask = mock(DownloadTask.class); final DownloadTask runningAsyncTask = mock(DownloadTask.class); final DownloadTask readyAsyncTask = mock(DownloadTask.class); when(runningSyncTask.getId()).thenReturn(1); when(runningAsyncTask.getId()).thenReturn(1); when(readyAsyncTask.getId()).thenReturn(1); final DownloadTask sameIdTask = mock(DownloadTask.class); when(sameIdTask.getId()).thenReturn(1); final DownloadCall runningAsyncCall = spy( DownloadCall.create(runningAsyncTask, false, store)); runningAsyncCalls.add(runningAsyncCall); dispatcher.cancel(sameIdTask); verify(runningAsyncCall).cancel(); verify(listener).taskEnd(eq(runningAsyncTask), eq(CANCELED), nullable(Exception.class)); }
boolean inspectCompleted(@NonNull DownloadTask task, @Nullable Collection<DownloadTask> completedCollection) { if (task.isPassIfAlreadyCompleted() && StatusUtil.isCompleted(task)) { if (task.getFilename() == null && !OkDownload.with().downloadStrategy() .validFilenameFromStore(task)) { return false; } OkDownload.with().downloadStrategy().validInfoOnCompleted(task, store); if (completedCollection != null) { completedCollection.add(task); } else { OkDownload.with().callbackDispatcher().dispatch() .taskEnd(task, EndCause.COMPLETED, null); } return true; } return false; }
@Test public void inspectForConflict_sameTask() throws IOException { mockOkDownload(); final CallbackDispatcher callbackDispatcher = OkDownload.with().callbackDispatcher(); final DownloadListener listener = callbackDispatcher.dispatch(); DownloadTask task = mock(DownloadTask.class); final Collection<DownloadCall> calls = new ArrayList<>(); final Collection<DownloadTask> sameTaskList = new ArrayList<>(); final Collection<DownloadTask> fileBusyList = new ArrayList<>(); final DownloadCall call = mock(DownloadCall.class); when(call.equalsTask(task)).thenReturn(true); calls.add(call); assertThat(dispatcher.inspectForConflict(task, calls, sameTaskList, fileBusyList)).isTrue(); assertThat(sameTaskList).containsExactly(task); assertThat(fileBusyList).isEmpty(); verify(listener, never()).taskEnd(eq(task), any(EndCause.class), nullable(Exception.class)); }