/*
* Copyright (c) 2007-2013 The Broad Institute, Inc.
* SOFTWARE COPYRIGHT NOTICE
* This software and its documentation are the copyright of the Broad Institute, Inc. All rights are reserved.
*
* This software is supplied without any warranty or guaranteed support whatsoever. The Broad Institute is not responsible for its use, misuse, or functionality.
*
* This software is licensed under the terms of the GNU Lesser General Public License (LGPL),
* Version 2.1 which is available at http://www.opensource.org/licenses/lgpl-2.1.php.
*/
package org.broad.igv.plugin.mongocollab;
import com.mongodb.*;
import org.apache.log4j.Logger;
import org.broad.igv.AbstractHeadlessTest;
import org.broad.igv.feature.BasicFeature;
import org.broad.igv.util.FileUtils;
import org.broad.igv.util.RuntimeUtils;
import org.broad.igv.util.TestUtils;
import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import java.awt.*;
import java.io.*;
import static org.junit.Assert.*;
/**
* Tests of our integration with MongoDB for collaboration/annotation
* Starts MongoDB on a separate process, host machine must have Mongo and
* test runner must be pointed to it by {@link #MONGO_EXEC_KEY}
* @author jacob
* @date 2013-Sep-10
*/
public class MongoCollabPluginTest extends AbstractHeadlessTest {
private static Logger log = Logger.getLogger(MongoCollabPluginTest.class);
private static String testFileSpecPath = TestUtils.DATA_DIR + "localMongo.db.spec";
private static Thread mongoProc;
private static String MONGO_EXEC_KEY = "MONGO_EXEC_PATH";
/**
* See build.xml for default value
*/
private static String MONGO_EXEC_PATH;
@BeforeClass
public static void setUpClass() throws Exception{
AbstractHeadlessTest.setUpClass();
MONGO_EXEC_PATH = System.getProperty(MONGO_EXEC_KEY, MONGO_EXEC_PATH);
log.info("Mongo exec path: " + MONGO_EXEC_PATH);
Assume.assumeTrue(MONGO_EXEC_PATH != null && MONGO_EXEC_PATH.length() > 0);
startTestMongo();
assumeTestDBRunning();
emptyTestCollection();
}
@AfterClass
public static void tearDownClass() throws Exception{
AbstractHeadlessTest.tearDownClass();
try{
emptyTestCollection();
}catch(Exception e){
log.error(e.getMessage(), e);
}
try {
stopTestMongo();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
@Test
public void testReadSpec() throws Exception{
MongoCollabPlugin.Locator locator = getTestLocator();
assertEquals("localhost", locator.host);
assertEquals(27017, locator.port);
}
@Test
public void testGetCollection() throws Exception{
MongoCollabPlugin.Locator locator = assumeTestDBRunning();
DBCollection collection = MongoCollabPlugin.getCollection(locator);
assertNotNull(collection);
}
@Test
public void testInsertFeature() throws Exception{
MongoCollabPlugin.Locator locator = assumeTestDBRunning();
BasicFeature feat = new BasicFeature("chromo", 50, 100);
//Set name/desc which look like colors, to make sure color parsing isn't activated
feat.setColor(Color.magenta);
feat.setName("0,1,2");
feat.setDescription("mydescription,is,here");
DBFeature dbFeat = DBFeature.create(feat);
assertNull(dbFeat.get_id());
DBCollection coll = MongoCollabPlugin.getCollection(locator);
coll.setObjectClass(DBFeature.class);
String err = MongoCollabPlugin.saveFeature(coll, dbFeat);
assertNull(err);
assertNotNull(dbFeat.get_id());
DBFeature retrievedFeat = (DBFeature) coll.find(new BasicDBObject("_id", dbFeat.get_id())).next();
TestUtils.assertFeaturesEqual(dbFeat, retrievedFeat);
assertEquals(dbFeat.getColor(), retrievedFeat.getColor());
assertEquals(dbFeat.getName(), retrievedFeat.getName());
assertEquals(dbFeat.getDescription(), retrievedFeat.getDescription());
}
@Test
public void testInsertFeatures() throws Exception{
DBCollection collection = emptyTestCollection();
int inserted = MongoCollabPlugin.insertFeaturesFromFile(collection, TestUtils.DATA_DIR + "bed/test.bed");
assertEquals(inserted, collection.count());
assertTrue(inserted > 0);
}
/**
* Assumes that test DB is running, return Locator (for convenience)
* if it is.
* @return
* @throws Exception
*/
public static MongoCollabPlugin.Locator assumeTestDBRunning() throws Exception{
MongoCollabPlugin.Locator locator = getTestLocator();
Assume.assumeTrue(canAccessDB(locator));
return locator;
}
public static DBCollection emptyTestCollection() throws Exception{
DBCollection collection = MongoCollabPlugin.getCollection(getTestLocator());
collection.dropIndexes();
collection.drop();
return collection;
}
public static MongoCollabPlugin.Locator getTestLocator() throws IOException{
try {
return new MongoCollabPlugin.Locator(testFileSpecPath);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
public static boolean canAccessDB(MongoCollabPlugin.Locator locator){
try {
Mongo mongo = MongoCollabPlugin.getMongo(locator.host, locator.port);
return mongo.getDatabaseNames() != null;
} catch (Exception e) {
return false;
}
}
static void startTestMongo() throws Exception{
String mongoExecPath = MONGO_EXEC_PATH;
int port = getTestLocator().port;
String dbRelPath = TestUtils.DATA_DIR + "mongodbtmp";
final File dbDir = new File(dbRelPath);
String dbAbsPath = dbDir.getAbsolutePath();
if(!dbDir.exists()){
dbDir.mkdirs();
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
FileUtils.deleteDir(dbDir);
}
});
}
final String[] commands = new String[]{mongoExecPath, "--port", "" + port, "--dbpath", dbAbsPath};
Thread runnable = new Thread(){
private Process proc;
@Override
public void run() {
try {
proc = RuntimeUtils.startExternalProcess(commands, null, null);
InputStream is = proc.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while((line = br.readLine()) != null){
log.debug(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void interrupt() {
if(this.proc != null){
this.proc.destroy();
}
super.interrupt();
}
};
runnable.start();
mongoProc = runnable;
//Need to wait for startup
Thread.sleep(5000);
}
// @Test
// public void testShutdown() throws Exception{
// assertTrue(canAccessDB(getTestLocator()));
// assertFalse(stopTestMongo());
// }
/**
* Stop the test Mongo instance
* @return state of server when done. False = stopped, true = running
* @throws IOException
*/
static boolean stopTestMongo() throws Exception{
MongoCollabPlugin.Locator testLocator = getTestLocator();
Mongo mongo = MongoCollabPlugin.getMongo(testLocator.host, testLocator.port);
DB db = mongo.getDB("admin");
//This actually works (from localhost only), but the java driver throws an error for some reason
try{
CommandResult command = db.command( new BasicDBObject( "shutdown", 1 ) );
}catch(Exception e){
}
Thread.sleep(5000);
if(mongoProc != null && mongoProc.isAlive()){
mongoProc.interrupt();
mongoProc.stop();
}
return canAccessDB(testLocator);
}
}