package com.limegroup.gnutella.updates;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import junit.framework.Test;
import com.limegroup.gnutella.Connection;
import com.limegroup.gnutella.ConnectionManager;
import com.limegroup.gnutella.RouterService;
import com.limegroup.gnutella.settings.ConnectionSettings;
import com.limegroup.gnutella.settings.FilterSettings;
import com.limegroup.gnutella.settings.UltrapeerSettings;
import com.limegroup.gnutella.stubs.ActivityCallbackStub;
import com.limegroup.gnutella.util.BaseTestCase;
import com.limegroup.gnutella.util.CommonUtils;
import com.limegroup.gnutella.util.PrivilegedAccessor;
/**
* Unit tests for UpdateMessageVerifier
*/
public class UpdateManagerTest extends BaseTestCase {
static final int OLD = 0;
static final int MIDDLE = 1;
static final int NEW = 2;
static final int DEF_SIGNATURE = 3;
static final int DEF_MESSAGE = 4;
static final int BAD_XML = 5;
static final int RANDOM_BYTES = 6;
private static File OLD_VERSION_FILE;
private static File MIDDLE_VERSION_FILE;
private static File NEW_VERSION_FILE;
private static File DEF_SIG_FILE;
private static File DEF_MESSAGE_FILE;
private static File BAD_XML_FILE;
private static File RANDOM_BYTES_FILE;
private static File updateXMLFile;
private static int updateVersion;
static final int PORT = 6347;
private static boolean testCallback = false;
private static final Object lock = new Object();
private static final long DELAY = 60l*1000;//1 min
private static final String defaultVersion = "0.0.0";
public UpdateManagerTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(UpdateManagerTest.class);//, "testUpdateMessageDelayed");
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
public static void globalSetUp() throws Exception {
setSettings();
RouterService rs = new RouterService(new MyActivityCallbackStub());
rs.start();
RouterService.clearHostCatcher();
RouterService.connect();
}
private static void setSettings() throws Exception {
//Get access to all the test files we need.
String updateDir = "com/limegroup/gnutella/updates/";
OLD_VERSION_FILE =
CommonUtils.getResourceFile(updateDir + "old_verFile.xml");
MIDDLE_VERSION_FILE =
CommonUtils.getResourceFile(updateDir + "middle_verFile.xml");
NEW_VERSION_FILE =
CommonUtils.getResourceFile(updateDir + "new_verFile.xml");
DEF_SIG_FILE =
CommonUtils.getResourceFile(updateDir + "def_verFile.xml");
DEF_MESSAGE_FILE =
CommonUtils.getResourceFile(updateDir + "def_messageFile.xml");
BAD_XML_FILE =
CommonUtils.getResourceFile(updateDir + "bad_xmlFile.xml");
RANDOM_BYTES_FILE =
CommonUtils.getResourceFile(updateDir + "random_bytesFile.xml");
assertTrue(OLD_VERSION_FILE.exists());
assertTrue(MIDDLE_VERSION_FILE.exists());
assertTrue(NEW_VERSION_FILE.exists());
assertTrue(DEF_SIG_FILE.exists());
assertTrue(DEF_MESSAGE_FILE.exists());
File pub = CommonUtils.getResourceFile(updateDir+"public.key");
File pub2 = new File(_settingsDir, "public.key");
CommonUtils.copy(pub, pub2);
assertTrue("test could not be set up", pub2.exists());
updateXMLFile = new File(_settingsDir,"update.xml");
//set the version file to be the old one.
changeUpdateFile(OLD_VERSION_FILE);
updateXMLFile = new File(_settingsDir,"update.xml");
FilterSettings.BLACK_LISTED_IP_ADDRESSES.setValue(
new String[] {"*.*.*.*"} );
FilterSettings.WHITE_LISTED_IP_ADDRESSES.setValue(
new String[] {"127.*.*.*"});
ConnectionSettings.PORT.setValue(PORT);
ConnectionSettings.CONNECT_ON_STARTUP.setValue(false);
UltrapeerSettings.EVER_ULTRAPEER_CAPABLE.setValue(true);
UltrapeerSettings.DISABLE_ULTRAPEER_MODE.setValue(false);
UltrapeerSettings.FORCE_ULTRAPEER_MODE.setValue(true);
UltrapeerSettings.MAX_LEAVES.setValue(5);
ConnectionSettings.NUM_CONNECTIONS.setValue(5);
ConnectionSettings.LOCAL_IS_PRIVATE.setValue(false);
ConnectionSettings.USE_GWEBCACHE.setValue(false);
ConnectionSettings.WATCHDOG_ACTIVE.setValue(false);
UltrapeerSettings.NEED_MIN_CONNECT_TIME.setValue(false);
//Set the version to a lower version
PrivilegedAccessor.setValue(CommonUtils.class, "testVersion", "3.2.2");
}
public void setUp() throws Exception {
/*
// Sleep for 3.0 seconds, regardless of exceptions
long stopTime = 3*1000 + System.currentTimeMillis();
long sleepLength = 3*1000;
while (sleepLength > 0) {
try {
Thread.sleep(sleepLength);
} catch (Exception ignoreMe){
//Minimize busy waiting in the face of exceptions.
Thread.yield();
}
sleepLength = stopTime - System.currentTimeMillis();
}
*/
// Sleep for 3.0 seconds, unless interrupted
Thread.sleep(3*1000);
setSettings();
}
/**
* Tests that UpdateManager thinks the version it knows about is the one on
* disk so long as it is verified correctly
*/
public void testSimpleVersionCheck() throws Exception {
UpdateManager man = UpdateManager.instance();
assertEquals("Problem with old update file", "2.9.3", man.getVersion());
}
public void testNewerVersionAccepted() throws Exception {
updateVersion = NEW;
changeUpdateFile();
UpdateManager man = UpdateManager.instance();
assertEquals("Problem with new update file", "3.6.3", man.getVersion());
}
public void testBadSignatureFails() throws Exception {
//Attempt to change the version to 3.6.3 using a bad signature
changeUpdateFile(DEF_SIG_FILE);
UpdateManager man = UpdateManager.instance();
assertEquals("Accepted defective signature", defaultVersion, man.getVersion());
}
public void testBadMessageFails() throws Exception {
//Attempt to change the version to 3.6.3 using a defective message
changeUpdateFile(DEF_MESSAGE_FILE);
UpdateManager man = UpdateManager.instance();
assertEquals("Problem with new update file", defaultVersion, man.getVersion());
}
public void testBadXMLFileFails() throws Exception {
//Attempt to change verision to 2.9.3 using a bad XML file
changeUpdateFile(BAD_XML_FILE);
UpdateManager man = UpdateManager.instance();
assertEquals("Problem with new update file", defaultVersion, man.getVersion());
}
public void testGarbageFileFails() throws Exception {
updateVersion = RANDOM_BYTES;
changeUpdateFile();
UpdateManager man = UpdateManager.instance();
assertEquals("Problem with new update file", defaultVersion, man.getVersion());
}
public void testOldVersionNotAcceptedFromNetwork() throws Exception {
updateVersion = MIDDLE;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6666,"3.6.3",OLD);
} catch(IOException iox) {
fail("could not set up test");
}
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"3.2.2",man.getVersion());
conn.killThread();
}
public void testIOXLeavesVersionIntact() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6667,"3.6.3",NEW);
} catch(IOException iox) {
fail("could not set up test");
}
conn.setSendUpdateData(false);
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"2.9.3",man.getVersion());
conn.killThread();
}
public void testBadSignatureFailsOnNetwork() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6668,"3.6.3", DEF_SIGNATURE);
} catch(IOException iox) {
fail("could not set test up");
}
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"2.9.3", man.getVersion());
conn.killThread();
}
public void testEqualVersionNotRequested() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6669, "2.9.3", NEW);
} catch(IOException iox) {
fail("could not set test up");
}
conn.setTestUpdateNotRequested(true);
conn.start();
try {
Thread.sleep(3000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"2.9.3", man.getVersion());
//conn.killThread();
}
public void testLowerMajorVersionNotRequested() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6670, "2.3.3", NEW);
} catch(IOException iox) {
fail("could not set test up");
}
conn.setTestUpdateNotRequested(true);
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"2.9.3", man.getVersion());
//conn.killThread();
}
public void testDifferentMinorVersionNotRequested() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6671, "2.9.5", NEW);
} catch(IOException iox) {
fail("could not set test up");
}
conn.setTestUpdateNotRequested(true);
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update manager accepted lower version",
"2.9.3", man.getVersion());
//conn.killThread();
}
public void testNewerVersionAcceptedOnNetwork() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try { //header says same as me, but my version file is older,
conn = new TestConnection(6672, "3.6.3", NEW);
} catch(IOException iox) {
fail("could not set test up");
}
conn.setTestUpdateNotRequested(false);
conn.start();
try {
Thread.sleep(2000);
} catch(InterruptedException ix) {
fail("unable to set up test");
}
UpdateManager man = UpdateManager.instance();
assertEquals("Update should have got new version",
"3.6.3", man.getVersion());
}
/**
* Tests that we will request the update file even our version is the same
* as the version advertised, but our version file is older than the version
* file advertised by the other guy
*/
public void testNewerVersionFileWithSameVersionRequested() throws Exception {
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try { //header says same as me, but my version file is older,
conn = new TestConnection(6673, "3.2.2", NEW);
} catch(IOException iox) {
fail("could not set test up");
}
conn.start();
try {
Thread.sleep(300);
} catch(Exception e) {}
UpdateManager man = UpdateManager.instance();
assertEquals("Update should have got new version",
"3.6.3", man.getVersion());
}
public void testBadMessageFailsOnNetwork() throws Exception {
removeConnections();
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try { //header says same as me, but my version file is older,
conn = new TestConnection(6674, "3.6.3", DEF_MESSAGE);
} catch(IOException iox) {
fail("could not set test up");
}
conn.start();
try {
Thread.sleep(300);
} catch(Exception e) {}
UpdateManager man = UpdateManager.instance();
assertEquals("Update should have got new version",
"2.9.3", man.getVersion());
}
public void testBadXMLFailsOnNetwork() throws Exception {
removeConnections();
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try { //header says same as me, but my version file is older,
conn = new TestConnection(6675, "3.6.3", BAD_XML);
} catch(IOException iox) {
fail("could not set test up");
}
conn.start();
try {
Thread.sleep(300);
} catch(Exception e) {}
UpdateManager man = UpdateManager.instance();
assertEquals("Update should have got new version",
"2.9.3", man.getVersion());
}
public void testGarbageDataFailsOnNetwork() throws Exception {
removeConnections();
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try { //header says same as me, but my version file is older,
conn = new TestConnection(6676, "3.6.3", RANDOM_BYTES);
} catch(IOException iox) {
fail("could not set test up");
}
conn.start();
try {
Thread.sleep(300);
} catch(Exception e) {}
UpdateManager man = UpdateManager.instance();
assertEquals("Update should have got new version",
"2.9.3", man.getVersion());
}
public void testUpdateNotRequesteFromSpecial() throws Exception {
removeConnections();
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6681, "@version@", NEW);
} catch (IOException e) {
fail("could not setup test");
}
conn.setTestUpdateNotRequested(true);
conn.start();
try {
Thread.sleep(300);
} catch (InterruptedException ix) { }
UpdateManager man = UpdateManager.instance();
assertEquals("should not have requested new file",
"2.9.3", man.getVersion());
}
public void testUpdateMessageDelayed() throws Exception {
removeConnections();
//Note:If the update file does not contain the timestamp attibute, the
//UpdateManager assumes it is the current time. We can use this to test
//that there is a delay in our displaying the message
testCallback = true;
updateVersion = OLD;
changeUpdateFile();
TestConnection conn = null;
try {
conn = new TestConnection(6682, "3.6.3", NEW);//no timestamp
} catch (IOException e) {
fail("could not setup test");
}
conn.start();
long startTime = System.currentTimeMillis();
synchronized(lock) {
try {
lock.wait(DELAY);
} catch (InterruptedException ix) {}
if(System.currentTimeMillis() == startTime)
fail("GUI notified too soon");
else if(System.currentTimeMillis() > startTime+DELAY)
fail("GUI notified too late");
}
testCallback = false;
}
/**
* puts an update file in the user pref dir based on updateVersion and set
* the UpdateManager.INSTANCE to null so the new file is parsed everytime we
* call UpdateManager.instance()
*
* @param updateFile the File that is to be coppied over the update XML file
*/
private static void changeUpdateFile(File updateFile) throws Exception {
CommonUtils.copy(updateFile, updateXMLFile);
//Set UpdateManager.INSTANCE to null
PrivilegedAccessor.setValue(UpdateManager.class, "INSTANCE", null);
}
/**
* puts an update file in the user pref dir based on updateVersion and set
* the UpdateManager.INSTANCE to null so the new file is parsed everytime we
* call UpdateManager.instance()
*/
private static void changeUpdateFile() throws Exception {
if(updateVersion == OLD)
CommonUtils.copy(OLD_VERSION_FILE, updateXMLFile);
else if(updateVersion == MIDDLE)
CommonUtils.copy(MIDDLE_VERSION_FILE, updateXMLFile);
else if(updateVersion == NEW)
CommonUtils.copy(NEW_VERSION_FILE, updateXMLFile);
else if(updateVersion == DEF_MESSAGE)
CommonUtils.copy(DEF_MESSAGE_FILE, updateXMLFile);
else if(updateVersion == DEF_SIGNATURE)
CommonUtils.copy(DEF_SIG_FILE, updateXMLFile);
else if(updateVersion == BAD_XML)
CommonUtils.copy(BAD_XML_FILE, updateXMLFile);
else if(updateVersion == RANDOM_BYTES)
CommonUtils.copy(RANDOM_BYTES_FILE, updateXMLFile);
else
fail("updateVersion set to wrong value");
//Set UpdateManager.INSTANCE to null
PrivilegedAccessor.setValue(UpdateManager.class, "INSTANCE", null);
}
private static class MyActivityCallbackStub extends ActivityCallbackStub {
public void indicateNewVersion() {
if(!testCallback)
return;
synchronized(lock) {
lock.notifyAll();
}
}
}
/**
* removes all existing connections to the node because previous tests
* may influence outcome
* @throws Exception
*/
private void removeConnections() {
ConnectionManager cman = RouterService.getConnectionManager();
for (Iterator iter = cman.getConnections().iterator();iter.hasNext();) {
Connection c = (Connection)iter.next();
c.close();
}
}
}