~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to .pc/port_to_nunit_2.5.patch/src/addins/NUnit/Services/ExternalTestRunner.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-07-11 19:09:31 UTC
  • mfrom: (1.3.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20110711190931-1gfoqejryhrliuuq
Tags: 2.5.92+dfsg-2ubuntu1
* Merge from Debian experimental:
  + debian/patches/no_appmenu: Disable AppMenu proxy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// ExternalTestRunner.cs
 
3
//
 
4
// Author:
 
5
//   Lluis Sanchez Gual
 
6
//
 
7
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
 
8
//
 
9
// Permission is hereby granted, free of charge, to any person obtaining
 
10
// a copy of this software and associated documentation files (the
 
11
// "Software"), to deal in the Software without restriction, including
 
12
// without limitation the rights to use, copy, modify, merge, publish,
 
13
// distribute, sublicense, and/or sell copies of the Software, and to
 
14
// permit persons to whom the Software is furnished to do so, subject to
 
15
// the following conditions:
 
16
// 
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
// 
 
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
//
 
28
 
 
29
 
 
30
using System;
 
31
using System.Reflection;
 
32
using System.IO;
 
33
using System.Collections;
 
34
using System.Collections.Generic;
 
35
using System.Threading;
 
36
using System.Text;
 
37
 
 
38
using MonoDevelop.Core;
 
39
using MonoDevelop.Core.Execution;
 
40
using NUnit.Core;
 
41
using NUnit.Util;
 
42
using NF = NUnit.Framework;
 
43
using NC = NUnit.Core;
 
44
 
 
45
namespace MonoDevelop.NUnit.External
 
46
{
 
47
        class ExternalTestRunner: RemoteProcessObject
 
48
        {
 
49
                NUnitTestRunner runner;
 
50
 
 
51
                public ExternalTestRunner ( )
 
52
                {
 
53
                        // In some cases MS.NET can't properly resolve assemblies even if they
 
54
                        // are already loaded. For example, when deserializing objects from remoting.
 
55
                        AppDomain.CurrentDomain.AssemblyResolve += delegate (object s, ResolveEventArgs args) {
 
56
                                foreach (Assembly am in AppDomain.CurrentDomain.GetAssemblies ()) {
 
57
                                        if (am.GetName ().FullName == args.Name)
 
58
                                                return am;
 
59
                                }
 
60
                                return null;
 
61
                        };
 
62
                        
 
63
                        // Preload the runner assembly. Required because TestNameFilter is implemented there
 
64
                        string asm = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "NUnitRunner.dll");
 
65
                        Assembly.LoadFrom (asm);
 
66
                }
 
67
                
 
68
                public UnitTestResult Run (IRemoteEventListener listener, ITestFilter filter, string path, string suiteName, List<string> supportAssemblies)
 
69
                {
 
70
                        NUnitTestRunner runner = GetRunner (path);
 
71
                        EventListenerWrapper listenerWrapper = listener != null ? new EventListenerWrapper (listener) : null;
 
72
                        
 
73
                        TestResult res = runner.Run (listenerWrapper, filter, path, suiteName, supportAssemblies);
 
74
                        return listenerWrapper.GetLocalTestResult (res);
 
75
                }
 
76
                
 
77
                public NunitTestInfo GetTestInfo (string path, List<string> supportAssemblies)
 
78
                {
 
79
                        NUnitTestRunner runner = GetRunner (path);
 
80
                        return runner.GetTestInfo (path, supportAssemblies);
 
81
                }
 
82
                
 
83
                NUnitTestRunner GetRunner (string assemblyPath)
 
84
                {
 
85
                        TestPackage package = new TestPackage (assemblyPath);
 
86
                        package.Settings ["ShadowCopyFiles"] = false;
 
87
                        DomainManager dm = new DomainManager ();
 
88
                        AppDomain domain = dm.CreateDomain (package);
 
89
                        string asm = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "NUnitRunner.dll");
 
90
                        runner = (NUnitTestRunner) domain.CreateInstanceFromAndUnwrap (asm, "MonoDevelop.NUnit.External.NUnitTestRunner");
 
91
                        runner.Initialize (typeof(NF.Assert).Assembly.Location, typeof(NC.Test).Assembly.Location);
 
92
                        return runner;
 
93
                }
 
94
        }
 
