package com.limegroup.bittorrent;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import junit.framework.Test;
import org.limewire.core.settings.ConnectionSettings;
import org.limewire.util.AssertComparisons;
import org.limewire.util.FileUtils;
import org.limewire.util.TestUtils;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.limegroup.gnutella.ActivityCallbackAdapter;
import com.limegroup.gnutella.LimeWireCoreModule;
import com.limegroup.gnutella.downloader.CoreDownloaderFactory;
import com.limegroup.gnutella.util.LimeTestCase;
/**
* Test cases for the BTDownloader.
*
* It takes a torrent file and downloads it, then checks the files contents
* against an MD5.
*
*/
public class BTDownloaderImplTest extends LimeTestCase {
private static final int TEST_PORT = 8080;
/**
* A directory containing the torrent data for this unit test.
*/
public static final File TORRENT_DIR = TestUtils
.getResourceFile("org/limewire/swarm/bittorrent/public_html/torrents");
/**
* A directory containing the download data for this unit test.
*/
public static final File FILE_DIR = TestUtils
.getResourceFile("org/limewire/swarm/bittorrent/public_html");
private boolean localIsPrivateBackup = false;
private boolean forceIPAddressBackup = false;
private String forceIPAddressStringBackup = null;
private FileServer fileServer = null;
public BTDownloaderImplTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(BTDownloaderImplTest.class);
}
@Override
protected void setUp() throws Exception {
localIsPrivateBackup = ConnectionSettings.LOCAL_IS_PRIVATE.getValue();
ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false);
forceIPAddressBackup = ConnectionSettings.FORCE_IP_ADDRESS.getValue();
ConnectionSettings.FORCE_IP_ADDRESS.setValue(true);
forceIPAddressStringBackup = ConnectionSettings.FORCED_IP_ADDRESS_STRING.getValue();
ConnectionSettings.FORCED_IP_ADDRESS_STRING.setValue("127.0.0.1");
fileServer = new FileServer(TEST_PORT, FILE_DIR);
fileServer.start();
super.setUp();
}
@Override
protected void tearDown() throws Exception {
ConnectionSettings.LOCAL_IS_PRIVATE.setValue(localIsPrivateBackup);
ConnectionSettings.FORCE_IP_ADDRESS.setValue(forceIPAddressBackup);
ConnectionSettings.FORCED_IP_ADDRESS_STRING.setValue(forceIPAddressStringBackup);
fileServer.stop();
fileServer.destroy();
super.tearDown();
}
/**
* This test tries to download a single file torrent from a tracker/peer
* setup on the www.limewire.org server.
*/
public void testSingleFilePeer() throws Exception {
File torrentFile = createFile("test-peer-dl-single-file.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File completeFile = torrentFileSystem.getCompleteFile();
completeFile.delete();
completeFile.deleteOnExit();
File incompleteFile = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile.delete();
incompleteFile.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile, 44425);
}
/**
* This test tries to download a multi file torrent from a tracker/peer
* setup on the www.limewire.org server.
*/
public void testMultipleFilePeer() throws Exception {
File torrentFile = createFile("test-peer-dl-multiple-file.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
try {
FileUtils.deleteRecursive(rootFile);
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
File incompleteFile2 = torrentFileSystem.getIncompleteFiles().get(1);
incompleteFile2.delete();
incompleteFile2.deleteOnExit();
File completeFile2 = torrentFileSystem.getFiles().get(1);
completeFile2.delete();
completeFile2.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
if (rootFile != null) {
FileUtils.deleteRecursive(rootFile);
}
}
}
public void testSingleWebSeedSingleFileNoPeer() throws Exception {
File torrentFile = createFile("test-single-webseed-single-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
rootFile.delete();
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
}
public void testMultiWebSeedSingleFileNoPeer() throws Exception {
File torrentFile = createFile("test-multiple-webseed-single-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
rootFile.delete();
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
}
public void testSingleWebSeedMultipleFileNoPeer() throws Exception {
File torrentFile = createFile("test-single-webseed-multiple-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
try {
FileUtils.deleteRecursive(rootFile);
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
File incompleteFile2 = torrentFileSystem.getIncompleteFiles().get(1);
incompleteFile2.delete();
incompleteFile2.deleteOnExit();
File completeFile2 = torrentFileSystem.getFiles().get(1);
completeFile2.delete();
completeFile2.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
if (rootFile != null) {
FileUtils.deleteRecursive(rootFile);
}
}
}
public void testMultiWebSeedMultipleFileNoPeer() throws Exception {
File torrentFile = createFile("test-multiple-webseed-multiple-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
try {
FileUtils.deleteRecursive(rootFile);
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
File incompleteFile2 = torrentFileSystem.getIncompleteFiles().get(1);
incompleteFile2.delete();
incompleteFile2.deleteOnExit();
File completeFile2 = torrentFileSystem.getFiles().get(1);
completeFile2.delete();
completeFile2.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
if (rootFile != null) {
FileUtils.deleteRecursive(rootFile);
}
}
}
public void testSingleWebSeedSingleFilePeers() throws Exception {
// TODO force peers and webseed to not have all pieces
// only when used together have all the pieces
File torrentFile = createFile("test-single-webseed-single-file-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
try {
FileUtils.deleteRecursive(rootFile);
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
} finally {
if (rootFile != null) {
FileUtils.deleteRecursive(rootFile);
}
}
}
/**
* This test has a peer and a bad webseed address.
* The bad address should be ignored and the download will happen from the peer.
*/
public void testSingleBadWebSeedSingleFilePeers() throws Exception {
File torrentFile = createFile("test-single-badwebseed-single-file-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
TorrentContext torrentContext = downloader.getTorrentContext();
TorrentFileSystem torrentFileSystem = torrentContext.getFileSystem();
File rootFile = torrentFileSystem.getCompleteFile();
try {
FileUtils.deleteRecursive(rootFile);
rootFile.deleteOnExit();
File incompleteFile1 = torrentFileSystem.getIncompleteFiles().get(0);
incompleteFile1.delete();
incompleteFile1.deleteOnExit();
File completeFile1 = torrentFileSystem.getFiles().get(0);
completeFile1.delete();
completeFile1.deleteOnExit();
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
} finally {
if (rootFile != null) {
FileUtils.deleteRecursive(rootFile);
}
}
}
private File createFile(String fileName) {
String torrentfilePath = TORRENT_DIR.getAbsolutePath() + "/" + fileName;
File torrentFile = new File(torrentfilePath);
return torrentFile;
}
private BTDownloaderImpl createBTDownloader(File torrentFile) throws IOException {
AssertComparisons.assertTrue(torrentFile.exists());
Injector injector = Guice.createInjector(Stage.PRODUCTION, new LimeWireCoreModule(
ActivityCallbackAdapter.class));
final BTMetaInfo metaInfo = injector.getInstance(BTMetaInfoFactory.class).createMetaInfo(torrentFile);
CoreDownloaderFactory coreDownloaderFactory = injector
.getInstance(CoreDownloaderFactory.class);
BTDownloaderImpl downloader = (BTDownloaderImpl) coreDownloaderFactory
.createBTDownloader(metaInfo);
downloader.initBtMetaInfo(metaInfo);
return downloader;
}
private void finishDownload(BTDownloader downloader) throws InterruptedException {
int maxIterations = 100;
int index = 0;
while (!downloader.isCompleted()) {
if (index++ > maxIterations) {
AssertComparisons.fail("Failure downloading the file. Taking too long.");
}
Thread.sleep(1000);
}
}
/**
* Asserts that the given file has the correct size, and matches the given
* md5sum.
*/
private void assertDownload(String md5, File file, long fileSize) throws InterruptedException,
NoSuchAlgorithmException, IOException {
long sleepTime = (long) ((fileSize * 0.0001) + 3000);
Thread.sleep(sleepTime);
AssertComparisons.assertTrue(file.exists());
AssertComparisons.assertEquals(fileSize, file.length());
String testmd5 = FileUtils.getMD5(file);
AssertComparisons.assertEquals(md5, testmd5);
}
}