2018-11-16 21:31:40 +03:00
|
|
|
using System;
|
2016-05-26 16:06:52 +03:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2021-05-06 16:11:42 +03:00
|
|
|
using System.Runtime.InteropServices;
|
2020-11-13 19:05:10 +03:00
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Microsoft.DotNet.XHarness.Common;
|
|
|
|
using Microsoft.DotNet.XHarness.Common.Logging;
|
2020-04-01 20:32:21 +03:00
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared;
|
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared.Execution;
|
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared.Hardware;
|
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared.Listeners;
|
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared.Logging;
|
|
|
|
using Microsoft.DotNet.XHarness.iOS.Shared.Utilities;
|
2020-03-10 15:12:33 +03:00
|
|
|
using Xharness.Targets;
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-03-31 06:23:33 +03:00
|
|
|
namespace Xharness {
|
|
|
|
public enum HarnessAction {
|
2016-05-26 16:06:52 +03:00
|
|
|
None,
|
|
|
|
Configure,
|
|
|
|
Run,
|
|
|
|
Install,
|
2017-01-02 10:58:46 +03:00
|
|
|
Uninstall,
|
2016-06-06 13:48:53 +03:00
|
|
|
Jenkins,
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-13 17:41:02 +03:00
|
|
|
public class HarnessConfiguration {
|
|
|
|
public bool AutoConf { get; set; }
|
2020-03-17 21:42:21 +03:00
|
|
|
public string BuildConfiguration { get; set; } = "Debug";
|
2020-03-13 17:41:02 +03:00
|
|
|
public bool DryRun { get; set; }
|
|
|
|
public Dictionary<string, string> EnvironmentVariables { get; set; } = new Dictionary<string, string> ();
|
|
|
|
public bool? IncludeSystemPermissionTests { get; set; }
|
|
|
|
public List<iOSTestProject> IOSTestProjects { get; set; } = new List<iOSTestProject> ();
|
|
|
|
public string JenkinsConfiguration { get; set; }
|
|
|
|
public HashSet<string> Labels { get; set; } = new HashSet<string> ();
|
|
|
|
public string LogDirectory { get; set; } = Environment.CurrentDirectory;
|
|
|
|
public string MarkdownSummaryPath { get; set; }
|
|
|
|
public string PeriodicCommand { get; set; }
|
|
|
|
public string PeriodicCommandArguments { get; set; }
|
|
|
|
public TimeSpan PeriodicCommandInterval { get; set; }
|
|
|
|
public string SdkRoot { get; set; }
|
2020-03-24 12:02:22 +03:00
|
|
|
public TestTarget Target { get; set; }
|
2020-03-13 17:41:02 +03:00
|
|
|
public double TimeoutInMinutes { get; set; } = 15;
|
|
|
|
public bool UseSystemXamarinIOSMac { get; set; }
|
|
|
|
public int Verbosity { get; set; }
|
|
|
|
public string WatchOSAppTemplate { get; set; }
|
|
|
|
public string WatchOSContainerTemplate { get; set; }
|
|
|
|
public XmlResultJargon XmlJargon { get; set; } = XmlResultJargon.NUnitV3;
|
2020-11-13 19:05:10 +03:00
|
|
|
|
2020-03-11 12:38:03 +03:00
|
|
|
// This is the maccore/tests directory.
|
|
|
|
static string root_directory;
|
|
|
|
public static string RootDirectory {
|
|
|
|
get {
|
|
|
|
if (root_directory == null) {
|
|
|
|
var testAssemblyDirectory = Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly ().Location);
|
|
|
|
var dir = testAssemblyDirectory;
|
|
|
|
var path = Path.Combine (testAssemblyDirectory, ".git");
|
|
|
|
while (!Directory.Exists (path) && path.Length > 3) {
|
|
|
|
dir = Path.GetDirectoryName (dir);
|
|
|
|
path = Path.Combine (dir, ".git");
|
|
|
|
}
|
|
|
|
if (!Directory.Exists (path))
|
|
|
|
throw new Exception ("Could not find the xamarin-macios repo.");
|
|
|
|
path = Path.Combine (Path.GetDirectoryName (path), "tests");
|
|
|
|
if (!Directory.Exists (path))
|
|
|
|
throw new Exception ("Could not find the tests directory.");
|
|
|
|
root_directory = path;
|
|
|
|
}
|
|
|
|
return root_directory;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
root_directory = value;
|
|
|
|
if (root_directory != null)
|
|
|
|
root_directory = Path.GetFullPath (root_directory).TrimEnd ('/');
|
|
|
|
}
|
|
|
|
}
|
2020-06-16 23:04:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public class Harness : IHarness {
|
|
|
|
readonly TestTarget target;
|
|
|
|
readonly string buildConfiguration = "Debug";
|
2020-11-13 19:05:10 +03:00
|
|
|
readonly IMlaunchProcessManager processManager;
|
2020-06-16 23:04:38 +03:00
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
public static readonly IHelpers Helpers = new Helpers ();
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-06-16 23:04:38 +03:00
|
|
|
public HarnessAction Action { get; }
|
|
|
|
public int Verbosity { get; }
|
2020-11-13 19:05:10 +03:00
|
|
|
public IFileBackedLog HarnessLog { get; set; }
|
2020-06-16 23:04:38 +03:00
|
|
|
public HashSet<string> Labels { get; }
|
|
|
|
public XmlResultJargon XmlJargon { get; }
|
|
|
|
public IResultParser ResultParser { get; }
|
|
|
|
public ITunnelBore TunnelBore { get; }
|
2020-11-13 19:05:10 +03:00
|
|
|
public AppBundleLocator AppBundleLocator { get; }
|
|
|
|
|
2020-04-16 17:25:24 +03:00
|
|
|
public string XIBuildPath => Path.GetFullPath (Path.Combine (RootDirectory, "..", "tools", "xibuild", "xibuild"));
|
2020-04-01 20:32:21 +03:00
|
|
|
|
2020-03-20 13:42:43 +03:00
|
|
|
string sdkRoot;
|
|
|
|
string SdkRoot {
|
|
|
|
get => sdkRoot;
|
|
|
|
set {
|
|
|
|
sdkRoot = value;
|
|
|
|
XcodeRoot = FindXcode (sdkRoot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
string MlaunchPath => Path.Combine (IOS_DESTDIR, "Library", "Frameworks", "Xamarin.iOS.framework", "Versions", "Current", "bin", "mlaunch");
|
|
|
|
|
2020-03-13 17:41:02 +03:00
|
|
|
public List<iOSTestProject> IOSTestProjects { get; }
|
|
|
|
public List<MacTestProject> MacTestProjects { get; } = new List<MacTestProject> ();
|
2017-02-01 19:05:08 +03:00
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
// Configure
|
2020-03-13 17:41:02 +03:00
|
|
|
readonly bool useSystemXamarinIOSMac; // if the system XI/XM should be used, or the locally build XI/XM.
|
|
|
|
readonly bool autoConf;
|
|
|
|
|
|
|
|
public string WatchOSContainerTemplate { get; private set; }
|
|
|
|
public string WatchOSAppTemplate { get; private set; }
|
|
|
|
public string WatchOSExtensionTemplate { get; private set; }
|
|
|
|
public string TodayContainerTemplate { get; private set; }
|
|
|
|
public string TodayExtensionTemplate { get; private set; }
|
|
|
|
public string BCLTodayExtensionTemplate { get; private set; }
|
2020-03-27 19:41:31 +03:00
|
|
|
public string MONO_PATH { get; } // Use same name as in Makefiles, so that a grep finds it.
|
|
|
|
public string TVOS_MONO_PATH { get; } // Use same name as in Makefiles, so that a grep finds it.
|
|
|
|
public bool INCLUDE_IOS { get; }
|
|
|
|
public bool INCLUDE_TVOS { get; }
|
|
|
|
public bool INCLUDE_WATCH { get; }
|
|
|
|
public bool INCLUDE_MAC { get; }
|
|
|
|
public string JENKINS_RESULTS_DIRECTORY { get; } // Use same name as in Makefiles, so that a grep finds it.
|
|
|
|
public string MAC_DESTDIR { get; }
|
|
|
|
public string IOS_DESTDIR { get; }
|
|
|
|
public string MONO_IOS_SDK_DESTDIR { get; }
|
|
|
|
public string MONO_MAC_SDK_DESTDIR { get; }
|
|
|
|
public bool ENABLE_XAMARIN { get; }
|
2021-05-20 16:37:22 +03:00
|
|
|
public bool ENABLE_DOTNET { get; }
|
2016-05-26 16:06:52 +03:00
|
|
|
|
|
|
|
// Run
|
2020-03-20 13:42:43 +03:00
|
|
|
|
|
|
|
public string XcodeRoot { get; private set; }
|
2020-03-17 21:42:21 +03:00
|
|
|
public string LogDirectory { get; } = Environment.CurrentDirectory;
|
2020-03-13 17:41:02 +03:00
|
|
|
public double Timeout { get; } = 15; // in minutes
|
|
|
|
public double LaunchTimeout { get; } // in minutes
|
|
|
|
public bool DryRun { get; } // Most things don't support this. If you need it somewhere, implement it!
|
|
|
|
public string JenkinsConfiguration { get; }
|
2020-03-17 21:42:21 +03:00
|
|
|
public Dictionary<string, string> EnvironmentVariables { get; } = new Dictionary<string, string> ();
|
2020-03-13 17:41:02 +03:00
|
|
|
public string MarkdownSummaryPath { get; }
|
|
|
|
public string PeriodicCommand { get; }
|
|
|
|
public string PeriodicCommandArguments { get; }
|
2020-03-20 13:42:43 +03:00
|
|
|
public TimeSpan PeriodicCommandInterval { get; }
|
2017-11-28 21:16:46 +03:00
|
|
|
// whether tests that require access to system resources (system contacts, photo library, etc) should be executed or not
|
2019-07-12 17:05:57 +03:00
|
|
|
public bool? IncludeSystemPermissionTests { get; set; }
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-06-16 23:04:38 +03:00
|
|
|
string RootDirectory => HarnessConfiguration.RootDirectory;
|
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
public Harness (IResultParser resultParser, HarnessAction action, HarnessConfiguration configuration)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-03-20 00:42:51 +03:00
|
|
|
ResultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
|
2020-03-13 17:41:02 +03:00
|
|
|
Action = action;
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2020-03-13 17:41:02 +03:00
|
|
|
if (configuration is null)
|
|
|
|
throw new ArgumentNullException (nameof (configuration));
|
|
|
|
|
|
|
|
autoConf = configuration.AutoConf;
|
2020-03-17 21:42:21 +03:00
|
|
|
buildConfiguration = configuration.BuildConfiguration ?? throw new ArgumentNullException (nameof (configuration));
|
2020-03-13 17:41:02 +03:00
|
|
|
DryRun = configuration.DryRun;
|
|
|
|
IncludeSystemPermissionTests = configuration.IncludeSystemPermissionTests;
|
|
|
|
IOSTestProjects = configuration.IOSTestProjects;
|
|
|
|
JenkinsConfiguration = configuration.JenkinsConfiguration;
|
|
|
|
LogDirectory = configuration.LogDirectory ?? throw new ArgumentNullException (nameof (configuration.LogDirectory));
|
|
|
|
MarkdownSummaryPath = configuration.MarkdownSummaryPath;
|
|
|
|
PeriodicCommand = configuration.PeriodicCommand;
|
|
|
|
PeriodicCommandArguments = configuration.PeriodicCommandArguments;
|
|
|
|
PeriodicCommandInterval = configuration.PeriodicCommandInterval;
|
2020-03-17 21:42:21 +03:00
|
|
|
target = configuration.Target;
|
2020-03-13 17:41:02 +03:00
|
|
|
Timeout = configuration.TimeoutInMinutes;
|
|
|
|
useSystemXamarinIOSMac = configuration.UseSystemXamarinIOSMac;
|
|
|
|
Verbosity = configuration.Verbosity;
|
|
|
|
WatchOSAppTemplate = configuration.WatchOSAppTemplate;
|
|
|
|
WatchOSContainerTemplate = configuration.WatchOSContainerTemplate;
|
|
|
|
XmlJargon = configuration.XmlJargon;
|
|
|
|
|
|
|
|
if (configuration.Labels != null)
|
|
|
|
Labels = new HashSet<string> (configuration.Labels);
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2020-03-13 17:41:02 +03:00
|
|
|
if (configuration.EnvironmentVariables != null)
|
|
|
|
EnvironmentVariables = new Dictionary<string, string> (configuration.EnvironmentVariables);
|
|
|
|
|
2020-03-11 12:38:03 +03:00
|
|
|
LaunchTimeout = InCI ? 3 : 120;
|
2020-03-31 06:23:33 +03:00
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
var config = ParseConfigFiles ();
|
|
|
|
var src_root = Path.GetDirectoryName (Path.GetFullPath (RootDirectory));
|
|
|
|
|
|
|
|
MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "external", "mono"));
|
|
|
|
TVOS_MONO_PATH = MONO_PATH;
|
|
|
|
INCLUDE_IOS = config.ContainsKey ("INCLUDE_IOS") && !string.IsNullOrEmpty (config ["INCLUDE_IOS"]);
|
|
|
|
INCLUDE_TVOS = config.ContainsKey ("INCLUDE_TVOS") && !string.IsNullOrEmpty (config ["INCLUDE_TVOS"]);
|
|
|
|
JENKINS_RESULTS_DIRECTORY = config ["JENKINS_RESULTS_DIRECTORY"];
|
|
|
|
INCLUDE_WATCH = config.ContainsKey ("INCLUDE_WATCH") && !string.IsNullOrEmpty (config ["INCLUDE_WATCH"]);
|
|
|
|
INCLUDE_MAC = config.ContainsKey ("INCLUDE_MAC") && !string.IsNullOrEmpty (config ["INCLUDE_MAC"]);
|
|
|
|
MAC_DESTDIR = config ["MAC_DESTDIR"];
|
|
|
|
|
|
|
|
IOS_DESTDIR = config ["IOS_DESTDIR"];
|
|
|
|
MONO_IOS_SDK_DESTDIR = config ["MONO_IOS_SDK_DESTDIR"];
|
|
|
|
MONO_MAC_SDK_DESTDIR = config ["MONO_MAC_SDK_DESTDIR"];
|
|
|
|
ENABLE_XAMARIN = config.ContainsKey ("ENABLE_XAMARIN") && !string.IsNullOrEmpty (config ["ENABLE_XAMARIN"]);
|
2021-05-20 16:37:22 +03:00
|
|
|
ENABLE_DOTNET = config.ContainsKey ("ENABLE_DOTNET") && !string.IsNullOrEmpty (config ["ENABLE_DOTNET"]);
|
2020-03-27 19:41:31 +03:00
|
|
|
|
|
|
|
if (string.IsNullOrEmpty (SdkRoot))
|
|
|
|
SdkRoot = config ["XCODE_DEVELOPER_ROOT"] ?? configuration.SdkRoot;
|
2020-03-31 06:23:33 +03:00
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
processManager = new MlaunchProcessManager (XcodeRoot, MlaunchPath);
|
2020-11-16 17:24:07 +03:00
|
|
|
AppBundleLocator = new AppBundleLocator (processManager, () => HarnessLog, XIBuildPath, config ["DOTNET"], config ["DOTNET6"]);
|
2020-05-04 20:21:38 +03:00
|
|
|
TunnelBore = new TunnelBore (processManager);
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2019-07-12 17:05:57 +03:00
|
|
|
public bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device)
|
|
|
|
{
|
|
|
|
// If we've been told something in particular, that takes precedence.
|
|
|
|
if (IncludeSystemPermissionTests.HasValue)
|
|
|
|
return IncludeSystemPermissionTests.Value;
|
|
|
|
|
|
|
|
// If we haven't been told, try to be smart.
|
|
|
|
switch (platform) {
|
|
|
|
case TestPlatform.iOS:
|
|
|
|
case TestPlatform.Mac:
|
|
|
|
case TestPlatform.Mac_Full:
|
|
|
|
case TestPlatform.Mac_Modern:
|
|
|
|
case TestPlatform.Mac_System:
|
|
|
|
// On macOS we can't edit the TCC database easily
|
|
|
|
// (it requires adding the mac has to be using MDM: https://carlashley.com/2018/09/28/tcc-round-up/)
|
|
|
|
// So by default ignore any tests that would pop up permission dialogs in CI.
|
|
|
|
return !InCI;
|
|
|
|
default:
|
|
|
|
// On device we have the same issue as on the mac: we can't edit the TCC database.
|
|
|
|
if (device)
|
|
|
|
return !InCI;
|
|
|
|
// But in the simulator we can just write to the simulator's TCC database (and we do)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2018-08-04 00:06:23 +03:00
|
|
|
static string FindXcode (string path)
|
|
|
|
{
|
2020-03-20 13:42:43 +03:00
|
|
|
if (string.IsNullOrEmpty (path))
|
|
|
|
return path;
|
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
string originalPath = path;
|
|
|
|
|
2018-08-04 00:06:23 +03:00
|
|
|
do {
|
2020-03-20 13:42:43 +03:00
|
|
|
if (path == "/") {
|
2020-11-13 19:05:10 +03:00
|
|
|
throw new Exception (string.Format ("Could not find Xcode.app in {0}", originalPath));
|
2020-03-20 13:42:43 +03:00
|
|
|
} else if (File.Exists (Path.Combine (path, "Contents", "MacOS", "Xcode"))) {
|
|
|
|
return path;
|
2018-08-04 00:06:23 +03:00
|
|
|
}
|
|
|
|
|
2020-03-20 13:42:43 +03:00
|
|
|
path = Path.GetDirectoryName (path);
|
|
|
|
} while (true);
|
2018-08-04 00:06:23 +03:00
|
|
|
}
|
|
|
|
|
2021-09-06 16:23:41 +03:00
|
|
|
void AutoConfigureDotNet ()
|
|
|
|
{
|
|
|
|
string [] noConfigurations = null;
|
|
|
|
var debugAndRelease = new string [] { "Debug", "Release" };
|
|
|
|
|
|
|
|
var projects = new [] {
|
|
|
|
new { ProjectPath = "introspection", IsFSharp = false, Configurations = noConfigurations, },
|
|
|
|
new { ProjectPath = "monotouch-test", IsFSharp = false, Configurations = noConfigurations, },
|
|
|
|
new { ProjectPath = Path.Combine ("linker", "ios", "dont link"), IsFSharp = false, Configurations = debugAndRelease, },
|
|
|
|
new { ProjectPath = Path.Combine ("linker", "ios", "link sdk"), IsFSharp = false, Configurations = debugAndRelease, },
|
|
|
|
new { ProjectPath = Path.Combine ("linker", "ios", "link all"), IsFSharp = false, Configurations = debugAndRelease, },
|
2021-12-15 11:27:00 +03:00
|
|
|
new { ProjectPath = Path.Combine ("linker", "ios", "trimmode copy"), IsFSharp = false, Configurations = debugAndRelease, },
|
|
|
|
new { ProjectPath = Path.Combine ("linker", "ios", "trimmode link"), IsFSharp = false, Configurations = debugAndRelease, },
|
2021-09-06 16:23:41 +03:00
|
|
|
new { ProjectPath = "fsharp", IsFSharp = true, Configurations = noConfigurations, },
|
|
|
|
new { ProjectPath = "framework-test", IsFSharp = false, Configurations = noConfigurations, },
|
|
|
|
new { ProjectPath = "interdependent-binding-projects", IsFSharp = false, Configurations = noConfigurations, },
|
|
|
|
new { ProjectPath = "xcframework-test", IsFSharp = false, Configurations = noConfigurations, },
|
|
|
|
};
|
|
|
|
|
|
|
|
// If .NET is not enabled, then ignore, otherwise leave undecided for other code to determine.
|
|
|
|
bool? dotnetIgnored = ENABLE_DOTNET ? null : (bool?) true;
|
|
|
|
foreach (var projectInfo in projects) {
|
|
|
|
var projectPath = projectInfo.ProjectPath;
|
|
|
|
var projectName = Path.GetFileName (projectPath);
|
|
|
|
var projExtension = projectInfo.IsFSharp ? ".fsproj" : ".csproj";
|
|
|
|
|
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, projectPath, "dotnet", "iOS", projectName + projExtension))) {
|
|
|
|
Name = projectName,
|
|
|
|
IsDotNetProject = true,
|
|
|
|
SkipiOSVariation = false,
|
|
|
|
SkiptvOSVariation = true,
|
|
|
|
SkipwatchOSVariation = true,
|
|
|
|
SkipTodayExtensionVariation = true,
|
|
|
|
SkipDeviceVariations = false,
|
|
|
|
TestPlatform = TestPlatform.iOS_Unified,
|
|
|
|
Ignore = dotnetIgnored,
|
|
|
|
Configurations = projectInfo.Configurations,
|
|
|
|
});
|
|
|
|
|
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, projectPath, "dotnet", "tvOS", projectName + projExtension))) {
|
|
|
|
Name = projectName,
|
|
|
|
IsDotNetProject = true,
|
|
|
|
SkipiOSVariation = true,
|
|
|
|
SkiptvOSVariation = true,
|
|
|
|
SkipwatchOSVariation = true,
|
|
|
|
SkipTodayExtensionVariation = true,
|
|
|
|
SkipDeviceVariations = false,
|
|
|
|
GenerateVariations = false,
|
|
|
|
TestPlatform = TestPlatform.tvOS,
|
|
|
|
Ignore = dotnetIgnored,
|
|
|
|
Configurations = projectInfo.Configurations,
|
|
|
|
});
|
|
|
|
|
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, projectPath, "dotnet", "macOS", projectName + projExtension))) {
|
|
|
|
Name = projectName,
|
|
|
|
IsDotNetProject = true,
|
|
|
|
TargetFrameworkFlavors = MacFlavors.DotNet,
|
|
|
|
Platform = "AnyCPU",
|
|
|
|
Ignore = dotnetIgnored,
|
|
|
|
TestPlatform = TestPlatform.Mac,
|
|
|
|
Configurations = projectInfo.Configurations,
|
|
|
|
});
|
|
|
|
|
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, projectPath, "dotnet", "MacCatalyst", projectName + projExtension))) {
|
|
|
|
Name = projectName,
|
|
|
|
IsDotNetProject = true,
|
|
|
|
TargetFrameworkFlavors = MacFlavors.MacCatalyst,
|
|
|
|
Platform = "AnyCPU",
|
|
|
|
Ignore = dotnetIgnored,
|
|
|
|
TestPlatform = TestPlatform.MacCatalyst,
|
|
|
|
Configurations = projectInfo.Configurations,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 19:46:41 +03:00
|
|
|
int AutoConfigureMac (bool generate_projects)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2019-06-19 19:46:41 +03:00
|
|
|
int rv = 0;
|
|
|
|
|
2018-01-16 21:15:59 +03:00
|
|
|
var test_suites = new [] {
|
2019-06-19 19:46:41 +03:00
|
|
|
new { Directory = "linker/mac/dont link", ProjectFile = "dont link-mac", Name = "dont link", Flavors = MacFlavors.Modern | MacFlavors.Full | MacFlavors.System },
|
2018-01-16 21:15:59 +03:00
|
|
|
};
|
2018-10-15 17:51:46 +03:00
|
|
|
foreach (var p in test_suites) {
|
2020-03-11 12:38:03 +03:00
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p.Directory, p.ProjectFile + ".csproj"))) {
|
2018-10-15 17:51:46 +03:00
|
|
|
Name = p.Name,
|
2019-06-19 19:46:41 +03:00
|
|
|
TargetFrameworkFlavors = p.Flavors,
|
2018-10-15 17:51:46 +03:00
|
|
|
});
|
|
|
|
}
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2020-03-11 12:38:03 +03:00
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "introspection", "Mac", "introspection-mac.csproj")), targetFrameworkFlavor: MacFlavors.Modern) { Name = "introspection" });
|
2020-11-26 16:47:41 +03:00
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "framework-test", "macOS", "framework-test-mac.csproj")), targetFrameworkFlavor: MacFlavors.Modern) { Name = "framework-test" });
|
2020-11-30 21:44:03 +03:00
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "xcframework-test", "macOS", "xcframework-test-mac.csproj")), targetFrameworkFlavor: MacFlavors.Modern) { Name = "xcframework-test" });
|
2017-02-01 19:05:08 +03:00
|
|
|
|
2017-05-08 14:20:01 +03:00
|
|
|
var hard_coded_test_suites = new [] {
|
2019-06-19 19:46:41 +03:00
|
|
|
new { Directory = "mmptest", ProjectFile = "mmptest", Name = "mmptest", IsNUnit = true, Configurations = (string[]) null, Platform = "x86", Flavors = MacFlavors.Console, },
|
|
|
|
new { Directory = "xammac_tests", ProjectFile = "xammac_tests", Name = "xammac tests", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "AnyCPU", Flavors = MacFlavors.Modern, },
|
|
|
|
new { Directory = "linker/mac/link all", ProjectFile = "link all-mac", Name = "link all", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "x86", Flavors = MacFlavors.Modern, },
|
|
|
|
new { Directory = "linker/mac/link sdk", ProjectFile = "link sdk-mac", Name = "link sdk", IsNUnit = false, Configurations = new string [] { "Debug", "Release" }, Platform = "x86", Flavors = MacFlavors.Modern, },
|
2017-05-08 14:20:01 +03:00
|
|
|
};
|
|
|
|
foreach (var p in hard_coded_test_suites) {
|
2020-03-11 12:38:03 +03:00
|
|
|
MacTestProjects.Add (new MacTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p.Directory, p.ProjectFile + ".csproj")), targetFrameworkFlavor: p.Flavors) {
|
2017-05-08 14:20:01 +03:00
|
|
|
Name = p.Name,
|
|
|
|
IsNUnitProject = p.IsNUnit,
|
2020-03-11 12:38:03 +03:00
|
|
|
SolutionPath = Path.GetFullPath (Path.Combine (RootDirectory, "tests-mac.sln")),
|
2017-05-25 08:11:36 +03:00
|
|
|
Configurations = p.Configurations,
|
2017-11-22 18:28:32 +03:00
|
|
|
Platform = p.Platform,
|
2017-05-08 14:20:01 +03:00
|
|
|
});
|
|
|
|
}
|
2017-02-01 19:05:08 +03:00
|
|
|
|
2019-06-19 19:46:41 +03:00
|
|
|
foreach (var flavor in new MonoNativeFlavor [] { MonoNativeFlavor.Compat, MonoNativeFlavor.Unified }) {
|
2020-07-21 12:38:53 +03:00
|
|
|
var monoNativeInfo = new MonoNativeInfo (DevicePlatform.macOS, flavor, RootDirectory, Log);
|
2019-06-19 19:46:41 +03:00
|
|
|
var macTestProject = new MacTestProject (monoNativeInfo.ProjectPath, targetFrameworkFlavor: MacFlavors.Modern | MacFlavors.Full) {
|
|
|
|
MonoNativeInfo = monoNativeInfo,
|
|
|
|
Name = monoNativeInfo.ProjectName,
|
|
|
|
Platform = "AnyCPU",
|
2018-11-14 21:26:30 +03:00
|
|
|
|
2019-06-19 19:46:41 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
MacTestProjects.Add (macTestProject);
|
2018-11-14 21:26:30 +03:00
|
|
|
}
|
2018-12-17 17:28:08 +03:00
|
|
|
|
2018-12-12 12:38:48 +03:00
|
|
|
var monoImportTestFactory = new BCLTestImportTargetFactory (this);
|
2019-01-31 20:28:38 +03:00
|
|
|
MacTestProjects.AddRange (monoImportTestFactory.GetMacBclTargets ());
|
2019-06-19 19:46:41 +03:00
|
|
|
|
|
|
|
// Generate test projects from templates (bcl/mono-native templates)
|
|
|
|
if (generate_projects) {
|
|
|
|
foreach (var mtp in MacTestProjects.Where (x => x.MonoNativeInfo != null).Select (x => x.MonoNativeInfo))
|
|
|
|
mtp.Convert ();
|
|
|
|
}
|
|
|
|
|
|
|
|
// All test projects should be either Modern projects or NUnit/console executables at this point.
|
|
|
|
// If we need to generate Full/System variations, we do that here.
|
|
|
|
var unified_targets = new List<MacTarget> ();
|
|
|
|
|
2019-06-24 17:08:13 +03:00
|
|
|
Action<MacTarget, string, bool, bool> configureTarget = (MacTarget target, string file, bool isNUnitProject, bool skip_generation) => {
|
2019-06-19 19:46:41 +03:00
|
|
|
target.TemplateProjectPath = file;
|
|
|
|
target.Harness = this;
|
|
|
|
target.IsNUnitProject = isNUnitProject;
|
2019-06-24 17:08:13 +03:00
|
|
|
if (!generate_projects || skip_generation)
|
2019-06-19 19:46:41 +03:00
|
|
|
target.ShouldSkipProjectGeneration = true;
|
|
|
|
target.Execute ();
|
|
|
|
};
|
|
|
|
|
2019-06-24 17:08:13 +03:00
|
|
|
foreach (var proj in MacTestProjects) {
|
|
|
|
var target = new MacTarget (MacFlavors.Modern);
|
|
|
|
configureTarget (target, proj.Path, proj.IsNUnitProject, true);
|
|
|
|
unified_targets.Add (target);
|
|
|
|
}
|
|
|
|
|
2019-06-19 19:46:41 +03:00
|
|
|
foreach (var proj in MacTestProjects.Where ((v) => v.GenerateVariations).ToArray ()) {
|
|
|
|
var file = proj.Path;
|
|
|
|
if (!File.Exists (file)) {
|
|
|
|
Console.WriteLine ($"Can't find the project file {file}.");
|
|
|
|
rv = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate variations if requested
|
|
|
|
if (proj.GenerateFull) {
|
|
|
|
var target = new MacTarget (MacFlavors.Full);
|
2019-06-24 17:08:13 +03:00
|
|
|
configureTarget (target, file, proj.IsNUnitProject, false);
|
2019-06-19 19:46:41 +03:00
|
|
|
unified_targets.Add (target);
|
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
var cloned_project = (MacTestProject) proj.Clone ();
|
2019-06-19 19:46:41 +03:00
|
|
|
cloned_project.TargetFrameworkFlavors = MacFlavors.Full;
|
|
|
|
cloned_project.Path = target.ProjectPath;
|
|
|
|
MacTestProjects.Add (cloned_project);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (proj.GenerateSystem) {
|
|
|
|
var target = new MacTarget (MacFlavors.System);
|
2019-06-24 17:08:13 +03:00
|
|
|
configureTarget (target, file, proj.IsNUnitProject, false);
|
2019-06-19 19:46:41 +03:00
|
|
|
unified_targets.Add (target);
|
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
var cloned_project = (MacTestProject) proj.Clone ();
|
2019-06-19 19:46:41 +03:00
|
|
|
cloned_project.TargetFrameworkFlavors = MacFlavors.System;
|
|
|
|
cloned_project.Path = target.ProjectPath;
|
|
|
|
MacTestProjects.Add (cloned_project);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're done generating now
|
|
|
|
// Re-use the existing TestProject instance instead of creating a new one.
|
|
|
|
proj.TargetFrameworkFlavors = MacFlavors.Modern; // the default/template flavor is 'Modern'
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2016-06-10 21:56:48 +03:00
|
|
|
void AutoConfigureIOS ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2021-10-05 19:06:35 +03:00
|
|
|
var library_projects = new string [] { "BundledResources", "EmbeddedResources", "bindings-test2" };
|
2016-05-26 16:06:52 +03:00
|
|
|
var fsharp_test_suites = new string [] { "fsharp" };
|
|
|
|
var fsharp_library_projects = new string [] { "fsharplibrary" };
|
2020-02-27 05:21:09 +03:00
|
|
|
|
2021-01-26 14:28:35 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "monotouch-test", "monotouch-test.csproj"))) {
|
|
|
|
Name = "monotouch-test",
|
|
|
|
});
|
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
foreach (var p in fsharp_test_suites)
|
2020-03-11 12:38:03 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj"))) { Name = p });
|
2016-05-26 16:06:52 +03:00
|
|
|
foreach (var p in library_projects)
|
2020-03-11 12:38:03 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".csproj")), false) { Name = p });
|
2016-05-26 16:06:52 +03:00
|
|
|
foreach (var p in fsharp_library_projects)
|
2020-03-11 12:38:03 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, p + "/" + p + ".fsproj")), false) { Name = p });
|
2017-02-01 19:05:08 +03:00
|
|
|
|
2021-10-05 19:06:35 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "bindings-framework-test", "iOS", "bindings-framework-test.csproj")), false) {
|
|
|
|
Name = "bindings-framework-test",
|
|
|
|
});
|
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "bindings-xcframework-test", "iOS", "bindings-xcframework-test.csproj")), false) {
|
|
|
|
Name = "bindings-xcframework-test",
|
|
|
|
});
|
2021-02-04 10:28:47 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "framework-test", "iOS", "framework-test-ios.csproj"))) {
|
|
|
|
Name = "framework-test",
|
|
|
|
});
|
2021-02-05 09:39:38 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "xcframework-test", "iOS", "xcframework-test-ios.csproj"))) {
|
|
|
|
Name = "xcframework-test",
|
|
|
|
});
|
2020-11-26 16:47:41 +03:00
|
|
|
|
2020-07-21 15:17:54 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "bindings-test", "iOS", "bindings-test.csproj")), false) { Name = "bindings-test" });
|
|
|
|
|
2020-08-12 17:04:20 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "interdependent-binding-projects", "interdependent-binding-projects.csproj"))) { Name = "interdependent-binding-projects" });
|
2021-09-07 19:35:33 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "introspection", "iOS", "introspection-ios.csproj"))) { Name = "introspection" });
|
2021-02-01 20:42:40 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "linker", "ios", "dont link", "dont link.csproj"))) {
|
|
|
|
Configurations = new string [] { "Debug", "Release" },
|
|
|
|
});
|
2021-02-05 09:43:33 +03:00
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "linker", "ios", "link all", "link all.csproj"))) {
|
|
|
|
Configurations = new string [] { "Debug", "Release" },
|
|
|
|
});
|
|
|
|
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "linker", "ios", "link sdk", "link sdk.csproj"))) {
|
|
|
|
Configurations = new string [] { "Debug", "Release" },
|
|
|
|
});
|
2021-08-10 08:40:00 +03:00
|
|
|
|
2020-03-16 16:26:46 +03:00
|
|
|
foreach (var flavor in new MonoNativeFlavor [] { MonoNativeFlavor.Compat, MonoNativeFlavor.Unified }) {
|
2020-07-21 12:38:53 +03:00
|
|
|
var monoNativeInfo = new MonoNativeInfo (DevicePlatform.iOS, flavor, RootDirectory, Log);
|
2019-06-19 19:46:41 +03:00
|
|
|
var iosTestProject = new iOSTestProject (monoNativeInfo.ProjectPath) {
|
2018-11-14 21:26:30 +03:00
|
|
|
MonoNativeInfo = monoNativeInfo,
|
2019-05-10 10:29:23 +03:00
|
|
|
Name = monoNativeInfo.ProjectName,
|
|
|
|
SkipwatchOSARM64_32Variation = monoNativeInfo.ProjectName.Contains ("compat"),
|
2018-11-14 21:26:30 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
IOSTestProjects.Add (iosTestProject);
|
|
|
|
}
|
|
|
|
|
2018-11-16 21:31:40 +03:00
|
|
|
// add all the tests that are using the precompiled mono assemblies
|
|
|
|
var monoImportTestFactory = new BCLTestImportTargetFactory (this);
|
2019-01-31 20:28:38 +03:00
|
|
|
IOSTestProjects.AddRange (monoImportTestFactory.GetiOSBclTargets ());
|
2018-11-16 21:31:40 +03:00
|
|
|
|
2020-03-11 12:38:03 +03:00
|
|
|
WatchOSContainerTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchContainer"));
|
|
|
|
WatchOSAppTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchApp"));
|
|
|
|
WatchOSExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates/WatchExtension"));
|
2017-01-04 21:45:26 +03:00
|
|
|
|
2020-03-11 12:38:03 +03:00
|
|
|
TodayContainerTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates", "TodayContainer"));
|
|
|
|
TodayExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "templates", "TodayExtension"));
|
|
|
|
BCLTodayExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test", "templates", "today"));
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
// Dictionary<string, string> make_config = new Dictionary<string, string> ();
|
2017-01-05 01:05:04 +03:00
|
|
|
IEnumerable<string> FindConfigFiles (string name)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-03-11 12:38:03 +03:00
|
|
|
var dir = Path.GetFullPath (RootDirectory);
|
2016-05-26 16:06:52 +03:00
|
|
|
while (dir != "/") {
|
|
|
|
var file = Path.Combine (dir, name);
|
|
|
|
if (File.Exists (file))
|
|
|
|
yield return file;
|
|
|
|
dir = Path.GetDirectoryName (dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
Dictionary<string, string> ParseConfigFiles ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-03-27 19:41:31 +03:00
|
|
|
var configuration = new Dictionary<string, string> ();
|
|
|
|
foreach (var file in GetConfigFiles ()) {
|
|
|
|
ParseConfigFile (file, configuration);
|
|
|
|
}
|
|
|
|
|
|
|
|
return configuration;
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-31 06:23:33 +03:00
|
|
|
IEnumerable<string> GetConfigFiles ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-03-27 19:41:31 +03:00
|
|
|
return FindConfigFiles (useSystemXamarinIOSMac ? "test-system.config" : "test.config")
|
|
|
|
.Concat (FindConfigFiles ("Make.config"))
|
|
|
|
.Concat (FindConfigFiles ("Make.config.local"));
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-27 19:41:31 +03:00
|
|
|
void ParseConfigFile (string file, Dictionary<string, string> configuration)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty (file))
|
|
|
|
return;
|
|
|
|
|
|
|
|
foreach (var line in File.ReadAllLines (file)) {
|
|
|
|
var eq = line.IndexOf ('=');
|
|
|
|
if (eq == -1)
|
|
|
|
continue;
|
2020-03-27 19:41:31 +03:00
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
var key = line.Substring (0, eq);
|
2020-03-27 19:41:31 +03:00
|
|
|
if (!configuration.ContainsKey (key))
|
|
|
|
configuration [key] = line.Substring (eq + 1);
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
int Configure ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2021-09-16 18:23:07 +03:00
|
|
|
var rv = AutoConfigureMac (true);
|
|
|
|
if (rv != 0)
|
|
|
|
return rv;
|
|
|
|
return ConfigureIOS ();
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-07-21 12:12:27 +03:00
|
|
|
// At startup we:
|
|
|
|
// * Load a list of well-known test projects IOSTestProjects/MacTestProjects. This happens in AutoConfigureIOS/AutoConfigureMac.
|
|
|
|
// Example projects:
|
|
|
|
// * introspection
|
|
|
|
// * dont link, link all, link sdk
|
|
|
|
// * Each of these test projects can used to generate other platform variations (tvOS, watchOS, macOS full, etc),
|
|
|
|
// if the the TestProject.GenerateVariations property is true.
|
|
|
|
// * For the mono-native template project, we generate a compat+unified version of the mono-native template project (in MonoNativeInfo.Convert).
|
|
|
|
// GenerateVariations is true for mono-native projects, which means we'll generate platform variations.
|
|
|
|
// * For the BCL tests, we use a BCL test project generator. The BCL test generator generates projects for
|
|
|
|
// all platforms we're interested in, so we set GenerateVariations to false to avoid generate the platform variations again.
|
|
|
|
|
2019-02-05 14:55:46 +03:00
|
|
|
int ConfigureIOS ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2019-02-05 14:55:46 +03:00
|
|
|
var rv = 0;
|
2016-05-26 16:06:52 +03:00
|
|
|
var unified_targets = new List<UnifiedTarget> ();
|
|
|
|
var tvos_targets = new List<TVOSTarget> ();
|
|
|
|
var watchos_targets = new List<WatchOSTarget> ();
|
2017-01-04 21:45:26 +03:00
|
|
|
var today_targets = new List<TodayExtensionTarget> ();
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-03-13 17:41:02 +03:00
|
|
|
if (autoConf)
|
2016-06-10 21:56:48 +03:00
|
|
|
AutoConfigureIOS ();
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2018-11-14 21:26:30 +03:00
|
|
|
foreach (var monoNativeInfo in IOSTestProjects.Where (x => x.MonoNativeInfo != null).Select (x => x.MonoNativeInfo))
|
|
|
|
monoNativeInfo.Convert ();
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-07-22 11:35:36 +03:00
|
|
|
foreach (var proj in IOSTestProjects.Where ((v) => v.GenerateVariations)) {
|
2016-06-06 13:48:53 +03:00
|
|
|
var file = proj.Path;
|
2019-02-05 23:38:47 +03:00
|
|
|
|
2019-02-05 14:55:46 +03:00
|
|
|
if (!File.Exists (file)) {
|
|
|
|
Console.WriteLine ($"Can't find the project file {file}.");
|
|
|
|
rv = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2017-09-22 19:04:32 +03:00
|
|
|
if (!proj.SkipwatchOSVariation) {
|
|
|
|
var watchos = new WatchOSTarget () {
|
|
|
|
TemplateProjectPath = file,
|
|
|
|
Harness = this,
|
|
|
|
TestProject = proj,
|
|
|
|
};
|
|
|
|
watchos.Execute ();
|
|
|
|
watchos_targets.Add (watchos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!proj.SkiptvOSVariation) {
|
|
|
|
var tvos = new TVOSTarget () {
|
|
|
|
TemplateProjectPath = file,
|
|
|
|
Harness = this,
|
|
|
|
TestProject = proj,
|
|
|
|
};
|
|
|
|
tvos.Execute ();
|
|
|
|
tvos_targets.Add (tvos);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!proj.SkipiOSVariation) {
|
|
|
|
var unified = new UnifiedTarget () {
|
|
|
|
TemplateProjectPath = file,
|
|
|
|
Harness = this,
|
|
|
|
TestProject = proj,
|
2020-06-19 15:41:22 +03:00
|
|
|
ShouldSkipProjectGeneration = proj.IsDotNetProject,
|
2017-09-22 19:04:32 +03:00
|
|
|
};
|
|
|
|
unified.Execute ();
|
|
|
|
unified_targets.Add (unified);
|
|
|
|
|
2020-06-30 19:14:55 +03:00
|
|
|
if (!proj.SkipTodayExtensionVariation) {
|
|
|
|
var today = new TodayExtensionTarget {
|
|
|
|
TemplateProjectPath = file,
|
|
|
|
Harness = this,
|
|
|
|
TestProject = proj,
|
2020-06-19 15:41:22 +03:00
|
|
|
ShouldSkipProjectGeneration = proj.IsDotNetProject,
|
2020-06-30 19:14:55 +03:00
|
|
|
};
|
|
|
|
today.Execute ();
|
|
|
|
today_targets.Add (today);
|
|
|
|
}
|
2017-09-22 19:04:32 +03:00
|
|
|
}
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-07-17 16:23:12 +03:00
|
|
|
SolutionGenerator.CreateSolution (this, watchos_targets, "watchos", DevicePlatform.watchOS);
|
|
|
|
SolutionGenerator.CreateSolution (this, tvos_targets, "tvos", DevicePlatform.tvOS);
|
|
|
|
SolutionGenerator.CreateSolution (this, today_targets, "today", DevicePlatform.iOS);
|
2019-02-05 14:55:46 +03:00
|
|
|
|
|
|
|
return rv;
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
int Install ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-11-13 19:05:10 +03:00
|
|
|
HarnessLog ??= GetAdHocLog();
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2016-06-10 21:56:48 +03:00
|
|
|
foreach (var project in IOSTestProjects) {
|
2020-03-27 19:41:31 +03:00
|
|
|
var runner = CreateAppRunner (project);
|
2019-02-20 08:33:30 +03:00
|
|
|
using (var install_log = new AppInstallMonitorLog (runner.MainLog)) {
|
|
|
|
var rv = runner.InstallAsync (install_log.CancellationToken).Result;
|
|
|
|
if (!rv.Succeeded)
|
|
|
|
return rv.ExitCode;
|
|
|
|
}
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
int Uninstall ()
|
2017-01-02 10:58:46 +03:00
|
|
|
{
|
2020-11-13 19:05:10 +03:00
|
|
|
HarnessLog ??= GetAdHocLog ();
|
2017-01-02 10:58:46 +03:00
|
|
|
|
|
|
|
foreach (var project in IOSTestProjects) {
|
2020-03-27 19:41:31 +03:00
|
|
|
var runner = CreateAppRunner (project);
|
2017-01-04 21:45:26 +03:00
|
|
|
var rv = runner.UninstallAsync ().Result;
|
|
|
|
if (!rv.Succeeded)
|
|
|
|
return rv.ExitCode;
|
2017-01-02 10:58:46 +03:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
int Run ()
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
2020-11-13 19:05:10 +03:00
|
|
|
HarnessLog ??= GetAdHocLog ();
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2016-06-10 21:56:48 +03:00
|
|
|
foreach (var project in IOSTestProjects) {
|
2020-03-27 19:41:31 +03:00
|
|
|
var runner = CreateAppRunner (project);
|
2016-06-17 18:21:18 +03:00
|
|
|
var rv = runner.RunAsync ().Result;
|
2016-05-26 16:06:52 +03:00
|
|
|
if (rv != 0)
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
void Log (int min_level, string message)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
|
|
|
if (Verbosity < min_level)
|
|
|
|
return;
|
|
|
|
Console.WriteLine (message);
|
2016-06-06 13:48:53 +03:00
|
|
|
HarnessLog?.WriteLine (message);
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-03-16 16:26:46 +03:00
|
|
|
public void Log (int min_level, string message, params object [] args)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
|
|
|
if (Verbosity < min_level)
|
|
|
|
return;
|
|
|
|
Console.WriteLine (message, args);
|
2016-06-06 13:48:53 +03:00
|
|
|
HarnessLog?.WriteLine (message, args);
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Log (string message)
|
|
|
|
{
|
|
|
|
Log (0, message);
|
|
|
|
}
|
|
|
|
|
2020-03-16 16:26:46 +03:00
|
|
|
public void Log (string message, params object [] args)
|
2016-05-26 16:06:52 +03:00
|
|
|
{
|
|
|
|
Log (0, message, args);
|
|
|
|
}
|
|
|
|
|
2019-07-01 20:02:56 +03:00
|
|
|
public bool InCI {
|
|
|
|
get {
|
|
|
|
// We use the 'BUILD_REVISION' variable to detect whether we're running CI or not.
|
|
|
|
return !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("BUILD_REVISION"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-04 20:21:38 +03:00
|
|
|
public bool UseTcpTunnel {
|
|
|
|
get {
|
|
|
|
// We use the 'USE_TCP_TUNNEL' variable to detect whether we're running CI or not.
|
|
|
|
return !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("USE_TCP_TUNNEL"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-20 14:10:18 +03:00
|
|
|
public bool UseGroupedApps {
|
|
|
|
get {
|
|
|
|
var groupApps = Environment.GetEnvironmentVariable ("BCL_GROUPED_APPS");
|
|
|
|
return string.IsNullOrEmpty (groupApps) || groupApps == "grouped";
|
|
|
|
}
|
|
|
|
}
|
2016-05-26 16:06:52 +03:00
|
|
|
|
2020-06-19 02:51:14 +03:00
|
|
|
public string VSDropsUri {
|
|
|
|
get {
|
|
|
|
var uri = Environment.GetEnvironmentVariable ("VSDROPS_URI");
|
|
|
|
return string.IsNullOrEmpty (uri) ? null : uri;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
public int Execute ()
|
|
|
|
{
|
|
|
|
switch (Action) {
|
|
|
|
case HarnessAction.Configure:
|
|
|
|
return Configure ();
|
|
|
|
case HarnessAction.Run:
|
|
|
|
return Run ();
|
|
|
|
case HarnessAction.Install:
|
|
|
|
return Install ();
|
2017-01-02 10:58:46 +03:00
|
|
|
case HarnessAction.Uninstall:
|
|
|
|
return Uninstall ();
|
2016-06-06 13:48:53 +03:00
|
|
|
case HarnessAction.Jenkins:
|
|
|
|
return Jenkins ();
|
2016-05-26 16:06:52 +03:00
|
|
|
default:
|
|
|
|
throw new NotImplementedException (Action.ToString ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-17 21:42:21 +03:00
|
|
|
int Jenkins ()
|
2020-03-11 12:38:03 +03:00
|
|
|
{
|
2020-03-13 17:41:02 +03:00
|
|
|
if (autoConf) {
|
2021-09-06 16:23:41 +03:00
|
|
|
AutoConfigureDotNet ();
|
2020-03-11 12:38:03 +03:00
|
|
|
AutoConfigureIOS ();
|
|
|
|
AutoConfigureMac (false);
|
|
|
|
}
|
2020-03-16 16:26:46 +03:00
|
|
|
|
2020-05-04 20:21:38 +03:00
|
|
|
var jenkins = new Jenkins.Jenkins (this, processManager, ResultParser, TunnelBore);
|
2020-03-11 12:38:03 +03:00
|
|
|
return jenkins.Run ();
|
|
|
|
}
|
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
public void Save (StringWriter doc, string path)
|
|
|
|
{
|
|
|
|
if (!File.Exists (path)) {
|
2020-07-17 19:20:28 +03:00
|
|
|
Directory.CreateDirectory (Path.GetDirectoryName (path));
|
2016-05-26 16:06:52 +03:00
|
|
|
File.WriteAllText (path, doc.ToString ());
|
|
|
|
Log (1, "Created {0}", path);
|
|
|
|
} else {
|
|
|
|
var existing = File.ReadAllText (path);
|
|
|
|
var updated = doc.ToString ();
|
|
|
|
|
|
|
|
if (existing == updated) {
|
|
|
|
Log (1, "Not saved {0}, no change", path);
|
|
|
|
} else {
|
|
|
|
File.WriteAllText (path, updated);
|
|
|
|
Log (1, "Updated {0}", path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool? disable_watchos_on_wrench;
|
2020-03-20 13:42:43 +03:00
|
|
|
|
2016-05-26 16:06:52 +03:00
|
|
|
public bool DisableWatchOSOnWrench {
|
|
|
|
get {
|
|
|
|
if (!disable_watchos_on_wrench.HasValue)
|
|
|
|
disable_watchos_on_wrench = !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("DISABLE_WATCH_ON_WRENCH"));
|
|
|
|
return disable_watchos_on_wrench.Value;
|
|
|
|
}
|
|
|
|
}
|
2016-06-17 18:21:18 +03:00
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
AppRunner CreateAppRunner (TestProject project)
|
2016-06-17 18:21:18 +03:00
|
|
|
{
|
2020-05-25 15:47:10 +03:00
|
|
|
var rv = new AppRunner (processManager,
|
2020-11-13 19:05:10 +03:00
|
|
|
new AppBundleInformationParser (processManager, AppBundleLocator),
|
2020-04-06 21:33:27 +03:00
|
|
|
new SimulatorLoaderFactory (processManager),
|
2020-05-07 00:34:24 +03:00
|
|
|
new SimpleListenerFactory (UseTcpTunnel ? TunnelBore : null),
|
2020-03-27 19:41:31 +03:00
|
|
|
new DeviceLoaderFactory (processManager),
|
|
|
|
new CrashSnapshotReporterFactory (processManager),
|
|
|
|
new CaptureLogFactory (),
|
|
|
|
new DeviceLogCapturerFactory (processManager),
|
2020-03-29 19:02:03 +03:00
|
|
|
new TestReporterFactory (processManager),
|
2020-03-27 19:41:31 +03:00
|
|
|
target,
|
|
|
|
this,
|
|
|
|
HarnessLog,
|
|
|
|
new Logs (LogDirectory),
|
|
|
|
project.Path,
|
|
|
|
buildConfiguration);
|
2020-05-25 15:47:10 +03:00
|
|
|
rv.InitializeAsync ().Wait ();
|
|
|
|
return rv;
|
2016-06-17 18:21:18 +03:00
|
|
|
}
|
2020-06-25 09:46:03 +03:00
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
public string GetDotNetExecutable (string directory) => AppBundleLocator.GetDotNetExecutable (directory);
|
2020-06-25 09:46:03 +03:00
|
|
|
|
2020-11-13 19:05:10 +03:00
|
|
|
private static IFileBackedLog GetAdHocLog () => Microsoft.DotNet.XHarness.Common.Logging.Log.CreateReadableAggregatedLog (
|
|
|
|
new LogFile ("HarnessLog", Path.GetTempFileName ()), new ConsoleLog ());
|
2021-05-06 16:11:42 +03:00
|
|
|
|
|
|
|
// Return true if the current machine can run ARM64 binaries.
|
|
|
|
static bool? canRunArm64;
|
|
|
|
public static bool CanRunArm64 {
|
|
|
|
get {
|
|
|
|
if (!canRunArm64.HasValue) {
|
|
|
|
int rv = 0;
|
|
|
|
IntPtr size = (IntPtr) sizeof (int);
|
|
|
|
if (sysctlbyname ("hw.optional.arm64", ref rv, ref size, IntPtr.Zero, IntPtr.Zero) == 0) {
|
|
|
|
canRunArm64 = rv == 1;
|
|
|
|
} else {
|
|
|
|
canRunArm64 = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return canRunArm64.Value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[DllImport ("libc")]
|
|
|
|
static extern int sysctlbyname (string name, ref int value, ref IntPtr size, IntPtr zero, IntPtr zeroAgain);
|
2016-05-26 16:06:52 +03:00
|
|
|
}
|
|
|
|
}
|