de.sulaco.bittorrent.service.downloader.TtorrentDownloaderTest.java Source code

Java tutorial

Introduction

Here is the source code for de.sulaco.bittorrent.service.downloader.TtorrentDownloaderTest.java

Source

/*
 * Copyright (C) 2016 Philipp Henkel
 *
 * 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.sulaco.bittorrent.service.downloader;

import com.turn.ttorrent.client.Client;
import com.turn.ttorrent.client.SharedTorrent;
import com.turn.ttorrent.common.Torrent;
import com.turn.ttorrent.tracker.TrackedTorrent;
import com.turn.ttorrent.tracker.Tracker;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;

import de.sulaco.bittorrent.service.intent.DownloadState;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;

@RunWith(ParameterizedRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public final class TtorrentDownloaderTest {

    private final static int RUN_COUNT = 1;

    private static final String TORRENT_FILE = "src/test/resources/torrents/photo.torrent";
    private static final String CORRUPT_TORRENT_FILE = "src/test/resources/torrents/corrupt.torrent";
    private static final String TEMPORARY_DIRECTORY = "src/test/resources/temporary";
    private static final String CONTENT_DIRECTORY = "src/test/resources/content";
    private static final String CONTENT_NAME = "photo.jpg";
    private static final String CONTENT_FILE_PART = "src/test/resources/content_part/photo.jpg.part";

    @ParameterizedRobolectricTestRunner.Parameters(name = "run {index}/" + (RUN_COUNT - 1))
    public static Collection data() {
        return Arrays.asList(new Object[RUN_COUNT][]);
    }

    public TtorrentDownloaderTest() {
    }

    @BeforeClass
    public static void beforeClass() throws Exception {
        ShadowLog.stream = System.out;
    }

    @Before
    public void createTempDirectory() throws IOException {
        FileUtils.forceMkdir(new File(TEMPORARY_DIRECTORY));
    }

    @After
    public void deleteTempDirectory() throws IOException {
        FileUtils.deleteDirectory(new File(TEMPORARY_DIRECTORY));
    }

    @Test
    public void testDownloadNullTorrentFile() {
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        try {
            ttorrentDownloader.download(null, "dir");
            failBecauseExceptionWasNotThrown(NullPointerException.class);
        } catch (NullPointerException expectedException) {
        }
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadStart(Mockito.anyString());
    }

    @Test
    public void testDownloadNullDestinationDirectory() {
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        try {
            ttorrentDownloader.download(TORRENT_FILE, null);
            failBecauseExceptionWasNotThrown(NullPointerException.class);
        } catch (NullPointerException expectedException) {
        }
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadStart(TORRENT_FILE);
    }

    @Test
    public void testDownloadTorrentFileDoesNotExist() {
        final String torrentFile = "torrent_does_not_exist";
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(torrentFile, TEMPORARY_DIRECTORY);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(torrentFile);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(torrentFile,
                DownloadState.ERROR_TORRENT_FILE_NOT_FOUND);
    }

    @Test
    public void testDownloadDestinationDoesNotExist() {
        final String destinationDirectory = "destination_does_not_exist";
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(TORRENT_FILE, destinationDirectory);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadProgress(Mockito.anyString(),
                Mockito.anyInt());
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE,
                DownloadState.ERROR_DESTINATION_NOT_FOUND);
    }

    @Test
    public void testDownloadDestinationIsNotADirectory() {
        final String destinationDirectory = TORRENT_FILE;
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(TORRENT_FILE, destinationDirectory);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadProgress(Mockito.anyString(),
                Mockito.anyInt());
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE,
                DownloadState.ERROR_DESTINATION_IS_NOT_A_DIRECTORY);
    }

    @Test
    public void testDownloadDestinationNotWritable() {
        File directory = new File(TEMPORARY_DIRECTORY);
        assertThat(directory.setWritable(false)).isTrue();
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);
        assertThat(directory.setWritable(true)).isTrue();
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadProgress(Mockito.anyString(),
                Mockito.anyInt());
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE,
                DownloadState.ERROR_DESTINATION_IS_NOT_WRITEABLE);
    }

    @Test
    public void testDownloadResumeCompleted() {
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(TORRENT_FILE, CONTENT_DIRECTORY);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadProgress(TORRENT_FILE, 100);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE, DownloadState.COMPLETED);
    }

    @Test
    public void testDownloadCorruptTorrentFile() {
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.download(CORRUPT_TORRENT_FILE, CONTENT_DIRECTORY);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(CORRUPT_TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(CORRUPT_TORRENT_FILE,
                DownloadState.ERROR_LOADING_TORRENT_FILE);
    }

    @Test
    public void testDownloadNoTracker() {
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.setTimeout(10 * 1000);
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadProgress(Mockito.anyString(),
                Mockito.anyInt());
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE, DownloadState.TIMED_OUT);
    }

    @Test
    public void testCancelDownloadWithoutTimeout() {
        final TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        final DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        ttorrentDownloader.setDownloadListener(downloadListener);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                ttorrentDownloader.setEnabled(false);
            }
        }).start();
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(0)).onDownloadProgress(Mockito.anyString(),
                Mockito.anyInt());
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE, DownloadState.ABORTED);
    }

    private Tracker startTracker() throws IOException, NoSuchAlgorithmException {
        Tracker tracker = new Tracker(new InetSocketAddress("127.0.0.1", 9876));
        tracker.announce(TrackedTorrent.load(new File(TORRENT_FILE)));
        tracker.start();
        return tracker;
    }

    private Client startSeeder() throws IOException, NoSuchAlgorithmException {
        Torrent torrent = Torrent.load(new File(TORRENT_FILE));
        File destination = new File(CONTENT_DIRECTORY);
        InetAddress addr = InetAddress.getLocalHost();
        Client client = new Client(addr, new SharedTorrent(torrent, destination));
        client.share();
        return client;
    }

    @Test
    public void testDownload() throws IOException, NoSuchAlgorithmException {
        // Start seeder and tracker
        Tracker tracker = startTracker();
        Client client = startSeeder();

        // Download file
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.setTimeout(60 * 1000);
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);

        // Verification
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadProgress(TORRENT_FILE, 100);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE, DownloadState.COMPLETED);
        File source = new File(CONTENT_DIRECTORY + File.separator + CONTENT_NAME);
        File result = new File(TEMPORARY_DIRECTORY + File.separator + CONTENT_NAME);
        assertThat(result.exists()).isTrue();
        assertThat(FileUtils.contentEquals(source, result)).isTrue();

        // Tear down seeder and tracker
        client.stop();
        tracker.stop();
    }

    @Test
    public void testDownloadWithoutDownloadListener() throws IOException, NoSuchAlgorithmException {
        // Start seeder and tracker
        Tracker tracker = startTracker();
        Client client = startSeeder();

        // Download file
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        ttorrentDownloader.setTimeout(60 * 1000);
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);

        // Verification
        File source = new File(CONTENT_DIRECTORY + File.separator + CONTENT_NAME);
        File result = new File(TEMPORARY_DIRECTORY + File.separator + CONTENT_NAME);
        assertThat(result.exists()).isTrue();
        assertThat(FileUtils.contentEquals(source, result)).isTrue();

        // Tear down seeder and tracker
        client.stop();
        tracker.stop();
    }

    @Test
    public void testDownloadResume() throws IOException, NoSuchAlgorithmException {
        // Start seeder and tracker
        Tracker tracker = startTracker();
        Client client = startSeeder();

        // Copy partly available file to download directory
        FileUtils.copyFileToDirectory(new File(CONTENT_FILE_PART), new File(TEMPORARY_DIRECTORY));
        File partFile = new File(CONTENT_FILE_PART);
        File sourceFile = new File(CONTENT_DIRECTORY + File.separator + CONTENT_NAME);
        assertThat(FileUtils.contentEquals(partFile, sourceFile)).isFalse();

        // Download file
        DownloadListener downloadListener = Mockito.mock(DownloadListener.class);
        TtorrentDownloader ttorrentDownloader = new TtorrentDownloader();
        ttorrentDownloader.setDownloadListener(downloadListener);
        ttorrentDownloader.setTimeout(60 * 1000);
        ttorrentDownloader.download(TORRENT_FILE, TEMPORARY_DIRECTORY);

        // Verification
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadEnd(TORRENT_FILE, DownloadState.COMPLETED);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadStart(TORRENT_FILE);
        Mockito.verify(downloadListener, Mockito.times(1)).onDownloadProgress(TORRENT_FILE, 100);
        File downloadFile = new File(TEMPORARY_DIRECTORY + File.separator + CONTENT_NAME);
        assertThat(downloadFile.exists()).isTrue();
        assertThat(FileUtils.contentEquals(sourceFile, downloadFile)).isTrue();

        // Tear down seeder and tracker
        client.stop();
        tracker.stop();
    }

}