* Update existing files (and added new ones) for nunit 2.1.91.
svn path=/trunk/mcs/; revision=28103
--- /dev/null
+#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;
+ }
+ }
+}
--- /dev/null
+#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 );
+ }
+ }
+ }
+}
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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 ); }
+// }
+ }
+}
--- /dev/null
+#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 ); }
+ }
+ }
+}
--- /dev/null
+#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 );
+ }
+ }
+}
--- /dev/null
+#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 ) { }
+ }
+}
--- /dev/null
+#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; }
+ }
+ }
+}
--- /dev/null
+#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;
+ }
+
+ }
+}
--- /dev/null
+#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; }
+ }
+ }
+}
--- /dev/null
+#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
+ }
+}
--- /dev/null
+#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
+ }
+}
--- /dev/null
+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 );
+ }
+ }
+}
--- /dev/null
+#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
+ }
+}
--- /dev/null
+#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;
+ }
+ }
+ }
+}
--- /dev/null
+<?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><?xml version="1.0" encoding="UTF-8" ?>\r
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r
+<xsl:output method='text'/>\r
+\r
+<xsl:template match="/">\r
+ <xsl:apply-templates/>\r
+</xsl:template>\r
+\r
+<xsl:template match="test-results">\r
+<xsl:text>Tests run: </xsl:text>\r
+<xsl:value-of select="@total"/>\r
+<xsl:text>, Failures: </xsl:text>\r
+<xsl:value-of select="@failures"/>\r
+<xsl:text>, Not run: </xsl:text>\r
+<xsl:value-of select="@not-run"/>\r
+<xsl:text>, Time: </xsl:text>\r
+<xsl:value-of select="test-suite/@time"/>\r
+<xsl:text> seconds\r
+</xsl:text>\r
+<xsl:text>\r
+</xsl:text>\r
+\r
+<xsl:if test="//test-case[failure]"><xsl:text>Failures:\r
+</xsl:text></xsl:if>\r
+<xsl:apply-templates select="//test-case[failure]"/>\r
+<xsl:if test="//test-case[@executed='False']"><xsl:text>Tests not run:\r
+</xsl:text></xsl:if>\r
+<xsl:apply-templates select="//test-case[@executed='False']"/>\r
+<xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>\r
+</xsl:template>\r
+\r
+<xsl:template match="test-case">\r
+ <xsl:value-of select="position()"/><xsl:text>) </xsl:text>\r
+ <xsl:value-of select="@name"/>\r
+ <xsl:text> : </xsl:text>\r
+ <xsl:value-of select="child::node()/message"/>\r
+<xsl:text disable-output-escaping='yes'>&#xD;&#xA;</xsl:text>\r
+ <xsl:if test="failure">\r
+ <xsl:value-of select="failure/stack-trace"/>\r
+<xsl:text>\r
+</xsl:text>\r
+ </xsl:if>\r
+</xsl:template>\r
+\r
+</xsl:stylesheet>\r
+\r
+ </value>\r
+ </data>\r
+</root>
\ No newline at end of file
--- /dev/null
+#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" ) ); }
+ }
+ }
+}
--- /dev/null
+#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
+ }
+}
--- /dev/null
+#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; }
+ }
+ }
+}
--- /dev/null
+#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;
+ }
+ }
+}
--- /dev/null
+#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( "]]>", "]]>" );
+ }
+
+ 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();
+ }
+ }
+ }
+}
--- /dev/null
+<?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>