Skip to content

Commit

Permalink
Move AvailableRuntimes to RuntimeFrameworkService
Browse files Browse the repository at this point in the history
  • Loading branch information
CharliePoole committed Jun 6, 2024
1 parent 02d8e0d commit 823da3d
Show file tree
Hide file tree
Showing 9 changed files with 453 additions and 285 deletions.
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-metadata-padding: 5
commits-since-version-source-padding: 5
branches:
master:
regex: ^(main|version3X)$
regex: ^(main|version4)$
tag: dev
release:
tag: pre
Expand Down
63 changes: 32 additions & 31 deletions src/NUnitEngine/nunit.engine.core.tests/RuntimeFrameworkTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,42 @@ public void CurrentFrameworkHasBuildSpecified()
Assert.That(RuntimeFramework.CurrentFramework.ClrVersion.Build, Is.GreaterThan(0));
}

[Test]
public void CurrentFrameworkMustBeAvailable()
{
var current = RuntimeFramework.CurrentFramework;
Console.WriteLine("Current framework is {0} ({1})", current.DisplayName, current.Id);
Assert.That(current.IsAvailable, "{0} not available", current);
}
// TODO: The commented tests should be in RuntimeFrameworkService Tests
//[Test]
//public void CurrentFrameworkMustBeAvailable()
//{
// var current = RuntimeFramework.CurrentFramework;
// Console.WriteLine("Current framework is {0} ({1})", current.DisplayName, current.Id);
// Assert.That(current.IsAvailable, "{0} not available", current);
//}

[Test]
public void AvailableFrameworksList()
{
RuntimeFramework[] available = RuntimeFramework.AvailableFrameworks;
Assert.That(RuntimeFramework.AvailableFrameworks.Length, Is.GreaterThan(0) );
foreach (var framework in RuntimeFramework.AvailableFrameworks)
Console.WriteLine("Available: {0}", framework.DisplayName);
}
//[Test]
//public void AvailableFrameworksList()
//{
// RuntimeFramework[] available = RuntimeFramework.AvailableFrameworks;
// Assert.That(RuntimeFramework.AvailableFrameworks.Length, Is.GreaterThan(0) );
// foreach (var framework in RuntimeFramework.AvailableFrameworks)
// Console.WriteLine("Available: {0}", framework.DisplayName);
//}

[Test]
public void AvailableFrameworksList_IncludesCurrentFramework()
{
foreach (var framework in RuntimeFramework.AvailableFrameworks)
if (RuntimeFramework.CurrentFramework.Supports(framework))
return;
//[Test]
//public void AvailableFrameworksList_IncludesCurrentFramework()
//{
// foreach (var framework in RuntimeFramework.AvailableFrameworks)
// if (RuntimeFramework.CurrentFramework.Supports(framework))
// return;

Assert.Fail("CurrentFramework not listed as available");
}
// Assert.Fail("CurrentFramework not listed as available");
//}

[Test]
public void AvailableFrameworksList_ContainsNoDuplicates()
{
var names = new List<string>();
foreach (var framework in RuntimeFramework.AvailableFrameworks)
names.Add(framework.DisplayName);
Assert.That(names, Is.Unique);
}
//[Test]
//public void AvailableFrameworksList_ContainsNoDuplicates()
//{
// var names = new List<string>();
// foreach (var framework in RuntimeFramework.AvailableFrameworks)
// names.Add(framework.DisplayName);
// Assert.That(names, Is.Unique);
//}

[TestCaseSource(nameof(frameworkData))]
public void CanCreateUsingFrameworkVersion(FrameworkData data)
Expand Down
234 changes: 2 additions & 232 deletions src/NUnitEngine/nunit.engine.core/RuntimeFramework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public string Id
#endregion

private static RuntimeFramework _currentFramework;
private static List<RuntimeFramework> _availableFrameworks;
//private static List<RuntimeFramework> _availableFrameworks;

private static readonly string DEFAULT_WINDOWS_MONO_DIR =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Mono");
Expand Down Expand Up @@ -314,20 +314,6 @@ public static RuntimeFramework CurrentFramework
}
}

