2004-05-25 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Wed, 26 May 2004 00:31:38 +0000 (00:31 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Wed, 26 May 2004 00:31:38 +0000 (00:31 -0000)
* Update existing files (and added new ones) for nunit 2.1.91.

svn path=/trunk/mcs/; revision=28103

24 files changed:
mcs/nunit20/util/ConsoleWriter.cs [new file with mode: 0755]
mcs/nunit20/util/FormSettings.cs [new file with mode: 0755]
mcs/nunit20/util/ITestEvents.cs [new file with mode: 0755]
mcs/nunit20/util/ITestLoader.cs [new file with mode: 0755]
mcs/nunit20/util/NUnitGuiSettings.cs [new file with mode: 0755]
mcs/nunit20/util/OptionSettings.cs [new file with mode: 0755]
mcs/nunit20/util/RecentFileSettings.cs [new file with mode: 0755]
mcs/nunit20/util/RecentProjectSettings.cs [new file with mode: 0755]
mcs/nunit20/util/ResultSummarizer.cs [new file with mode: 0755]
mcs/nunit20/util/StackTraceFilter.cs [new file with mode: 0755]
mcs/nunit20/util/SummaryVisitor.cs [new file with mode: 0755]
mcs/nunit20/util/TestDomain.cs [new file with mode: 0755]
mcs/nunit20/util/TestEventDispatcher.cs [new file with mode: 0755]
mcs/nunit20/util/TestExceptionHandler.cs [new file with mode: 0755]
mcs/nunit20/util/TestLoader.cs [new file with mode: 0755]
mcs/nunit20/util/TestResultItem.cs [new file with mode: 0755]
mcs/nunit20/util/Transform.resources [new file with mode: 0755]
mcs/nunit20/util/Transform.resx [new file with mode: 0755]
mcs/nunit20/util/UserSettings.cs [new file with mode: 0755]
mcs/nunit20/util/VSProject.cs [new file with mode: 0755]
mcs/nunit20/util/VSProjectConfig.cs [new file with mode: 0755]
mcs/nunit20/util/VSProjectConfigCollection.cs [new file with mode: 0755]
mcs/nunit20/util/XmlResultVisitor.cs [new file with mode: 0755]
mcs/nunit20/util/nunit.util.build [new file with mode: 0755]

diff --git a/mcs/nunit20/util/ConsoleWriter.cs b/mcs/nunit20/util/ConsoleWriter.cs
new file mode 100755 (executable)
index 0000000..6b0d432
--- /dev/null
@@ -0,0 +1,73 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using System.IO;
+       using System.Text;
+
+       /// <summary>
+       /// Class used for receiving console output from the running test and displaying it.
+       /// </summary>
+       public class ConsoleWriter : TextWriter
+       {
+               private TextWriter console;
+                       
+               public ConsoleWriter(TextWriter console)
+               {
+                       this.console = console;
+               }
+                       
+               public override void Write(char c)
+               {
+                       console.Write(c);
+               }
+
+               public override void Write(String s)
+               {
+                       console.Write(s);
+               }
+
+               public override void WriteLine(string s)
+               {
+                       console.WriteLine(s);
+               }
+
+               public override Encoding Encoding
+               {
+                       get { return Encoding.Default; }
+               }
+
+               public override Object InitializeLifetimeService()
+               {
+                       return null;
+               }
+       }
+}
diff --git a/mcs/nunit20/util/FormSettings.cs b/mcs/nunit20/util/FormSettings.cs
new file mode 100755 (executable)
index 0000000..561ea53
--- /dev/null
@@ -0,0 +1,190 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using System.Drawing;
+
+       /// <summary>
+       /// FormSettings holds settings for NUnitForm
+       /// </summary>
+       public class FormSettings : SettingsGroup
+       {
+               private static readonly string NAME = "Form";
+
+               private static readonly string MAXIMIZED = "maximized";
+               private static readonly string WIDTH = "width";
+               private static readonly string HEIGHT = "height";
+               private static readonly string XLOCATION = "x-location";
+               private static readonly string YLOCATION = "y-location";
+               private static readonly string TREE_SPLITTER_POSITION = "tree-splitter-position";
+               private static readonly string TAB_SPLITTER_POSITION = "tab-splitter-position";
+
+               public static readonly int DEFAULT_WIDTH = 756;
+               public static readonly int MIN_WIDTH = 160;
+
+               public static readonly int DEFAULT_HEIGHT = 512;
+               public static readonly int MIN_HEIGHT = 32; 
+               
+               public static readonly int DEFAULT_XLOCATION = 10;
+               
+               public static readonly int DEFAULT_YLOCATION = 10;
+
+               public static readonly int TREE_DEFAULT_POSITION = 300;
+               public static readonly int TREE_MIN_POSITION = 240;
+               
+               public static readonly int TAB_DEFAULT_POSITION = 119;
+               public static readonly int TAB_MIN_POSITION = 100;
+
+               public FormSettings( ) : base( NAME, UserSettings.GetStorageImpl( NAME ) ) { }
+
+               public FormSettings( SettingsStorage storage ) : base( NAME, storage ) { }
+
+               public FormSettings( SettingsGroup parent ) : base( NAME, parent ) { }
+
+               private Point location = Point.Empty;
+               private Size size = Size.Empty;
+               private int treeSplitterPosition = -1;
+               private int tabSplitterPosition = -1;
+
+               public bool IsMaximized
+               {
+                       get
+                       {
+                               return LoadIntSetting( MAXIMIZED, 0 ) == 1 ? true : false;
+                       }
+
+                       set
+                       {
+                               SaveIntSetting( MAXIMIZED, value ? 1 : 0 );
+                       }
+               }
+
+               public Point Location
+               {
+                       get 
+                       {
+                               if ( location == Point.Empty )
+                               {
+                                       int x = LoadIntSetting( XLOCATION, DEFAULT_XLOCATION );
+                                       int y = LoadIntSetting( YLOCATION, DEFAULT_YLOCATION );
+
+                                       location = new Point(x, y);
+
+                                       if ( !IsValidLocation( location ) )
+                                               location = new Point( DEFAULT_XLOCATION, DEFAULT_YLOCATION );
+                               }
+                               
+                               return location; 
+                       }
+                       set 
+                       { 
+                               location = value;
+                               SaveSetting( XLOCATION, location.X );
+                               SaveSetting( YLOCATION, location.Y );
+                       }
+               }
+
+               private bool IsValidLocation( Point location )
+               {
+                       Rectangle workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
+                       Rectangle myArea = new Rectangle( location, this.Size );
+                       return ( myArea.IntersectsWith( workingArea ) );
+               }
+
+               public Size Size
+               {
+                       get 
+                       { 
+                               if ( size == Size.Empty )
+                               {
+                                       int width = LoadIntSetting( WIDTH, DEFAULT_WIDTH );
+                                       if ( width < MIN_WIDTH ) width = MIN_WIDTH;
+                                       int height = LoadIntSetting( HEIGHT, DEFAULT_HEIGHT );
+                                       if ( height < MIN_HEIGHT ) height = MIN_HEIGHT;
+
+                                       size = new Size(width, height);
+                               }
+
+                               return size;
+                       }
+                       set
+                       { 
+                               size = value;
+                               SaveIntSetting( WIDTH, size.Width );
+                               SaveIntSetting( HEIGHT, size.Height );
+                       }
+               }
+
+               public int TreeSplitterPosition
+               {
+                       get 
+                       {
+                               if ( treeSplitterPosition == -1 )
+                               {
+                                       treeSplitterPosition = 
+                                               LoadIntSetting( TREE_SPLITTER_POSITION, TREE_DEFAULT_POSITION );
+
+                                       if ( treeSplitterPosition < TREE_MIN_POSITION  || treeSplitterPosition > this.Size.Width )
+                                               treeSplitterPosition = TREE_MIN_POSITION;
+                               }
+                               
+                               return treeSplitterPosition; 
+                       }
+                       set 
+                       { 
+                               treeSplitterPosition = value;
+                               SaveSetting( TREE_SPLITTER_POSITION, treeSplitterPosition );
+                       }
+               }
+
+               public int TabSplitterPosition
+               {
+                       get 
+                       {
+                               if ( tabSplitterPosition == -1 )
+                               {
+                                       tabSplitterPosition = 
+                                               LoadIntSetting( TAB_SPLITTER_POSITION, TAB_DEFAULT_POSITION );
+                                       
+                                       if ( tabSplitterPosition < TAB_MIN_POSITION || tabSplitterPosition > this.Size.Height )
+                                               tabSplitterPosition = TAB_MIN_POSITION;
+                               }
+                               
+                               return tabSplitterPosition; 
+                       }
+                       set 
+                       { 
+                               tabSplitterPosition = value;
+                               SaveSetting( TAB_SPLITTER_POSITION, tabSplitterPosition );
+                       }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/ITestEvents.cs b/mcs/nunit20/util/ITestEvents.cs
new file mode 100755 (executable)
index 0000000..03614e3
--- /dev/null
@@ -0,0 +1,54 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using NUnit.Core;
+
+//TODO: rename this file
+namespace NUnit.Util
+{
+       /// <summary>
+       /// IProjectEvents interface extends NUnit.Core.ITestEvents adding
+       /// events that are fired as projects are loaded and unloaded.
+       /// </summary>
+       public interface IProjectEvents : ITestEvents
+       {
+               // Events related to the loading and unloading
+               // of projects - including wrapper projects
+               // created in order to load assemblies. This
+               // occurs separately from the loading of tests
+               // for the assemblies in the project.
+               event TestProjectEventHandler ProjectLoading;
+               event TestProjectEventHandler ProjectLoaded;
+               event TestProjectEventHandler ProjectLoadFailed;
+               event TestProjectEventHandler ProjectUnloading;
+               event TestProjectEventHandler ProjectUnloaded;
+               event TestProjectEventHandler ProjectUnloadFailed;
+       }
+}
diff --git a/mcs/nunit20/util/ITestLoader.cs b/mcs/nunit20/util/ITestLoader.cs
new file mode 100755 (executable)
index 0000000..f37adbd
--- /dev/null
@@ -0,0 +1,113 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Collections;
+using NUnit.Core;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// The ITestLoader interface supports the loading and running
+       /// of tests in a remote domain. In addition to methods for
+       /// performing these operations, it inherits from the ITestEvents
+       /// interface to provide appropriate events. The two interfaces
+       /// are kept separate so that client objects not intended to
+       /// issue commands can just handle the first interface.
+       /// </summary>
+       public interface ITestLoader
+       {
+               #region Properties
+
+               // See if a project is loaded
+               bool IsProjectLoaded { get; }
+
+               // See if a test has been loaded from the project
+               bool IsTestLoaded { get; }
+
+               // See if a test is running
+               bool IsTestRunning { get; }
+
+               // The loaded test project
+               NUnitProject TestProject { get; set; }
+
+               string TestFileName { get; }
+
+               // Our last test results
+               TestResult[] Results { get; }
+
+               #endregion
+
+               #region Methods
+
+               // Create a new empty project using a default name
+               void NewProject();
+
+               // Create a new project given a filename
+               void NewProject( string filename );
+
+               // Load a project given a filename
+               void LoadProject( string filename );
+
+               // Load a project given a filename and config
+               void LoadProject( string filename, string configname );
+
+               // Load a project given an array of assemblies
+               void LoadProject( string[] assemblies );
+
+               // Unload current project
+               void UnloadProject();
+
+               // Load tests for current project and config
+               void LoadTest();
+
+               // Load a specific test for current project and config
+               void LoadTest( string testName );
+
+               // Unload current test
+               void UnloadTest();
+               
+               // Reload current test
+               void ReloadTest();
+
+               // Set a filter for running tests
+               void SetFilter( IFilter filter );
+
+               // Run a test suite
+               void RunTest( ITest test );
+
+               // Run a collection of tests
+               void RunTests(ITest[] tests);
+
+               // Cancel the running test
+               void CancelTestRun();
+
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/mcs/nunit20/util/NUnitGuiSettings.cs b/mcs/nunit20/util/NUnitGuiSettings.cs
new file mode 100755 (executable)
index 0000000..b857946
--- /dev/null
@@ -0,0 +1,57 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// NUnitGuiSettings hods settings for the GUI test runner
+       /// </summary>
+       public class NUnitGuiSettings : SettingsGroup
+       {
+               private static readonly string NAME = "NUnitGui";
+
+               public NUnitGuiSettings( ) : base( NAME, UserSettings.GetStorageImpl( NAME ) ) { }
+
+               public NUnitGuiSettings( SettingsStorage storage ) : base( NAME, storage ) { }
+
+               public NUnitGuiSettings( SettingsGroup parent ) : base( NAME, parent ) { }
+
+               public FormSettings  Form
+               {
+                       get { return new FormSettings( this ); }
+               }
+
+//             public GuiOptionsSettings Options
+//             {
+//                     get { return new GuiOptionsSettings( this ); }
+//             }
+       }
+}
diff --git a/mcs/nunit20/util/OptionSettings.cs b/mcs/nunit20/util/OptionSettings.cs
new file mode 100755 (executable)
index 0000000..1e21c93
--- /dev/null
@@ -0,0 +1,108 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Summary description for OptionSettings.
+       /// </summary>
+       public class OptionSettings : SettingsGroup
+       {
+               private static readonly string NAME = "Options";
+
+               public OptionSettings( ) : base( NAME, UserSettings.GetStorageImpl( NAME ) ) { }
+
+               public OptionSettings( SettingsStorage storage ) : base( NAME, storage ) { }
+
+               public OptionSettings( SettingsGroup parent ) : base( NAME, parent ) { }
+
+               public bool LoadLastProject
+               {
+                       get { return LoadIntSetting( "LoadLastProject", 1 ) != 0; }
+                       set { SaveIntSetting( "LoadLastProject", value ? 1 : 0 ); }
+               }
+
+               public int InitialTreeDisplay
+               {
+                       get { return LoadIntSetting( "InitialTreeDisplay", 0 ); }
+                       set { SaveIntSetting( "InitialTreeDisplay", value ); }
+               }
+
+               public bool ReloadOnRun
+               {
+                       get { return LoadIntSetting( "ReloadOnRun", 1 ) != 0; }
+                       set { SaveIntSetting( "ReloadOnRun", value ? 1 : 0 ); }
+               }
+
+               public bool ShowCheckBoxes
+               {
+                       get { return LoadIntSetting( "ShowCheckBoxes", 0 ) != 0; }
+                       set { SaveIntSetting( "ShowCheckBoxes", value ? 1 : 0 ); }
+               }
+
+               public bool ReloadOnChange
+               {
+                       get
+                       {
+                               if ( Environment.OSVersion.Platform != System.PlatformID.Win32NT )
+                                       return false;
+
+                               return LoadIntSetting( "ReloadOnChange", 1 ) != 0; 
+                       }
+
+                       set 
+                       {
+                               if ( Environment.OSVersion.Platform != System.PlatformID.Win32NT )
+                                       return;
+
+                               SaveIntSetting( "ReloadOnChange", value ? 1 : 0 ); 
+                       }
+               }
+
+               public bool ClearResults
+               {
+                       get { return LoadIntSetting( "ClearResults", 1 ) != 0; }
+                       set { SaveIntSetting( "ClearResults", value ? 1 : 0 ); }
+               }
+
+               public bool TestLabels
+               {
+                       get { return LoadIntSetting( "TestLabels", 0 ) != 0; }
+                       set { SaveIntSetting( "TestLabels", value ? 1 : 0 ); }
+               }
+
+               public bool VisualStudioSupport
+               {
+                       get { return LoadIntSetting( "VisualStudioSupport", 0 ) != 0; }
+                       set { SaveIntSetting( "VisualStudioSupport", value ? 1 : 0 ); }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/RecentFileSettings.cs b/mcs/nunit20/util/RecentFileSettings.cs
new file mode 100755 (executable)
index 0000000..17216c3
--- /dev/null
@@ -0,0 +1,173 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Collections;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Base class for settings that hold lists of recent files
+       /// </summary>
+       public abstract class RecentFileSettings : SettingsGroup
+       {
+               // TODO: This class does more loading and
+               // storing than it should but this is the
+               // current simplest solution to having
+               // multiple recentfiles objects around.
+               // We can fix this by using a singleton.
+               private IList fileEntries;
+
+               public static readonly int MinSize = 1;
+
+               public static readonly int MaxSize = 24;
+
+               public static readonly int DefaultSize = 5;
+
+               public RecentFileSettings( string name ) : base ( name, UserSettings.GetStorageImpl( name ) )
+               {
+                       LoadFiles();
+               }
+
+               public RecentFileSettings( string name, SettingsStorage storage ) : base( name, storage ) 
+               {
+                       LoadFiles();
+               }
+
+               public RecentFileSettings( string name, SettingsGroup parent ) : base( name, parent ) 
+               { 
+                       LoadFiles();
+               }
+
+               public int MaxFiles
+               {
+                       get 
+                       { 
+                               int size = LoadIntSetting( "MaxFiles", DefaultSize );
+                               
+                               if ( size < MinSize ) size = MinSize;
+                               if ( size > MaxSize ) size = MaxSize;
+                               
+                               return size;
+                       }
+                       set 
+                       { 
+                               int oldSize = MaxFiles;
+                               int newSize = value;
+                               
+                               if ( newSize < MinSize ) newSize = MinSize;
+                               if ( newSize > MaxSize ) newSize = MaxSize;
+
+                               SaveIntSetting( "MaxFiles", newSize );
+                               if ( newSize < oldSize ) SaveSettings();
+                       }
+               }
+
+               protected void LoadFiles()
+               {
+                       fileEntries = new ArrayList();
+                       for ( int index = 1; index <= MaxFiles; index++ )
+                       {
+                               string fileName = LoadStringSetting( ValueName( index ) );
+                               if ( fileName != null )
+                                       fileEntries.Add( fileName );
+                       }
+               }
+
+               public override void Clear()
+               {
+                       base.Clear();
+                       fileEntries = new ArrayList();
+               }
+
+               public IList GetFiles()
+               {
+                       LoadFiles();
+                       return fileEntries;
+               }
+               
+               public string RecentFile
+               {
+                       get 
+                       { 
+                               LoadFiles();
+                               if( fileEntries.Count > 0 )
+                                       return (string)fileEntries[0];
+
+                               return null;
+                       }
+                       set
+                       {
+                               LoadFiles();
+
+                               int index = fileEntries.IndexOf(value);
+
+                               if(index == 0) return;
+
+                               if(index != -1)
+                               {
+                                       fileEntries.RemoveAt(index);
+                               }
+
+                               fileEntries.Insert( 0, value );
+                               if( fileEntries.Count > MaxFiles )
+                                       fileEntries.RemoveAt( MaxFiles );
+
+                               SaveSettings();                 
+                       }
+               }
+
+               public void Remove( string fileName )
+               {
+                       LoadFiles();
+                       fileEntries.Remove( fileName );
+                       SaveSettings();
+               }
+
+               private void SaveSettings()
+               {
+                       while( fileEntries.Count > MaxFiles )
+                               fileEntries.RemoveAt( fileEntries.Count - 1 );
+
+                       for( int index = 0; index < MaxSize; index++ ) 
+                       {
+                               string valueName = ValueName( index + 1 );
+                               if ( index < fileEntries.Count )
+                                       SaveSetting( valueName, fileEntries[index] );
+                               else
+                                       RemoveSetting( valueName );
+                       }
+               }
+
+               private string ValueName( int index )
+               {
+                       return string.Format( "File{0}", index );
+               }
+       }
+}
diff --git a/mcs/nunit20/util/RecentProjectSettings.cs b/mcs/nunit20/util/RecentProjectSettings.cs
new file mode 100755 (executable)
index 0000000..80c1f6a
--- /dev/null
@@ -0,0 +1,60 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Holds list of most recent projects
+       /// 
+       /// NOTE: An earlier version had separate settings for
+       /// RecentProjects and RecentAssemblies. Currently we
+       /// currently only have RecentProjects, displayed in
+       /// the user interface as "Recent Files" and containing
+       /// all types of projects and assemblies that have
+       /// been opened. We retained the separation into two
+       /// classes in case we should need another recent list
+       /// at some time in the future. The UI component
+       /// RecentFilesMenuHandler can deal with any class
+       /// derived from RecentFileSettings.
+       /// </summary>
+       public class RecentProjectSettings : RecentFileSettings
+       {
+               private static readonly string NAME = "Recent-Projects";
+               
+               public RecentProjectSettings( ) : base ( NAME ) { }
+
+               public RecentProjectSettings( SettingsStorage storage ) 
+                       : base( NAME, storage ) { }
+
+               public RecentProjectSettings( SettingsGroup parent ) 
+                       : base( NAME, parent ) { }
+       }
+}
diff --git a/mcs/nunit20/util/ResultSummarizer.cs b/mcs/nunit20/util/ResultSummarizer.cs
new file mode 100755 (executable)
index 0000000..80cb871
--- /dev/null
@@ -0,0 +1,87 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using NUnit.Core;
+
+       /// <summary>
+       /// Summary description for ResultSummarizer.
+       /// </summary>
+       public class ResultSummarizer
+       {
+               private SummaryVisitor visitor = new SummaryVisitor();
+
+               public ResultSummarizer(TestResult result)
+               {
+                       result.Accept(visitor);
+               }
+
+               public string Name
+               {
+                       get { return visitor.Name; }
+               }
+
+               public bool Success
+               {
+                       get { return visitor.Success; }
+               }
+
+               public int ResultCount
+               {
+                       get { return visitor.Count; }
+               }
+
+//             public int Errors
+//             {
+//                     get { return visitor.Errors; }
+//             }
+
+               public int Failures 
+               {
+                       get { return visitor.Failures; }
+               }
+
+               public double Time
+               {
+                       get { return visitor.Time; }
+               }
+
+               public int TestsNotRun
+               {
+                       get { return visitor.TestsNotRun; }
+               }
+
+               public int SuitesNotRun
+               {
+                       get { return visitor.SuitesNotRun; }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/StackTraceFilter.cs b/mcs/nunit20/util/StackTraceFilter.cs
new file mode 100755 (executable)
index 0000000..0d61683
--- /dev/null
@@ -0,0 +1,85 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using System.IO;
+
+       /// <summary>
+       /// Summary description for StackTraceFilter.
+       /// </summary>
+       public class StackTraceFilter
+       {
+               public static string Filter(string stack) 
+               {
+                       if(stack == null) return null;
+                       StringWriter sw = new StringWriter();
+                       StringReader sr = new StringReader(stack);
+
+                       try 
+                       {
+                               string line;
+                               while ((line = sr.ReadLine()) != null) 
+                               {
+                                       if (!FilterLine(line))
+                                               sw.WriteLine(line);
+                               }
+                       } 
+                       catch (Exception) 
+                       {
+                               return stack;
+                       }
+                       return sw.ToString();
+               }
+
+               static bool FilterLine(string line) 
+               {
+                       string[] patterns = new string[]
+                       {
+                               "NUnit.Core.TestCase",
+                               "NUnit.Core.ExpectedExceptionTestCase",
+                               "NUnit.Core.TemplateTestCase",
+                               "NUnit.Core.TestResult",
+                               "NUnit.Core.TestSuite",
+                               "NUnit.Framework.Assertion", 
+                               "NUnit.Framework.Assert" 
+                       };
+
+                       for (int i = 0; i < patterns.Length; i++) 
+                       {
+                               if (line.IndexOf(patterns[i]) > 0)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
+       }
+}
diff --git a/mcs/nunit20/util/SummaryVisitor.cs b/mcs/nunit20/util/SummaryVisitor.cs
new file mode 100755 (executable)
index 0000000..d79099a
--- /dev/null
@@ -0,0 +1,129 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using NUnit.Core;
+
+       /// <summary>
+       /// Summary description for SiummaryVisitor.
+       /// </summary>
+       public class SummaryVisitor : ResultVisitor
+       {
+               private int totalCount;
+               private int failureCount;
+               private int testsNotRun;
+               private int suitesNotRun;
+               
+               private double time;
+               private string name;
+               private bool initialized;
+
+               public SummaryVisitor()
+               {
+                       totalCount = 0;
+                       initialized = false;
+               }
+
+               public void Visit(TestCaseResult caseResult) 
+               {
+                       SetNameandTime(caseResult.Name, caseResult.Time);
+
+                       if(caseResult.Executed)
+                       {
+                               totalCount++;
+                               if(caseResult.IsFailure)
+                                       failureCount++;
+                       }
+                       else
+                               testsNotRun++;
+               }
+
+               public void Visit(TestSuiteResult suiteResult) 
+               {
+                       SetNameandTime(suiteResult.Name, suiteResult.Time);
+
+                       
+                       
+                       foreach (TestResult result in suiteResult.Results)
+                       {
+                               result.Accept(this);
+                       }
+                       
+                       if(!suiteResult.Executed)
+                               suitesNotRun++;
+               }
+
+               public double Time
+               {
+                       get { return time; }
+               }
+
+               private void SetNameandTime(string name, double time)
+               {
+                       if(!initialized)
+                       {
+                               this.time = time;
+                               this.name = name;
+                               initialized = true;
+                       }
+               }
+
+               public bool Success
+               {
+                       get { return (failureCount == 0); }
+               }
+
+               public int Count
+               {
+                       get { return totalCount; }
+               }
+
+               public int Failures
+               {
+                       get { return failureCount; }
+               }
+
+               public int TestsNotRun
+               {
+                       get { return testsNotRun; }
+               }
+
+               public int SuitesNotRun
+               {
+                       get { return suitesNotRun; }
+               }
+
+               public string Name
+               {
+                       get { return name; }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/TestDomain.cs b/mcs/nunit20/util/TestDomain.cs
new file mode 100755 (executable)
index 0000000..2dffe46
--- /dev/null
@@ -0,0 +1,468 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+
+namespace NUnit.Util
+{
+       using System.Runtime.Remoting;
+       using System.Security.Policy;
+       using System.Reflection;
+       using System.Collections;
+       using System.Collections.Specialized;
+       using System.Configuration;
+       using System.IO;
+
+       using NUnit.Core;
+
+       public class TestDomain : TestRunner
+       {
+               #region Instance Variables
+
+               /// <summary>
+               /// The appdomain used  to load tests
+               /// </summary>
+               private AppDomain domain; 
+
+               /// <summary>
+               /// The path to our cache
+               /// </summary>
+               private string cachePath;
+               
+               /// <summary>
+               /// The remote runner loaded in the test appdomain
+               /// </summary>
+               private TestRunner testRunner;
+
+               /// <summary>
+               /// Writer for console standard output
+               /// </summary>
+               private TextWriter outWriter;
+
+               /// <summary>
+               /// Writer for console error output
+               /// </summary>
+               private TextWriter errorWriter;
+
+               /// <summary>
+               /// Holds the event listener while we are running
+               /// </summary>
+               private EventListener listener;
+
+               #endregion
+
+               #region Properties
+
+               public TextWriter Out
+               {
+                       get { return outWriter; }
+                       set { outWriter = value; }
+               }
+
+               public TextWriter Error
+               {
+                       get { return errorWriter; }
+                       set { errorWriter = value; }
+               }
+
+               private TestRunner Runner
+               {
+                       get 
+                       {
+                               if ( testRunner == null )
+                                       testRunner = MakeRemoteTestRunner( domain );
+
+                               return testRunner; 
+                       }
+               }
+
+               public bool DisplayTestLabels
+               {
+                       get { return Runner.DisplayTestLabels; }
+                       set { Runner.DisplayTestLabels = value; }
+               }
+
+               private TestRunner MakeRemoteTestRunner( AppDomain runnerDomain )
+               {
+                       object obj = runnerDomain.CreateInstanceAndUnwrap(
+                               typeof(RemoteTestRunner).Assembly.FullName, 
+                               typeof(RemoteTestRunner).FullName,
+                               false, BindingFlags.Default,null,null,null,null,null);
+                       
+                       RemoteTestRunner runner = (RemoteTestRunner) obj;
+
+                       runner.Out = this.outWriter;
+                       runner.Error = this.errorWriter;
+
+                       return runner;
+               }
+
+               public Version FrameworkVersion
+               {
+                       get { return Runner.FrameworkVersion; }
+               }
+
+               #endregion
+
+               #region Constructors
+
+               public TestDomain( TextWriter outWriter, TextWriter errorWriter )
+               { 
+                       this.outWriter = outWriter;
+                       this.errorWriter = errorWriter;
+               }
+
+               public TestDomain() : this( TextWriter.Null, TextWriter.Null ) { }
+
+               #endregion
+
+               #region Loading and Unloading Tests
+
+               public Test Load( string assemblyFileName )
+               {
+                       return Load( assemblyFileName, string.Empty );
+               }
+
+               public Test Load(string assemblyFileName, string testFixture)
+               {
+                       Unload();
+
+                       try
+                       {
+                               CreateDomain( assemblyFileName );
+                               string assemblyPath = Path.GetFullPath( assemblyFileName );
+
+                               if ( testFixture != null && testFixture != string.Empty )
+                                       return Runner.Load( assemblyPath, testFixture );
+                               else
+                                       return Runner.Load( assemblyPath );
+                       }
+                       catch
+                       {
+                               Unload();
+                               throw;
+                       }
+               }
+
+               public Test Load( string testFileName, string[] assemblies )
+               {
+                       return Load( testFileName, assemblies, null );
+               }
+
+               public Test Load( string testFileName, string[] assemblies, string testFixture )
+               {
+                       FileInfo testFile = new FileInfo( testFileName );               
+                       return Load( testFileName, testFile.DirectoryName, testFile.FullName + ".config", GetBinPath(assemblies), assemblies, testFixture );
+               }
+
+               public Test Load( string testFileName, string appBase, string configFile, string binPath, string[] assemblies, string testFixture )
+               {
+                       Unload();
+
+                       try
+                       {
+                               CreateDomain( testFileName, appBase, configFile, binPath, assemblies );
+
+                               if ( testFixture != null )
+                                       return Runner.Load( testFileName, assemblies, testFixture );
+                               else
+                                       return Runner.Load( testFileName, assemblies );
+                       }
+                       catch
+                       {
+                               Unload();
+                               throw;
+                       }
+               }
+
+               public Test Load( NUnitProject project )
+               {
+                       if ( project.IsAssemblyWrapper )
+                               return Load( project.ActiveConfig.Assemblies[0].FullPath );
+                       else
+                               return Load( project.ProjectPath, project.ActiveConfig.TestAssemblies );
+               }
+
+               public Test Load( NUnitProject project, string testFixture )
+               {
+                       if ( project.IsAssemblyWrapper )
+                               return Load( project.ActiveConfig.Assemblies[0].FullPath, testFixture );
+                       else
+                               return Load( project.ProjectPath, project.ActiveConfig.TestAssemblies, testFixture );
+               }
+
+               public void Unload()
+               {
+                       testRunner = null;
+
+                       if(domain != null) 
+                       {
+                               try
+                               {
+                                       AppDomain.Unload(domain);
+                                       DirectoryInfo cacheDir = new DirectoryInfo(cachePath);
+                                       if(cacheDir.Exists) cacheDir.Delete(true);
+                               }
+                               catch( CannotUnloadAppDomainException )
+                               {
+                                       // TODO: Do something useful. For now we just
+                                       // leave the orphaned AppDomain "out there"
+                                       // rather than aborting the application.
+                               }
+                               finally
+                               {
+                                       domain = null;
+                               }
+                       }
+               }
+
+               public static string GetBinPath( string[] assemblies )
+               {
+                       ArrayList dirs = new ArrayList();
+                       string binPath = null;
+
+                       foreach( string path in assemblies )
+                       {
+                               string dir = Path.GetDirectoryName( Path.GetFullPath( path ) );
+                               if ( !dirs.Contains( dir ) )
+                               {
+                                       dirs.Add( dir );
+
+                                       if ( binPath == null )
+                                               binPath = dir;
+                                       else
+                                               binPath = binPath + ";" + dir;
+                               }
+                       }
+
+                       return binPath;
+               }
+
+               #endregion
+
+               #region Counting Tests
+
+               public int CountTestCases()
+               {
+                       return Runner.CountTestCases();
+               }
+
+               public int CountTestCases( string testName )
+               {
+                       return Runner.CountTestCases( testName );
+               }
+
+               
+               public int CountTestCases( string[] testNames )
+               {
+                       return Runner.CountTestCases( testNames );
+               }
+
+               #endregion
+
+               public ICollection GetCategories()
+               {
+                       return Runner.GetCategories();
+               }
+
+               #region Running Tests
+
+//             public TestResult Run(NUnit.Core.EventListener listener, IFilter filter)
+//             {
+//                     return Runner.Run( listener, filter );
+//             }
+
+               public void SetFilter( IFilter filter )
+               {
+                       Runner.SetFilter( filter );
+               }
+
+               public TestResult Run(NUnit.Core.EventListener listener)
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               return Runner.Run( listener );
+                       }
+               }
+               
+               public TestResult Run(NUnit.Core.EventListener listener, string testName)
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               return Runner.Run( listener, testName );
+                       }
+               }
+
+               public TestResult[] Run(NUnit.Core.EventListener listener, string[] testNames)
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               return Runner.Run( listener, testNames );
+                       }
+               }
+
+               public void RunTest(NUnit.Core.EventListener listener )
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               Runner.RunTest( listener );
+                       }
+               }
+               
+               public void RunTest(NUnit.Core.EventListener listener, string testName )
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               Runner.RunTest( listener, testName );
+                       }
+               }
+
+               public void RunTest(NUnit.Core.EventListener listener, string[] testNames)
+               {
+                       using( new TestExceptionHandler( new UnhandledExceptionEventHandler( OnUnhandledException ) ) )
+                       {
+                               this.listener = listener;
+                               Runner.RunTest( listener, testNames );
+                       }
+               }
+
+               public void CancelRun()
+               {
+                       Runner.CancelRun();
+               }
+
+               // For now, just publish any unhandled exceptions and let the listener
+               // figure out what to do with them.
+               private void OnUnhandledException( object sender, UnhandledExceptionEventArgs e )
+               {
+                       this.listener.UnhandledException( (Exception)e.ExceptionObject );
+               }
+
+               #endregion
+
+               #region Helpers Used in AppDomain Creation
+
+               /// <summary>
+               /// Construct an application domain for testing a single assembly
+               /// </summary>
+               /// <param name="assemblyFileName">The assembly file name</param>
+               private void CreateDomain( string assemblyFileName )
+               {
+                       FileInfo testFile = new FileInfo( assemblyFileName );
+                       
+                       string assemblyPath = Path.GetFullPath( assemblyFileName );
+                       string domainName = string.Format( "domain-{0}", Path.GetFileName( assemblyFileName ) );
+
+                       domain = MakeAppDomain( domainName, testFile.DirectoryName, testFile.FullName + ".config", testFile.DirectoryName );
+               }
+
+               /// <summary>
+               /// Construct an application domain for testing multiple assemblies
+               /// </summary>
+               /// <param name="testFileName">The file name of the project file</param>
+               /// <param name="appBase">The application base path</param>
+               /// <param name="configFile">The configuration file to use</param>
+               /// <param name="binPath">The private bin path</param>
+               /// <param name="assemblies">A collection of assemblies to load</param>
+               private void CreateDomain( string testFileName, string appBase, string configFile, string binPath, string[] assemblies )
+               {
+                       string domainName = string.Format( "domain-{0}", Path.GetFileName( testFileName ) );
+                       domain = MakeAppDomain( testFileName, appBase, configFile, binPath );
+               }
+
+               private void CreateDomain( NUnitProject project )
+               {
+                       ProjectConfig cfg = project.ActiveConfig;
+
+                       if ( project.IsAssemblyWrapper )
+                               CreateDomain( cfg.Assemblies[0].FullPath );
+                       else
+                               CreateDomain( project.ProjectPath, cfg.BasePath, cfg.ConfigurationFilePath, cfg.PrivateBinPath, cfg.TestAssemblies );
+               }
+
+               /// <summary>
+               /// This method creates appDomains for the framework.
+               /// </summary>
+               /// <param name="domainName">Name of the domain</param>
+               /// <param name="appBase">ApplicationBase for the domain</param>
+               /// <param name="configFile">ConfigurationFile for the domain</param>
+               /// <param name="binPath">PrivateBinPath for the domain</param>
+               /// <returns></returns>
+               private AppDomain MakeAppDomain( string domainName, string appBase, string configFile, string binPath )
+               {
+                       Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
+                       Evidence evidence = new Evidence(baseEvidence);
+
+                       AppDomainSetup setup = new AppDomainSetup();
+
+                       // We always use the same application name
+                       setup.ApplicationName = "Tests";
+                       // We always want to do shadow copying. Note that we do NOT
+                       // set ShadowCopyDirectories because we  rely on the default
+                       // setting of ApplicationBase plus PrivateBinPath
+                       setup.ShadowCopyFiles = "true";
+                       setup.ShadowCopyDirectories = appBase;
+
+                       setup.ApplicationBase = appBase;
+                       setup.ConfigurationFile =  configFile;
+                       setup.PrivateBinPath = binPath;
+
+                       AppDomain runnerDomain = AppDomain.CreateDomain(domainName, evidence, setup);
+                       
+                       ConfigureCachePath(runnerDomain);
+
+                       return runnerDomain;
+               }
+
+               /// <summary>
+               /// Set the location for caching and delete any old cache info
+               /// </summary>
+               /// <param name="domain">Our domain</param>
+               private void ConfigureCachePath(AppDomain domain)
+               {
+                       cachePath = String.Format(@"{0}\{1}", 
+                               ConfigurationSettings.AppSettings["shadowfiles.path"], DateTime.Now.Ticks);
+                       cachePath = Environment.ExpandEnvironmentVariables(cachePath);
+
+                       DirectoryInfo dir = new DirectoryInfo(cachePath);
+                       if(dir.Exists) dir.Delete(true);
+
+                       domain.SetCachePath(cachePath);
+
+                       return;
+               }
+
+               #endregion
+       }
+}
diff --git a/mcs/nunit20/util/TestEventDispatcher.cs b/mcs/nunit20/util/TestEventDispatcher.cs
new file mode 100755 (executable)
index 0000000..3c4a289
--- /dev/null
@@ -0,0 +1,257 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Collections;
+using NUnit.Core;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Helper class used to dispatch test events
+       /// </summary>
+       public class ProjectEventDispatcher : TestEventDispatcher, IProjectEvents
+       {
+               #region Events
+
+               // Project loading events
+               public event TestProjectEventHandler ProjectLoading;
+               public event TestProjectEventHandler ProjectLoaded;
+               public event TestProjectEventHandler ProjectLoadFailed;
+               public event TestProjectEventHandler ProjectUnloading;
+               public event TestProjectEventHandler ProjectUnloaded;
+               public event TestProjectEventHandler ProjectUnloadFailed;
+
+               // Test loading events
+//             public event TestEventHandler TestLoading;      
+//             public event TestEventHandler TestLoaded;       
+//             public event TestEventHandler TestLoadFailed;
+//
+//             public event TestEventHandler TestReloading;
+//             public event TestEventHandler TestReloaded;
+//             public event TestEventHandler TestReloadFailed;
+//
+//             public event TestEventHandler TestUnloading;
+//             public event TestEventHandler TestUnloaded;
+//             public event TestEventHandler TestUnloadFailed;
+//
+//             // Test running events
+//             public event TestEventHandler RunStarting;      
+//             public event TestEventHandler RunFinished;
+//             
+//             public event TestEventHandler SuiteStarting;
+//             public event TestEventHandler SuiteFinished;
+//
+//             public event TestEventHandler TestStarting;
+//             public event TestEventHandler TestFinished;
+//
+//             public event TestEventHandler TestException;
+
+               #endregion
+
+               #region Methods for Firing Events
+               
+               private void Fire( 
+                       TestEventHandler handler, TestEventArgs e )
+               {
+                       if ( handler != null )
+                               handler( this, e );
+               }
+
+               private void Fire( 
+                       TestProjectEventHandler handler, TestProjectEventArgs e )
+               {
+                       if ( handler != null )
+                               handler( this, e );
+               }
+
+               public void FireProjectLoading( string fileName )
+               {
+                       Fire(
+                               ProjectLoading,
+                               new TestProjectEventArgs( TestProjectAction.ProjectLoading, fileName ) );
+               }
+
+               public void FireProjectLoaded( string fileName )
+               {
+                       Fire( 
+                               ProjectLoaded,
+                               new TestProjectEventArgs( TestProjectAction.ProjectLoaded, fileName ) );
+               }
+
+               public void FireProjectLoadFailed( string fileName, Exception exception )
+               {
+                       Fire( 
+                               ProjectLoadFailed,
+                               new TestProjectEventArgs( TestProjectAction.ProjectLoadFailed, fileName, exception ) );
+               }
+
+               public void FireProjectUnloading( string fileName )
+               {
+                       Fire( 
+                               ProjectUnloading,
+                               new TestProjectEventArgs( TestProjectAction.ProjectUnloading, fileName ) );
+               }
+
+               public void FireProjectUnloaded( string fileName )
+               {
+                       Fire( 
+                               ProjectUnloaded,
+                               new TestProjectEventArgs( TestProjectAction.ProjectUnloaded, fileName ) );
+               }
+
+               public void FireProjectUnloadFailed( string fileName, Exception exception )
+               {
+                       Fire( 
+                               ProjectUnloadFailed,
+                               new TestProjectEventArgs( TestProjectAction.ProjectUnloadFailed, fileName, exception ) );
+               }
+
+//             public void FireTestLoading( string fileName )
+//             {
+//                     Fire( 
+//                             TestLoading,
+//                             new TestEventArgs( TestAction.TestLoading, fileName ) );
+//             }
+//
+//             public void FireTestLoaded( string fileName, ITest test )
+//             {
+//                     Fire( 
+//                             TestLoaded,
+//                             new TestEventArgs( TestAction.TestLoaded, fileName, test ) );
+//             }
+//
+//             public void FireTestLoadFailed( string fileName, Exception exception )
+//             {
+//                     Fire(
+//                             TestLoadFailed,
+//                             new TestEventArgs( TestAction.TestLoadFailed, fileName, exception ) );
+//             }
+//
+//             public void FireTestUnloading( string fileName, ITest test )
+//             {
+//                     Fire(
+//                             TestUnloading,
+//                             new TestEventArgs( TestAction.TestUnloading, fileName, test ) );
+//             }
+//
+//             public void FireTestUnloaded( string fileName, ITest test )
+//             {
+//                     Fire(
+//                             TestUnloaded,
+//                             new TestEventArgs( TestAction.TestUnloaded, fileName, test ) );
+//             }
+//
+//             public void FireTestUnloadFailed( string fileName, Exception exception )
+//             {
+//                     Fire(
+//                             TestUnloadFailed, 
+//                             new TestEventArgs( TestAction.TestUnloadFailed, fileName, exception ) );
+//             }
+//
+//             public void FireTestReloading( string fileName, ITest test )
+//             {
+//                     Fire(
+//                             TestReloading,
+//                             new TestEventArgs( TestAction.TestReloading, fileName, test ) );
+//             }
+//
+//             public void FireTestReloaded( string fileName, ITest test )
+//             {
+//                     Fire(
+//                             TestReloaded,
+//                             new TestEventArgs( TestAction.TestReloaded, fileName, test ) );
+//             }
+//
+//             public void FireTestReloadFailed( string fileName, Exception exception )
+//             {
+//                     Fire(
+//                             TestReloadFailed, 
+//                             new TestEventArgs( TestAction.TestReloadFailed, fileName, exception ) );
+//             }
+//
+//             public void FireRunStarting( ITest[] tests, int count )
+//             {
+//                     Fire(
+//                             RunStarting,
+//                             new TestEventArgs( TestAction.RunStarting, tests, count ) );
+//             }
+//
+//             public void FireRunFinished( TestResult[] results )
+//             {       
+//                     Fire(
+//                             RunFinished,
+//                             new TestEventArgs( TestAction.RunFinished, results ) );
+//             }
+//
+//             public void FireRunFinished( Exception exception )
+//             {
+//                     Fire(
+//                             RunFinished,
+//                             new TestEventArgs( TestAction.RunFinished, exception ) );
+//             }
+//
+//             public void FireTestStarting( ITest test )
+//             {
+//                     Fire(
+//                             TestStarting,
+//                             new TestEventArgs( TestAction.TestStarting, test ) );
+//             }
+//
+//             public void FireTestFinished( TestResult result )
+//             {       
+//                     Fire(
+//                             TestFinished,
+//                             new TestEventArgs( TestAction.TestFinished, result ) );
+//             }
+//
+//             public void FireSuiteStarting( ITest test )
+//             {
+//                     Fire(
+//                             SuiteStarting,
+//                             new TestEventArgs( TestAction.SuiteStarting, test ) );
+//             }
+//
+//             public void FireSuiteFinished( TestResult result )
+//             {       
+//                     Fire(
+//                             SuiteFinished,
+//                             new TestEventArgs( TestAction.SuiteFinished, result ) );
+//             }
+//
+//             public void FireTestException( Exception exception )
+//             {
+//                     Fire(
+//                             TestException,
+//                             new TestEventArgs( TestAction.TestException, exception ) );
+//             }
+
+               #endregion
+       }
+}
diff --git a/mcs/nunit20/util/TestExceptionHandler.cs b/mcs/nunit20/util/TestExceptionHandler.cs
new file mode 100755 (executable)
index 0000000..2e370c2
--- /dev/null
@@ -0,0 +1,40 @@
+using System;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Summary description for UnhandledExceptionCatcher.
+       /// </summary>
+       public class TestExceptionHandler : IDisposable
+       {
+               private UnhandledExceptionEventHandler handler;
+
+               public TestExceptionHandler( UnhandledExceptionEventHandler handler )
+               {
+                       this.handler = handler;
+                       AppDomain.CurrentDomain.UnhandledException += handler;
+               }
+
+               ~TestExceptionHandler()
+               {
+                       if ( handler != null )
+                       {
+                               AppDomain.CurrentDomain.UnhandledException -= handler;
+                               handler = null;
+                       }
+               }
+
+
+
+               public void Dispose()
+               {
+                       if ( handler != null )
+                       {
+                               AppDomain.CurrentDomain.UnhandledException -= handler;
+                               handler = null;
+                       }
+
+                       System.GC.SuppressFinalize( this );
+               }
+       }
+}
diff --git a/mcs/nunit20/util/TestLoader.cs b/mcs/nunit20/util/TestLoader.cs
new file mode 100755 (executable)
index 0000000..3775d0f
--- /dev/null
@@ -0,0 +1,698 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using System.IO;
+       using System.Collections;
+       using System.Configuration;
+       using System.Threading;
+       using NUnit.Core;
+
+
+       /// <summary>
+       /// TestLoader handles interactions between a test runner and a 
+       /// client program - typically the user interface - for the 
+       /// purpose of loading, unloading and running tests.
+       /// 
+       /// It implemements the EventListener interface which is used by 
+       /// the test runner and repackages those events, along with
+       /// others as individual events that clients may subscribe to
+       /// in collaboration with a TestEventDispatcher helper object.
+       /// 
+       /// TestLoader is quite handy for use with a gui client because
+       /// of the large number of events it supports. However, it has
+       /// no dependencies on ui components and can be used independently.
+       /// </summary>
+       public class TestLoader : LongLivingMarshalByRefObject, NUnit.Core.EventListener, ITestLoader
+       {
+               #region Instance Variables
+
+               /// <summary>
+               /// StdOut stream for use by the TestRunner
+               /// </summary>
+               private TextWriter stdOutWriter;
+
+               /// <summary>
+               /// StdErr stream for use by the TestRunner
+               /// </summary>
+               private TextWriter stdErrWriter;
+
+               /// <summary>
+               /// Our event dispatiching helper object
+               /// </summary>
+               private ProjectEventDispatcher events;
+
+               /// <summary>
+               /// Loads and executes tests. Non-null when
+               /// we have loaded a test.
+               /// </summary>
+               private TestDomain testDomain = null;
+
+               /// <summary>
+               /// Our current test project, if we have one.
+               /// </summary>
+               private NUnitProject testProject = null;
+
+               /// <summary>
+               /// The currently loaded test, returned by the testrunner
+               /// </summary>
+               private Test loadedTest = null;
+
+               /// <summary>
+               /// The test name that was specified when loading
+               /// </summary>
+               private string loadedTestName = null;
+
+               /// <summary>
+               /// The tests that are running
+               /// </summary>
+               private ITest[] runningTests = null;
+
+               /// <summary>
+               /// Result of the last test run
+               /// </summary>
+               private TestResult[] results = null;
+
+               /// <summary>
+               /// The last exception received when trying to load, unload or run a test
+               /// </summary>
+               private Exception lastException = null;
+
+               /// <summary>
+               /// Watcher fires when the assembly changes
+               /// </summary>
+               private AssemblyWatcher watcher;
+
+               /// <summary>
+               /// Assembly changed during a test and
+               /// needs to be reloaded later
+               /// </summary>
+               private bool reloadPending = false;
+
+               /// <summary>
+               /// Indicates whether to watch for changes
+               /// and reload the tests when a change occurs.
+               /// </summary>
+               private bool reloadOnChange = false;
+
+               /// <summary>
+               /// Indicates whether to reload the tests
+               /// before each run.
+               /// </summary>
+               private bool reloadOnRun = false;
+
+               private IFilter filter;
+
+               #endregion
+
+               #region Constructor
+
+               public TestLoader(TextWriter stdOutWriter, TextWriter stdErrWriter )
+               {
+                       this.stdOutWriter = stdOutWriter;
+                       this.stdErrWriter = stdErrWriter;
+                       this.events = new ProjectEventDispatcher();
+               }
+
+               #endregion
+
+               #region Properties
+
+               public bool IsProjectLoaded
+               {
+                       get { return testProject != null; }
+               }
+
+               public bool IsTestLoaded
+               {
+                       get { return loadedTest != null; }
+               }
+
+               public bool IsTestRunning
+               {
+                       get { return runningTests != null; }
+               }
+
+               public NUnitProject TestProject
+               {
+                       get { return testProject; }
+                       set     { OnProjectLoad( value ); }
+               }
+
+               public IProjectEvents Events
+               {
+                       get { return events; }
+               }
+
+               public string TestFileName
+               {
+                       get { return testProject.ProjectPath; }
+               }
+
+               public TestResult[] Results
+               {
+                       get { return results; }
+               }
+
+               public Exception LastException
+               {
+                       get { return lastException; }
+               }
+
+               public bool ReloadOnChange
+               {
+                       get { return reloadOnChange; }
+                       set { reloadOnChange = value; }
+               }
+
+               public bool ReloadOnRun
+               {
+                       get { return reloadOnRun; }
+                       set { reloadOnRun = value; }
+               }
+
+               public Version FrameworkVersion
+               {
+                       get { return this.testDomain.FrameworkVersion; }
+               }
+
+               #endregion
+
+               #region EventListener Handlers
+
+               void EventListener.RunStarted(Test[] tests)
+               {
+                       int count = 0;
+                       foreach( Test test in tests )
+                               count += filter == null ? test.CountTestCases() : test.CountTestCases( filter );
+
+                       events.FireRunStarting( tests, count );
+               }
+
+               void EventListener.RunFinished(NUnit.Core.TestResult[] results)
+               {
+                       this.results = results;
+                       events.FireRunFinished( results );
+                       runningTests = null;
+               }
+
+               void EventListener.RunFinished(Exception exception)
+               {
+                       this.lastException = exception;
+                       events.FireRunFinished( exception );
+                       runningTests = null;
+               }
+
+               /// <summary>
+               /// Trigger event when each test starts
+               /// </summary>
+               /// <param name="testCase">TestCase that is starting</param>
+               void EventListener.TestStarted(NUnit.Core.TestCase testCase)
+               {
+                       events.FireTestStarting( testCase );
+               }
+
+               /// <summary>
+               /// Trigger event when each test finishes
+               /// </summary>
+               /// <param name="result">Result of the case that finished</param>
+               void EventListener.TestFinished(TestCaseResult result)
+               {
+                       events.FireTestFinished( result );
+               }
+
+               /// <summary>
+               /// Trigger event when each suite starts
+               /// </summary>
+               /// <param name="suite">Suite that is starting</param>
+               void EventListener.SuiteStarted(TestSuite suite)
+               {
+                       events.FireSuiteStarting( suite );
+               }
+
+               /// <summary>
+               /// Trigger event when each suite finishes
+               /// </summary>
+               /// <param name="result">Result of the suite that finished</param>
+               void EventListener.SuiteFinished(TestSuiteResult result)
+               {
+                       events.FireSuiteFinished( result );
+               }
+
+               /// <summary>
+               /// Trigger event when an unhandled exception occurs during a test
+               /// </summary>
+               /// <param name="exception">The unhandled exception</param>
+               void EventListener.UnhandledException(Exception exception)
+               {
+                       events.FireTestException( exception );
+               }
+
+               #endregion
+
+               #region Methods for Loading and Unloading Projects
+               
+               /// <summary>
+               /// Create a new project with default naming
+               /// </summary>
+               public void NewProject()
+               {
+                       try
+                       {
+                               events.FireProjectLoading( "New Project" );
+
+                               OnProjectLoad( NUnitProject.NewProject() );
+                       }
+                       catch( Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireProjectLoadFailed( "New Project", exception );
+                       }
+               }
+
+               /// <summary>
+               /// Create a new project using a given path
+               /// </summary>
+               public void NewProject( string filePath )
+               {
+                       try
+                       {
+                               events.FireProjectLoading( filePath );
+
+                               NUnitProject project = new NUnitProject( filePath );
+
+                               project.Configs.Add( "Debug" );
+                               project.Configs.Add( "Release" );                       
+                               project.IsDirty = false;
+
+                               OnProjectLoad( project );
+                       }
+                       catch( Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireProjectLoadFailed( filePath, exception );
+                       }
+               }
+
+               /// <summary>
+               /// Load a new project, optionally selecting the config and fire events
+               /// </summary>
+               public void LoadProject( string filePath, string configName )
+               {
+                       try
+                       {
+                               events.FireProjectLoading( filePath );
+
+                               NUnitProject newProject = NUnitProject.LoadProject( filePath );
+                               if ( configName != null ) 
+                               {
+                                       newProject.SetActiveConfig( configName );
+                                       newProject.IsDirty = false;
+                               }
+
+                               OnProjectLoad( newProject );
+
+//                             return true;
+                       }
+                       catch( Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireProjectLoadFailed( filePath, exception );
+
+//                             return false;
+                       }
+               }
+
+               /// <summary>
+               /// Load a new project using the default config and fire events
+               /// </summary>
+               public void LoadProject( string filePath )
+               {
+                       LoadProject( filePath, null );
+               }
+
+               /// <summary>
+               /// Load a project from a list of assemblies and fire events
+               /// </summary>
+               public void LoadProject( string[] assemblies )
+               {
+                       try
+                       {
+                               events.FireProjectLoading( "New Project" );
+
+                               NUnitProject newProject = NUnitProject.FromAssemblies( assemblies );
+
+                               OnProjectLoad( newProject );
+
+//                             return true;
+                       }
+                       catch( Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireProjectLoadFailed( "New Project", exception );
+
+//                             return false;
+                       }
+               }
+
+               /// <summary>
+               /// Unload the current project and fire events
+               /// </summary>
+               public void UnloadProject()
+               {
+                       string testFileName = TestFileName;
+
+                       try
+                       {
+                               events.FireProjectUnloading( testFileName );
+
+#if !MONO
+                               if ( testFileName != null && File.Exists( testFileName ) )
+                                       UserSettings.RecentProjects.RecentFile = testFileName;
+#endif
+
+                               if ( IsTestLoaded )
+                                       UnloadTest();
+
+                               testProject.Changed -= new ProjectEventHandler( OnProjectChanged );
+                               testProject = null;
+
+                               events.FireProjectUnloaded( testFileName );
+                       }
+                       catch (Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireProjectUnloadFailed( testFileName, exception );
+                       }
+
+               }
+
+               /// <summary>
+               /// Common operations done each time a project is loaded
+               /// </summary>
+               /// <param name="testProject">The newly loaded project</param>
+               private void OnProjectLoad( NUnitProject testProject )
+               {
+                       if ( IsProjectLoaded )
+                               UnloadProject();
+
+                       this.testProject = testProject;
+                       testProject.Changed += new ProjectEventHandler( OnProjectChanged );
+
+                       events.FireProjectLoaded( TestFileName );
+               }
+
+               private void OnProjectChanged( object sender, ProjectEventArgs e )
+               {
+                       switch ( e.type )
+                       {
+                               case ProjectChangeType.ActiveConfig:
+                                       if( TestProject.IsLoadable )
+                                               LoadTest();
+                                       break;
+
+                               case ProjectChangeType.AddConfig:
+                               case ProjectChangeType.UpdateConfig:
+                                       if ( e.configName == TestProject.ActiveConfigName && TestProject.IsLoadable )
+                                               LoadTest();
+                                       break;
+
+                               case ProjectChangeType.RemoveConfig:
+                                       if ( IsTestLoaded && TestProject.Configs.Count == 0 )
+                                               UnloadTest();
+                                       break;
+
+                               default:
+                                       break;
+                       }
+               }
+
+               #endregion
+
+               #region Methods for Loading and Unloading Tests
+
+               public void LoadTest()
+               {
+                       LoadTest( null );
+               }
+               
+               public void LoadTest( string testName )
+               {
+                       try
+                       {
+                               events.FireTestLoading( TestFileName );
+
+                               testDomain = new TestDomain( stdOutWriter, stdErrWriter );              
+                               Test test = testDomain.Load( TestProject, testName );
+
+                               TestSuite suite = test as TestSuite;
+                               if ( suite != null )
+                                       suite.Sort();
+                       
+                               loadedTest = test;
+                               loadedTestName = testName;
+                               results = null;
+                               reloadPending = false;
+                       
+                               if ( ReloadOnChange )
+                                       InstallWatcher( );
+
+                               events.FireTestLoaded( TestFileName, this.loadedTest );
+                       }
+                       catch( FileNotFoundException exception )
+                       {
+                               lastException = exception;
+
+                               foreach( string assembly in TestProject.ActiveConfig.AbsolutePaths )
+                               {
+                                       if ( Path.GetFileNameWithoutExtension( assembly ) == exception.FileName &&
+                                               !ProjectPath.SamePathOrUnder( testProject.ActiveConfig.BasePath, assembly ) )
+                                       {
+                                               lastException = new ApplicationException( string.Format( "Unable to load {0} because it is not located under the AppBase", exception.FileName ), exception );
+                                               break;
+                                       }
+                               }
+
+                               events.FireTestLoadFailed( TestFileName, lastException );
+                       }
+                       catch( Exception exception )
+                       {
+                               lastException = exception;
+                               events.FireTestLoadFailed( TestFileName, exception );
+                       }
+               }
+
+               /// <summary>
+               /// Unload the current test suite and fire the Unloaded event
+               /// </summary>
+               public void UnloadTest( )
+               {
+                       if( IsTestLoaded )
+                       {
+                               // Hold the name for notifications after unload
+                               string fileName = TestFileName;
+
+                               try
+                               {
+                                       events.FireTestUnloading( TestFileName, this.loadedTest );
+
+                                       RemoveWatcher();
+
+                                       testDomain.Unload();
+
+                                       testDomain = null;
+
+                                       loadedTest = null;
+                                       loadedTestName = null;
+                                       results = null;
+                                       reloadPending = false;
+
+                                       events.FireTestUnloaded( fileName, this.loadedTest );
+                               }
+                               catch( Exception exception )
+                               {
+                                       lastException = exception;
+                                       events.FireTestUnloadFailed( fileName, exception );
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// Reload the current test on command
+               /// </summary>
+               public void ReloadTest()
+               {
+                       OnTestChanged( TestFileName );
+               }
+
+               /// <summary>
+               /// Handle watcher event that signals when the loaded assembly
+               /// file has changed. Make sure it's a real change before
+               /// firing the SuiteChangedEvent. Since this all happens
+               /// asynchronously, we use an event to let ui components
+               /// know that the failure happened.
+               /// </summary>
+               /// <param name="assemblyFileName">Assembly file that changed</param>
+               public void OnTestChanged( string testFileName )
+               {
+                       if ( IsTestRunning )
+                               reloadPending = true;
+                       else 
+                               try
+                               {
+                                       events.FireTestReloading( testFileName, this.loadedTest );
+
+                                       // Don't unload the old domain till after the event
+                                       // handlers get a chance to compare the trees.
+                                       TestDomain newDomain = new TestDomain( stdOutWriter, stdErrWriter );
+                                       Test newTest = newDomain.Load( testProject, loadedTestName );
+                                       TestSuite suite = newTest as TestSuite;
+                                       if ( suite != null )
+                                               suite.Sort();
+
+                                       testDomain.Unload();
+
+                                       testDomain = newDomain;
+                                       loadedTest = newTest;
+                                       reloadPending = false;
+
+                                       events.FireTestReloaded( testFileName, newTest );                               
+                               }
+                               catch( Exception exception )
+                               {
+                                       lastException = exception;
+                                       events.FireTestReloadFailed( testFileName, exception );
+                               }
+               }
+
+               #endregion
+
+               #region Methods for Running Tests
+
+               public void SetFilter( IFilter filter )
+               {
+                       this.filter = filter;
+               }
+
+               /// <summary>
+               /// Run the currently loaded top level test suite
+               /// </summary>
+               public void RunLoadedTest()
+               {
+                       RunTest( loadedTest );
+               }
+
+               /// <summary>
+               /// Run a testcase or testsuite from the currrent tree
+               /// firing the RunStarting and RunFinished events.
+               /// Silently ignore the call if a test is running
+               /// to allow for latency in the UI.
+               /// </summary>
+               /// <param name="testName">The test to be run</param>
+               public void RunTest( ITest test )
+               {
+                       RunTests( new ITest[] { test } );
+               }
+
+               public void RunTests( ITest[] tests )
+               {
+                       if ( !IsTestRunning )
+                       {
+                               if ( reloadPending || ReloadOnRun )
+                                       ReloadTest();
+
+                               runningTests = tests;
+
+                               //kind of silly
+                               string[] testNames = new string[ runningTests.Length ];
+                               int index = 0; 
+                               foreach (ITest node in runningTests) 
+                                       testNames[index++] = node.UniqueName;
+
+                               testDomain.SetFilter( filter );
+#if !MONO
+                               testDomain.DisplayTestLabels = UserSettings.Options.TestLabels;
+#endif
+                               testDomain.RunTest( this, testNames );
+                       }
+               }
+
+               /// <summary>
+               /// Cancel the currently running test.
+               /// Fail silently if there is none to
+               /// allow for latency in the UI.
+               /// </summary>
+               public void CancelTestRun()
+               {
+                       if ( IsTestRunning )
+                               testDomain.CancelRun();
+               }
+
+               public IList GetCategories() 
+               {
+                       ArrayList list = new ArrayList();
+                       list.AddRange(testDomain.GetCategories());
+                       return list;
+               }
+
+               #endregion
+
+               #region Helper Methods
+
+               /// <summary>
+               /// Install our watcher object so as to get notifications
+               /// about changes to a test.
+               /// </summary>
+               /// <param name="assemblyFileName">Full path of the assembly to watch</param>
+               private void InstallWatcher()
+               {
+                       if(watcher!=null) watcher.Stop();
+
+                       watcher = new AssemblyWatcher( 1000, TestProject.ActiveConfig.AbsolutePaths );
+                       watcher.AssemblyChangedEvent += new AssemblyWatcher.AssemblyChangedHandler( OnTestChanged );
+                       watcher.Start();
+               }
+
+               /// <summary>
+               /// Stop and remove our current watcher object.
+               /// </summary>
+               private void RemoveWatcher()
+               {
+                       if ( watcher != null )
+                       {
+                               watcher.Stop();
+                               watcher = null;
+                       }
+               }
+
+               #endregion
+       }
+}
diff --git a/mcs/nunit20/util/TestResultItem.cs b/mcs/nunit20/util/TestResultItem.cs
new file mode 100755 (executable)
index 0000000..06fac46
--- /dev/null
@@ -0,0 +1,86 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+
+namespace NUnit.Util
+{
+       using NUnit.Core;
+
+       /// <summary>
+       /// Summary description for TestResultItem.
+       /// </summary>
+       public class TestResultItem
+       {
+               private string testName;
+               private string message;
+               private string stackTrace;
+
+               public TestResultItem(TestResult result )
+               {
+                       testName = result.Name;
+                       message = result.Message;
+                       stackTrace = result.StackTrace;
+               }
+
+               public override string ToString()
+               {
+                       return String.Format("{0} : {1}", testName, message);
+               }
+
+               public string GetMessage()
+               {
+                       return ToString();
+               }
+
+        public string GetToolTipMessage()   //NRG 05/28/03 - Substitute spaces for tab characters
+        {
+            return (ReplaceTabs(GetMessage(), 8)); // Change each tab to 8 space characters
+        }
+
+        public string ReplaceTabs(string strOriginal, int nSpaces)  //NRG 05/28/03
+        {
+            string strSpaces = string.Empty;
+            strSpaces = strSpaces.PadRight(nSpaces, ' ');
+            return(strOriginal.Replace("\t", strSpaces));
+        }
+
+               public string StackTrace
+               {
+                       get 
+                       {
+                               string trace = "No stack trace is available";
+                               if(stackTrace != null)
+                                       trace = StackTraceFilter.Filter(stackTrace);
+
+                               return stackTrace;
+                       }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/Transform.resources b/mcs/nunit20/util/Transform.resources
new file mode 100755 (executable)
index 0000000..3c1f9ab
Binary files /dev/null and b/mcs/nunit20/util/Transform.resources differ
diff --git a/mcs/nunit20/util/Transform.resx b/mcs/nunit20/util/Transform.resx
new file mode 100755 (executable)
index 0000000..17b347a
--- /dev/null
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8" ?>\r
+<root>\r
+       <!-- \r
+            Microsoft ResX Schema \r
+        \r
+            Version 1.3\r
+                \r
+            The primary goals of this format is to allow a simple XML format \r
+            that is mostly human readable. The generation and parsing of the \r
+            various data types are done through the TypeConverter classes \r
+            associated with the data types.\r
+        \r
+            Example:\r
+        \r
+                ... ado.net/XML headers & schema ...\r
+                <resheader name="resmimetype">text/microsoft-resx</resheader>\r
+                <resheader name="version">1.3</resheader>\r
+                <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\r
+                <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\r
+                <data name="Name1">this is my long string</data>\r
+                <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>\r
+                <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">\r
+                    [base64 mime encoded serialized .NET Framework object]\r
+                </data>\r
+                <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">\r
+                    [base64 mime encoded string representing a byte array form of the .NET Framework object]\r
+                </data>\r
+        \r
+            There are any number of "resheader" rows that contain simple \r
+            name/value pairs.\r
+            \r
+            Each data row contains a name, and value. The row also contains a \r
+            type or mimetype. Type corresponds to a .NET class that support \r
+            text/value conversion through the TypeConverter architecture. \r
+            Classes that don't support this are serialized and stored with the \r
+            mimetype set.\r
+                     \r
+            The mimetype is used for serialized objects, and tells the \r
+            ResXResourceReader how to depersist the object. This is currently not \r
+            extensible. For a given mimetype the value must be set accordingly:\r
+        \r
+            Note - application/x-microsoft.net.object.binary.base64 is the format \r
+                   that the ResXResourceWriter will generate, however the reader can \r
+                   read any of the formats listed below.\r
+        \r
+            mimetype: application/x-microsoft.net.object.binary.base64\r
+            value   : The object must be serialized with \r
+                    : System.Serialization.Formatters.Binary.BinaryFormatter\r
+                    : and then encoded with base64 encoding.\r
+        \r
+            mimetype: application/x-microsoft.net.object.soap.base64\r
+            value   : The object must be serialized with \r
+                    : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\r
+                    : and then encoded with base64 encoding.\r
+            mimetype: application/x-microsoft.net.object.bytearray.base64\r
+            value   : The object must be serialized into a byte array \r
+                    : using a System.ComponentModel.TypeConverter\r
+                    : and then encoded with base64 encoding.\r
+        -->\r
+       <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
+               <xsd:element name="root" msdata:IsDataSet="true">\r
+                       <xsd:complexType>\r
+                               <xsd:choice maxOccurs="unbounded">\r
+                                       <xsd:element name="data">\r
+                                               <xsd:complexType>\r
+                                                       <xsd:sequence>\r
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                                                               <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
+                                                       </xsd:sequence>\r
+                                                       <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />\r
+                                                       <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />\r
+                                                       <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />\r
+                                               </xsd:complexType>\r
+                                       </xsd:element>\r
+                                       <xsd:element name="resheader">\r
+                                               <xsd:complexType>\r
+                                                       <xsd:sequence>\r
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
+                                                       </xsd:sequence>\r
+                                                       <xsd:attribute name="name" type="xsd:string" use="required" />\r
+                                               </xsd:complexType>\r
+                                       </xsd:element>\r
+                               </xsd:choice>\r
+                       </xsd:complexType>\r
+               </xsd:element>\r
+       </xsd:schema>\r
+       <resheader name="resmimetype">\r
+               <value>text/microsoft-resx</value>\r
+       </resheader>\r
+       <resheader name="version">\r
+               <value>1.3</value>\r
+       </resheader>\r
+       <resheader name="reader">\r
+               <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+       </resheader>\r
+       <resheader name="writer">\r
+               <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
+       </resheader>\r
+       <data name="Summary.xslt">\r
+               <value>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;\r
+&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;\r
+&lt;xsl:output method='text'/&gt;\r
+\r
+&lt;xsl:template match="/"&gt;\r
+       &lt;xsl:apply-templates/&gt;\r
+&lt;/xsl:template&gt;\r
+\r
+&lt;xsl:template match="test-results"&gt;\r
+&lt;xsl:text&gt;Tests run: &lt;/xsl:text&gt;\r
+&lt;xsl:value-of select="@total"/&gt;\r
+&lt;xsl:text&gt;, Failures: &lt;/xsl:text&gt;\r
+&lt;xsl:value-of select="@failures"/&gt;\r
+&lt;xsl:text&gt;, Not run: &lt;/xsl:text&gt;\r
+&lt;xsl:value-of select="@not-run"/&gt;\r
+&lt;xsl:text&gt;, Time: &lt;/xsl:text&gt;\r
+&lt;xsl:value-of select="test-suite/@time"/&gt;\r
+&lt;xsl:text&gt; seconds\r
+&lt;/xsl:text&gt;\r
+&lt;xsl:text&gt;\r
+&lt;/xsl:text&gt;\r
+\r
+&lt;xsl:if test="//test-case[failure]"&gt;&lt;xsl:text&gt;Failures:\r
+&lt;/xsl:text&gt;&lt;/xsl:if&gt;\r
+&lt;xsl:apply-templates select="//test-case[failure]"/&gt;\r
+&lt;xsl:if test="//test-case[@executed='False']"&gt;&lt;xsl:text&gt;Tests not run:\r
+&lt;/xsl:text&gt;&lt;/xsl:if&gt;\r
+&lt;xsl:apply-templates select="//test-case[@executed='False']"/&gt;\r
+&lt;xsl:text disable-output-escaping='yes'&gt;&amp;#xD;&amp;#xA;&lt;/xsl:text&gt;\r
+&lt;/xsl:template&gt;\r
+\r
+&lt;xsl:template match="test-case"&gt;\r
+       &lt;xsl:value-of select="position()"/&gt;&lt;xsl:text&gt;) &lt;/xsl:text&gt;\r
+       &lt;xsl:value-of select="@name"/&gt;\r
+       &lt;xsl:text&gt; : &lt;/xsl:text&gt;\r
+       &lt;xsl:value-of select="child::node()/message"/&gt;\r
+&lt;xsl:text disable-output-escaping='yes'&gt;&amp;#xD;&amp;#xA;&lt;/xsl:text&gt;\r
+       &lt;xsl:if test="failure"&gt;\r
+               &lt;xsl:value-of select="failure/stack-trace"/&gt;\r
+&lt;xsl:text&gt;\r
+&lt;/xsl:text&gt;\r
+       &lt;/xsl:if&gt;\r
+&lt;/xsl:template&gt;\r
+\r
+&lt;/xsl:stylesheet&gt;\r
+\r
+  </value>\r
+       </data>\r
+</root>
\ No newline at end of file
diff --git a/mcs/nunit20/util/UserSettings.cs b/mcs/nunit20/util/UserSettings.cs
new file mode 100755 (executable)
index 0000000..0f0a8c6
--- /dev/null
@@ -0,0 +1,69 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Drawing;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// UserSettings represents the main group of per-user
+       /// settings used by NUnit.
+       /// </summary>
+       public class UserSettings : SettingsGroup
+       {
+               private UserSettings()
+                       : base( "UserSettings", GetStorageImpl( )  ) { }
+
+               public static SettingsStorage GetStorageImpl()
+               {
+                       return new RegistrySettingsStorage( NUnitRegistry.CurrentUser );
+               }
+
+               public static SettingsStorage GetStorageImpl( string name )
+               {
+                       return new RegistrySettingsStorage( name, NUnitRegistry.CurrentUser );
+               }
+
+               public static OptionSettings Options
+               {
+                       get { return new OptionSettings( GetStorageImpl( "Options" ) ); }
+               }
+
+               public static FormSettings Form
+               {
+                       get { return new FormSettings( GetStorageImpl( "Form" ) ); }
+               }
+
+               public static RecentProjectSettings RecentProjects
+               {
+                       get { return new RecentProjectSettings( GetStorageImpl( "Recent-Projects" ) ); }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/VSProject.cs b/mcs/nunit20/util/VSProject.cs
new file mode 100755 (executable)
index 0000000..a67043e
--- /dev/null
@@ -0,0 +1,229 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.IO;
+using System.Xml;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// This class allows loading information about
+       /// configurations and assemblies in a Visual
+       /// Studio project file and inspecting them.
+       /// Only the most common project types are
+       /// supported and an exception is thrown if
+       /// an attempt is made to load an invalid
+       /// file or one of an unknown type.
+       /// </summary>
+       public class VSProject
+       {
+               #region Static and Instance Variables
+
+               /// <summary>
+               /// VS Project extentions
+               /// </summary>
+               private static readonly string[] validExtensions = { ".csproj", ".vbproj", ".vjsproj", ".vcproj" };
+               
+               /// <summary>
+               /// VS Solution extension
+               /// </summary>
+               private static readonly string solutionExtension = ".sln";
+
+               /// <summary>
+               /// Path to the file storing this project
+               /// </summary>
+               private string projectPath;
+
+               /// <summary>
+               /// Collection of configs for the project
+               /// </summary>
+               private VSProjectConfigCollection configs;
+
+               #endregion
+
+               #region Constructor
+
+               public VSProject( string projectPath )
+               {
+                       this.projectPath = Path.GetFullPath( projectPath );
+                       configs = new VSProjectConfigCollection();              
+
+                       Load();
+               }
+
+               #endregion
+
+               #region Properties
+
+               /// <summary>
+               /// The name of the project.
+               /// </summary>
+               public string Name
+               {
+                       get { return Path.GetFileNameWithoutExtension( projectPath ); }
+               }
+
+               /// <summary>
+               /// The path to the project
+               /// </summary>
+               public string ProjectPath
+               {
+                       get { return projectPath; }
+               }
+
+               /// <summary>
+               /// Our collection of configurations
+               /// </summary>
+               public VSProjectConfigCollection Configs
+               {
+                       get { return configs; }
+               }
+
+               #endregion
+
+               #region Static Methods
+
+               public static bool IsProjectFile( string path )
+               {
+                       string extension = Path.GetExtension( path );
+
+                       foreach( string validExtension in validExtensions )
+                               if ( extension == validExtension )
+                                       return true;
+
+                       return false;
+               }
+
+               public static bool IsSolutionFile( string path )
+               {
+                       return Path.GetExtension( path ) == solutionExtension;
+               }
+
+               #endregion
+
+               #region Instance Methods
+
+               public void Load()
+               {
+                       if ( !IsProjectFile( projectPath ) )
+                               ThrowInvalidFileType( projectPath );
+
+                       string projectDirectory = Path.GetFullPath( Path.GetDirectoryName( projectPath ) );
+                       string currentDirectory = Environment.CurrentDirectory;
+
+                       try
+                       {
+                               XmlDocument doc = new XmlDocument();
+                               doc.Load( projectPath );
+
+                               string extension = Path.GetExtension( projectPath );
+                               string assemblyName;
+
+                               switch ( extension )
+                               {
+                                       case ".vcproj":
+                                               foreach ( XmlNode configNode in doc.SelectNodes( "/VisualStudioProject/Configurations/Configuration" ) )
+                                               {
+                                                       string name = configNode.Attributes["Name"].Value;
+                                                       string outputPath = configNode.Attributes["OutputDirectory"].Value;
+                                                       string outputDirectory = Path.Combine( projectDirectory, outputPath );
+                                                       XmlNode toolNode = configNode.SelectSingleNode( "Tool[@Name='VCLinkerTool']" );
+                                                       assemblyName = Path.GetFileName( toolNode.Attributes["OutputFile"].Value );
+                                                       string assemblyPath = Path.Combine( outputDirectory, assemblyName );
+
+                                                       VSProjectConfig config = new VSProjectConfig ( name );
+                                                       config.Assemblies.Add( assemblyPath );
+
+                                                       this.configs.Add( config );
+                                               }
+                                       
+                                               break;
+
+                                       case ".csproj":
+                                       case ".vbproj":
+                                       case ".vjsproj":
+                                               XmlNode settingsNode = doc.SelectSingleNode( "/VisualStudioProject/*/Build/Settings" );
+                       
+                                               assemblyName = settingsNode.Attributes["AssemblyName"].Value;
+                                               string outputType = settingsNode.Attributes["OutputType"].Value;
+
+                                               if ( outputType == "Exe" || outputType == "WinExe" )
+                                                       assemblyName = assemblyName + ".exe";
+                                               else
+                                                       assemblyName = assemblyName + ".dll";
+
+                                               XmlNodeList nodes = settingsNode.SelectNodes("Config");
+                                               if ( nodes != null ) 
+                                                       foreach ( XmlNode configNode in nodes )
+                                                       {
+                                                               string name = configNode.Attributes["Name"].Value;
+                                                               string outputPath = configNode.Attributes["OutputPath"].Value;
+                                                               string outputDirectory = Path.Combine( projectDirectory, outputPath );
+                                                               string assemblyPath = Path.Combine( outputDirectory, assemblyName );
+                               
+                                                               VSProjectConfig config = new VSProjectConfig ( name );
+                                                               config.Assemblies.Add( assemblyPath );
+
+                                                               configs.Add( config );
+                                                       }
+
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+                       }
+                       catch( FileNotFoundException )
+                       {
+                               throw;
+                       }
+                       catch( Exception e )
+                       {
+                               ThrowInvalidFormat( projectPath, e );
+                       }
+               }
+
+               private void ThrowInvalidFileType( string projectPath )
+               {
+                       throw new ArgumentException( 
+                               string.Format( "Invalid project file type: {0}", 
+                                                               Path.GetFileName( projectPath ) ) );
+               }
+
+               private void ThrowInvalidFormat( string projectPath, Exception e )
+               {
+                       throw new ArgumentException( 
+                               string.Format( "Invalid project file format: {0}", 
+                                                               Path.GetFileName( projectPath ) ), e );
+               }
+
+               #endregion
+       }
+}
diff --git a/mcs/nunit20/util/VSProjectConfig.cs b/mcs/nunit20/util/VSProjectConfig.cs
new file mode 100755 (executable)
index 0000000..0ca2407
--- /dev/null
@@ -0,0 +1,62 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Collections.Specialized;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// Originally, we used the same ProjectConfig class for both
+       /// NUnit and Visual Studio projects. Since we really do very
+       /// little with VS Projects, this class has been created to 
+       /// hold the name and the collection of assembly paths.
+       /// </summary>
+       public class VSProjectConfig
+       {
+               private string name;
+               
+               private StringCollection assemblies = new StringCollection();
+
+               public VSProjectConfig( string name )
+               {
+                       this.name = name;
+               }
+
+               public string Name
+               {
+                       get { return name; }
+               }
+
+               public StringCollection Assemblies
+               {
+                       get { return assemblies; }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/VSProjectConfigCollection.cs b/mcs/nunit20/util/VSProjectConfigCollection.cs
new file mode 100755 (executable)
index 0000000..b335d61
--- /dev/null
@@ -0,0 +1,71 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright  2000-2002 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright  2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright  2000-2002 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+using System;
+using System.Collections;
+
+namespace NUnit.Util
+{
+       /// <summary>
+       /// A simple collection to hold VSProjectConfigs. Originally,
+       /// we used the (NUnit) ProjectConfigCollection, but the
+       /// classes have since diverged.
+       /// </summary>
+       public class VSProjectConfigCollection : CollectionBase
+       {
+               public VSProjectConfig this[int index]
+               {
+                       get { return List[index] as VSProjectConfig; }
+               }
+
+               public VSProjectConfig this[string name]
+               {
+                       get
+                       {
+                               foreach ( VSProjectConfig config in InnerList )
+                                       if ( config.Name == name ) return config;
+
+                               return null;
+                       }
+               }
+
+               public void Add( VSProjectConfig config )
+               {
+                       List.Add( config );
+               }
+
+               public bool Contains( string name )
+               {
+                       foreach( VSProjectConfig config in InnerList )
+                               if ( config.Name == name ) return true;
+
+                       return false;
+               }
+       }
+}
diff --git a/mcs/nunit20/util/XmlResultVisitor.cs b/mcs/nunit20/util/XmlResultVisitor.cs
new file mode 100755 (executable)
index 0000000..8de6378
--- /dev/null
@@ -0,0 +1,201 @@
+#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
+/************************************************************************************
+'
+' Copyright © 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' Copyright © 2000-2003 Philip A. Craig
+'
+' This software is provided 'as-is', without any express or implied warranty. In no 
+' event will the authors be held liable for any damages arising from the use of this 
+' software.
+' 
+' Permission is granted to anyone to use this software for any purpose, including 
+' commercial applications, and to alter it and redistribute it freely, subject to the 
+' following restrictions:
+'
+' 1. The origin of this software must not be misrepresented; you must not claim that 
+' you wrote the original software. If you use this software in a product, an 
+' acknowledgment (see the following) in the product documentation is required.
+'
+' Portions Copyright © 2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
+' or Copyright © 2000-2003 Philip A. Craig
+'
+' 2. Altered source versions must be plainly marked as such, and must not be 
+' misrepresented as being the original software.
+'
+' 3. This notice may not be removed or altered from any source distribution.
+'
+'***********************************************************************************/
+#endregion
+
+namespace NUnit.Util
+{
+       using System;
+       using System.Globalization;
+       using System.IO;
+       using System.Xml;
+       using NUnit.Core;
+
+       /// <summary>
+       /// Summary description for XmlResultVisitor.
+       /// </summary>
+       public class XmlResultVisitor : ResultVisitor
+       {
+               private XmlTextWriter xmlWriter;
+               private TextWriter writer;
+               private MemoryStream memoryStream;
+
+               public XmlResultVisitor(string fileName, TestResult result)
+               {
+                       xmlWriter = new XmlTextWriter( new StreamWriter(fileName, false, System.Text.Encoding.UTF8) );
+                       Initialize(result);
+               }
+
+               public XmlResultVisitor( TextWriter writer, TestResult result )
+               {
+                       this.memoryStream = new MemoryStream();
+                       this.writer = writer;
+                       this.xmlWriter = new XmlTextWriter( new StreamWriter( memoryStream, System.Text.Encoding.UTF8 ) );
+                       Initialize( result );
+               }
+
+               private void Initialize(TestResult result) 
+               {
+                       ResultSummarizer summaryResults = new ResultSummarizer(result);
+
+                       xmlWriter.Formatting = Formatting.Indented;
+                       xmlWriter.WriteStartDocument(false);
+                       xmlWriter.WriteComment("This file represents the results of running a test suite");
+
+                       xmlWriter.WriteStartElement("test-results");
+
+                       xmlWriter.WriteAttributeString("name", summaryResults.Name);
+                       xmlWriter.WriteAttributeString("total", summaryResults.ResultCount.ToString());
+                       xmlWriter.WriteAttributeString("failures", summaryResults.Failures.ToString());
+                       xmlWriter.WriteAttributeString("not-run", summaryResults.TestsNotRun.ToString());
+
+                       DateTime now = DateTime.Now;
+                       xmlWriter.WriteAttributeString("date", now.ToShortDateString());
+                       xmlWriter.WriteAttributeString("time", now.ToShortTimeString());
+               }
+
+               public void Visit(TestCaseResult caseResult) 
+               {
+                       xmlWriter.WriteStartElement("test-case");
+                       xmlWriter.WriteAttributeString("name",caseResult.Name);
+
+                       if(caseResult.Description != null)
+                               xmlWriter.WriteAttributeString("description", caseResult.Description);
+
+                       xmlWriter.WriteAttributeString("executed", caseResult.Executed.ToString());
+                       if(caseResult.Executed)
+                       {
+                               xmlWriter.WriteAttributeString("success", caseResult.IsSuccess.ToString());
+
+                               xmlWriter.WriteAttributeString("time", caseResult.Time.ToString("#####0.000", NumberFormatInfo.InvariantInfo));
+
+                               xmlWriter.WriteAttributeString("asserts", caseResult.AssertCount.ToString() );
+                               WriteCategories(caseResult);
+                               if(caseResult.IsFailure)
+                               {
+                                       if(caseResult.IsFailure)
+                                               xmlWriter.WriteStartElement("failure");
+                                       else
+                                               xmlWriter.WriteStartElement("error");
+                               
+                                       xmlWriter.WriteStartElement("message");
+                                       xmlWriter.WriteCData( EncodeCData( caseResult.Message ) );
+                                       xmlWriter.WriteEndElement();
+                               
+                                       xmlWriter.WriteStartElement("stack-trace");
+                                       if(caseResult.StackTrace != null)
+                                               xmlWriter.WriteCData( EncodeCData( StackTraceFilter.Filter( caseResult.StackTrace ) ) );
+                                       xmlWriter.WriteEndElement();
+                               
+                                       xmlWriter.WriteEndElement();
+                               }
+                               
+                       }
+                       else
+                       {
+                               WriteCategories(caseResult);
+                               xmlWriter.WriteStartElement("reason");
+                               xmlWriter.WriteStartElement("message");
+                               xmlWriter.WriteCData(caseResult.Message);
+                               xmlWriter.WriteEndElement();
+                               xmlWriter.WriteEndElement();
+                       }
+            
+                       xmlWriter.WriteEndElement();
+               }
+
+               private string EncodeCData( string text )
+               {
+                       if ( text.IndexOf( "]]>" ) < 0 )
+                               return text;
+
+                       return text.Replace( "]]>", "]]&gt;" );
+               }
+
+               public void WriteCategories(TestResult result)
+               {
+                       if (result.Test.Categories != null && result.Test.Categories.Count > 0)
+                       {
+                               xmlWriter.WriteStartElement("categories");
+                               foreach (string category in result.Test.Categories)
+                               {
+                                       xmlWriter.WriteStartElement("category");
+                                       xmlWriter.WriteAttributeString("name", category);
+                                       xmlWriter.WriteEndElement();
+                               }
+                               xmlWriter.WriteEndElement();
+                       }
+               }
+
+               public void Visit(TestSuiteResult suiteResult) 
+               {
+                       xmlWriter.WriteStartElement("test-suite");
+                       xmlWriter.WriteAttributeString("name",suiteResult.Name);
+                       if(suiteResult.Description != null)
+                               xmlWriter.WriteAttributeString("description", suiteResult.Description);
+
+                       xmlWriter.WriteAttributeString("success", suiteResult.IsSuccess.ToString());
+                       xmlWriter.WriteAttributeString("time", suiteResult.Time.ToString());
+                       xmlWriter.WriteAttributeString("asserts", suiteResult.AssertCount.ToString() );
+         
+                       WriteCategories(suiteResult);
+                       xmlWriter.WriteStartElement("results");                  
+                       foreach (TestResult result in suiteResult.Results)
+                       {
+                               result.Accept(this);
+                       }
+                       xmlWriter.WriteEndElement();
+
+                       xmlWriter.WriteEndElement();
+               }
+
+               public void Write()
+               {
+                       try 
+                       {
+                               xmlWriter.WriteEndElement();
+                               xmlWriter.WriteEndDocument();
+                               xmlWriter.Flush();
+
+                               if ( memoryStream != null && writer != null )
+                               {
+                                       memoryStream.Position = 0;
+                                       using ( StreamReader rdr = new StreamReader( memoryStream ) )
+                                       {
+                                               writer.Write( rdr.ReadToEnd() );
+                                       }
+                               }
+
+                               xmlWriter.Close();
+                       } 
+                       finally 
+                       {
+                               //writer.Close();
+                       }
+               }
+       }
+}
diff --git a/mcs/nunit20/util/nunit.util.build b/mcs/nunit20/util/nunit.util.build
new file mode 100755 (executable)
index 0000000..e6843dc
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<project name="NUnit.Util" default="build">
+
+    <!--
+        Required properties:
+            * bin.dir               - bin directory
+            * src.dir               - source location(build) or target(copy)
+            * build.debug           - (true|false) debug build?
+            * build.win32           - (true|false) win32 build?
+            * build.defines.csc     - build defines for build config
+            * runtime.defines.csc   - build defines for target framework
+    -->
+
+    <target name="build" depends="copy">
+        <csc target="library" output="${bin.dir}/nunit.util.dll"
+                debug="${build.debug}" define="${build.defines.csc},${runtime.defines.csc}">
+            <sources basedir="${src.dir}/util">
+                <includes name="**/*.cs"/>
+            </sources>
+             <resources basedir="${src.dir}/util" prefix="NUnit.Util">
+                <includes name="Transform.resx"/>
+            </resources>
+            <references basedir="${bin.dir}">
+                <includes name="nunit.core.dll"/>
+                <includes name="nunit.framework.dll"/>
+            </references>
+        </csc>
+    </target>
+
+    <target name="copy">
+        <copy todir="${src.dir}/util">
+            <fileset basedir=".">
+                <includes name="nunit.util.dll.csproj"/>
+                <includes name="nunit.util.build"/>
+                <includes name="AssemblyInfo.cs"/>
+                <includes name="AssemblyList.cs"/>
+                <includes name="AssemblyListItem.cs"/>
+                <includes name="AssemblyWatcher.cs"/>
+                <includes name="CommandLineOptions.cs"/>
+                <includes name="ConsoleOptions.cs"/>
+                <includes name="ConsoleWriter.cs"/>
+                <includes name="FormSettings.cs" if="${build.win32}"/>
+                <includes name="GuiOptions.cs"/>
+                <includes name="ITestEvents.cs"/>
+                <includes name="ITestLoader.cs"/>
+                <includes name="NUnitGuiSettings.cs" if="${build.win32}"/>
+                <includes name="NUnitProject.cs"/>
+                <includes name="NUnitRegistry.cs" if="${build.win32}"/>
+                <includes name="OptionSettings.cs" if="${build.win32}"/>
+                <includes name="ProjectConfig.cs"/>
+                <includes name="ProjectConfigCollection.cs"/>
+                <includes name="ProjectFormatException.cs"/>
+                <includes name="ProjectPath.cs"/>
+                <includes name="RecentFileSettings.cs" if="${build.win32}"/>
+                <includes name="RecentProjectSettings.cs" if="${build.win32}"/>
+                <includes name="RegistrySettingsStorage.cs" if="${build.win32}"/>
+                <includes name="ResultSummarizer.cs"/>
+               <includes name="SettingsGroup.cs"/>
+                <includes name="SettingsStorage.cs"/>
+                <includes name="StackTraceFilter.cs"/>
+                <includes name="SummaryVisitor.cs"/>
+                <includes name="TestDomain.cs"/>
+                <includes name="TestEventArgs.cs"/>
+                <includes name="TestEventDispatcher.cs"/>
+                <includes name="TestExceptionHandler.cs"/>
+                <includes name="TestLoader.cs"/>
+                <includes name="TestResultItem.cs"/>
+                <includes name="UIHelper.cs"/>
+                <includes name="UITestNode.cs"/>
+                <includes name="UserSettings.cs" if="${build.win32}"/>
+                <includes name="VSProject.cs"/>
+                <includes name="VSProjectConfig.cs"/>
+                <includes name="VSProjectConfigCollection.cs"/>
+                <includes name="XmlResultVisitor.cs"/>
+                <includes name="Transform.resx"/>
+            </fileset>
+        </copy>
+    </target>
+</project>