Welcome to mirror list, hosted at ThFree Co, Russian Federation.

StandardLoader.cs « NUnitCore « src « nunit « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5666c56aac30c126c6a2fbe0ea5e7bbc1744a5fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
namespace NUnit.Runner
{
	using System;
	using System.Collections;
	using System.Reflection;
	using NUnit.Framework;
	
	/// <summary>
	/// Same as StandardLoader.
	/// TODO: Clean up "Unloading" concepts in framework
	/// </summary>
	public class UnloadingLoader : StandardLoader{}

	/// <summary>
	/// TestLoader that 
	/// </summary>
	public class StandardLoader : ITestLoader
	{
		#region Overidable loader implementatioons
		/// <summary>
		/// Attempts by all means possible to return a test for the given type.
		/// Check in the following order:
		/// 1. For a static Suite property, that implments ITest.
		/// 2. Tries to dynamically create a suite for the type.
		/// </summary>
		/// <param name="testClass"></param>
		/// <returns></returns>
		protected virtual ITest CoerceTestFrom(Type testClass)
		{
			try
			{
				ITest test = GetStaticSuiteProperty(testClass);
				if (test == null )
				{
					// try to extract a test suite automatically
					test = new TestSuite(testClass);
				}
				return test;
			}
			catch (Exception e)
			{
				throw new NUnitException("Error building test for class: "
					+ testClass.FullName,e);
			}
		}
		
		/// <summary>
		/// Searches for the type specified by the testClassName in the 
		/// specified assembly, and if found, attempts to coerce a test
		/// from the type.
		/// </summary>
		/// <param name="testClassName"></param>
		/// <param name="assemblyFileName"></param>
		/// <returns></returns>
		public virtual ITest LoadTest(string testClassName,
			string assemblyFileName)
		{
			try
			{
				return this.CoerceTestFrom(
					getAssembly(assemblyFileName).GetType(testClassName));
			}
			catch (Exception e)
			{
				throw new LoaderException("Error loading test class: "
					+ testClassName + "," + assemblyFileName, e);
			}
		}
		/// <summary>
		/// Determines if a Type is a test.
		/// </summary>
		/// <param name="typeToCheck"></param>
		protected virtual bool IsTestClass(Type typeToCheck) 
		{
			if(typeToCheck!=null)
			{
				if( typeToCheck.IsClass
					&& typeToCheck.IsPublic
					&& !typeToCheck.IsAbstract)
				{
					try 
					{
						if( (typeof(ITest).IsAssignableFrom(typeToCheck)
							// Has public single string constructor
							&& (typeToCheck.GetConstructor(new Type[]{typeof(string)})!=null))
							|| GetStaticSuiteProperty(typeToCheck)!= null)
						{
							return true;
						}
					} 
					catch(System.Security.SecurityException)
					{
						// eat security exceptions, since shouldn't 
						// have errors on classes we can't access
					}
				}
				return false;
			}
			else
			{
				throw new ArgumentNullException("typeToCheck");
			}
		}
		/// <summary>
		/// Uses reflection to obtain the suite property for the Type
		/// </summary>
		/// <param name="testClass"></param>
		/// <returns>The Suite property of the Type, or null if the property 
		/// does not exist</returns>
		protected virtual TestSuite GetStaticSuiteProperty(Type testClass) 
		{
			if(testClass!=null)
			{
				TestSuite test = null;
				PropertyInfo suiteProperty = testClass.GetProperty("Suite"
					,BindingFlags.Static|BindingFlags.Public
					,Type.DefaultBinder			// unknown
					,typeof(ITest)				// Itest return type
					,Type.EmptyTypes			// no parameters
					,new ParameterModifier[0]	// unknown
					);
				if (suiteProperty != null )
				{
					test = (TestSuite)suiteProperty.GetValue(null, new Object[0]);
				}
				return test;
			}
			else
			{
				throw new ArgumentNullException ("testClass");
			}
		}
		private Assembly getAssembly(string assemblyFileName)
		{
			try
			{
				return Assembly.LoadFrom(assemblyFileName);
			}
			catch(ArgumentNullException)
			{
				throw new ArgumentNullException("assemblyFileName");
			}
		}
		#endregion
		
		#region ILoader Methods
		/// <summary>
		/// Implements ILoader.GetLoadName().
		/// </summary>
		/// <param name="test"></param>
		/// <returns></returns>
		public virtual string GetLoadName(ITest test)
		{
			Type testType = test.GetType();
			if(testType.Equals(typeof(TestSuite)))
			{
				string tname = test.ToString();
				testType = Type.GetType(tname);
			}
			if(testType != null)
				return testType.FullName+","+testType.Assembly.CodeBase;
			else
				return string.Empty;
		}
		/// <summary>
		/// Implements ILoader.LoadTest().
		/// Loads an instance of the test class specified by the 
		/// AssemblyQualifiedName. The assembly qualified name
		/// contains the Full Clas Name, followed by the CodeBase
		/// (file or url) of the assembly. If the class is found,
		/// the loader will attempt to return a TestSuite for the
		/// class. Trying first the static Suite property, followed 
		/// by trying to dynamically create a suite for the class.
		/// </summary>
		/// <param name="assemblyQualifiedName">The qualified name
		/// for the class taking the form 
		/// "Namespace.ClassName,AssemblyFileName" without the quotes.
		/// Assembly file name can be a fulied qualified path name, or
		/// a URL.</param>
		/// <returns></returns>
		public virtual ITest LoadTest(string assemblyQualifiedName)
		{
			if(assemblyQualifiedName==null)
				throw new ArgumentNullException("assemblyQualifiedName");

			string[] nameParts = assemblyQualifiedName.Split(new Char[]{','});
			if(nameParts.Length >= 1)
			{
				return this.LoadTest(nameParts[0].Trim(),nameParts[1].Trim());
			}
			else
			{
				throw new ArgumentException("Expected an Assembly Qualified Class"
					+ " Name, containing the file name of the assembly",
					"assemblyQualifiedName");
			}
		}
		#endregion

		/// <summary>
		/// Examies all types in the specified assembly and returns a list of those
		/// types that can be coerced into tests.
		/// </summary>
		/// <param name="assemblyFileName"></param>
		/// <returns></returns>
		public virtual Type[] GetTestTypes(string assemblyFileName)
		{
			Assembly assembly = getAssembly(assemblyFileName);
			ArrayList Tests = new ArrayList(assembly.GetExportedTypes().Length);
			foreach(Type typeToCheck in assembly.GetExportedTypes())
			{
				if(this.IsTestClass(typeToCheck))
				{
					Tests.Add(typeToCheck);
				}
			}
			Type[] ret = new Type[Tests.Count];
			Tests.CopyTo(ret);
			return ret;
		}
	}
}