1  /**
     2   * Copyright the original author or authors.
     3   * 
     4   * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (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.mozilla.org/MPL/MPL-1.1.html
     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   
    17  import org.as2lib.data.holder.array.TypedArray;
    18  import org.as2lib.app.exec.BatchProcess;
    19  import org.as2lib.test.unit.Test;
    20  import org.as2lib.test.unit.TestResult;
    21  import org.as2lib.test.unit.TestRunner;
    22  import org.as2lib.env.except.IllegalArgumentException;
    23  import org.as2lib.test.unit.TestSuiteResult;
    24  import org.as2lib.app.exec.Process;
    25  import org.as2lib.test.unit.TestCaseResult;
    26  import org.as2lib.test.unit.TestCaseMethodInfo;
    27  
    28  /**
    29   * {@code TestSuite} is a composite implementation of {@link Test}.
    30   * 
    31   * <p>A {@code TestSuite} is a collection of {@code Test}s. A {@code TestSuite} 
    32   * does not contain any executable code but it may contain different {@code Test}s
    33   * that can be added with {@link #addTest}.
    34   * 
    35   * <p>In contrast to {@code TestCase} the {@code TestSuite} has no external
    36   * {@code TestRunner}. {@code TestSuite} is its own implementation of
    37   * {@code TestRunner}.
    38   * 
    39   * @author Martin Heidegger
    40   * @version 2.0
    41   * @see org.as2lib.test.unit.TestSuiteFactory
    42   */
    43  class org.as2lib.test.unit.TestSuite extends BatchProcess implements Test, TestRunner {
    44  
    45  	/** 
    46  	 * Blocks the collection of 
    47  	 * {@code org.as2lib.test.unit.TestSuiteFactory#collectAllTestCases}.
    48  	 * 
    49  	 * @return {@code true} to block the collection
    50  	 */
    51  	public static function blockCollecting(Void):Boolean {
    52  		return true;
    53  	}
    54  	
    55  	/** All test contained within the TestSuite. */
    56  	private var tests:TypedArray;
    57  	
    58  	/** Name of the TestSuite. */
    59  	private var name:String;
    60  	
    61  	/** Result for the execution of the TestSuite. */
    62  	private var testResult:TestSuiteResult;
    63  
    64  	/**
    65  	 * Constructs a new {@code TestSuite}.
    66  	 * 
    67  	 * @param name name of the {@code TestSuite}
    68  	 */
    69  	public function TestSuite(name:String) {
    70  		this.tests = new TypedArray(TestRunner);
    71  		testResult = new TestSuiteResult(this);
    72  		this.name = name;
    73  	}
    74  	
    75  	/**
    76  	 * Helper to validate if the added {@code Test} contains the current testsuite.
    77  	 * 
    78  	 * <p>Since its possible to add any {@code Test} to this suite it could be
    79  	 * possible to add this {@code TestSuite} instance. That would result in a 
    80  	 * endless recursion.
    81  	 * 
    82  	 * @param test test to be validated
    83  	 * @throws IllegalArgumentException if the passed-in {@code Test} contains this
    84  	 *         instance as child.
    85  	 */
    86  	private function checkRecursion(test:TestResult) {
    87  		if (test === testResult) {
    88  			throw new IllegalArgumentException(
    89  				"The test "+test+" contains or is the current test",
    90  				this, arguments);
    91  		}
    92  		var content:Array = test.getTestResults();
    93  		for (var i=0; i<content.length; i++) {
    94  			if (content[i] != test) {
    95  				checkRecursion(content[i]);
    96  			}
    97  		}
    98  	}
    99  	
   100  	/**
   101  	 * Adds a process to the {@code TestSuite}.
   102  	 * 
   103  	 * <p>{@code TestSuite} does only allow {@code TestRunner} as sub processes.
   104  	 * 
   105  	 * <p>Overrides the implementation in {@link BatchProcess#addProcess}.
   106  	 * 
   107  	 * @param p {@code Process} to be added to the {@code TestSuite}
   108  	 * @throws IllegalArgumentException if the passed-in {@code p} contains this
   109  	 *         instance as child.
   110  	 */
   111  	public function addProcess(p:Process):Void {
   112  		var eP:TestRunner = TestRunner(p);
   113  		if (eP) {
   114  			checkRecursion(eP.getTestResult());
   115  			testResult.addTest(eP.getTestResult());
   116  			tests.push(p);
   117  			super.addProcess(p);
   118  		} else {
   119  			throw new IllegalArgumentException("Only Tests are allowed for processing", this, arguments);
   120  		}
   121  	}
   122  	
   123  	/**
   124  	 * Adds a {@code Test} to the {@code TestSuite}.
   125  	 * 
   126  	 * @param test {@code Test} to be added
   127  	 * @throws IllegalArgumentException if the passed-in {@code Test} contains this
   128  	 *         instance as child.
   129  	 */
   130  	public function addTest(test:Test):Void {
   131  		addProcess(test.getTestRunner());
   132  	}
   133  	
   134  	/**
   135  	 * Returns the name of the {@code TestSuite}.
   136  	 * 
   137  	 * @return name of the {@code TestSuite}.
   138  	 */
   139  	public function getName(Void):String {
   140  		if(!name) {
   141  			return "";	
   142  		}
   143  		return name;
   144  	}
   145  	
   146  	/**
   147  	 * Runs the {@code TestSuite}.
   148  	 * 
   149  	 * @return {@code TestRunner} that run this test
   150  	 */
   151  	public function run(Void):TestRunner {
   152  		start();
   153  		return this;
   154  	}
   155  	
   156  	/**
   157  	 * Returns the {@code TestRunner} that executes this {@code TestSuite}.
   158  	 * 
   159  	 * @return {@code TestRunner} that executes this {@code TestSuite}
   160  	 */
   161  	public function getTestRunner(Void):TestRunner {
   162  		return this;
   163  	}
   164  	
   165  	/**
   166  	 * Returns all {@code Tests} contained within this {@code TestSuite}.
   167  	 * 
   168  	 * @return {@link TypedArray} that contains all {@code Test}s of this {@code TestSuite}.
   169  	 */
   170  	public function getTests(Void):TypedArray {
   171  		return this.tests;
   172  	}
   173  	
   174  	/**
   175  	 * Event handling for a error during a proces.
   176  	 * 
   177  	 * @param process {@code Process} that throws the error
   178  	 * @return {@code false} to stop further execution
   179  	 */
   180  	public function onProcessError(process:Process, error):Boolean {
   181  		return false;
   182  	}
   183  
   184  	/** 
   185  	 * Returns the {@code TestResult} to the {@code TestSuite}.
   186  	 * 
   187  	 * <p>The returned {@code TestResult} may not be complete. This is the case
   188  	 * if the test has not been executed or has not finished yet.
   189  	 * 
   190  	 * @return {@link TestResult} for the {@code TestSuite} that contains all informations
   191  	 */
   192  	public function getTestResult(Void):TestResult {
   193  		return testResult;
   194  	}
   195  	
   196  	/**
   197  	 * Returns the current executing {@code TestCaseResult}.
   198  	 * 
   199  	 * <p>It is necessary to get the {@code TestCaseResult} for the {@code TestCase}
   200  	 * that just gets executed because there can be more than one {@code TestCase}
   201  	 * available within a {@code TestResult}. 
   202  	 * 
   203  	 * @return {@code TestResult} to the current executing {@code TestCase}
   204  	 */
   205  	public function getCurrentTestCase(Void):TestCaseResult {
   206  		return list[current].getCurrentTestCase();
   207  	}
   208  	
   209  	/**
   210  	 * Returns the current executing {@code TestCaseMethodInfo}.
   211  	 * 
   212  	 * <p>It is necessary to get the {@code TestCaseMethodInfo} for the method
   213  	 * that just gets executed because there can be more than one methods available
   214  	 * within a {@code TestCaseResult}.
   215  	 * 
   216  	 * @return informations about the current executing method
   217  	 * @see #getCurrentTestCase
   218  	 */
   219  	public function getCurrentTestCaseMethodInfo(Void):TestCaseMethodInfo {
   220  		return list[current].getCurrentTestCaseMethodInfo();
   221  	}
   222  }