PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NUnit/interfaces/RuntimeFramework.cs

#
C# | 463 lines | 311 code | 61 blank | 91 comment | 89 complexity | 0eb1c68f7979bbd2acab5a683190de7a MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // This is free software licensed under the NUnit license. You
  3. // may obtain a copy of the license as well as information regarding
  4. // copyright ownership at http://nunit.org.
  5. // ****************************************************************
  6. using System;
  7. using System.IO;
  8. using System.Reflection;
  9. using System.Collections;
  10. using Microsoft.Win32;
  11. namespace NUnit.Core
  12. {
  13. /// <summary>
  14. /// Enumeration identifying a common language
  15. /// runtime implementation.
  16. /// </summary>
  17. public enum RuntimeType
  18. {
  19. /// <summary>Any supported runtime framework</summary>
  20. Any,
  21. /// <summary>Microsoft .NET Framework</summary>
  22. Net,
  23. /// <summary>Microsoft .NET Compact Framework</summary>
  24. NetCF,
  25. /// <summary>Microsoft Shared Source CLI</summary>
  26. SSCLI,
  27. /// <summary>Mono</summary>
  28. Mono
  29. }
  30. /// <summary>
  31. /// RuntimeFramework represents a particular version
  32. /// of a common language runtime implementation.
  33. /// </summary>
  34. [Serializable]
  35. public sealed class RuntimeFramework
  36. {
  37. #region Static and Instance Fields
  38. /// <summary>
  39. /// DefaultVersion is an empty Version, used to indicate that
  40. /// NUnit should select the CLR version to use for the test.
  41. /// </summary>
  42. public static readonly Version DefaultVersion = new Version();
  43. private static RuntimeFramework currentFramework;
  44. private static RuntimeFramework[] availableFrameworks;
  45. private RuntimeType runtime;
  46. private Version frameworkVersion;
  47. private Version clrVersion;
  48. private string displayName;
  49. #endregion
  50. #region Constructor
  51. /// <summary>
  52. /// Construct from a runtime type and version
  53. /// </summary>
  54. /// <param name="runtime">The runtime type of the framework</param>
  55. /// <param name="version">The version of the framework</param>
  56. public RuntimeFramework( RuntimeType runtime, Version version)
  57. {
  58. this.runtime = runtime;
  59. this.frameworkVersion = version;
  60. this.clrVersion = version;
  61. if (frameworkVersion.Major == 3)
  62. this.clrVersion = new Version(2, 0);
  63. else if (runtime == RuntimeType.Mono && version.Major == 1)
  64. this.clrVersion = new Version(1, 1);
  65. this.displayName = GetDefaultDisplayName(runtime, version);
  66. }
  67. #endregion
  68. #region Properties
  69. /// <summary>
  70. /// Static method to return a RuntimeFramework object
  71. /// for the framework that is currently in use.
  72. /// </summary>
  73. public static RuntimeFramework CurrentFramework
  74. {
  75. get
  76. {
  77. if (currentFramework == null)
  78. {
  79. Type monoRuntimeType = Type.GetType("Mono.Runtime", false);
  80. bool isMono = monoRuntimeType != null;
  81. RuntimeType runtime = isMono ? RuntimeType.Mono : RuntimeType.Net;
  82. int major = Environment.Version.Major;
  83. int minor = Environment.Version.Minor;
  84. if (isMono && major == 1)
  85. minor = 0;
  86. currentFramework = new RuntimeFramework(runtime, new Version(major, minor));
  87. currentFramework.clrVersion = Environment.Version;
  88. if (isMono)
  89. {
  90. MethodInfo getDisplayNameMethod = monoRuntimeType.GetMethod(
  91. "GetDisplayName", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding);
  92. if (getDisplayNameMethod != null)
  93. currentFramework.displayName = (string)getDisplayNameMethod.Invoke(null, new object[0]);
  94. }
  95. }
  96. return currentFramework;
  97. }
  98. }
  99. /// <summary>
  100. /// Gets an array of all available frameworks
  101. /// </summary>
  102. public static RuntimeFramework[] AvailableFrameworks
  103. {
  104. get
  105. {
  106. if (availableFrameworks == null)
  107. {
  108. FrameworkCollection frameworks = new FrameworkCollection();
  109. AppendDotNetFrameworks(frameworks);
  110. AppendDefaultMonoFramework(frameworks);
  111. // NYI
  112. //AppendMonoFrameworks(frameworks);
  113. availableFrameworks = frameworks.ToArray();
  114. }
  115. return availableFrameworks;
  116. }
  117. }
  118. /// <summary>
  119. /// Returns true if the current RuntimeFramework is available.
  120. /// In the current implementation, only Mono and Microsoft .NET
  121. /// are supported.
  122. /// </summary>
  123. /// <returns>True if it's available, false if not</returns>
  124. public bool IsAvailable
  125. {
  126. get
  127. {
  128. foreach (RuntimeFramework framework in AvailableFrameworks)
  129. if (this.Matches(framework))
  130. return true;
  131. return false;
  132. }
  133. }
  134. /// <summary>
  135. /// The type of this runtime framework
  136. /// </summary>
  137. public RuntimeType Runtime
  138. {
  139. get { return runtime; }
  140. }
  141. /// <summary>
  142. /// The framework version for this runtime framework
  143. /// </summary>
  144. public Version FrameworkVersion
  145. {
  146. get { return frameworkVersion; }
  147. }
  148. /// <summary>
  149. /// The CLR version for this runtime framework
  150. /// </summary>
  151. public Version ClrVersion
  152. {
  153. get { return clrVersion; }
  154. }
  155. /// <summary>
  156. /// Return true if any CLR version may be used in
  157. /// matching this RuntimeFramework object.
  158. /// </summary>
  159. public bool AllowAnyVersion
  160. {
  161. get { return this.clrVersion == DefaultVersion; }
  162. }
  163. /// <summary>
  164. /// Returns the Display name for this framework
  165. /// </summary>
  166. public string DisplayName
  167. {
  168. get { return displayName; }
  169. }
  170. #endregion
  171. #region Public Methods
  172. /// <summary>
  173. /// Parses a string representing a RuntimeFramework.
  174. /// The string may be just a RuntimeType name or just
  175. /// a Version or a hyphentated RuntimeType-Version or
  176. /// a Version prefixed by 'v'.
  177. /// </summary>
  178. /// <param name="s"></param>
  179. /// <returns></returns>
  180. public static RuntimeFramework Parse(string s)
  181. {
  182. RuntimeType runtime = RuntimeType.Any;
  183. Version version = DefaultVersion;
  184. string[] parts = s.Split(new char[] { '-' });
  185. if (parts.Length == 2)
  186. {
  187. runtime = (RuntimeType)System.Enum.Parse(typeof(RuntimeType), parts[0], true);
  188. string vstring = parts[1];
  189. if (vstring != "")
  190. version = new Version(vstring);
  191. }
  192. else if (char.ToLower(s[0]) == 'v')
  193. {
  194. version = new Version(s.Substring(1));
  195. }
  196. else if (IsRuntimeTypeName(s))
  197. {
  198. runtime = (RuntimeType)System.Enum.Parse(typeof(RuntimeType), s, true);
  199. }
  200. else
  201. {
  202. version = new Version(s);
  203. }
  204. return new RuntimeFramework(runtime, version);
  205. }
  206. /// <summary>
  207. /// Returns the best available framework that matches a target framework.
  208. /// If the target framework has a build number specified, then an exact
  209. /// match is needed. Otherwise, the matching framework with the highest
  210. /// build number is used.
  211. /// </summary>
  212. /// <param name="target"></param>
  213. /// <returns></returns>
  214. public static RuntimeFramework GetBestAvailableFramework(RuntimeFramework target)
  215. {
  216. RuntimeFramework result = target;
  217. if (target.ClrVersion.Build < 0)
  218. {
  219. foreach (RuntimeFramework framework in AvailableFrameworks)
  220. if (framework.Matches(target) &&
  221. framework.ClrVersion.Build > result.ClrVersion.Build)
  222. {
  223. result = framework;
  224. }
  225. }
  226. return result;
  227. }
  228. /// <summary>
  229. /// Overridden to return the short name of the framework
  230. /// </summary>
  231. /// <returns></returns>
  232. public override string ToString()
  233. {
  234. if (this.AllowAnyVersion)
  235. {
  236. return runtime.ToString().ToLower();
  237. }
  238. else
  239. {
  240. string vstring = frameworkVersion.ToString();
  241. if (runtime == RuntimeType.Any)
  242. return "v" + vstring;
  243. else
  244. return runtime.ToString().ToLower() + "-" + vstring;
  245. }
  246. }
  247. /// <summary>
  248. /// Returns true if this framework "matches" the one supplied
  249. /// as an argument. Two frameworks match if their runtime types
  250. /// are the same or either one is RuntimeType.Any and all specified
  251. /// components of the CLR version are equal. Negative (i.e. unspecified)
  252. /// version components are ignored.
  253. /// </summary>
  254. /// <param name="other">The RuntimeFramework to be matched.</param>
  255. /// <returns>True on match, otherwise false</returns>
  256. public bool Matches(RuntimeFramework other)
  257. {
  258. if (this.Runtime != RuntimeType.Any
  259. && other.Runtime != RuntimeType.Any
  260. && this.Runtime != other.Runtime)
  261. return false;
  262. if (this.AllowAnyVersion || other.AllowAnyVersion)
  263. return true;
  264. return this.ClrVersion.Major == other.ClrVersion.Major
  265. && this.ClrVersion.Minor == other.ClrVersion.Minor
  266. && ( this.ClrVersion.Build < 0
  267. || other.ClrVersion.Build < 0
  268. || this.ClrVersion.Build == other.ClrVersion.Build )
  269. && ( this.ClrVersion.Revision < 0
  270. || other.ClrVersion.Revision < 0
  271. || this.ClrVersion.Revision == other.ClrVersion.Revision );
  272. }
  273. #endregion
  274. #region Helper Methods
  275. private static bool IsRuntimeTypeName(string name)
  276. {
  277. foreach (string item in Enum.GetNames(typeof(RuntimeType)))
  278. if (item.ToLower() == name.ToLower())
  279. return true;
  280. return false;
  281. }
  282. private static string GetDefaultDisplayName(RuntimeType runtime, Version version)
  283. {
  284. if (version == DefaultVersion)
  285. return runtime.ToString();
  286. else if (runtime == RuntimeType.Any)
  287. return "v" + version.ToString();
  288. else
  289. return runtime.ToString() + " " + version.ToString();
  290. }
  291. private static void AppendMonoFrameworks(FrameworkCollection frameworks)
  292. {
  293. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  294. AppendAllMonoFrameworks(frameworks);
  295. else
  296. AppendDefaultMonoFramework(frameworks);
  297. }
  298. private static void AppendAllMonoFrameworks(FrameworkCollection frameworks)
  299. {
  300. // TODO: Find multiple installed Mono versions under Linux
  301. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  302. {
  303. // Use registry to find alternate versions
  304. RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Novell\Mono");
  305. if (key == null) return;
  306. foreach (string version in key.GetSubKeyNames())
  307. {
  308. RegistryKey subKey = key.OpenSubKey(version);
  309. string monoPrefix = subKey.GetValue("SdkInstallRoot") as string;
  310. AppendMonoFramework(frameworks, monoPrefix, version);
  311. }
  312. }
  313. else
  314. AppendDefaultMonoFramework(frameworks);
  315. }
  316. // This method works for Windows and Linux but currently
  317. // is only called under Linux.
  318. private static void AppendDefaultMonoFramework(FrameworkCollection frameworks)
  319. {
  320. string monoPrefix = null;
  321. string version = null;
  322. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  323. {
  324. RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Novell\Mono");
  325. if (key != null)
  326. {
  327. version = key.GetValue("DefaultCLR") as string;
  328. if (version != null && version != "")
  329. {
  330. key = key.OpenSubKey(version);
  331. if (key != null)
  332. monoPrefix = key.GetValue("SdkInstallRoot") as string;
  333. }
  334. }
  335. }
  336. else // Assuming we're currently running Mono - change if more runtimes are added
  337. {
  338. string libMonoDir = Path.GetDirectoryName(typeof(object).Assembly.Location);
  339. monoPrefix = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(libMonoDir)));
  340. }
  341. AppendMonoFramework(frameworks, monoPrefix, version);
  342. }
  343. private static void AppendMonoFramework(FrameworkCollection frameworks, string monoPrefix, string version)
  344. {
  345. if (monoPrefix != null)
  346. {
  347. string displayFmt = version != null
  348. ? "Mono " + version + " - {0} Profile"
  349. : "Mono {0} Profile";
  350. if (File.Exists(Path.Combine(monoPrefix, "lib/mono/1.0/mscorlib.dll")))
  351. {
  352. RuntimeFramework framework = new RuntimeFramework(RuntimeType.Mono, new Version(1, 1, 4322));
  353. framework.displayName = string.Format(displayFmt, "1.0");
  354. frameworks.Add(framework);
  355. }
  356. if (File.Exists(Path.Combine(monoPrefix, "lib/mono/2.0/mscorlib.dll")))
  357. {
  358. RuntimeFramework framework = new RuntimeFramework(RuntimeType.Mono, new Version(2, 0, 50727));
  359. framework.displayName = string.Format(displayFmt, "2.0");
  360. frameworks.Add(framework);
  361. }
  362. if (File.Exists(Path.Combine(monoPrefix, "lib/mono/4.0/mscorlib.dll")))
  363. {
  364. RuntimeFramework framework = new RuntimeFramework(RuntimeType.Mono, new Version(4, 0, 30319));
  365. framework.displayName = string.Format(displayFmt, "4.0");
  366. frameworks.Add(framework);
  367. }
  368. }
  369. }
  370. private static void AppendDotNetFrameworks(FrameworkCollection frameworks)
  371. {
  372. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  373. {
  374. RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\.NETFramework\policy");
  375. if (key != null)
  376. {
  377. foreach (string name in key.GetSubKeyNames())
  378. {
  379. if (name.StartsWith("v"))
  380. {
  381. RegistryKey key2 = key.OpenSubKey(name);
  382. foreach (string build in key2.GetValueNames())
  383. frameworks.Add(new RuntimeFramework(RuntimeType.Net, new Version(name.Substring(1) + "." + build)));
  384. }
  385. }
  386. }
  387. }
  388. }
  389. #if NET_2_0
  390. private class FrameworkCollection : System.Collections.Generic.List<RuntimeFramework> { }
  391. #else
  392. private class FrameworkCollection : ArrayList
  393. {
  394. public new RuntimeFramework[] ToArray()
  395. {
  396. return (RuntimeFramework[])ToArray(typeof(RuntimeFramework));
  397. }
  398. }
  399. #endif
  400. #endregion
  401. }
  402. }