31
31
using System.Reflection;
33
33
using System.Collections;
34
using System.Collections.Generic;
34
35
using System.Threading;
36
38
using MonoDevelop.Core;
37
39
using MonoDevelop.Core.Execution;
39
42
using NF = NUnit.Framework;
43
using NC = NUnit.Core;
41
namespace MonoDevelop.NUnit
45
namespace MonoDevelop.NUnit.External
43
[AddinDependency ("MonoDevelop.Projects")]
44
47
class ExternalTestRunner: RemoteProcessObject
47
StringWriter stdout = new StringWriter ();
48
StringWriter stderr = new StringWriter ();
50
public TestResult Run (EventListener listener, IFilter filter, string path, string suiteName)
52
TestSuite rootTS = LoadTestSuite (path, suiteName);
54
throw new Exception ("Test suite '" + suiteName + "' not found.");
56
// Force the loading of the NUnit.Framework assembly.
57
// It's needed since that dll is not located in the test dll directory.
58
typeof(NF.Assert).ToString ();
60
TextWriter origStdout = Console.Out;
61
TextWriter origStderr = Console.Error;
62
Console.SetOut (stdout);
63
Console.SetError (stderr);
65
string cdir = Environment.CurrentDirectory;
66
Environment.CurrentDirectory = Path.GetDirectoryName (path);
69
return rootTS.Run (listener, filter);
71
Environment.CurrentDirectory = cdir;
72
Console.SetOut (origStdout);
73
Console.SetError (origStderr);
77
public string ResetTestConsoleOutput ()
79
string s = stdout.ToString ();
80
stdout = new StringWriter ();
81
Console.SetOut (stdout);
85
public string ResetTestConsoleError ()
87
string s = stderr.ToString ();
88
stderr = new StringWriter ();
89
Console.SetError (stderr);
93
TestSuite LoadTestSuite (string path, string fullName)
95
ResolveEventHandler reh = new ResolveEventHandler (TryLoad);
96
AppDomain.CurrentDomain.AssemblyResolve += reh;
101
return new TestSuiteBuilder ().Build (path, fullName);
103
return new TestSuiteBuilder ().Build (path);
105
AppDomain.CurrentDomain.AssemblyResolve -= reh;
109
Assembly TryLoad (object sender, ResolveEventArgs args)
112
// NUnit2 uses Assembly.Load on the filename without extension.
113
// This is done just to allow loading from a full path name.
114
return Assembly.LoadFrom (assemblyName);
120
public TestInfo GetTestInfo (string path)
122
// Force the loading of the NUnit.Framework assembly.
123
// It's needed since that dll is not located in the test dll directory.
124
typeof(NF.Assert).ToString ();
126
TestSuite rootTS = LoadTestSuite (path, "");
127
return BuildTestInfo (rootTS);
130
TestInfo BuildTestInfo (Test test)
132
TestInfo ti = new TestInfo ();
134
int i = test.FullName.LastIndexOf ('.');
136
ti.PathName = test.FullName.Substring (0,i);
49
NUnitTestRunner runner;
51
public UnitTestResult Run (IRemoteEventListener listener, ITestFilter filter, string path, string suiteName, List<string> supportAssemblies)
53
NUnitTestRunner runner = GetRunner (path);
54
EventListenerWrapper listenerWrapper = listener != null ? new EventListenerWrapper (listener) : null;
56
TestResult res = runner.Run (listenerWrapper, filter, path, suiteName, supportAssemblies);
57
return listenerWrapper.GetLocalTestResult (res);
60
public NunitTestInfo GetTestInfo (string path, List<string> supportAssemblies)
62
NUnitTestRunner runner = GetRunner (path);
63
return runner.GetTestInfo (path, supportAssemblies);
66
NUnitTestRunner GetRunner (string assemblyPath)
68
TestPackage package = new TestPackage (assemblyPath);
69
package.Settings ["ShadowCopyFiles"] = false;
70
DomainManager dm = new DomainManager ();
71
AppDomain domain = dm.CreateDomain (package);
72
string asm = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "NUnitRunner.dll");
73
runner = (NUnitTestRunner) domain.CreateInstanceFromAndUnwrap (asm, "MonoDevelop.NUnit.External.NUnitTestRunner");
74
runner.Initialize (typeof(NF.Assert).Assembly.Location, typeof(NC.Test).Assembly.Location);
79
class EventListenerWrapper: MarshalByRefObject, EventListener
81
IRemoteEventListener wrapped;
82
StringBuilder consoleOutput;
83
StringBuilder consoleError;
85
public EventListenerWrapper (IRemoteEventListener wrapped)
87
this.wrapped = wrapped;
90
public void RunFinished (Exception exception)
94
public void RunFinished (TestResult results)
98
public void RunStarted (string name, int testCount)
102
public void SuiteFinished (TestSuiteResult result)
104
wrapped.SuiteFinished (GetTestName (result.Test.TestName), GetLocalTestResult (result));
107
public void SuiteStarted (TestName suite)
109
wrapped.SuiteStarted (GetTestName (suite));
112
public void TestFinished (TestCaseResult result)
114
wrapped.TestFinished (GetTestName (result.Test.TestName), GetLocalTestResult (result));
117
public void TestOutput (TestOutput testOutput)
119
if (consoleOutput == null)
121
else if (testOutput.Type == TestOutputType.Out)
122
consoleOutput.Append (testOutput.Text);
140
if (test.Tests != null && test.Tests.Count > 0) {
141
ti.Tests = new TestInfo [test.Tests.Count];
142
for (int n=0; n<test.Tests.Count; n++)
143
ti.Tests [n] = BuildTestInfo ((Test)test.Tests [n]);
153
public string PathName;
154
public TestInfo[] Tests;
157
class LocalTestMonitor: MarshalByRefObject, EventListener
162
ExternalTestRunner runner;
163
UnitTest runningTest;
165
Hashtable outputText = new Hashtable ();
166
Hashtable errorText = new Hashtable ();
168
internal UnitTestResult SingleTestResult;
170
public LocalTestMonitor (TestContext context, ExternalTestRunner runner, UnitTest rootTest, string rootFullName, bool singleTestRun)
172
this.runner = runner;
173
this.rootFullName = rootFullName;
174
this.rootTest = rootTest;
175
this.context = context;
176
this.singleTestRun = singleTestRun;
179
public UnitTest RunningTest {
180
get { return runningTest; }
183
void EventListener.RunStarted (Test [] tests)
187
void EventListener.RunFinished (TestResult [] results)
191
void EventListener.UnhandledException (Exception exception)
195
void EventListener.RunFinished (Exception exc)
199
void EventListener.TestStarted (TestCase testCase)
204
UnitTest t = GetLocalTest (testCase);
209
context.Monitor.BeginTest (t);
210
t.Status = TestStatus.Running;
213
void EventListener.TestFinished (TestCaseResult result)
215
outputText [result] = runner.ResetTestConsoleOutput ();
216
errorText [result] = runner.ResetTestConsoleError ();
219
SingleTestResult = GetLocalTestResult (result);
223
UnitTest t = GetLocalTest ((Test) result.Test);
227
UnitTestResult res = GetLocalTestResult (result);
231
t.RegisterResult (context, res);
232
context.Monitor.EndTest (t, res);
233
t.Status = TestStatus.Ready;
237
void EventListener.SuiteStarted (TestSuite suite)
242
UnitTest t = GetLocalTest (suite);
246
t.Status = TestStatus.Running;
247
context.Monitor.BeginTest (t);
250
void EventListener.SuiteFinished (TestSuiteResult result)
255
UnitTest t = GetLocalTest ((Test) result.Test);
259
UnitTestResult res = GetLocalTestResult (result);
260
t.RegisterResult (context, res);
261
t.Status = TestStatus.Ready;
262
context.Monitor.EndTest (t, res);
265
public void TestOutput (TestOutput testOutput)
270
UnitTest GetLocalTest (Test t)
272
if (t == null) return null;
273
if (t.Parent == null) return rootTest;
275
string fn = t.FullName;
276
string sname = fn.Substring (rootFullName.Length);
277
if (sname.StartsWith (".")) sname = sname.Substring (1);
278
UnitTest tt = FindTest (rootTest, sname);
282
UnitTest FindTest (UnitTest t, string testPath)
287
string[] path = testPath.Split ('.');
288
foreach (string part in path) {
289
UnitTestGroup group = t as UnitTestGroup;
293
t = group.Tests [part];
124
consoleError.Append (testOutput.Text);
127
public void TestStarted (TestName testCase)
129
wrapped.TestStarted (GetTestName (testCase));
130
consoleOutput = new StringBuilder ();
131
consoleError = new StringBuilder ();
134
public override object InitializeLifetimeService ()
139
public string GetTestName (TestName t)
300
146
public UnitTestResult GetLocalTestResult (TestResult t)
302
148
UnitTestResult res = new UnitTestResult ();
149
res.Message = t.Message;
304
151
if (t is TestSuiteResult) {
305
152
int s=0, f=0, i=0;
220
public void UnhandledException (Exception exception)
225
interface IRemoteEventListener
227
void TestStarted (string testCase);
228
void TestFinished (string test, UnitTestResult result);
229
void SuiteStarted (string suite);
230
void SuiteFinished (string suite, UnitTestResult result);
233
class LocalTestMonitor: MarshalByRefObject, IRemoteEventListener
238
UnitTest runningTest;
240
UnitTestResult singleTestResult;
242
public LocalTestMonitor (TestContext context, ExternalTestRunner runner, UnitTest rootTest, string rootFullName, bool singleTestRun)
244
this.rootFullName = rootFullName;
245
this.rootTest = rootTest;
246
this.context = context;
247
this.singleTestRun = singleTestRun;
250
public UnitTest RunningTest {
251
get { return runningTest; }
254
internal UnitTestResult SingleTestResult {
256
if (singleTestResult == null)
257
singleTestResult = new UnitTestResult ();
258
return singleTestResult;
261
singleTestResult = value;
265
void IRemoteEventListener.TestStarted (string testCase)
270
UnitTest t = GetLocalTest (testCase);
275
context.Monitor.BeginTest (t);
276
t.Status = TestStatus.Running;
279
void IRemoteEventListener.TestFinished (string test, UnitTestResult result)
282
SingleTestResult = result;
286
UnitTest t = GetLocalTest (test);
290
t.RegisterResult (context, result);
291
context.Monitor.EndTest (t, result);
292
t.Status = TestStatus.Ready;
296
void IRemoteEventListener.SuiteStarted (string suite)
301
UnitTest t = GetLocalTest (suite);
305
t.Status = TestStatus.Running;
306
context.Monitor.BeginTest (t);
309
void IRemoteEventListener.SuiteFinished (string suite, UnitTestResult result)
314
UnitTest t = GetLocalTest (suite);
318
t.RegisterResult (context, result);
319
t.Status = TestStatus.Ready;
320
context.Monitor.EndTest (t, result);
323
UnitTest GetLocalTest (string sname)
325
if (sname == null) return null;
326
if (sname == "<root>") return rootTest;
328
if (sname.StartsWith (rootFullName)) {
329
sname = sname.Substring (rootFullName.Length);
331
if (sname.StartsWith (".")) sname = sname.Substring (1);
332
UnitTest tt = FindTest (rootTest, sname);
336
UnitTest FindTest (UnitTest t, string testPath)
341
UnitTestGroup group = t as UnitTestGroup;
345
UnitTest returnTest = group.Tests [testPath];
346
if (returnTest != null)
349
string[] paths = testPath.Split (new char[] {'.'}, 2);
350
if (paths.Length == 2) {
351
string nextPathSection = paths[0];
352
string nextTestCandidate = paths[1];
354
UnitTest childTest = group.Tests [nextPathSection];
355
if (childTest != null)
356
return FindTest (childTest, nextTestCandidate);