Package org.broad.igv.util

Source Code of org.broad.igv.util.TestUtils

/*
* Copyright (c) 2007-2012 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.util;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import htsjdk.samtools.util.ftp.FTPClient;
import org.broad.igv.DirectoryManager;
import org.broad.igv.Globals;
import org.broad.igv.PreferenceManager;
import org.broad.igv.feature.NamedFeature;
import org.broad.igv.feature.genome.Genome;
import org.broad.igv.feature.genome.GenomeListItem;
import org.broad.igv.feature.genome.GenomeManager;
import org.broad.igv.tools.IgvTools;
import org.broad.igv.track.Track;
import org.broad.igv.ui.IGV;
import htsjdk.tribble.Feature;
import htsjdk.tribble.readers.AsciiLineReader;
import org.junit.Assert;
import org.junit.Ignore;
import org.w3c.dom.Document;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.*;
import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

/**
* @author jrobinso
* @date Jul 28, 2010
*/
@Ignore
public class TestUtils {
    public static final String DATA_DIR = "test/data/";
    public static final String TMP_OUTPUT_DIR = DATA_DIR + "out/";
    public static final String defaultGenome = DATA_DIR + "/genomes/hg18.unittest.genome";
    public static final String AVAILABLE_FTP_URL = "ftp://ftp.broadinstitute.org/pub/igv/TEST/test.txt";
    public static final String UNAVAILABLE_FTP_URL = "ftp://www.example.com/file.txt";
    //This is so ant can set the large data directory
    private static String LARGE_DATA_DIR_KEY = "LARGE_DATA_DIR";
    public static String LARGE_DATA_DIR = "test/largedata/";

    static {
        LARGE_DATA_DIR = System.getProperty(LARGE_DATA_DIR_KEY, LARGE_DATA_DIR);
    }

    public static void setUpTestEnvironment() throws IOException {
        Globals.setTesting(true);
        //Globals.setBatch(true);
        resetPrefsFile();
        resetTestUserDefinedGenomes();
        Globals.READ_TIMEOUT = 60 * 1000;
        Globals.CONNECT_TIMEOUT = 60 * 1000;
        FTPClient.READ_TIMEOUT = 60 * 1000;

        //Create output directory if it doesn't exist
        File outDir = new File(TestUtils.TMP_OUTPUT_DIR);
        if (!outDir.exists()) {
            outDir.mkdir();
        }
        clearOutputDir();
    }

    public static void resetPrefsFile(){
        File prefsFile = new File("testprefs.properties");
        prefsFile.delete();
        prefsFile.deleteOnExit();
        PreferenceManager.getInstance().setPrefsFile(prefsFile.getAbsolutePath());
    }

    /**
     * Loads the session into IGV. This blocks until the session
     * is loaded.
     *
     * @param igv
     * @param sessionPath
     * @throws InterruptedException
     */
    public static void loadSession(IGV igv, String sessionPath) throws InterruptedException {
        igv.doRestoreSession(sessionPath, null, false);
    }

    /**
     * See {@link #createIndex(String, int, int)}
     *
     * @param file
     * @throws IOException
     */
    public static void createIndex(String file) throws IOException {
        createIndex(file, IgvTools.LINEAR_INDEX, IgvTools.LINEAR_BIN_SIZE);
    }

    /**
     * Destroys index file if it exists, and creates new one under
     * the specified parameters
     *
     * @param file
     * @param indexType
     * @param binSize
     * @throws IOException
     */
    public static void createIndex(String file, int indexType, int binSize) throws IOException {
        String indexPath = (new IgvTools()).doIndex(file, null, indexType, binSize);
        File indexFile = new File(indexPath);
        indexFile.deleteOnExit();
    }

    /**
     * Load a test genome
     *
     * @return
     * @throws IOException
     */
    public static Genome loadGenome() throws IOException {
        final String genomeFile = defaultGenome;
        return IgvTools.loadGenome(genomeFile);
    }

