/* * Copyright (c) 2012 The Broad Institute * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.broadinstitute.variant; import org.testng.Assert; import java.io.File; import java.io.IOException; import java.util.*; /** * Base class for test classes within org.broadinstitute.variant */ public class VariantBaseTest { public static final String hg19Reference = "/seq/references/Homo_sapiens_assembly19/v1/Homo_sapiens_assembly19.fasta"; public static final String b37KGReference = "/humgen/1kg/reference/human_g1k_v37.fasta"; // TODO: change this to an appropriate value once the move to the Picard repo takes place public static final String variantTestDataRoot = new File("private/testdata/").getAbsolutePath() + "/"; /** * Simple generic utility class to creating TestNG data providers: * * 1: inherit this class, as in * * private class SummarizeDifferenceTest extends TestDataProvider { * public SummarizeDifferenceTest() { * super(SummarizeDifferenceTest.class); * } * ... * } * * Provide a reference to your class to the TestDataProvider constructor. * * 2: Create instances of your subclass. Return from it the call to getTests, providing * the class type of your test * * @DataProvider(name = "summaries" * public Object[][] createSummaries() { * new SummarizeDifferenceTest().addDiff("A", "A").addSummary("A:2"); * new SummarizeDifferenceTest().addDiff("A", "B").addSummary("A:1", "B:1"); * return SummarizeDifferenceTest.getTests(SummarizeDifferenceTest.class); * } * * This class magically tracks created objects of this */ public static class TestDataProvider { private static final Map> tests = new HashMap>(); protected String name; /** * Create a new TestDataProvider instance bound to the class variable C * @param c */ public TestDataProvider(Class c, String name) { if ( ! tests.containsKey(c) ) tests.put(c, new ArrayList()); tests.get(c).add(this); this.name = name; } public TestDataProvider(Class c) { this(c, ""); } public void setName(final String name) { this.name = name; } /** * Return all of the data providers in the form expected by TestNG of type class C * @param c * @return */ public static Object[][] getTests(Class c) { List params2 = new ArrayList(); for ( Object x : tests.get(c) ) params2.add(new Object[]{x}); return params2.toArray(new Object[][]{}); } @Override public String toString() { return "TestDataProvider("+name+")"; } } /** * Creates a temp file that will be deleted on exit after tests are complete. * @param name Prefix of the file. * @param extension Extension to concat to the end of the file. * @return A file in the temporary directory starting with name, ending with extension, which will be deleted after the program exits. */ public static File createTempFile(String name, String extension) { try { File file = File.createTempFile(name, extension); file.deleteOnExit(); return file; } catch (IOException ex) { throw new RuntimeException("Cannot create temp file: " + ex.getMessage(), ex); } } private static final double DEFAULT_FLOAT_TOLERANCE = 1e-1; public static final void assertEqualsDoubleSmart(final Object actual, final Double expected) { Assert.assertTrue(actual instanceof Double, "Not a double"); assertEqualsDoubleSmart((double)(Double)actual, (double)expected); } public static final void assertEqualsDoubleSmart(final Object actual, final Double expected, final double tolerance) { Assert.assertTrue(actual instanceof Double, "Not a double"); assertEqualsDoubleSmart((double)(Double)actual, (double)expected, tolerance); } public static final void assertEqualsDoubleSmart(final double actual, final double expected) { assertEqualsDoubleSmart(actual, expected, DEFAULT_FLOAT_TOLERANCE); } public static final void assertEqualsSet(final Set actual, final Set expected, final String info) { final Set actualSet = new HashSet(actual); final Set expectedSet = new HashSet(expected); Assert.assertTrue(actualSet.equals(expectedSet), info); // note this is necessary due to testng bug for set comps } public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance) { assertEqualsDoubleSmart(actual, expected, tolerance, null); } public static void assertEqualsDoubleSmart(final double actual, final double expected, final double tolerance, final String message) { if ( Double.isNaN(expected) ) // NaN == NaN => false unfortunately Assert.assertTrue(Double.isNaN(actual), "expected is nan, actual is not"); else if ( Double.isInfinite(expected) ) // NaN == NaN => false unfortunately Assert.assertTrue(Double.isInfinite(actual), "expected is infinite, actual is not"); else { final double delta = Math.abs(actual - expected); final double ratio = Math.abs(actual / expected - 1.0); Assert.assertTrue(delta < tolerance || ratio < tolerance, "expected = " + expected + " actual = " + actual + " not within tolerance " + tolerance + (message == null ? "" : "message: " + message)); } } }