1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package vogar.target.junit; 18 19import java.util.concurrent.atomic.AtomicReference; 20import org.junit.runner.JUnitCore; 21import org.junit.runner.Runner; 22import org.junit.runner.manipulation.NoTestsRemainException; 23import org.junit.runner.manipulation.Sorter; 24import org.junit.runners.model.RunnerBuilder; 25import vogar.monitor.TargetMonitor; 26import vogar.target.SkipPastFilter; 27import vogar.target.TargetMonitorRunListener; 28import vogar.target.TargetRunner; 29import vogar.target.TestEnvironment; 30import vogar.target.TestEnvironmentRunListener; 31 32/** 33 * Adapts a JUnit3 test for use by vogar. 34 */ 35public final class JUnitTargetRunner implements TargetRunner { 36 37 private static final Sorter DESCRIPTION_SORTER = 38 new Sorter(DescriptionComparator.getInstance()); 39 40 private final TargetMonitor monitor; 41 private final AtomicReference<String> skipPastReference; 42 43 private final TestEnvironment testEnvironment; 44 private final Class<?> testClass; 45 private final RunnerParams runnerParams; 46 47 public JUnitTargetRunner(TargetMonitor monitor, AtomicReference<String> skipPastReference, 48 TestEnvironment testEnvironment, 49 int timeoutSeconds, Class<?> testClass, 50 String qualification, String[] args) { 51 this.monitor = monitor; 52 this.skipPastReference = skipPastReference; 53 this.testEnvironment = testEnvironment; 54 this.testClass = testClass; 55 56 TimeoutAndAbortRunRule timeoutRule = new TimeoutAndAbortRunRule(timeoutSeconds); 57 runnerParams = new RunnerParams(qualification, args, timeoutRule); 58 } 59 60 public boolean run() { 61 // Use JUnit infrastructure to run the tests. 62 RunnerBuilder builder = new VogarRunnerBuilder(runnerParams); 63 Runner runner = builder.safeRunnerForClass(testClass); 64 if (runner == null) { 65 throw new IllegalStateException("Cannot create runner for: " + testClass.getName()); 66 } 67 68 // Sort to ensure consistent ordering, that is done before applying any filters as the 69 // SkipPastFilter requires a consistent ordering across runs in order to work properly. 70 DESCRIPTION_SORTER.apply(runner); 71 72 String skipPast = skipPastReference.get(); 73 if (skipPast != null) { 74 try { 75 new SkipPastFilter(skipPastReference).apply(runner); 76 } catch (NoTestsRemainException ignored) { 77 return true; 78 } 79 } 80 81 try { 82 JUnitCore core = new JUnitCore(); 83 // The TestEnvironmentRunListener resets static state between tests. 84 core.addListener(new TestEnvironmentRunListener(testEnvironment)); 85 // The TargetMonitorRunListener sends the result of the tests back to the main Vogar 86 // process. 87 core.addListener(new TargetMonitorRunListener(monitor)); 88 core.run(runner); 89 } catch (VmIsUnstableException e) { 90 // If a test reports that the VM is unstable then inform the caller so that the 91 // current process can be exited abnormally which will trigger the vogar main process 92 // to rerun the tests from after the timing out test. 93 return false; 94 } 95 96 return true; 97 } 98} 99