    public static void clearOutputDir() throws IOException {
        File outputDir = new File(TMP_OUTPUT_DIR);
        if (outputDir.isDirectory()) {
            File[] listFiles = outputDir.listFiles();
            for (File fi : listFiles) {
                //Keep hidden files and directories
                if (!fi.isHidden()) {
                    if(fi.isFile()){
                        fi.delete();
                    }else if(fi.isDirectory()){
                        FileUtils.deleteDir(fi);
                    }
                }
            }
        }
    }

    /**
     * Returns either 1 or 2, representing the number of
     * bytes used to end a line. Reads only from first line of a file
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static int getBytesAtEnd(String filePath) throws IOException {
        InputStream is = new FileInputStream(filePath);
        AsciiLineReader reader = new AsciiLineReader(is);
        String line = reader.readLine();
        int bytesThisLine = (int) reader.getPosition();

        reader.close();

        return bytesThisLine - line.length();

    }

    /**
     * Check that the features are all the same. Checks size of list, chr, start, and end of
     * each feature
     *
     * @param expected
     * @param actIter
     * @throws AssertionError
     */
    public static void assertFeatureListsEqual(Iterator<? extends Feature> expected, Iterator<? extends Feature> actIter) throws AssertionError {
        while (expected.hasNext()) {
            Feature exp = expected.next();
            assertTrue(actIter.hasNext());
            Feature act = actIter.next();
            assertFeaturesEqual(exp, act);
        }
        assertFalse(actIter.hasNext());
    }


    public static void assertFeaturesEqual(Feature exp, Feature act) {
        assertEquals(exp.getChr(), act.getChr());
        assertEquals(exp.getStart(), act.getStart());
        assertEquals(exp.getEnd(), act.getEnd());
    }

    /**
     * Name matching is case-insensitive
     * @param exp
     * @param act
     */
    public static void assertNamedFeaturesEqual(NamedFeature exp, NamedFeature act) {
        assertFeaturesEqual(exp, act);
        assertEquals(exp.getName().toUpperCase(), act.getName().toUpperCase());
    }

    public static void assertTrackLoaded(IGV igv, String trackName){
        boolean found = false;
        for(Track t: igv.getAllTracks()){
            if(t.getName().equals(trackName)){
                found = true;
                break;
            }
        }
        Assert.assertTrue("Track not loaded", found);
    }

    /**
     *
     * @param featureIterator
     * @return Number of features in the iterator
     * @throws Exception
     */
    public static int assertFeatureIteratorSorted(Iterator<? extends Feature> featureIterator){
        int lastStart = -1;
        int count = 0;
        while (featureIterator.hasNext()) {
            Feature f0 = featureIterator.next();
            assertTrue(f0.getStart() >= lastStart);
            lastStart = f0.getStart();
            count++;
        }
        return count;
    }

