Java tutorial
/* * Copyright 2013 Sigurd Randoll <srandoll@digiway.de>. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.digiway.rapidbreeze.server.model.download; import de.digiway.rapidbreeze.server.TestUtil; import de.digiway.rapidbreeze.shared.rest.download.DownloadStatus; import de.digiway.rapidbreeze.server.model.storage.StorageProvider; import de.digiway.rapidbreeze.server.model.storage.StorageProviderDownloadClient; import de.digiway.rapidbreeze.server.model.storage.UrlStatus; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Random; import org.apache.commons.io.FileUtils; import org.junit.After; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import static org.mockito.Mockito.*; /** * * @author Sigurd Randoll <srandoll@digiway.de> */ public class DownloadTest { private StorageProvider storageProvider; private StorageProviderDownloadClient downloadClient; private InputStream is; private UrlStatus urlStatus; private Random random = new Random(); private URL dummyUrl; private Path tempFile; @Before public void setup() throws Exception { storageProvider = mock(StorageProvider.class); downloadClient = mock(StorageProviderDownloadClient.class); dummyUrl = new URL("http://test"); tempFile = TestUtil.getNonExistingTemporaryPath(); // Mocking provider: is = mock(InputStream.class); when(is.read(any(byte[].class), anyInt(), anyInt())).thenReturn(1); when(storageProvider.createDownloadClient()).thenReturn(downloadClient); when(downloadClient.start(dummyUrl, 0)).thenReturn(is); // Mock Url Status: urlStatus = mock(UrlStatus.class); when(urlStatus.getFileSize()).thenReturn(Download.BLOCK_SIZE * 3); when(downloadClient.getUrlStatus(dummyUrl)).thenReturn(urlStatus); } @After public void tearDown() throws IOException { TestUtil.deleteTemp(); } @Test public void testStart() throws Exception { // download to a targetFile: final Download download = new Download(dummyUrl, tempFile, storageProvider); assertEquals(DownloadStatus.WAITING, download.getDownloadStatus()); download.start(); assertEquals(DownloadStatus.RUNNING, download.getDownloadStatus()); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); assertEquals(DownloadStatus.FINISHED_SUCCESSFUL, download.getDownloadStatus()); } @Test public void testStart_exceptional() throws Exception { // Mocking provider with null inputstream. Will raise exception: when(downloadClient.start(dummyUrl, 0)).thenReturn(null); // try to download: Download download = new Download(dummyUrl, tempFile, storageProvider); download.start(); handleUntilStatus(download, DownloadStatus.ERROR); assertEquals(DownloadStatus.ERROR, download.getDownloadStatus()); assertNotNull(download.getError()); assertTrue(download.getError() instanceof NullPointerException); } @Test public void testStart_targetFileIssue() throws Exception { Path errorPath = Paths.get("c:/blubb/bbbb"); // download to a non-writeable file: Download download = new Download(dummyUrl, errorPath, storageProvider); download.start(); assertEquals(DownloadStatus.ERROR, download.getDownloadStatus()); assertTrue(download.getError() instanceof IOException); } @Test public void testStart_MultipleBuffers() throws Exception { // Mocking provider with bigger content byte[] bytes = new byte[100000]; InputStream is = new ByteArrayInputStream(bytes); when(downloadClient.start(dummyUrl, 0)).thenReturn(is); // Mock Url Status: when(urlStatus.getFileSize()).thenReturn((long) bytes.length); Download download = new Download(dummyUrl, tempFile, storageProvider); download.start(); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); } @Test public void testContent() throws IOException { // Dummy content: byte[] bytes = new byte[100000]; random.nextBytes(bytes); InputStream is = new ByteArrayInputStream(bytes); // Mocking provider with: when(downloadClient.start(dummyUrl, 0)).thenReturn(is); // Mock Url Status: when(urlStatus.getFileSize()).thenReturn((long) bytes.length); // Download content to temp file: Download download = new Download(dummyUrl, tempFile, storageProvider); download.start(); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); // Compare content: byte[] target = FileUtils.readFileToByteArray(tempFile.toFile()); assertArrayEquals(bytes, target); } @Test public void testGetUrlStatus() throws Exception { UrlStatus status1 = mock(UrlStatus.class); UrlStatus status2 = mock(UrlStatus.class); assertNotSame(status1, status2); when(downloadClient.getUrlStatus(dummyUrl)).thenReturn(status1, status2); // Check url status: Download download = new Download(dummyUrl, tempFile, storageProvider); UrlStatus getStatus = download.getUrlStatus(); assertEquals(getStatus, download.getUrlStatus()); assertEquals(status1, getStatus); // Exception should request new url status (null inputstream forces exception): when(downloadClient.start(dummyUrl, 0)).thenReturn(null); download.start(); getStatus = download.getUrlStatus(); assertEquals(status2, getStatus); assertNotSame(status1, download.getUrlStatus()); } @Test public void testGetProgress() throws Exception { // Mock Url Status: when(urlStatus.getFileSize()).thenReturn(Download.BLOCK_SIZE * 5); when(downloadClient.getUrlStatus(dummyUrl)).thenReturn(urlStatus); Download download = new Download(dummyUrl, tempFile, storageProvider); assertTrue(download.getProgress() == 0.0D); download.start(); Double p1 = download.getProgress(); download.handle(); Double p2 = download.getProgress(); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); Double p3 = download.getProgress(); assertTrue(p1 == 0.0D); assertTrue(p1 < p2); assertTrue(p2 < p3); assertTrue(download.getProgress() == 1.0D); } @Test public void testGetCurrentSize() throws Exception { Download download = new Download(dummyUrl, tempFile, storageProvider); assertEquals(0, download.getCurrentSize()); download.start(); assertEquals(0, download.getCurrentSize()); download.handle(); assertTrue(download.getCurrentSize() > 0); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); assertEquals((long) urlStatus.getFileSize(), download.getCurrentSize()); } @Test public void testGetIdentifier() throws MalformedURLException, IOException { Path p1 = TestUtil.getNonExistingTemporaryPath(); Path p2 = TestUtil.getNonExistingTemporaryPath(); Download download1 = new Download(new URL("http://www.google.de"), p1, mock(StorageProvider.class)); Download download2 = new Download(new URL("http://www.google.de"), p2, mock(StorageProvider.class)); assertNotSame(download1.getIdentifier(), download2.getIdentifier()); } @Test public void testPause() throws Exception { // download to a targetFile: Download download = new Download(dummyUrl, tempFile, storageProvider); download.start(); download.handle(); long size = download.getCurrentSize(); assertTrue(download.getCurrentSize() > 0); download.pause(); download.handle(); assertEquals(DownloadStatus.PAUSE, download.getDownloadStatus()); assertEquals(size, download.getCurrentSize()); // resume download: download.start(); download.handle(); assertEquals(DownloadStatus.RUNNING, download.getDownloadStatus()); assertTrue(download.getCurrentSize() > size); } @Test public void testWaitState() throws Exception { Download download = new Download(dummyUrl, tempFile, storageProvider); download.start(); download.waitState(); assertEquals(DownloadStatus.WAITING, download.getDownloadStatus()); download.start(); download.pause(); download.waitState(); assertEquals(DownloadStatus.WAITING, download.getDownloadStatus()); download.start(); handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); } @Test public void testListeners() throws Exception { // download to a targetFile: Download download = new Download(dummyUrl, tempFile, storageProvider); DownloadListener listener = mock(DownloadListener.class); download.addListener(listener); // Start download should fire listener: download.start(); ArgumentCaptor<DownloadEvent> eventCapture = ArgumentCaptor.forClass(DownloadEvent.class); // pause download should fire listener: download.pause(); // Restart again: download.start(); // finish it: handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); // Should be called 4 times: verify(listener, times(4)).onDownloadStatusChange(eventCapture.capture()); // Check states: DownloadEvent event1 = eventCapture.getAllValues().get(0); assertEquals(DownloadStatus.RUNNING, event1.getNewStatus()); assertEquals(DownloadStatus.WAITING, event1.getOldStatus()); assertNull(event1.getException()); assertEquals(download, event1.getSource()); DownloadEvent event2 = eventCapture.getAllValues().get(1); assertEquals(DownloadStatus.PAUSE, event2.getNewStatus()); assertEquals(DownloadStatus.RUNNING, event2.getOldStatus()); assertNull(event2.getException()); assertEquals(download, event2.getSource()); DownloadEvent event3 = eventCapture.getAllValues().get(2); assertEquals(DownloadStatus.RUNNING, event3.getNewStatus()); assertEquals(DownloadStatus.PAUSE, event3.getOldStatus()); assertNull(event3.getException()); assertEquals(download, event3.getSource()); DownloadEvent event4 = eventCapture.getAllValues().get(3); assertEquals(DownloadStatus.FINISHED_SUCCESSFUL, event4.getNewStatus()); assertEquals(DownloadStatus.RUNNING, event4.getOldStatus()); assertNull(event4.getException()); assertEquals(download, event4.getSource()); } // @Test // public void testThrottle() throws IOException { // when(is.read(any(byte[].class), anyInt(), anyInt())).thenReturn((int) Download.BLOCK_SIZE); // when(urlStatus.getFileSize()).thenReturn(Download.BLOCK_SIZE * 10); // // Download download = new Download(dummyUrl, tempFile, storageProvider); // download.start(); // // download.setThrottle(100000); // handleUntilStatus(download, DownloadStatus.FINISHED_SUCCESSFUL); // double bps = download.getBytesPerSecond(); // // assertTrue(bps > 90000); // assertTrue(bps < 110000); // } @Test public void testHandleIdle() throws IOException, InterruptedException { when(is.read(any(byte[].class), anyInt(), anyInt())).thenReturn((int) Download.BLOCK_SIZE); when(urlStatus.getFileSize()).thenReturn(Download.BLOCK_SIZE * 10); Download download = new Download(dummyUrl, tempFile, storageProvider); download.setThrottle(100000); download.start(); while (!download.getDownloadStatus().equals(DownloadStatus.FINISHED_SUCCESSFUL)) { int idle = download.handle(); Thread.sleep(idle); System.out.println("idle:" + idle); } System.out.println("bps:" + download.getBytesPerSecond()); } private void handleUntilStatus(Download download, DownloadStatus status) { for (int i = 0; i <= 10000; i++) { download.handle(); if (download.getDownloadStatus().equals(status)) { return; } } throw new IllegalStateException( "State " + status + " for download: " + download + " not reached within execution loop."); } }