1/* 2 * Copyright 2001-2008 Artima, Inc. 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 */ 16package org.scalatest 17 18import org.scalatest.Suite.checkForPublicNoArgConstructor 19 20import org.scalatest.events._ 21import Suite.formatterForSuiteStarting 22import Suite.formatterForSuiteCompleted 23import Suite.formatterForSuiteAborted 24 25/** 26 * A Rerunner for Suites. 27 * 28 * @author Bill Venners 29 */ 30private[scalatest] class SuiteRerunner(suiteClassName: String) extends Rerunner { 31 32 if (suiteClassName == null) 33 throw new NullPointerException 34 35 def apply(report: Reporter, stopRequested: Stopper, filter: Filter, 36 configMap: Map[String, Any], distributor: Option[Distributor], tracker: Tracker, loader: ClassLoader) { 37 38 val tagsToInclude = 39 filter.tagsToInclude match { 40 case None => Set[String]() 41 case Some(tti) => tti 42 } 43 val tagsToExclude = filter.tagsToExclude 44 45 val runStartTime = System.currentTimeMillis 46 47 try { 48 val suiteClass = loader.loadClass(suiteClassName) 49 val suite = suiteClass.newInstance().asInstanceOf[Suite] 50 val expectedTestCount = suite.expectedTestCount(filter) 51 52 // Create a Rerunner if the Suite has a public no-arg constructor 53 val rerunnable = 54 if (Suite.checkForPublicNoArgConstructor(suite.getClass)) 55 Some(new SuiteRerunner(suite.getClass.getName)) 56 else 57 None 58 59 report(RunStarting(tracker.nextOrdinal(), expectedTestCount, configMap)) 60 61 val suiteStartTime = System.currentTimeMillis 62 try { 63 64 val rawString = Resources("suiteExecutionStarting") 65 val formatter = formatterForSuiteStarting(suite) 66 67 report(SuiteStarting(tracker.nextOrdinal(), suite.suiteName, Some(suite.getClass.getName), formatter, rerunnable)) 68 69 suite.run(None, report, stopRequested, filter, configMap, distributor, tracker) 70 71 val rawString2 = Resources("suiteCompletedNormally") 72 val formatter2 = formatterForSuiteCompleted(suite) 73 val duration = System.currentTimeMillis - suiteStartTime 74 75 report(SuiteCompleted(tracker.nextOrdinal(), suite.suiteName, Some(suite.getClass.getName), Some(duration), formatter2, rerunnable)) 76 } 77 catch { 78 case e: RuntimeException => { 79 val rawString3 = Resources("executeException") 80 val formatter3 = formatterForSuiteAborted(suite, rawString3) 81 82 val duration = System.currentTimeMillis - suiteStartTime 83 report(SuiteAborted(tracker.nextOrdinal(), rawString3, suite.suiteName, Some(suite.getClass.getName), Some(e), Some(duration), formatter3, rerunnable)) 84 } 85 } 86 87 val duration = System.currentTimeMillis - runStartTime 88 if (stopRequested()) { 89 report(RunStopped(tracker.nextOrdinal(), Some(duration))) 90 } 91 else { 92 report(RunCompleted(tracker.nextOrdinal(), Some(duration))) 93 } 94 } 95 catch { 96 case e: ClassNotFoundException => { 97 val duration = System.currentTimeMillis - runStartTime 98 report(RunAborted(tracker.nextOrdinal(), Resources("cannotLoadSuite", e.getMessage), Some(e), Some(duration))) 99 } 100 case e: InstantiationException => { 101 val duration = System.currentTimeMillis - runStartTime 102 report(RunAborted(tracker.nextOrdinal(), Resources("cannotInstantiateSuite", e.getMessage), Some(e), Some(duration))) 103 } 104 case e: IllegalAccessException => { 105 val duration = System.currentTimeMillis - runStartTime 106 report(RunAborted(tracker.nextOrdinal(), Resources("cannotInstantiateSuite", e.getMessage), Some(e), Some(duration))) 107 } 108 case e: SecurityException => { 109 val duration = System.currentTimeMillis - runStartTime 110 report(RunAborted(tracker.nextOrdinal(), Resources("securityWhenRerruning", e.getMessage), Some(e), Some(duration))) 111 } 112 case e: NoClassDefFoundError => { 113 // Suggest the problem might be a bad runpath 114 // Maybe even print out the current runpath 115 val duration = System.currentTimeMillis - runStartTime 116 report(RunAborted(tracker.nextOrdinal(), Resources("cannotLoadClass", e.getMessage), Some(e), Some(duration))) 117 } 118 case e: Throwable => { 119 val duration = System.currentTimeMillis - runStartTime 120 report(RunAborted(tracker.nextOrdinal(), Resources.bigProblems(e), Some(e), Some(duration))) 121 } 122 } 123 } 124} 125