* Convert.cs: Numerous fixed in overloads taking base to match
[mono.git] / mcs / nunit20 / nunit-console / ConsoleUi.cs
1 #region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
2 /************************************************************************************
3 '
4 ' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
5 ' Copyright © 2000-2003 Philip A. Craig
6 '
7 ' This software is provided 'as-is', without any express or implied warranty. In no 
8 ' event will the authors be held liable for any damages arising from the use of this 
9 ' software.
10
11 ' Permission is granted to anyone to use this software for any purpose, including 
12 ' commercial applications, and to alter it and redistribute it freely, subject to the 
13 ' following restrictions:
14 '
15 ' 1. The origin of this software must not be misrepresented; you must not claim that 
16 ' you wrote the original software. If you use this software in a product, an 
17 ' acknowledgment (see the following) in the product documentation is required.
18 '
19 ' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
20 ' or Copyright © 2000-2003 Philip A. Craig
21 '
22 ' 2. Altered source versions must be plainly marked as such, and must not be 
23 ' misrepresented as being the original software.
24 '
25 ' 3. This notice may not be removed or altered from any source distribution.
26 '
27 '***********************************************************************************/
28 #endregion
29
30 namespace NUnit.Console
31 {
32         using System;
33         using System.Collections;
34         using System.Collections.Specialized;
35         using System.IO;
36         using System.Reflection;
37         using System.Xml;
38         using System.Xml.Xsl;
39         using System.Xml.XPath;
40         using System.Resources;
41         using System.Text;
42         using System.Text.RegularExpressions;
43         using System.Diagnostics;
44         using NUnit.Core;
45         using NUnit.Util;
46         
47
48         /// <summary>
49         /// Summary description for ConsoleUi.
50         /// </summary>
51         public class ConsoleUi
52         {
53                 [STAThread]
54                 public static int Main(string[] args)
55                 {
56                         ConsoleOptions options = new ConsoleOptions(args);
57                         if(!options.nologo)
58                                 WriteCopyright();
59
60                         if(options.help)
61                         {
62                                 options.Help();
63                                 return 0;
64                         }
65                         
66                         if(options.NoArgs) 
67                         {
68                                 Console.Error.WriteLine("fatal error: no inputs specified");
69                                 options.Help();
70                                 return 0;
71                         }
72                         
73                         if(!options.Validate())
74                         {
75                                 Console.Error.WriteLine("fatal error: invalid arguments");
76                                 options.Help();
77                                 return 2;
78                         }
79
80                         try
81                         {
82                                 ConsoleUi consoleUi = new ConsoleUi();
83                                 return consoleUi.Execute( options );
84                         }
85                         catch( FileNotFoundException ex )
86                         {
87                                 Console.WriteLine( ex.Message );
88                                 return 2;
89                         }
90                         catch( BadImageFormatException ex )
91                         {
92                                 Console.WriteLine( ex.Message );
93                                 return 2;
94                         }
95                         catch( Exception ex )
96                         {
97                                 Console.WriteLine( "Unhandled Exception:\n{0}", ex.ToString() );
98                                 return 2;
99                         }
100                         finally
101                         {
102                                 if(options.wait)
103                                 {
104                                         Console.Out.WriteLine("\nHit <enter> key to continue");
105                                         Console.ReadLine();
106                                 }
107                         }
108                 }
109
110                 private static XmlTextReader GetTransformReader(ConsoleOptions parser)
111                 {
112                         XmlTextReader reader = null;
113                         if(!parser.IsTransform)
114                         {
115                                 Assembly assembly = Assembly.GetAssembly(typeof(XmlResultVisitor));
116                                 ResourceManager resourceManager = new ResourceManager("NUnit.Util.Transform",assembly);
117                                 string xmlData = (string)resourceManager.GetObject("Summary.xslt");
118
119                                 reader = new XmlTextReader(new StringReader(xmlData));
120                         }
121                         else
122                         {
123                                 FileInfo xsltInfo = new FileInfo(parser.transform);
124                                 if(!xsltInfo.Exists)
125                                 {
126                                         Console.Error.WriteLine("Transform file: {0} does not exist", xsltInfo.FullName);
127                                         reader = null;
128                                 }
129                                 else
130                                 {
131                                         reader = new XmlTextReader(xsltInfo.FullName);
132                                 }
133                         }
134
135                         return reader;
136                 }
137
138                 private static void WriteCopyright()
139                 {
140                         Assembly executingAssembly = Assembly.GetExecutingAssembly();
141                         System.Version version = executingAssembly.GetName().Version;
142
143                         object[] objectAttrs = executingAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
144                         AssemblyProductAttribute productAttr = (AssemblyProductAttribute)objectAttrs[0];
145
146                         objectAttrs = executingAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
147                         AssemblyCopyrightAttribute copyrightAttr = (AssemblyCopyrightAttribute)objectAttrs[0];
148
149                         Console.WriteLine(String.Format("{0} version {1}", productAttr.Product, version.ToString(3)));
150                         Console.WriteLine(copyrightAttr.Copyright);
151                         Console.WriteLine();
152
153                         string clrPlatform = Type.GetType("Mono.Runtime", false) == null ? ".NET" : "Mono";
154                         Console.WriteLine( string.Format("OS Version: {0}    {1} Version: {2}",
155                                 Environment.OSVersion, clrPlatform, Environment.Version ) );
156                         Console.WriteLine();
157                 }
158
159                 private static Test MakeTestFromCommandLine(TestDomain testDomain, ConsoleOptions parser)
160                 {
161                         NUnitProject project;
162
163                         if ( parser.IsTestProject )
164                         {
165                                 project = NUnitProject.LoadProject( (string)parser.Parameters[0] );
166                                 string configName = (string) parser.config;
167                                 if ( configName != null )
168                                         project.SetActiveConfig( configName );
169                         }
170                         else
171                                 project = NUnitProject.FromAssemblies( (string[])parser.Parameters.ToArray( typeof( string ) ) );
172
173                         return testDomain.Load( project, parser.fixture );
174                 }
175
176                 public ConsoleUi()
177                 {
178                 }
179
180                 public int Execute( ConsoleOptions options )
181                 {
182                         XmlTextReader transformReader = GetTransformReader(options);
183                         if(transformReader == null) return 3;
184
185                         ConsoleWriter outStream = options.isOut
186                                 ? new ConsoleWriter( new StreamWriter( options.output ) )
187                                 : new ConsoleWriter(Console.Out);
188
189                         ConsoleWriter errorStream = options.isErr
190                                 ? new ConsoleWriter( new StreamWriter( options.err ) )
191                                 : new ConsoleWriter(Console.Error);
192
193                         TestDomain testDomain = new TestDomain(outStream, errorStream);
194                         if ( options.noshadow  ) testDomain.ShadowCopyFiles = false;
195
196                         Test test = MakeTestFromCommandLine(testDomain, options);
197
198                         if(test == null)
199                         {
200                                 Console.Error.WriteLine("Unable to locate fixture {0}", options.fixture);
201                                 return 2;
202                         }
203
204                         Directory.SetCurrentDirectory(new FileInfo((string)options.Parameters[0]).DirectoryName);
205                 
206                         EventCollector collector = new EventCollector( options, outStream );
207
208                         string savedDirectory = Environment.CurrentDirectory;
209
210                         if (options.HasInclude)
211                         {
212                                 Console.WriteLine( "Included categories: " + options.include );
213                                 testDomain.SetFilter( new CategoryFilter( options.IncludedCategories ) );
214                         }
215                         else if ( options.HasExclude )
216                         {
217                                 Console.WriteLine( "Excluded categories: " + options.exclude );
218                                 testDomain.SetFilter( new CategoryFilter( options.ExcludedCategories, true ) );
219                         }
220
221                         TestResult result = null;
222                         if ( options.thread )
223                         {
224                                 testDomain.RunTest( collector );
225                                 testDomain.Wait();
226                                 result = testDomain.Result;
227                         }
228                         else
229                         {
230                                 result = testDomain.Run( collector );
231                         }
232
233                         Directory.SetCurrentDirectory( savedDirectory );
234                         
235                         Console.WriteLine();
236                         Console.WriteLine();
237                         collector.PrintSummary( result );
238                         Console.WriteLine();
239
240                         string xmlOutput = CreateXmlOutput( result );
241                         
242                         if (options.xmlConsole)
243                                 Console.WriteLine(xmlOutput);
244                         else
245                                 CreateSummaryDocument(xmlOutput, transformReader, outStream);
246
247                         // Write xml output here
248                         string xmlResultFile = options.IsXml ? options.xml : "TestResult.xml";
249
250                         using ( StreamWriter writer = new StreamWriter( xmlResultFile ) ) 
251                         {
252                                 writer.Write(xmlOutput);
253                         }
254                         outStream.Flush();
255                         errorStream.Flush();
256
257                         if ( testDomain != null )
258                                 testDomain.Unload();
259
260                         return result.IsFailure ? 1 : 0;
261                 }
262
263                 private string CreateXmlOutput( TestResult result )
264                 {
265                         StringBuilder builder = new StringBuilder();
266                         XmlResultVisitor resultVisitor = new XmlResultVisitor(new StringWriter( builder ), result);
267                         result.Accept(resultVisitor);
268                         resultVisitor.Write();
269
270                         return builder.ToString();
271                 }
272
273                 private void CreateSummaryDocument(string xmlOutput, XmlTextReader transformReader,
274                                                    ConsoleWriter outStream)
275                 {
276                         XPathDocument originalXPathDocument = new XPathDocument(new StringReader(xmlOutput));
277                         XslTransform summaryXslTransform = new XslTransform();
278                         
279                         // Using obsolete form for now, remove warning suppression from project after changing
280                         summaryXslTransform.Load(transformReader);
281                         
282                         // Using obsolete form for now, remove warning suppression from project after changing
283                         summaryXslTransform.Transform(originalXPathDocument,null,outStream);
284                 }
285
286                 #region Nested Class to Handle Events
287
288                 private class EventCollector : LongLivingMarshalByRefObject, EventListener
289                 {
290                         private int testRunCount;
291                         private int testIgnoreCount;
292                         private int failureCount;
293                         private int level;
294
295                         private ConsoleOptions options;
296                         private ConsoleWriter writer;
297
298                         StringCollection messages;
299                 
300                         private bool debugger = false;
301                         private string currentTestName;
302
303                         public EventCollector( ConsoleOptions options, ConsoleWriter writer )
304                         {
305                                 debugger = Debugger.IsAttached;
306                                 level = 0;
307                                 this.options = options;
308                                 this.writer = writer;
309                                 this.currentTestName = string.Empty;
310                         }
311
312                         public void RunStarted(Test[] tests)
313                         {
314                         }
315
316                         public void RunFinished(TestResult[] results)
317                         {
318                         }
319
320                         public void RunFinished(Exception exception)
321                         {
322                         }
323
324                         public void TestFinished(TestCaseResult testResult)
325                         {
326                                 if ( !options.xmlConsole && !options.labels )
327                                 {
328                                         if(testResult.Executed)
329                                         {
330                                                 testRunCount++;
331                                                 
332                                                 if(testResult.IsFailure)
333                                                 {       
334                                                         failureCount++;
335                                                         Console.Write("F");
336                                                         if ( debugger )
337                                                         {
338                                                                 messages.Add( string.Format( "{0}) {1} :", failureCount, testResult.Test.FullName ) );
339                                                                 messages.Add( testResult.Message.Trim( Environment.NewLine.ToCharArray() ) );
340
341                                                                 string stackTrace = StackTraceFilter.Filter( testResult.StackTrace );
342                                                                 string[] trace = stackTrace.Split( System.Environment.NewLine.ToCharArray() );
343                                                                 foreach( string s in trace )
344                                                                 {
345                                                                         if ( s != string.Empty )
346                                                                         {
347                                                                                 string link = Regex.Replace( s.Trim(), @".* in (.*):line (.*)", "$1($2)");
348                                                                                 messages.Add( string.Format( "at\n{0}", link ) );
349                                                                         }
350                                                                 }
351                                                         }
352                                                 }
353                                         }
354                                         else
355                                         {
356                                                 testIgnoreCount++;
357                                                 Console.Write("N");
358                                         }
359                                 }
360
361                                 currentTestName = string.Empty;
362                         }
363
364                         public void TestStarted(TestCase testCase)
365                         {
366                                 currentTestName = testCase.FullName;
367
368                                 if ( options.labels )
369                                         writer.WriteLine("***** {0}", testCase.FullName );
370                                 else if ( !options.xmlConsole )
371                                         Console.Write(".");
372 }
373
374                         public void SuiteStarted(TestSuite suite) 
375                         {
376                                 if ( debugger && level++ == 0 )
377                                 {
378                                         messages = new StringCollection();
379                                         testRunCount = 0;
380                                         testIgnoreCount = 0;
381                                         failureCount = 0;
382                                         Trace.WriteLine( "################################ UNIT TESTS ################################" );
383                                         Trace.WriteLine( "Running tests in '" + suite.FullName + "'..." );
384                                 }
385                         }
386
387                         public void SuiteFinished(TestSuiteResult suiteResult) 
388                         {
389                                 if ( debugger && --level == 0) 
390                                 {
391                                         Trace.WriteLine( "############################################################################" );
392
393                                         if (messages.Count == 0) 
394                                         {
395                                                 Trace.WriteLine( "##############                 S U C C E S S               #################" );
396                                         }
397                                         else 
398                                         {
399                                                 Trace.WriteLine( "##############                F A I L U R E S              #################" );
400                                                 
401                                                 foreach ( string s in messages ) 
402                                                 {
403                                                         Trace.WriteLine(s);
404                                                 }
405                                         }
406
407                                         Trace.WriteLine( "############################################################################" );
408                                         Trace.WriteLine( "Executed tests : " + testRunCount );
409                                         Trace.WriteLine( "Ignored tests  : " + testIgnoreCount );
410                                         Trace.WriteLine( "Failed tests   : " + failureCount );
411                                         Trace.WriteLine( "Total time     : " + suiteResult.Time + " seconds" );
412                                         Trace.WriteLine( "############################################################################");
413                                 }
414                         }
415
416                         public void PrintSummary (TestResult suiteResult)
417                         {
418                                 Console.WriteLine("Tests run: {0}, Failures: {1}, Not run: {2}, Time: {3} seconds",
419                                                   testRunCount, failureCount, testIgnoreCount, suiteResult.Time);
420                         }
421
422                         public void UnhandledException( Exception exception )
423                         {
424                                 string msg = string.Format( "##### Unhandled Exception while running {0}", currentTestName );
425
426                                 // If we do labels, we already have a newline
427                                 if ( !options.labels ) writer.WriteLine();
428                                 writer.WriteLine( msg );
429                                 writer.WriteLine( exception.ToString() );
430
431                                 if ( debugger )
432                                 {
433                                         Trace.WriteLine( msg );
434                                         Trace.WriteLine( exception.ToString() );
435                                 }
436                         }
437                 }
438
439                 #endregion
440         }
441 }
442