<commit_before>/**
 * Copyright (c) 2009 Digital Primates IT Consulting Group
 * 
 * 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.
 * 
 * @author     <NAME> <<EMAIL>>
 * @version    
 **/ 
package org.flexunit.internals.runners {
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	import flex.lang.reflect.Klass;
	import flex.lang.reflect.Method;
	
	import flexunit.framework.Test;
	import flexunit.framework.TestCase;
	import flexunit.framework.TestListener;
	import flexunit.framework.TestResult;
	import flexunit.framework.TestSuite;
	
	import org.flexunit.runner.Description;
	import org.flexunit.runner.IDescribable;
	import org.flexunit.runner.IDescription;
	import org.flexunit.runner.IRunner;
	import org.flexunit.runner.manipulation.Filter;
	import org.flexunit.runner.manipulation.IFilterable;
	import org.flexunit.runner.notification.IRunNotifier;
	import org.flexunit.runners.model.FrameworkMethod;
	import org.flexunit.token.AsyncTestToken;
	import org.flexunit.token.ChildResult;
	import org.flexunit.utils.ClassNameUtil;
	
	public class FlexUnit1ClassRunner implements IRunner, IFilterable {

		private var test:Test;
		private var klassOrTest:*;
		private var totalTestCount:int = 0;
		private var numTestsRun:int = 0;
		private var filterRef:Filter = null;
		private var testCompletedToken : AsyncTestToken;

		public function FlexUnit1ClassRunner( klassOrTest:* ) {
			super();

			this.klassOrTest = klassOrTest;

			if ( klassOrTest is Test ) {
				this.test = klassOrTest;
			} else {
				//in this case, we need to make a suite
				this.test = createTestSuiteWithFilter( filterRef );
			}
		}

		protected function describeChild( child:* ):IDescription {
			var method:FrameworkMethod = FrameworkMethod( child );
			return Description.createTestDescription( klassOrTest, method.name, method.metadata?method.metadata[ 0 ]:null );
		}
		
		private function shouldRun( item:* ):Boolean {
			return filterRef == null || filterRef.shouldRun( describeChild( item ) );
		}
		
		private function getMethodListFromFilter( klassInfo:Klass, filter:Filter ):Array {
			var list:Array = [];

			for ( var i:int=0; i<klassInfo.methods.length; i++ ) {
				var method:Method = klassInfo.methods[ i ] as Method;
				var frameworkMethod:FrameworkMethod = new FrameworkMethod( method );

				if ( shouldRun( frameworkMethod ) ) {
					list.push( method.name );
				}  
			}

			return list;
		}
		
		private function createTestSuiteWithFilter( filter:Filter = null ):Test {
			if ( !filter ) {
				return new TestSuite( klassOrTest );
			} else {
				var suite:TestSuite = new TestSuite();
				var klassInfo:Klass = new Klass( klassOrTest );
				var methodList:Array = getMethodListFromFilter( klassInfo, filter );

				for ( var i:int=0; i<methodList.length; i++ ) {
					var numConstructorArgs:int = klassInfo.constructor.parameterTypes.length;
					var test:Test;
					
					if ( numConstructorArgs == 0 ) {
						test = klassInfo.constructor.newInstance() as Test;
						if ( test is TestCase ) {
							//If this is a testCase && it does not take a constructor argument
							//then we try to pass it into methodName
							TestCase( test ).methodName = methodList[ i ];
						}
					} else if ( numConstructorArgs == 1 ) {
						test = klassInfo.constructor.newInstance( methodList[ i ] ) as Test;
					} else {
						throw new InitializationError( "Asking to instatiate TestClass with unknown number of arguments" );
					}

					suite.addTest( test );
				}
				return suite;
			}
		}

		public static function getClassFromTest( test:Test ):Class {
			var name:String = getQualifiedClassName( test );
			return getDefinitionByName( name ) as Class;		
		}

		public function run( notifier:IRunNotifier, previousToken:AsyncTestToken ):void {
			var token:AsyncTestToken = new AsyncTestToken( ClassNameUtil.getLoggerFriendlyClassName( this ) );
			token.parentToken = previousToken;
			token.addNotificationMethod( handleTestComplete );
			
			var result:TestResult = new TestResult();
			result.addListener( createAdaptingListener( notifier, token ));

			totalTestCount = test.countTestCases();

			try {
				test.runWithResult(result);
			} catch (e:Error ) {
				trace("error");
			}
		}
		
		protected function handleTestComplete( result:ChildResult ):void {
			//trace( numTestsRun + ' ' + totalTestCount );
			if ( ++numTestsRun == totalTestCount ) {
				testCompletedToken = result.token;
				
				// FlexUnit 0.9 has a timer set up in TestSuiteTestListener executed 
				// 5ms after each test execution to clean up the static property listenerStack.
				// We have to add this 5ms delay here as well otherwise the parentToken would be executed
				// before the TestSuiteTestListener timer and would mess things up.
				var timer : Timer = new Timer ( 5, 1 );
				timer.addEventListener( TimerEvent.TIMER,handleAllTestsComplete,false, 0, false );
				timer.start();
			}
		}
		
		private function handleAllTestsComplete( event : TimerEvent ) : void
		{
			(event.target as Timer).removeEventListener( TimerEvent.TIMER, handleAllTestsComplete );
			testCompletedToken.parentToken.sendResult();
		}

		public static function createAdaptingListener( notifier:IRunNotifier, token:AsyncTestToken ):TestListener {
			return new OldTestClassAdaptingListener(notifier, token );
		}
		
		private var cachedDescription:IDescription;
		public function get description():IDescription {
			if ( !cachedDescription ) {
				cachedDescription = makeDescription( test );
			}<commit_msg>fixed issue FB-22242<commit_after>/**
 * Copyright (c) 2009 Digital Primates IT Consulting Group
 * 
 * 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.
 * 
 * @author     <NAME> <<EMAIL>>
 * @version    
 **/ 
package org.flexunit.internals.runners {
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	import flex.lang.reflect.Klass;
	import flex.lang.reflect.Method;
	
	import flexunit.framework.Test;
	import flexunit.framework.TestCase;
	import flexunit.framework.TestListener;
	import flexunit.framework.TestResult;
	import flexunit.framework.TestSuite;
	
	import org.flexunit.runner.Description;
	import org.flexunit.runner.IDescribable;
	import org.flexunit.runner.IDescription;
	import org.flexunit.runner.IRunner;
	import org.flexunit.runner.manipulation.Filter;
	import org.flexunit.runner.manipulation.IFilterable;
	import org.flexunit.runner.notification.IRunNotifier;
	import org.flexunit.runners.model.FrameworkMethod;
	import org.flexunit.token.AsyncTestToken;
	import org.flexunit.token.ChildResult;
	import org.flexunit.utils.ClassNameUtil;
	
	public class FlexUnit1ClassRunner implements IRunner, IFilterable {

		private var test:Test;
		private var klassOrTest:*;
		private var totalTestCount:int = 0;
		private var numTestsRun:int = 0;
		private var filterRef:Filter = null;
		private var testCompletedToken : AsyncTestToken;

		public function FlexUnit1ClassRunner( klassOrTest:* ) {
			super();

			this.klassOrTest = klassOrTest;

			if ( klassOrTest is Test ) {
				this.test = klassOrTest;
			} else {
				//in this case, we need to make a suite
				this.test = createTestSuiteWithFilter( filterRef );
			}
		}

		protected function describeChild( child:* ):IDescription {
			var method:FrameworkMethod = FrameworkMethod( child );
			return Description.createTestDescription( klassOrTest, method.name, method.metadata?method.metadata[ 0 ]:null );
		}
		
		private function shouldRun( item:* ):Boolean {
			return filterRef == null || filterRef.shouldRun( describeChild( item ) );
		}
		
		private function getMethodListFromFilter( klassInfo:Klass, filter:Filter ):Array {
			var list:Array = [];

			for ( var i:int=0; i<klassInfo.methods.length; i++ ) {
				var method:Method = klassInfo.methods[ i ] as Method;
				var frameworkMethod:FrameworkMethod = new FrameworkMethod( method );

				if ( shouldRun( frameworkMethod ) ) {
					list.push( method.name );
				}  
			}

			return list;
		}
		
		private function createTestSuiteWithFilter( filter:Filter = null ):Test {
			if ( !filter ) {
				return new TestSuite( klassOrTest );
			} else {
				var suite:TestSuite = new TestSuite();
				var klassInfo:Klass = new Klass( klassOrTest );
				var methodList:Array = getMethodListFromFilter( klassInfo, filter );

				for ( var i:int=0; i<methodList.length; i++ ) {
					var numConstructorArgs:int = klassInfo.constructor.parameterTypes.length;
					var test:Test;
					
					if ( numConstructorArgs == 0 ) {
						test = klassInfo.constructor.newInstance() as Test;
						if ( test is TestCase ) {
							//If this is a testCase && it does not take a constructor argument
							//then we try to pass it into methodName
							TestCase( test ).methodName = methodList[ i ];
						}
					} else if ( numConstructorArgs == 1 ) {
						test = klassInfo.constructor.newInstance( methodList[ i ] ) as Test;
					} else {
						throw new InitializationError( "Asking to instatiate TestClass with unknown number of arguments" );
					}

					suite.addTest( test );
				}
				return suite;
			}
		}

		public static function getClassFromTest( test:Test ):Class {
			var name:String = getQualifiedClassName( test );
			return getDefinitionByName( name ) as Class;		
		}

		public function run( notifier:IRunNotifier, previousToken:AsyncTestToken ):void {
			var token:AsyncTestToken = new AsyncTestToken( ClassNameUtil.getLoggerFriendlyClassName( this ) );
			token.parentToken = previousToken;
			token.addNotificationMethod( handleTestComplete );
			
			var result:TestResult = new TestResult();
			result.addListener( createAdaptingListener( notifier, token ));

			totalTestCount = test.countTestCases();

			try {
				test.runWithResult(result);
			} catch (e:Error ) {
				trace("error");
			}
		}
		
		protected function handleTestComplete( result:ChildResult ):void {
			//trace( numTestsRun + ' ' + totalTestCount );
			if ( ++numTestsRun == totalTestCount ) {
				testCompletedToken = result.token;
				
				// FlexUnit 0.9 has a timer set up in TestSuiteTestListener executed 
				// 5ms after each test execution to clean up the static property listenerStack.
				// We have to add this 100ms delay here as well otherwise the parentToken would be executed
				// before the TestSuiteTestListener timer and would mess things up.
				// We are delaying 100ms and not less since this might be ~2 frames. Since this timer is
				// created before than the timer in TestSuiteTestListener, due to Flash Player behaviour,
				// if the timers are executed in the same frame and even thouh the time of the second one is 
				// smaller the first added timer will be executed first
				var timer : Timer = new Timer ( 100, 1 );
				timer.addEventListener( TimerEvent.TIMER,handleAllTestsComplete,false, 0, false );
				timer.start();
			}
		}
		
		private function handleAllTestsComplete( event : TimerEvent ) : void
		{
			(event.target as Timer).removeEventListener( TimerEvent.TIMER, handleAllTestsComplete );
			testCompletedToken.parentToken.sendResult();
		}

		public static function createAdaptingListener( notifier:IRunNotifier, token:AsyncTestToken ):TestListener {
			return new OldTestClassAdaptingListener(notifier, token );
		}
		
		private var cachedDescription:IDescription;
		public function get description():IDescription {
			if ( !cachedDescription ) {
				cachedDescription = makeDescription( test );
			}
{'fraction_non_alphanumeric': 0.08672943945858468, 'fraction_numerical': 0.00389877887303222, 'mean_word_length': 3.8260560880369185, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1373513', 'n_tokens_mistral': 4428, 'n_tokens_neox': 3748, 'n_words': 1231}