    /*
     * The FEST library finds components by name
     * We set the name property to equal the variable name.
     * Intended for testing ONLY
     * @param parent Element in which to set child names. Each field of this Object which is a Component
     *               will have it's name set
     * @param recursive Whether to set names on grand-child components. Note that this is all-or-none,
     *                  if this is true it goes recursively all the way down. Recursion is breadth-first,
     *                  stops at each level when an object has only non-Component fields
     */
    public static void setAllNames(Object parent, boolean recursive) {
        Field[] fields = parent.getClass().getDeclaredFields();
        java.util.List<Component> childComponents = new ArrayList<Component>(fields.length);
        try {
            for (Field f : fields) {
                Component c = null;
                f.setAccessible(true);
                try {
                    c = (Component) f.get(parent);
                } catch (ClassCastException e) {
                    continue;
                }
                //Null valued fields don't throw a CCE
                //We don't overwrite names, this should also prevent
                //infinite recursion
                if (c == null || c.getName() != null) {
                    continue;
                }
                //At this point, we've established
                //that the field in question is a Component
                c.setName(f.getName());
                childComponents.add(c);

                f.setAccessible(false);
            }

            if (recursive) {
                for (Component c : childComponents) {
                    setAllNames(c, recursive);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public static void checkDeadlockedThreads() throws IllegalThreadStateException {
        ThreadMXBean tmx = ManagementFactory.getThreadMXBean();
        long[] ids = tmx.findDeadlockedThreads();
        if (ids != null) {
            ThreadInfo[] infos = tmx.getThreadInfo(ids, true, true);
            String log = "The following threads are deadlocked:\n";
            for (ThreadInfo ti : infos) {
                System.out.println(ti);
                log += ti.toString() + "\n";
            }

            throw new IllegalThreadStateException(log);
        }
    }

    public static Timer startDeadlockChecker(final int period) {

        TimerTask checker = new TimerTask() {
            @Override
            public void run() {
                //System.out.println("deadlock checker thread:" + Thread.currentThread().getName());
                checkDeadlockedThreads();
            }
        };
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(checker, 0, period);
        return timer;
    }

    /**
     * Executes {@code predicate} on those objects supplied by {@code supplier},
     * timing each iteration. Goes {@code nTrials} times
     *
     * @param supplier
     * @param predicate
     * @param nTrials
     * @param <T>
     * @return The runtime, in nanoseconds, of each call of predicate with input of supplier.
     *         Array is sorted ascending
     */
    public static <T> long[] timeMethod(Supplier<T> supplier, Function<T, Void> predicate, int nTrials) {
        long total = 0;
        long[] times = new long[nTrials];
        System.gc();

        for (int tri = 0; tri < nTrials; tri++) {

            T input = supplier.get();

            long startTime = System.nanoTime();

            predicate.apply(input);

            long endTime = System.nanoTime();
            long elapsed = endTime - startTime;
            times[tri] = elapsed;
            total += elapsed;
        }

        Arrays.sort(times);
        long minTime = times[0];
        long maxTime = times[nTrials - 1];
        long median = times[times.length / 2];
        double average = (total * 1.0 / nTrials);
        double stdev = -1;
        try {
            stdev = stdev(times, (long) average);
        } catch (ArithmeticException e) {
            //pass
        }

        System.out.println(String.format("Avg. time: %2.2e sec. Median: %2.2e sec", average * 1.0 / 1e9, median * 1.0 / 1e9));
        System.out.println(String.format("Best: %2.2e sec. Worst: %2.2e sec", minTime * 1.0 / 1e9, maxTime * 1.0 / 1e9));
        System.out.println(String.format("Standard deviation: %2.2e sec", stdev / 1e9));
        System.out.println(String.format("Total time: %2.2e sec", total * 1.0 / 1e9));

        return times;
    }

    public static double average(long[] vals) {
        long sum = 0;
        double n = (double) vals.length;
        for (Long i : vals)
            sum += ((double) i);
        return sum / n;
    }

    public static double stdev(long[] vals, long average) {
        long sum = 0;
        for (Long i : vals)
            sum += Math.pow((i - average), 2);
        return Math.sqrt(sum / (vals.length - 1)); // sample
    }

    private static long benchmarkTime = -1;

    public static long getBenchmarkTime() {
        if (benchmarkTime < 0) {
            //Generate some numbers to average
            Random r = new Random();
            int numNumbers = 1000000;
            long[] vals = new long[numNumbers];
            for (int rr = 0; rr < numNumbers; rr++) {
                vals[rr] = r.nextInt();
            }
            System.gc();

            long startTime = System.nanoTime();

            double avg = average(vals);

            long endTime = System.nanoTime();
            benchmarkTime = endTime - startTime;
            System.out.println("Benchmark Time (s): " + ((double) benchmarkTime)/1e9d);
        }
        return benchmarkTime;
    }



    /**
     * Marshalls {@code inObj} and unmarshalls the result, returning the
     * unmarshalled version
     *
     * @param inObj
     * @return
     * @throws Exception
     */
    public static <T> T marshallUnmarshall(T inObj) throws Exception{

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.newDocument();

        JAXBContext jc = JAXBContext.newInstance(inObj.getClass());
        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FRAGMENT, true);

        //This JAXBElement business is necessary because we don't know if we have @XmlRootElement on inObj
        JAXBElement inel = new JAXBElement(new QName("", "obj"), inObj.getClass(), inObj);
        //m.marshal(inel, System.out);
        m.marshal(inel, doc);

        Unmarshaller u = jc.createUnmarshaller();
        JAXBElement el = (JAXBElement) u.unmarshal(doc, inObj.getClass());
        return (T) el.getValue();
    }

    private static Object getField(Object object, Class clazz, String fieldName) throws Exception{
        if(clazz == null) throw new NoSuchFieldException(fieldName + " not found all the way up");
        Field field;
        try{
            field = object.getClass().getDeclaredField(fieldName);
        }catch (NoSuchFieldException e){
            return getField(object, clazz.getSuperclass(), fieldName);
        }
        field.setAccessible(true);
        return field.get(object);
    }

    /**
     * Get the specified field, ignoring access restrictions
     * @param object
     * @param fieldName
     * @return
     */
    public static Object getField(Object object, String fieldName) throws Exception{
        return getField(object, object.getClass(), fieldName);
    }

    private static Object runMethod(Object object, Class clazz, String methodName, Object... args) throws Exception{
        if(clazz == null) throw new NoSuchFieldException(methodName + " not found all the way up");
        Method method;
        try{
            method = object.getClass().getDeclaredMethod(methodName);
        }catch (NoSuchMethodException e){
            return runMethod(object, clazz.getSuperclass(), methodName, args);
        }
        method.setAccessible(true);
        return method.invoke(object, args);
    }

    public static Object runMethod(Object object, String methodName, Object... args) throws Exception{
        return runMethod(object, object.getClass(), methodName, args);
    }


    private static Map<String, String> replaceMap = new HashMap<String, String>(2);
    static{
        replaceMap.put("${DATA_DIR}", TestUtils.DATA_DIR);
        replaceMap.put("${LARGE_DATA_DIR}", TestUtils.LARGE_DATA_DIR);
    }
    /**
     * Mainly for session files, we want use some test paths stored in otherwise hardcoded
     * test data files. This re-writes the input text file
     * @param inputPath
     * @return File of the output location
     */
    public static File replaceTestPaths(File inputPath) throws Exception{

        BufferedReader reader = new BufferedReader(new FileReader(inputPath));

        File outputFile = new File("tmpsession.xml");
        outputFile.delete();
        outputFile.deleteOnExit();
        PrintWriter writer = new PrintWriter(new FileWriter(outputFile));

        String line;
        while((line = reader.readLine()) != null){
            for(Map.Entry<String, String> entry: replaceMap.entrySet()){
                line = line.replace(entry.getKey(), entry.getValue());
            }
            writer.println(line);
        }
        writer.flush();
        writer.close();
        return outputFile;
    }

    /**
     * Note: THIS METHOD IS VERY FRAGILE, NOT GUARANTEED TO WORK ON ALL JVMs
     * @return
     */
    static long getProcessID(){
        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();

        // The name representing the running Java virtual machine.
        // It returns something like 12345@blah. The value
        // before the @ symbol is the PID.
        String jvmName = bean.getName();
        return Long.valueOf(jvmName.split("@")[0]);
    }

    /**
     * Uses lsof, only works on *nix systems
     *
     * @return
     */
    public static int getNumberOpenFileHandles() throws IOException{
        long pid = getProcessID();
        String result = RuntimeUtils.executeShellCommand(new String[]{"lsof", "-p", "" + pid}, null, null, false);
        return result.split("\n").length;
    }

    public static void resetTestUserDefinedGenomes() throws IOException{
        File userDefinedGenomeListFile = new File(DirectoryManager.getGenomeCacheDirectory(), GenomeManager.TEST_USER_DEFINED_GENOME_LIST_FILE);
        userDefinedGenomeListFile.delete();
        userDefinedGenomeListFile.deleteOnExit();

        Collection<GenomeListItem> userDefined = GenomeManager.getInstance().getUserDefinedGenomeArchiveList();
        userDefined.clear();
        GenomeManager.getInstance().buildGenomeItemList();
    }
}
TOP

Related Classes of org.broad.igv.util.TestUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.