package com.limegroup.bittorrent;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import junit.framework.Test;
import org.limewire.core.settings.BittorrentSettings;
import org.limewire.core.settings.ConnectionSettings;
import org.limewire.core.settings.SharingSettings;
import org.limewire.gnutella.tests.LimeTestCase;
import org.limewire.inject.GuiceUtils;
import org.limewire.listener.EventListener;
import org.limewire.util.AssertComparisons;
import org.limewire.util.FileUtils;
import org.limewire.util.TestUtils;
import org.limewire.bittorrent.TorrentManager;
import org.limewire.bittorrent.TorrentEvent;
import org.limewire.inspection.InspectionUtils;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.limegroup.gnutella.ActivityCallbackAdapter;
import com.limegroup.gnutella.Downloader.DownloadState;
import com.limegroup.gnutella.LimeWireCoreModule;
import com.limegroup.gnutella.downloader.CoreDownloaderFactory;
import com.limegroup.gnutella.downloader.DownloadStateEvent;
/**
* 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.
*/
private File torrentDir = null;
/**
* A directory containing the download data for this unit test.
*/
private File fileDir = null;
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 {
torrentDir = TestUtils
.extractResourceDirectory("org/limewire/swarm/bittorrent/public_html/torrents");
fileDir = TestUtils.extractResourceDirectory("org/limewire/swarm/bittorrent/public_html");
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.get();
ConnectionSettings.FORCED_IP_ADDRESS_STRING.set("127.0.0.1");
BittorrentSettings.LIBTORRENT_ENABLED.set(true);
fileServer = new FileServer(TEST_PORT, fileDir);
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.set(forceIPAddressStringBackup);
BittorrentSettings.LIBTORRENT_ENABLED.set(false);
fileServer.stop();
fileServer.destroy();
FileUtils.deleteRecursive(torrentDir);
FileUtils.deleteRecursive(fileDir);
super.tearDown();
}
public void testInspections() throws Exception {
File torrentFile = createFile("test-peer-dl-single-file.torrent");
Injector injector = Guice.createInjector(Stage.DEVELOPMENT, new LimeWireCoreModule(
ActivityCallbackAdapter.class));
GuiceUtils.loadEagerSingletons(injector);
injector.getInstance(TorrentManager.class).isValid();
BTDownloaderImpl downloader = createBTDownloader(torrentFile, injector);
try {
// TODO more InspectionTool code into common so it can generate the mapping
assertEquals("0", InspectionUtils.inspectValue("com.limegroup.bittorrent.BTDownloaderImpl:torrentsStarted", injector, true));
assertEquals("0", InspectionUtils.inspectValue("com.limegroup.bittorrent.BTDownloaderImpl:torrentsFinished", injector, true));
//downloader.startDownload();
downloader.handleEvent(TorrentEvent.STARTED);
Thread.sleep(500);
assertEquals("1", InspectionUtils.inspectValue("com.limegroup.bittorrent.BTDownloaderImpl:torrentsStarted", injector, true));
// downloader.handleEvent(TorrentEvent.COMPLETED);
// Thread.sleep(500);
// assertEquals("1", InspectionUtils.inspectValue("com.limegroup.bittorrent.BTDownloaderImpl:torrentsFinished", injector, true));
} finally {
cleanup(downloader);
}
}
/**
* 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);
File completeFile = downloader.getSaveFile();
try {
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile, 44425);
} finally {
cleanup(downloader);
}
}
/**
* 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);
try {
File completeFile1 = downloader.getCompleteFiles().get(0);
File completeFile2 = downloader.getCompleteFiles().get(1);
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
cleanup(downloader);
}
}
public void testSingleWebSeedSingleFileNoPeer() throws Exception {
File torrentFile = createFile("test-single-webseed-single-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
File completeFile = downloader.getSaveFile();
try {
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile, 44425);
} finally {
cleanup(downloader);
}
}
public void testMultiWebSeedSingleFileNoPeer() throws Exception {
File torrentFile = createFile("test-multiple-webseed-single-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
File completeFile = downloader.getSaveFile();
try {
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile, 44425);
} finally {
cleanup(downloader);
}
}
public void testSingleWebSeedMultipleFileNoPeer() throws Exception {
File torrentFile = createFile("test-single-webseed-multiple-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
try {
File completeFile1 = downloader.getCompleteFiles().get(0);
File completeFile2 = downloader.getCompleteFiles().get(1);
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
cleanup(downloader);
}
}
public void testMultiWebSeedMultipleFileNoPeer() throws Exception {
File torrentFile = createFile("test-multiple-webseed-multiple-file-no-peer.torrent");
BTDownloaderImpl downloader = createBTDownloader(torrentFile);
try {
File completeFile1 = downloader.getCompleteFiles().get(0);
File completeFile2 = downloader.getCompleteFiles().get(1);
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
assertDownload("db1dc452e77d30ce14acca6bac8c66bc", completeFile2, 411090);
} finally {
cleanup(downloader);
}
}
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);
try {
File completeFile1 = downloader.getCompleteFiles().get(0);
downloader.startDownload();
finishDownload(downloader);
assertDownload("8055d620ba0c507c1af957b43648c99f", completeFile1, 44425);
} finally {
cleanup(downloader);
}
}
private File createFile(String fileName) {
String torrentfilePath = torrentDir.getAbsolutePath() + "/" + fileName;
File torrentFile = new File(torrentfilePath);
return torrentFile;
}
private BTDownloaderImpl createBTDownloader(File torrentFile) throws IOException {
Injector injector = Guice.createInjector(Stage.DEVELOPMENT, new LimeWireCoreModule(
ActivityCallbackAdapter.class));
GuiceUtils.loadEagerSingletons(injector);
return createBTDownloader(torrentFile, injector);
}
private BTDownloaderImpl createBTDownloader(File torrentFile, Injector injector) throws IOException {
AssertComparisons.assertTrue(torrentFile.exists());
CoreDownloaderFactory coreDownloaderFactory = injector
.getInstance(CoreDownloaderFactory.class);
BTDownloaderImpl downloader = (BTDownloaderImpl) coreDownloaderFactory
.createBTDownloader(torrentFile, SharingSettings.getSaveDirectory());
File incompleteFile = downloader.getIncompleteFile();
FileUtils.deleteRecursive(incompleteFile);
File completeFile = downloader.getSaveFile();
FileUtils.deleteRecursive(completeFile);
downloader.registerTorrentWithTorrentManager();
return downloader;
}
private void finishDownload(BTDownloader downloader) throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(1);
downloader.addListener(new EventListener<DownloadStateEvent>() {
@Override
public void handleEvent(DownloadStateEvent event) {
if(DownloadState.COMPLETE == event.getType()) {
countDownLatch.countDown();
}
}
});
if(downloader.getState() != DownloadState.COMPLETE) {
assertTrue("Time ran out before download completed.", countDownLatch.await(100, TimeUnit.SECONDS));
}
assertEquals(DownloadState.COMPLETE, downloader.getState());
}
/**
* 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 {
AssertComparisons.assertTrue(file.exists());
AssertComparisons.assertEquals(fileSize, file.length());
String testmd5 = FileUtils.getMD5(file);
AssertComparisons.assertEquals(md5, testmd5);
}
private void cleanup(BTDownloaderImpl downloader) {
downloader.finish();
downloader.getTorrent().stop();
File incompleteFile = downloader.getIncompleteFile();
FileUtils.deleteRecursive(incompleteFile);
File completeFile = downloader.getSaveFile();
FileUtils.deleteRecursive(completeFile);
}
}