FlexUnit4/src/org/flexunit/internals/runners/statements/StatementSequencer.as (159 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.flexunit.internals.runners.statements { import flash.utils.*; import org.flexunit.internals.runners.model.MultipleFailureException; import org.flexunit.runner.notification.StoppedByUserException; import org.flexunit.token.AsyncTestToken; import org.flexunit.token.ChildResult; import org.flexunit.utils.ClassNameUtil; /** * The <code>StatementSequencer</code> is a class that is responsible for the execution of * <code>IAsyncStatement</code>s. These statements can be provided to the <code>StatementSequencer</code> * as an array during instantiation or added using the <code>#addStep</code> method.<br/> * * The list of statements can be executed using the <code>#evaluate</code> method and any errors encountered * during execution will be noted and reported. Each statement will be run in sequence, meaning the next will not * start to be executed until the current statement has finished. */ public class StatementSequencer extends AsyncStatementBase implements IAsyncStatement { /** * An array of queued statements to run. */ protected var queue:Array; /** * An array of errors that have been encountered during the execution of statements. */ protected var errors:Array; /** * Constructor. * * @param queue An array containing objects that implement <code>IAsyncStatment</code> that are to be * evaluated by the sequencer. */ public function StatementSequencer( queue:Array=null ) { super(); if (!queue) { queue = new Array(); } //Copy the queue this.queue = queue.slice(); this.errors = new Array(); //Create a new token that will alert this class when the provided statement has completed myToken = new AsyncTestToken( ClassNameUtil.getLoggerFriendlyClassName( this ) ); myToken.addNotificationMethod( handleChildExecuteComplete ); } /** * Adds a <code>child</code> that implements <code>IAsyncStatement</code> to the end of the queue of * statments to execute by the sequencer. * * @param child The object that implements <code>IAsyncStatement</code> to add. */ public function addStep( child:IAsyncStatement ):void { if ( child ) { queue.push( child ); } } /** * Evaluates the provided <code>child</code> if the <code>child</code> is an * <code>IAsyncStatement</code>. * * @param child The child object to be evaluated. */ protected function executeStep( child:* ):void { if ( child is IAsyncStatement ) { IAsyncStatement( child ).evaluate( myToken ); } } /** * Starts evaluating the queue of statements that was provided to the sequencer. * * @param parentToken The token to be notified when all statements have finished running. */ public function evaluate( parentToken:AsyncTestToken ):void { this.parentToken = parentToken; handleChildExecuteComplete( null ); } /** * Determine if any errors were encountered for a potential statement that has just run and returned the * provided <code>result</code>. If an error was encountered during the last statement, add that error to * a list of errors encountered in every statement in the sequencer.<br/> * * If there are still statements that need to be evaluated, execute the first unexecuted step in the sequence. * Otherwise, if all statements have finished running, the <code>StatementSequencer</code> has finished and will * report any errors that have been encoutnred. * * @param result A potential <code>ChildResult</code> that was encountered during the execution of the * previous statement. */ public function handleChildExecuteComplete( result:ChildResult ):void { var step:*; if ( result && result.error ) { errors.push( result.error ); if ( result.error is StoppedByUserException ) { sendComplete(); return; } } if ( queue.length > 0 ) { step = queue.shift(); //trace("Sequence Executing Next Step " + step ); executeStep( step ); //trace("Sequence Done Executing Step " + step ); } else { //trace("Sequence Sending Complete " + this ); sendComplete(); } } /** * If an <code>error</code> is provided, it will be added to the list of errors encountered during the execution * of the statements. If the error list contains more than one error, a <code>MultipleFailureException</code> * will be created an given the corresponding errors. The parentToken will then be notified of any error * encountered during execution of the statements. * * @inheritDoc */ override protected function sendComplete( error:Error=null ):void { var sendError:Error; //Determine if any errors were passed to this method if ( error ) { errors.push( error ); } //Determine whether to send a single error or MultipleFailureException containing the array of errors if (errors.length == 1) sendError = errors[ 0 ]; else if ( errors.length > 1 ) { sendError = new MultipleFailureException(errors); } super.sendComplete( sendError ); } /** * Returns the current queue of statements that are in the sequence. * * @return a string representing the sequence queue. */ override public function toString():String { var sequenceString:String = "StatementSequencer :\n"; if ( queue ) { for ( var i:int=0; i<queue.length; i++ ) { sequenceString += ( " " + i + " : " + queue[ i ].toString() + "\n" ); } } return sequenceString; } } }