PageRenderTime 42ms CodeModel.GetById 17ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/src/NUnit/core/SimpleTestRunner.cs

#
C# | 235 lines | 139 code | 40 blank | 56 comment | 13 complexity | a89d5c5f41f93e1d823469abc3242eae MD5 | raw file
  1// ****************************************************************
  2// Copyright 2007, Charlie Poole
  3// This is free software licensed under the NUnit license. You may
  4// obtain a copy of the license at http://nunit.org.
  5// ****************************************************************
  6using System;
  7using System.IO;
  8using System.Threading;
  9using System.Collections;
 10using System.Collections.Specialized;
 11using NUnit.Core.Filters;
 12using System.Reflection;
 13
 14namespace NUnit.Core
 15{
 16	/// <summary>
 17	/// SimpleTestRunner is the simplest direct-running TestRunner. It
 18	/// passes the event listener interface that is provided on to the tests
 19	/// to use directly and does nothing to redirect text output. Both
 20	/// Run and BeginRun are actually synchronous, although the client
 21	/// can usually ignore this. BeginRun + EndRun operates as expected.
 22	/// </summary>
 23	public class SimpleTestRunner : MarshalByRefObject, TestRunner
 24	{
 25        static Logger log = InternalTrace.GetLogger(typeof(SimpleTestRunner));
 26
 27		#region Instance Variables
 28
 29		/// <summary>
 30		/// Identifier for this runner. Must be unique among all
 31		/// active runners in order to locate tests. Default
 32		/// value of 0 is adequate in applications with a single
 33		/// runner or a non-branching chain of runners.
 34		/// </summary>
 35		private int runnerID = 0;
 36
 37		/// <summary>
 38		/// The loaded test suite
 39		/// </summary>
 40		private Test test;
 41
 42		/// <summary>
 43		/// The builder we use to load tests, created for each load
 44		/// </summary>
 45		private TestSuiteBuilder builder;
 46
 47		/// <summary>
 48		/// Results from the last test run
 49		/// </summary>
 50		private TestResult testResult;
 51
 52		/// <summary>
 53		/// The thread on which Run was called. Set to the
 54		/// current thread while a run is in process.
 55		/// </summary>
 56		private Thread runThread;
 57
 58		#endregion
 59
 60		#region Constructor
 61		public SimpleTestRunner() : this( 0 ) { }
 62
 63		public SimpleTestRunner( int runnerID )
 64		{
 65			this.runnerID = runnerID;
 66		}
 67		#endregion
 68
 69		#region Properties
 70		public virtual int ID
 71		{
 72			get { return runnerID; }
 73		}
 74
 75		public IList AssemblyInfo
 76		{
 77			get { return builder.AssemblyInfo; }
 78		}
 79		
 80		public ITest Test
 81		{
 82			get { return test == null ? null : new TestNode( test ); }
 83		}
 84
 85		/// <summary>
 86		/// Results from the last test run
 87		/// </summary>
 88		public TestResult TestResult
 89		{
 90			get { return testResult; }
 91		}
 92
 93		public virtual bool Running
 94		{
 95			get { return runThread != null && runThread.IsAlive; }
 96		}
 97		#endregion
 98
 99		#region Methods for Loading Tests
100		/// <summary>
101		/// Load a TestPackage
102		/// </summary>
103		/// <param name="package">The package to be loaded</param>
104		/// <returns>True on success, false on failure</returns>
105		public bool Load( TestPackage package )
106		{
107            log.Debug("Loading package " + package.Name);
108
109			this.builder = new TestSuiteBuilder();
110
111			this.test = builder.Build( package );
112			if ( test == null ) return false;
113
114			test.SetRunnerID( this.runnerID, true );
115			return true;
116		}
117
118		/// <summary>
119		/// Unload all tests previously loaded
120		/// </summary>
121		public void Unload()
122		{
123            log.Debug("Unloading");
124			this.test = null; // All for now
125		}
126		#endregion
127
128		#region CountTestCases
129		public int CountTestCases( ITestFilter filter )
130		{
131			return test.CountTestCases( filter );
132		}
133		#endregion
134
135		#region Methods for Running Tests
136		public virtual TestResult Run( EventListener listener )
137		{
138			return Run( listener, TestFilter.Empty );
139		}
140
141		public virtual TestResult Run( EventListener listener, ITestFilter filter )
142		{
143			try
144			{
145                log.Debug("Starting test run");
146
147				// Take note of the fact that we are running
148				this.runThread = Thread.CurrentThread;
149
150				listener.RunStarted( this.Test.TestName.FullName, test.CountTestCases( filter ) );
151				
152				testResult = test.Run( listener, filter );
153
154				// Signal that we are done
155				listener.RunFinished( testResult );
156                log.Debug("Test run complete");
157
158				// Return result array
159				return testResult;
160			}
161			catch( Exception exception )
162			{
163				// Signal that we finished with an exception
164				listener.RunFinished( exception );
165				// Rethrow - should we do this?
166				throw;
167			}
168			finally
169			{
170				runThread = null;
171			}
172		}
173
174		public void BeginRun( EventListener listener )
175		{
176			testResult = this.Run( listener );
177		}
178
179		public void BeginRun( EventListener listener, ITestFilter filter )
180		{
181			testResult = this.Run( listener, filter );
182		}
183
184		public virtual TestResult EndRun()
185		{
186			return TestResult;
187		}
188
189		/// <summary>
190		/// Wait is a NOP for SimpleTestRunner
191		/// </summary>
192		public virtual void Wait()
193		{
194		}
195
196		public virtual void CancelRun()
197		{
198			if (this.runThread != null)
199			{
200				// Cancel Synchronous run only if on another thread
201				if ( runThread == Thread.CurrentThread )
202					throw new InvalidOperationException( "May not CancelRun on same thread that is running the test" );
203
204				// Make a copy of runThread, which will be set to 
205				// null when the thread terminates.
206				Thread cancelThread = this.runThread;
207
208				// Tell the thread to abort
209				this.runThread.Abort();
210				
211				// Wake up the thread if necessary
212				// Figure out if we need to do an interupt
213				if ( (cancelThread.ThreadState & ThreadState.WaitSleepJoin ) != 0 )
214					cancelThread.Interrupt();
215			}
216		}
217		#endregion
218
219        #region InitializeLifetimeService Override
220        public override object InitializeLifetimeService()
221        {
222            return null;
223        }
224	#endregion
225
226        #region IDisposable Members
227
228        public void Dispose()
229        {
230            Unload();
231        }
232
233        #endregion
234    }
235}