/// <summary>
/// Gets an array of all available frameworks
/// </summary>
public static RuntimeFramework[] AvailableFrameworks
{
get
{
if (_availableFrameworks == null)
FindAvailableFrameworks();

return _availableFrameworks.ToArray();
}
}

/// <summary>
/// The version of Mono in use or null if no Mono runtime
/// is available on this machine.
Expand Down Expand Up @@ -356,25 +342,7 @@ public static string MonoExePath
}
}

/// <summary>
/// Returns true if the current RuntimeFramework is available.
/// In the current implementation, only Mono and Microsoft .NET
/// are supported.
/// </summary>
/// <returns>True if it's available, false if not</returns>
public bool IsAvailable
{
get
{
foreach (RuntimeFramework framework in AvailableFrameworks)
if (framework.Supports(this))
return true;

return false;
}
}

/// <summary>
/// <summary>
/// Parses a string representing a RuntimeFramework.
/// The string may be just a RuntimeType name or just
/// a Version or a hyphenated RuntimeType-Version or
Expand Down Expand Up @@ -548,204 +516,6 @@ private static string GetMonoPrefixFromAssembly(Assembly assembly)

return prefix;
}

private static void FindAvailableFrameworks()
{
_availableFrameworks = new List<RuntimeFramework>();

if (Environment.OSVersion.Platform == PlatformID.Win32NT)
_availableFrameworks.AddRange(DotNetFrameworkLocator.FindDotNetFrameworks());

FindDefaultMonoFramework();
FindDotNetCoreFrameworks();
}

private static void FindDefaultMonoFramework()
{
if (CurrentFramework.Runtime == RuntimeType.Mono)
UseCurrentMonoFramework();
else
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
FindBestMonoFrameworkOnWindows();
}

private static void UseCurrentMonoFramework()
{
Debug.Assert(CurrentFramework.Runtime == RuntimeType.Mono && MonoPrefix != null && MonoVersion != null);

// Multiple profiles are no longer supported with Mono 4.0
if (MonoVersion.Major < 4 && FindAllMonoProfiles() > 0)
return;

// If Mono 4.0+ or no profiles found, just use current runtime
_availableFrameworks.Add(RuntimeFramework.CurrentFramework);
}

private static void FindBestMonoFrameworkOnWindows()
{
// First, look for recent frameworks that use the Software\Mono Key
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Mono");

if (key != null && (int)key.GetValue("Installed", 0) == 1)
{
string version = key.GetValue("Version") as string;
MonoPrefix = key.GetValue("SdkInstallRoot") as string;

if (version != null)
{
MonoVersion = new Version(version);
AddMonoFramework(new Version(4, 5), null);
return;
}
}

// Some later 3.x Mono releases didn't use the registry
// so check in standard location for them.
if (Directory.Exists(DEFAULT_WINDOWS_MONO_DIR))
{
MonoPrefix = DEFAULT_WINDOWS_MONO_DIR;
AddMonoFramework(new Version(4, 5), null);
return;
}

// Look in the Software\Novell key for older versions
key = Registry.LocalMachine.OpenSubKey(@"Software\Novell\Mono");
if (key != null)
{
string version = key.GetValue("DefaultCLR") as string;
if (version != null)
{
RegistryKey subKey = key.OpenSubKey(version);
if (subKey != null)
{
MonoPrefix = subKey.GetValue("SdkInstallRoot") as string;
MonoVersion = new Version(version);

FindAllMonoProfiles();
}
}
}
}