95
        
 
96
        class EventListenerWrapper: MarshalByRefObject, EventListener
 
97
        {
 
98
                IRemoteEventListener wrapped;
 
99
                StringBuilder consoleOutput;
 
100
                StringBuilder consoleError;
 
101
                
 
102
                public EventListenerWrapper (IRemoteEventListener wrapped)
 
103
                {
 
104
                        this.wrapped = wrapped;
 
105
                }
 
106
                
 
107
                public void RunFinished (Exception exception)
 
108
                {
 
109
                }
 
110
                
 
111
                public void RunFinished (TestResult results)
 
112
                {
 
113
                }
 
114
                
 
115
                public void RunStarted (string name, int testCount)
 
116
                {
 
117
                }
 
118
                
 
119
                public void SuiteFinished (TestSuiteResult result)
 
120
                {
 
121
                        testSuites.Pop ();
 
122
                        wrapped.SuiteFinished (GetTestName (result.Test), GetLocalTestResult (result));
 
123
                }
 
124
                Stack<string> testSuites = new Stack<string>();
 
125
                public void SuiteStarted (TestName suite)
 
126
                {
 
127
                        testSuites.Push (suite.FullName);
 
128
                        wrapped.SuiteStarted (GetTestName (suite));
 
129
                }
 
130
                
 
131
                public void TestFinished (TestCaseResult result)
 
132
                {
 
133
                        wrapped.TestFinished (GetTestName (result.Test), GetLocalTestResult (result));
 
134
                }
 
135
                
 
136
                public void TestOutput (TestOutput testOutput)
 
137
                {
 
138
                        if (consoleOutput == null) {
 
139
                                Console.WriteLine (testOutput.Text);
 
140
                                return;
 
141
                        }
 
142
                        else if (testOutput.Type == TestOutputType.Out)
 
143
                                consoleOutput.Append (testOutput.Text);
 
144
                        else
 
145
                                consoleError.Append (testOutput.Text);
 
146
                }
 
147
                
 
148
                public void TestStarted (TestName testCase)
 
149
                {
 
150
                        wrapped.TestStarted (GetTestName (testCase));
 
151
                        consoleOutput = new StringBuilder ();
 
152
                        consoleError = new StringBuilder ();
 
153
                }
 
154
                
 
155
                public override object InitializeLifetimeService ()
 
156
                {
 
157
                        return null;
 
158
                }
 
159
                
 
160
                string GetTestName (ITest t)
 
161
                {
 
162
                        if (t == null)
 
163
                                return null;
 
164
                        // Theoretically t.TestName.FullName should work, but when a test class inherits from a base
 
165
                        // class that contains tests the full name is that one of the base class, which is wrong.
 
166
                        // I suspect that is a NUnit bug, when this is fixed this code should be overworked and the testSuites stack be removed.
 
167
                        // see: Bug 677228 - RemotingException isn't counted as failure
 
168
                        if (t.TestType != "Test Case" || testSuites.Count == 0)
 
169
                                return t.TestName.FullName;
 
170
                        return testSuites.Peek () + "." + t.TestName.Name;
 
171
                }
 
172
                
 
173
                public string GetTestName (TestName t)
 
174
                {
 
175
                        if (t == null)
 
176
                                return null;
 
177
                        return t.FullName;
 
178
                }
 
179
                
 
180
                public UnitTestResult GetLocalTestResult (TestResult t)
 
181
                {
 
182
                        UnitTestResult res = new UnitTestResult ();
 
183
                        res.Message = t.Message;
 
184
                        
 
185
                        if (t is TestSuiteResult) {
 
186
                                int s=0, f=0, i=0;
 
187
                                CountResults ((TestSuiteResult)t, ref s, ref f, ref i);
 
188
                                res.TotalFailures = f;
 
189
                                res.TotalSuccess = s;
 
190
                                res.TotalIgnored = i;
 
191
                                if (f > 0)
 
192
                                        res.Status |= ResultStatus.Failure;
 
193
                                if (s > 0)
 
194
                                        res.Status |= ResultStatus.Success;
 
195
                                if (i > 0)
 
196
                                        res.Status |= ResultStatus.Ignored;
 
197
                        } else {
 
198
                                if (t.IsFailure) {
 
199
                                        res.Status = ResultStatus.Failure;
 
200
                                        res.TotalFailures = 1;
 
201
                                }
 
202
                                else if (!t.Executed) {
 
203
                                        res.Status = ResultStatus.Ignored;
 
204
                                        res.TotalIgnored = 1;
 
205
                                }
 
206
                                else {
 
207
                                        res.Status = ResultStatus.Success;
 
208
                                        res.TotalSuccess = 1;
 
209
                                }
 
210
                        
 
211
                                if (string.IsNullOrEmpty (res.Message)) {
 
212
                                        if (t.IsFailure)
 
213
                                                res.Message = GettextCatalog.GetString ("Test failed");
 
214
                                        else if (!t.Executed)
 
215
                                                res.Message = GettextCatalog.GetString ("Test ignored");
 
216
                                        else {
 
217
                                                res.Message = GettextCatalog.GetString ("Test successful") + "\n\n";
 
218
                                                res.Message += GettextCatalog.GetString ("Execution time: {0:0.00}ms", t.Time);
 
219
                                        }
 
220
                                }
 
221
                        }
 
222
                        res.StackTrace = t.StackTrace;
 
223
                        res.Time = TimeSpan.FromSeconds (t.Time);
 
224
                        
 
225
                        if (consoleOutput != null) {
 
226
                                res.ConsoleOutput = consoleOutput.ToString ();
 
227
                                res.ConsoleError = consoleError.ToString ();
 
228
                                consoleOutput = null;
 
229
                                consoleError = null;
 
230
                        }
 
231
                        
 
232
                        return res;
 
233
                }               
 
234
                
 
235
                void CountResults (TestSuiteResult ts, ref int s, ref int f, ref int i)
 
236
                {
 
237
                        if (ts.Results == null)
 
238
                                return;
 
239
 
 
240
                        foreach (TestResult t in ts.Results) {
 
241
                                if (t is TestCaseResult) {
 
242
                                        if (t.IsFailure)
 
243
                                                f++;
 
244
                                        else if (!t.Executed)
 
245
                                                i++;
 
246
                                        else
 
247
                                                s++;
 
248
                                } else if (t is TestSuiteResult) {
 
249
                                        CountResults ((TestSuiteResult) t, ref s, ref f, ref i);
 
250
                                }
 
251
                        }
 
252
                }
 
253
                
 
254
                public void UnhandledException (Exception exception)
 
255
                {
 
256
                }
 
257
        }
 
