1 // ***********************************************************************
2 // Copyright (c) 2007-2016 Charlie Poole
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
25 #define NUNIT_FRAMEWORK
31 using System.Collections.Generic;
34 using System.Reflection;
35 using Microsoft.Win32;
37 namespace NUnit.Framework.Internal
40 /// Enumeration identifying a common language
41 /// runtime implementation.
43 public enum RuntimeType
45 /// <summary>Any supported runtime framework</summary>
47 /// <summary>Microsoft .NET Framework</summary>
49 /// <summary>Microsoft .NET Compact Framework</summary>
51 /// <summary>Microsoft Shared Source CLI</summary>
53 /// <summary>Mono</summary>
55 /// <summary>Silverlight</summary>
57 /// <summary>MonoTouch</summary>
62 /// RuntimeFramework represents a particular version
63 /// of a common language runtime implementation.
66 public sealed class RuntimeFramework
68 // NOTE: This version of RuntimeFramework is for use
69 // within the NUnit framework assembly. It is simpler
70 // than the version in the test engine because it does
71 // not need to know what frameworks are available,
72 // only what framework is currently running.
73 #region Static and Instance Fields
76 /// DefaultVersion is an empty Version, used to indicate that
77 /// NUnit should select the CLR version to use for the test.
79 public static readonly Version DefaultVersion = new Version(0,0);
81 private static readonly Lazy<RuntimeFramework> currentFramework = new Lazy<RuntimeFramework>(() =>
84 var currentFramework = new RuntimeFramework(
85 RuntimeType.Silverlight,
86 new Version(Environment.Version.Major, Environment.Version.Minor));
88 Type monoRuntimeType = Type.GetType("Mono.Runtime", false);
89 Type monoTouchType = Type.GetType("MonoTouch.UIKit.UIApplicationDelegate,monotouch");
90 bool isMonoTouch = monoTouchType != null;
91 bool isMono = monoRuntimeType != null;
93 RuntimeType runtime = isMonoTouch
94 ? RuntimeType.MonoTouch
97 : Environment.OSVersion.Platform == PlatformID.WinCE
101 int major = Environment.Version.Major;
102 int minor = Environment.Version.Minor;
117 else /* It's windows */
120 using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework"))
124 string installRoot = key.GetValue("InstallRoot") as string;
125 if (installRoot != null)
127 if (Directory.Exists(Path.Combine(installRoot, "v3.5")))
132 else if (Directory.Exists(Path.Combine(installRoot, "v3.0")))
141 else if (major == 4 && Type.GetType("System.Reflection.AssemblyMetadataAttribute") != null)
146 var currentFramework = new RuntimeFramework( runtime, new Version (major, minor) )
148 ClrVersion = Environment.Version
153 MethodInfo getDisplayNameMethod = monoRuntimeType.GetMethod(
154 "GetDisplayName", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.ExactBinding);
155 if (getDisplayNameMethod != null)
156 currentFramework.DisplayName = (string)getDisplayNameMethod.Invoke(null, new object[0]);
159 return currentFramework;
167 /// Construct from a runtime type and version. If the version has
168 /// two parts, it is taken as a framework version. If it has three
169 /// or more, it is taken as a CLR version. In either case, the other
170 /// version is deduced based on the runtime type and provided version.
172 /// <param name="runtime">The runtime type of the framework</param>
173 /// <param name="version">The version of the framework</param>
174 public RuntimeFramework( RuntimeType runtime, Version version)
178 if (version.Build < 0)
179 InitFromFrameworkVersion(version);
181 InitFromClrVersion(version);
183 DisplayName = GetDefaultDisplayName(runtime, version);
186 private void InitFromFrameworkVersion(Version version)
188 FrameworkVersion = ClrVersion = version;
190 if (version.Major > 0) // 0 means any version
193 case RuntimeType.Net:
194 case RuntimeType.Mono:
195 case RuntimeType.Any:
196 switch (version.Major)
199 switch (version.Minor)
202 ClrVersion = Runtime == RuntimeType.Mono
203 ? new Version(1, 1, 4322)
204 : new Version(1, 0, 3705);
207 if (Runtime == RuntimeType.Mono)
208 FrameworkVersion = new Version(1, 0);
209 ClrVersion = new Version(1, 1, 4322);
212 ThrowInvalidFrameworkVersion(version);
218 ClrVersion = new Version(2, 0, 50727);
221 ClrVersion = new Version(4, 0, 30319);
224 ThrowInvalidFrameworkVersion(version);
229 case RuntimeType.Silverlight:
230 ClrVersion = version.Major >= 4
231 ? new Version(4, 0, 60310)
232 : new Version(2, 0, 50727);
235 case RuntimeType.NetCF:
236 switch (version.Major)
239 switch (version.Minor)
242 ClrVersion = new Version(3, 5, 7283);
251 private static void ThrowInvalidFrameworkVersion(Version version)
253 throw new ArgumentException("Unknown framework version " + version, "version");
256 private void InitFromClrVersion(Version version)
258 FrameworkVersion = new Version(version.Major, version.Minor);
259 ClrVersion = version;
260 if (Runtime == RuntimeType.Mono && version.Major == 1)
261 FrameworkVersion = new Version(1, 0);
268 /// Static method to return a RuntimeFramework object
269 /// for the framework that is currently in use.
271 public static RuntimeFramework CurrentFramework
275 return currentFramework.Value;
280 /// The type of this runtime framework
282 public RuntimeType Runtime { get; private set; }
285 /// The framework version for this runtime framework
287 public Version FrameworkVersion { get; private set; }
290 /// The CLR version for this runtime framework
292 public Version ClrVersion { get; private set; }
295 /// Return true if any CLR version may be used in
296 /// matching this RuntimeFramework object.
298 public bool AllowAnyVersion
300 get { return ClrVersion == DefaultVersion; }
304 /// Returns the Display name for this framework
306 public string DisplayName { get; private set; }
310 #region Public Methods
313 /// Parses a string representing a RuntimeFramework.
314 /// The string may be just a RuntimeType name or just
315 /// a Version or a hyphenated RuntimeType-Version or
316 /// a Version prefixed by 'versionString'.
318 /// <param name="s"></param>
319 /// <returns></returns>
320 public static RuntimeFramework Parse(string s)
322 RuntimeType runtime = RuntimeType.Any;
323 Version version = DefaultVersion;
325 string[] parts = s.Split('-');
326 if (parts.Length == 2)
328 runtime = (RuntimeType)Enum.Parse(typeof(RuntimeType), parts[0], true);
329 string vstring = parts[1];
331 version = new Version(vstring);
333 else if (char.ToLower(s[0]) == 'v')
335 version = new Version(s.Substring(1));
337 else if (IsRuntimeTypeName(s))
339 runtime = (RuntimeType)Enum.Parse(typeof(RuntimeType), s, true);
343 version = new Version(s);
346 return new RuntimeFramework(runtime, version);
350 /// Overridden to return the short name of the framework
352 /// <returns></returns>
353 public override string ToString()
357 return Runtime.ToString().ToLower();
361 string vstring = FrameworkVersion.ToString();
362 if (Runtime == RuntimeType.Any)
363 return "v" + vstring;
365 return Runtime.ToString().ToLower() + "-" + vstring;
370 /// Returns true if the current framework matches the
371 /// one supplied as an argument. Two frameworks match
372 /// if their runtime types are the same or either one
373 /// is RuntimeType.Any and all specified version components
374 /// are equal. Negative (i.e. unspecified) version
375 /// components are ignored.
377 /// <param name="target">The RuntimeFramework to be matched.</param>
378 /// <returns>True on match, otherwise false</returns>
379 public bool Supports(RuntimeFramework target)
381 if (Runtime != RuntimeType.Any
382 && target.Runtime != RuntimeType.Any
383 && Runtime != target.Runtime)
386 if (AllowAnyVersion || target.AllowAnyVersion)
389 if (!VersionsMatch(ClrVersion, target.ClrVersion))
392 return Runtime == RuntimeType.Silverlight
393 ? FrameworkVersion.Major == target.FrameworkVersion.Major && FrameworkVersion.Minor == target.FrameworkVersion.Minor
394 : FrameworkVersion.Major >= target.FrameworkVersion.Major && FrameworkVersion.Minor >= target.FrameworkVersion.Minor;
399 #region Helper Methods
401 private static bool IsRuntimeTypeName(string name)
403 return TypeHelper.GetEnumNames( typeof(RuntimeType)).Any( item => item.ToLower() == name.ToLower() );
406 private static string GetDefaultDisplayName(RuntimeType runtime, Version version)
408 if (version == DefaultVersion)
409 return runtime.ToString();
410 else if (runtime == RuntimeType.Any)
411 return "v" + version;
413 return runtime + " " + version;
416 private static bool VersionsMatch(Version v1, Version v2)
418 return v1.Major == v2.Major &&
419 v1.Minor == v2.Minor &&
420 (v1.Build < 0 || v2.Build < 0 || v1.Build == v2.Build) &&
421 (v1.Revision < 0 || v2.Revision < 0 || v1.Revision == v2.Revision);