private static int FindAllMonoProfiles()
{
int count = 0;

if (MonoPrefix != null)
{
if (File.Exists(Path.Combine(MonoPrefix, "lib/mono/1.0/mscorlib.dll")))
{
AddMonoFramework(new Version(1, 1, 4322), "1.0");
count++;
}

if (File.Exists(Path.Combine(MonoPrefix, "lib/mono/2.0/mscorlib.dll")))
{
AddMonoFramework(new Version(2, 0), "2.0");
count++;
}

if (Directory.Exists(Path.Combine(MonoPrefix, "lib/mono/3.5")))
{
AddMonoFramework(new Version(3, 5), "3.5");
count++;
}

if (File.Exists(Path.Combine(MonoPrefix, "lib/mono/4.0/mscorlib.dll")))
{
AddMonoFramework(new Version(4, 0), "4.0");
count++;
}

if (File.Exists(Path.Combine(MonoPrefix, "lib/mono/4.5/mscorlib.dll")))
{
AddMonoFramework(new Version(4, 5), "4.5");
count++;
}
}

return count;
}

private static void AddMonoFramework(Version frameworkVersion, string profile)
{
var framework = new RuntimeFramework(RuntimeType.Mono, frameworkVersion)
{
Profile = profile,
DisplayName = MonoVersion != null
? "Mono " + MonoVersion.ToString() + " - " + profile + " Profile"
: "Mono - " + profile + " Profile"
};

_availableFrameworks.Add(framework);
}

private static void FindDotNetCoreFrameworks()
{
const string WINDOWS_INSTALL_DIR = "C:\\Program Files\\dotnet\\";
const string LINUX_INSTALL_DIR = "/usr/shared/dotnet/";
string INSTALL_DIR = Path.DirectorySeparatorChar == '\\'
? WINDOWS_INSTALL_DIR
: LINUX_INSTALL_DIR;

if (!Directory.Exists(INSTALL_DIR))
return;
if (!File.Exists(Path.Combine(INSTALL_DIR, "dotnet.exe")))
return;

string runtimeDir = Path.Combine(INSTALL_DIR, Path.Combine("shared", "Microsoft.NETCore.App"));
if (!Directory.Exists(runtimeDir))
return;

var dirList = new DirectoryInfo(runtimeDir).GetDirectories();
var dirNames = new List<string>();
foreach (var dir in dirList)
dirNames.Add(dir.Name);
var runtimes = GetNetCoreRuntimesFromDirectoryNames(dirNames);

_availableFrameworks.AddRange(runtimes);
}

// Deal with oddly named directories, which may sometimes appear when previews are installed
internal static IList<RuntimeFramework> GetNetCoreRuntimesFromDirectoryNames(IEnumerable<string> dirNames)
{
const string VERSION_CHARS = ".0123456789";
var runtimes = new List<RuntimeFramework>();

foreach (string dirName in dirNames)
{
int len = 0;
foreach (char c in dirName)
{
if (VERSION_CHARS.IndexOf(c) >= 0)
len++;
else
break;
}

if (len == 0)
continue;

Version fullVersion = null;
try
{
fullVersion = new Version(dirName.Substring(0, len));
}
catch
{
continue;
}

var newVersion = new Version(fullVersion.Major, fullVersion.Minor);
int count = runtimes.Count;
if (count > 0 && runtimes[count - 1].FrameworkVersion == newVersion)
continue;

runtimes.Add(new RuntimeFramework(RuntimeType.NetCore, newVersion));
}

return runtimes;
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

#if NETFRAMEWORK
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NUnit.Framework;
using NUnit.Tests;

namespace NUnit.Engine.Services.Tests
{
Expand Down Expand Up @@ -76,8 +73,6 @@ public void EngineOptionPreferredOverImageTarget(string framework, int majorVers
public void RuntimeFrameworkIsSetForSubpackages()
{
//Runtime Service verifies that requested frameworks are available, therefore this test can only currently be run on platforms with both CLR v2 and v4 available
Assume.That(new RuntimeFramework(RuntimeType.Net, new Version("2.0.50727")), Has.Property(nameof(RuntimeFramework.IsAvailable)).True);
Assume.That(new RuntimeFramework(RuntimeType.Net, new Version("4.0.30319")), Has.Property(nameof(RuntimeFramework.IsAvailable)).True);

var topLevelPackage = new TestPackage(new [] {"a.dll", "b.dll"});

Expand Down
Loading

0 comments on commit 823da3d

Please sign in to comment.