258
        
 
259
        interface IRemoteEventListener
 
260
        {
 
261
                void TestStarted (string testCase);
 
262
                void TestFinished (string test, UnitTestResult result);
 
263
                void SuiteStarted (string suite);
 
264
                void SuiteFinished (string suite, UnitTestResult result);
 
265
        }
 
266
        
 
267
        class LocalTestMonitor: MarshalByRefObject, IRemoteEventListener
 
268
        {
 
269
                TestContext context;
 
270
                UnitTest rootTest;
 
271
                string rootFullName;
 
272
                UnitTest runningTest;
 
273
                bool singleTestRun;
 
274
                UnitTestResult singleTestResult;
 
275
                public bool Canceled;
 
276
                
 
277
                public LocalTestMonitor (TestContext context, ExternalTestRunner runner, UnitTest rootTest, string rootFullName, bool singleTestRun)
 
278
                {
 
279
                        this.rootFullName = rootFullName;
 
280
                        this.rootTest = rootTest;
 
281
                        this.context = context;
 
282
                        this.singleTestRun = singleTestRun;
 
283
                }
 
284
                
 
285
                public UnitTest RunningTest {
 
286
                        get { return runningTest; }
 
287
                }
 
288
                
 
289
                internal UnitTestResult SingleTestResult {
 
290
                        get {
 
291
                                if (singleTestResult == null)
 
292
                                        singleTestResult = new UnitTestResult ();
 
293
                                return singleTestResult;
 
294
                        }
 
295
                        set {
 
296
                                singleTestResult = value;
 
297
                        }
 
298
                }
 
299
                
 
300
                void IRemoteEventListener.TestStarted (string testCase)
 
301
                {
 
302
                        if (singleTestRun || Canceled)
 
303
                                return;
 
304
                        
 
305
                        UnitTest t = GetLocalTest (testCase);
 
306
                        if (t == null)
 
307
                                return;
 
308
                        
 
309
                        runningTest = t;
 
310
                        context.Monitor.BeginTest (t);
 
311
                        t.Status = TestStatus.Running;
 
312
                }
 
313
                        
 
314
                void IRemoteEventListener.TestFinished (string test, UnitTestResult result)
 
315
                {
 
316
                        if (Canceled)
 
317
                                return;
 
318
                        if (singleTestRun) {
 
319
                                SingleTestResult = result;
 
320
                                return;
 
321
                        }
 
322
                        
 
323
                        UnitTest t = GetLocalTest (test);
 
324
                        if (t == null)
 
325
                                return;
 
326
                        
 
327
                        t.RegisterResult (context, result);
 
328
                        context.Monitor.EndTest (t, result);
 
329
                        t.Status = TestStatus.Ready;
 
330
                        runningTest = null;
 
331
                }
 
332
 
 
333
                void IRemoteEventListener.SuiteStarted (string suite)
 
334
                {
 
335
                        if (singleTestRun || Canceled)
 
336
                                return;
 
337
                        
 
338
                        UnitTest t = GetLocalTest (suite);
 
339
                        if (t == null)
 
340
                                return;
 
341
                        
 
342
                        t.Status = TestStatus.Running;
 
343
                        context.Monitor.BeginTest (t);
 
344
                }
 
345
 
 
346
                void IRemoteEventListener.SuiteFinished (string suite, UnitTestResult result)
 
347
                {
 
348
                        if (singleTestRun || Canceled)
 
349
                                return;
 
350
                        
 
351
                        UnitTest t = GetLocalTest (suite);
 
352
                        if (t == null)
 
353
                                return;
 
354
                        
 
355
                        t.RegisterResult (context, result);
 
356
                        t.Status = TestStatus.Ready;
 
357
                        context.Monitor.EndTest (t, result);
 
358
                }
 
359
                
 
360
                UnitTest GetLocalTest (string sname)
 
361
                {
 
362
                        if (sname == null) return null;
 
363
                        if (sname == "<root>") return rootTest;
 
364
                        
 
365
                        if (sname.StartsWith (rootFullName)) {
 
366
                                sname = sname.Substring (rootFullName.Length);
 
367
                        }
 
368
                        if (sname.StartsWith (".")) sname = sname.Substring (1);
 
369
                        UnitTest tt = FindTest (rootTest, sname);
 
370
                        return tt;
 
371
                }
 
372
                
 
373
                UnitTest FindTest (UnitTest t, string testPath)
 
374
                {
 
375
                        if (testPath == "")
 
376
                                return t;
 
377
 
 
378
                        UnitTestGroup group = t as UnitTestGroup;
 
379
                        if (group == null)
 
380
                                return null;
 
381
 
 
382
                        UnitTest returnTest = group.Tests [testPath];
 
383
                        if (returnTest != null)
 
384
                                return returnTest;
 
385
 
 
386
                        string[] paths = testPath.Split (new char[] {'.'}, 2);
 
387
                        if (paths.Length == 2) {
 
388
                                string nextPathSection = paths[0];
 
389
                                string nextTestCandidate = paths[1];
 
390
 
 
391
                                UnitTest childTest = group.Tests [nextPathSection];
 
392
                                if (childTest != null)
 
393
                                        return FindTest (childTest, nextTestCandidate);
 
394
                        }
 
395
                        return null;
 
396
                }
 
397
                
 
398
                public override object InitializeLifetimeService ()
 
399
                {
 
400
                        return null;
 
401
                }
 
402
 
 
403
        }       
 
404
}
 
405