de.digiway.rapidbreeze.server.model.download.DownloadTest.java Source code

Java tutorial

Introduction

Here is the source code for de.digiway.rapidbreeze.server.model.download.DownloadTest.java

Source

/*
 * 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.");
    }
}