diff --git a/public/java/src/org/broadinstitute/sting/gatk/executive/HierarchicalMicroScheduler.java b/public/java/src/org/broadinstitute/sting/gatk/executive/HierarchicalMicroScheduler.java index 433c7d82f..1cea14a9d 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/executive/HierarchicalMicroScheduler.java +++ b/public/java/src/org/broadinstitute/sting/gatk/executive/HierarchicalMicroScheduler.java @@ -47,7 +47,7 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar /** * An exception that's occurred in this traversal. If null, no exception has occurred. */ - private Throwable error = null; + private RuntimeException error = null; /** * Queue of incoming shards. @@ -345,22 +345,22 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar return error != null; } - private synchronized StingException getTraversalError() { + private synchronized RuntimeException getTraversalError() { if(!hasTraversalErrorOccurred()) throw new ReviewedStingException("User has attempted to retrieve a traversal error when none exists"); - - // If the error is already a StingException, pass it along as is. Otherwise, wrap it. - if(error instanceof StingException) - return (StingException)error; - else - return new ReviewedStingException("An error occurred during the traversal.",error); + return error; } /** * Allows other threads to notify of an error during traversal. */ protected synchronized void notifyOfTraversalError(Throwable error) { - this.error = error; + // If the error is already a Runtime, pass it along as is. Otherwise, wrap it. + if (error instanceof RuntimeException) + this.error = (RuntimeException)error; + else + this.error = new ReviewedStingException("An error occurred during the traversal.", error); + } diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/ErrorThrowingWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/ErrorThrowingWalker.java new file mode 100644 index 000000000..6f0490fd3 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/ErrorThrowingWalker.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011, 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.sting.gatk.walkers.qc; + +import org.broadinstitute.sting.commandline.Input; +import org.broadinstitute.sting.gatk.contexts.AlignmentContext; +import org.broadinstitute.sting.gatk.contexts.ReferenceContext; +import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker; +import org.broadinstitute.sting.gatk.walkers.RodWalker; +import org.broadinstitute.sting.gatk.walkers.TreeReducible; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.exceptions.UserException; + +/** + * a walker that simply throws errors. Allows us to test that the engine is behaving as expected with error handling + */ +public class ErrorThrowingWalker extends RodWalker implements TreeReducible { + @Input(fullName="exception", shortName = "E", doc="Java class of exception to throw", required=true) + public String exceptionToThrow; + + // + // Template code to allow us to build the walker, doesn't actually do anything + // + @Override + public Integer map(RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { + if ( exceptionToThrow.equals("UserException") ) { + throw new UserException("UserException"); + } else if ( exceptionToThrow.equals("NullPointerException") ) { + throw new NullPointerException(); + } else if ( exceptionToThrow.equals("ReviewedStingException") ) { + throw new ReviewedStingException("ReviewedStingException"); + } else { + throw new UserException.BadArgumentValue("exception", "exception isn't a recognized value " + exceptionToThrow); + } + } + + @Override + public Integer reduceInit() { + return 0; + } + + @Override + public Integer reduce(Integer value, Integer sum) { + return value + sum; + } + + public Integer treeReduce(final Integer lhs, final Integer rhs) { + return lhs + rhs; + } +} diff --git a/public/java/test/org/broadinstitute/sting/gatk/EngineFeaturesIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/EngineFeaturesIntegrationTest.java index 8cc2ffd96..192c86fe3 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/EngineFeaturesIntegrationTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/EngineFeaturesIntegrationTest.java @@ -25,9 +25,13 @@ package org.broadinstitute.sting.gatk; import org.broadinstitute.sting.WalkerTest; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.util.Arrays; + /** * */ @@ -73,4 +77,45 @@ public class EngineFeaturesIntegrationTest extends WalkerTest { @Test() private void testMissingInterval() { testMissingFile("missing interval", "-T UnifiedGenotyper -L missing.interval_list -I " + b37GoodBAM); } + + + // -------------------------------------------------------------------------------- + // + // Test that our exceptions are coming back as we expect + // + // -------------------------------------------------------------------------------- + + private class EngineErrorHandlingTestProvider extends TestDataProvider { + Class expectedException; + boolean multiThreaded; + + public EngineErrorHandlingTestProvider(Class exceptedException, final boolean multiThreaded) { + super(EngineErrorHandlingTestProvider.class); + this.expectedException = exceptedException; + this.multiThreaded = multiThreaded; + setName(String.format("Engine error handling: expected %s, is-multithreaded %b", exceptedException, multiThreaded)); + } + } + + @DataProvider(name = "EngineErrorHandlingTestProvider") + public Object[][] makeEngineErrorHandlingTestProvider() { + for ( final boolean multiThreaded : Arrays.asList(true, false)) { + new EngineErrorHandlingTestProvider(NullPointerException.class, multiThreaded); + new EngineErrorHandlingTestProvider(UserException.class, multiThreaded); + new EngineErrorHandlingTestProvider(ReviewedStingException.class, multiThreaded); + } + + return EngineErrorHandlingTestProvider.getTests(EngineErrorHandlingTestProvider.class); + } + + // + // Loop over errors to throw, make sure they are the errors we get back from the engine, regardless of NT type + // + @Test(dataProvider = "EngineErrorHandlingTestProvider") + public void testEngineErrorHandlingTestProvider(EngineErrorHandlingTestProvider cfg) { + final String root = "-T ErrorThrowing -R " + b37KGReference; + final String args = root + (cfg.multiThreaded ? " -nt 2" : "") + " -E " + cfg.expectedException.getSimpleName(); + WalkerTestSpec spec = new WalkerTestSpec(args, 0, cfg.expectedException); + executeTest(cfg.toString(), spec); + } } \ No newline at end of file