diff --git a/tests/xharness/Harness.cs b/tests/xharness/Harness.cs
index fe58e63acc..1548b6197e 100644
--- a/tests/xharness/Harness.cs
+++ b/tests/xharness/Harness.cs
@@ -298,7 +298,7 @@ namespace Xharness {
}
foreach (var flavor in new MonoNativeFlavor [] { MonoNativeFlavor.Compat, MonoNativeFlavor.Unified }) {
- var monoNativeInfo = new MacMonoNativeInfo (this, flavor);
+ var monoNativeInfo = new MacMonoNativeInfo (this, flavor, RootDirectory);
var macTestProject = new MacTestProject (monoNativeInfo.ProjectPath, targetFrameworkFlavor: MacFlavors.Modern | MacFlavors.Full) {
MonoNativeInfo = monoNativeInfo,
Name = monoNativeInfo.ProjectName,
@@ -404,7 +404,7 @@ namespace Xharness {
IOSTestProjects.Add (new iOSTestProject (Path.GetFullPath (Path.Combine (RootDirectory, "linker", "ios", "link sdk", "link sdk.csproj"))) { Configurations = new string [] { "Debug", "Release" } });
foreach (var flavor in new MonoNativeFlavor [] { MonoNativeFlavor.Compat, MonoNativeFlavor.Unified }) {
- var monoNativeInfo = new MonoNativeInfo (this, flavor);
+ var monoNativeInfo = new MonoNativeInfo (this, flavor, RootDirectory);
var iosTestProject = new iOSTestProject (monoNativeInfo.ProjectPath) {
MonoNativeInfo = monoNativeInfo,
Name = monoNativeInfo.ProjectName,
@@ -663,28 +663,6 @@ namespace Xharness {
return jenkins.Run ();
}
- public void Save (XmlDocument doc, string path)
- {
- if (!File.Exists (path)) {
- doc.Save (path);
- Log (1, "Created {0}", path);
- } else {
- var tmpPath = path + ".tmp";
- doc.Save (tmpPath);
- var existing = File.ReadAllText (path);
- var updated = File.ReadAllText (tmpPath);
-
- if (existing == updated) {
- File.Delete (tmpPath);
- Log (1, "Not saved {0}, no change", path);
- } else {
- File.Delete (path);
- File.Move (tmpPath, path);
- Log (1, "Updated {0}", path);
- }
- }
- }
-
public void Save (StringWriter doc, string path)
{
if (!File.Exists (path)) {
diff --git a/tests/xharness/Jenkins/Jenkins.cs b/tests/xharness/Jenkins/Jenkins.cs
index 861195058b..0991389553 100644
--- a/tests/xharness/Jenkins/Jenkins.cs
+++ b/tests/xharness/Jenkins/Jenkins.cs
@@ -246,18 +246,18 @@ namespace Xharness.Jenkins {
if (!project.IsExecutableProject)
return false;
- if (project.IsBclTest) {
- if (!project.IsBclxUnit)
+ if (project.IsBclTest ()) {
+ if (!project.IsBclxUnit ())
return IncludeBcl || IncludeBCLNUnit;
- if (project.IsMscorlib)
+ if (project.IsMscorlib ())
return IncludeMscorlib;
return IncludeBcl || IncludeBCLxUnit;
}
- if (!IncludeMonotouch && project.IsMonotouch)
+ if (!IncludeMonotouch && project.IsMonotouch ())
return false;
- if (!IncludeNonMonotouch && !project.IsMonotouch)
+ if (!IncludeNonMonotouch && !project.IsMonotouch ())
return false;
if (Harness.IncludeSystemPermissionTests == false && project.Name == "introspection")
@@ -1105,7 +1105,7 @@ namespace Xharness.Jenkins {
} else {
exec = new MacExecuteTask (this, build, processManager, crashReportSnapshotFactory) {
Ignored = ignored_main,
- BCLTest = project.IsBclTest,
+ BCLTest = project.IsBclTest (),
TestName = project.Name,
IsUnitTest = true,
};
diff --git a/tests/xharness/MacTestProject.cs b/tests/xharness/MacTestProject.cs
new file mode 100644
index 0000000000..2b1ae63172
--- /dev/null
+++ b/tests/xharness/MacTestProject.cs
@@ -0,0 +1,50 @@
+using System;
+namespace Xharness {
+
+ [Flags]
+ public enum MacFlavors {
+ Modern = 1, // Xamarin.Mac/Modern app
+ Full = 2, // Xamarin.Mac/Full app
+ System = 4, // Xamarin.Mac/System app
+ Console = 8, // Console executable
+ }
+
+ public class MacTestProject : TestProject
+ {
+ public MacFlavors TargetFrameworkFlavors;
+
+ public bool GenerateFull => GenerateVariations && (TargetFrameworkFlavors & MacFlavors.Full) == MacFlavors.Full;
+ public bool GenerateSystem => GenerateVariations && (TargetFrameworkFlavors & MacFlavors.System) == MacFlavors.System;
+
+ public bool GenerateVariations {
+ get {
+ // If a bitwise combination of flavors, then we're generating variations
+ return TargetFrameworkFlavors != MacFlavors.Modern && TargetFrameworkFlavors != MacFlavors.Full && TargetFrameworkFlavors != MacFlavors.System && TargetFrameworkFlavors != MacFlavors.Console;
+ }
+ }
+
+ public string Platform = "x86";
+
+ public MacTestProject () : base ()
+ {
+ }
+
+ public MacTestProject (string path, bool isExecutableProject = true, MacFlavors targetFrameworkFlavor = MacFlavors.Full | MacFlavors.Modern) : base (path, isExecutableProject)
+ {
+ TargetFrameworkFlavors = targetFrameworkFlavor;
+ }
+
+ public override TestProject Clone()
+ {
+ var rv = (MacTestProject) base.Clone ();
+ rv.TargetFrameworkFlavors = TargetFrameworkFlavors;
+ rv.Platform = Platform;
+ return rv;
+ }
+
+ public override string ToString ()
+ {
+ return base.ToString () + " (" + TargetFrameworkFlavors.ToString () + ")";
+ }
+ }
+}
diff --git a/tests/xharness/MonoNativeInfo.cs b/tests/xharness/MonoNativeInfo.cs
index 00e70df0b0..04ace40174 100644
--- a/tests/xharness/MonoNativeInfo.cs
+++ b/tests/xharness/MonoNativeInfo.cs
@@ -143,21 +143,23 @@ namespace Xharness {
public class MonoNativeInfo
{
- public Harness Harness { get; }
+ public IHarness Harness { get; }
public MonoNativeFlavor Flavor { get; }
protected virtual DevicePlatform DevicePlatform { get { return DevicePlatform.iOS; } }
+ string rootDirectory;
- public MonoNativeInfo (Harness harness, MonoNativeFlavor flavor)
+ public MonoNativeInfo (IHarness harness, MonoNativeFlavor flavor, string rootDirectory)
{
- Harness = harness;
- Flavor = flavor;
+ this.Harness = harness ?? throw new ArgumentNullException (nameof (rootDirectory));
+ this.rootDirectory = rootDirectory ?? throw new ArgumentNullException (nameof (rootDirectory));
+ this.Flavor = flavor;
}
public string FlavorSuffix => Flavor == MonoNativeFlavor.Compat ? "-compat" : "-unified";
public string ProjectName => "mono-native" + FlavorSuffix;
- public string ProjectPath => Path.Combine (Harness.RootDirectory, "mono-native", TemplateName + FlavorSuffix + ".csproj");
+ public string ProjectPath => Path.Combine (rootDirectory, "mono-native", TemplateName + FlavorSuffix + ".csproj");
string TemplateName => "mono-native" + TemplateSuffix;
- public string TemplatePath => Path.Combine (Harness.RootDirectory, "mono-native", TemplateName + ".csproj.template");
+ public string TemplatePath => Path.Combine (rootDirectory, "mono-native", TemplateName + ".csproj.template");
protected virtual string TemplateSuffix => string.Empty;
public void Convert ()
@@ -177,7 +179,7 @@ namespace Xharness {
AddProjectDefines (inputProject);
- Harness.Save (inputProject, ProjectPath);
+ inputProject.Save (ProjectPath, Harness);
}
public void AddProjectDefines (XmlDocument project)
@@ -191,7 +193,7 @@ namespace Xharness {
var info_plist = new XmlDocument ();
info_plist.LoadWithoutNetworkAccess (template_info_plist);
SetInfoPListMinimumOSVersion (info_plist, MonoNativeHelper.GetMinimumOSVersion (DevicePlatform, Flavor));
- Harness.Save (info_plist, target_plist);
+ info_plist.Save (target_plist, Harness);
return info_plist;
}
@@ -206,8 +208,8 @@ namespace Xharness {
protected override string TemplateSuffix => "-mac";
protected override DevicePlatform DevicePlatform { get { return DevicePlatform.macOS; } }
- public MacMonoNativeInfo (Harness harness, MonoNativeFlavor flavor)
- : base (harness, flavor)
+ public MacMonoNativeInfo (Harness harness, MonoNativeFlavor flavor, string rootDirectory)
+ : base (harness, flavor, rootDirectory)
{
}
diff --git a/tests/xharness/Targets/Target.cs b/tests/xharness/Targets/Target.cs
index 3c6d840bcb..8c97ed3d0f 100644
--- a/tests/xharness/Targets/Target.cs
+++ b/tests/xharness/Targets/Target.cs
@@ -121,7 +121,7 @@ namespace Xharness.Targets
{
ProcessProject ();
PostProcessExecutableProject ();
- Harness.Save (inputProject, ProjectPath);
+ inputProject.Save (ProjectPath, Harness);
UpdateInfoPList ();
}
@@ -137,7 +137,7 @@ namespace Xharness.Targets
protected void CreateLibraryProject ()
{
ProcessProject ();
- Harness.Save (inputProject, ProjectPath);
+ inputProject.Save (ProjectPath, Harness);
ProjectGuid = inputProject.GetProjectGuid ();
}
diff --git a/tests/xharness/Targets/TodayExtensionTarget.cs b/tests/xharness/Targets/TodayExtensionTarget.cs
index d00d30b2bd..37becd739b 100644
--- a/tests/xharness/Targets/TodayExtensionTarget.cs
+++ b/tests/xharness/Targets/TodayExtensionTarget.cs
@@ -68,7 +68,7 @@ namespace Xharness.Targets {
MonoNativeInfo.AddProjectDefines (csproj);
csproj.AddAdditionalDefines ("MONO_NATIVE_TODAY");
}
- Harness.Save (csproj, TodayContainerProjectPath);
+ csproj.Save(TodayContainerProjectPath, Harness);
XmlDocument info_plist = new XmlDocument ();
var target_info_plist = Path.Combine ((IsGeneratedBclTest) ? GeneratedPath : TargetDirectory, $"Info{suffix}.plist");
@@ -76,7 +76,7 @@ namespace Xharness.Targets {
info_plist.SetCFBundleIdentifier (BundleIdentifier);
info_plist.SetCFBundleName (Name);
info_plist.SetMinimumOSVersion (GetMinimumOSVersion ("8.0"));
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
void CreateTodayExtensionProject ()
@@ -101,7 +101,7 @@ namespace Xharness.Targets {
csproj.AddAdditionalDefines ("MONO_NATIVE_TODAY");
}
- Harness.Save (csproj, TodayExtensionProjectPath);
+ csproj.Save (TodayExtensionProjectPath, Harness);
TodayExtensionGuid = csproj.GetProjectGuid ();
@@ -122,7 +122,7 @@ namespace Xharness.Targets {
NSExtensionPointIdentifier
com.apple.widget-extension
");
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
protected override void ExecuteInternal ()
diff --git a/tests/xharness/Targets/UnifiedTarget.cs b/tests/xharness/Targets/UnifiedTarget.cs
index ee4af5272c..a522e79d23 100644
--- a/tests/xharness/Targets/UnifiedTarget.cs
+++ b/tests/xharness/Targets/UnifiedTarget.cs
@@ -138,13 +138,13 @@ namespace Xharness.Targets {
inputProject.FixInfoPListInclude (Suffix);
inputProject.SetExtraLinkerDefs ("extra-linker-defs" + ExtraLinkerDefsSuffix + ".xml");
- Harness.Save (inputProject, ProjectPath);
+ inputProject.Save (ProjectPath, Harness);
XmlDocument info_plist = new XmlDocument ();
var target_info_plist = Path.Combine (TargetDirectory, "Info" + Suffix + ".plist");
info_plist.LoadWithoutNetworkAccess (Path.Combine (TargetDirectory, "Info.plist"));
info_plist.SetMinimumOSVersion (GetMinimumOSVersion (info_plist.GetMinimumOSVersion ()));
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
}
}
diff --git a/tests/xharness/Targets/WatchOSTarget.cs b/tests/xharness/Targets/WatchOSTarget.cs
index e0a6edeb69..c167d75d3c 100644
--- a/tests/xharness/Targets/WatchOSTarget.cs
+++ b/tests/xharness/Targets/WatchOSTarget.cs
@@ -44,7 +44,7 @@ namespace Xharness.Targets {
MonoNativeHelper.AddProjectDefines (csproj, MonoNativeInfo.Flavor);
MonoNativeHelper.RemoveSymlinkMode (csproj);
}
- Harness.Save (csproj, WatchOSAppProjectPath);
+ csproj.Save (WatchOSAppProjectPath, Harness);
XmlDocument info_plist = new XmlDocument ();
var target_info_plist = Path.Combine (TargetDirectory, $"Info{Suffix}-app.plist");
@@ -53,7 +53,7 @@ namespace Xharness.Targets {
info_plist.SetPListStringValue ("WKCompanionAppBundleIdentifier", BundleIdentifier);
info_plist.SetPListStringValue ("CFBundleName", Name);
info_plist.SetMinimumOSVersion (GetMinimumOSVersion (info_plist.GetMinimumOSVersion ()));
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save(target_info_plist, Harness);
}
void CreateWatchOSContainerProject ()
@@ -72,7 +72,7 @@ namespace Xharness.Targets {
MonoNativeHelper.AddProjectDefines (csproj, MonoNativeInfo.Flavor);
MonoNativeHelper.RemoveSymlinkMode (csproj);
}
- Harness.Save (csproj, WatchOSProjectPath);
+ csproj.Save (WatchOSProjectPath, Harness);
XmlDocument info_plist = new XmlDocument ();
var target_info_plist = Path.Combine (TargetDirectory, $"Info{Suffix}.plist");
@@ -80,7 +80,7 @@ namespace Xharness.Targets {
info_plist.SetCFBundleIdentifier (BundleIdentifier);
info_plist.SetCFBundleName (Name);
info_plist.SetMinimumOSVersion ("9.0");
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
void CreateWatchOSExtensionProject ()
@@ -145,7 +145,7 @@ namespace Xharness.Targets {
csproj.AddExtraMtouchArgs ($"--gcc_flags='{flags}'", "iPhone", c);
}
- Harness.Save (csproj, WatchOSExtensionProjectPath);
+ csproj.Save (WatchOSExtensionProjectPath, Harness);
WatchOSExtensionGuid = csproj.GetProjectGuid ();
@@ -176,7 +176,7 @@ namespace Xharness.Targets {
");
}
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
protected override string Imports {
@@ -204,7 +204,7 @@ namespace Xharness.Targets {
csproj.FixProjectReferences (Suffix);
csproj.SetExtraLinkerDefs ("extra-linker-defs" + ExtraLinkerDefsSuffix + ".xml");
csproj.FixTestLibrariesReferences (Platform);
- Harness.Save (csproj, WatchOSProjectPath);
+ csproj.Save (WatchOSProjectPath, Harness);
WatchOSGuid = csproj.GetProjectGuid ();
}
diff --git a/tests/xharness/Targets/iOSTarget.cs b/tests/xharness/Targets/iOSTarget.cs
index 376042b8fe..5e023397e6 100644
--- a/tests/xharness/Targets/iOSTarget.cs
+++ b/tests/xharness/Targets/iOSTarget.cs
@@ -30,7 +30,7 @@ namespace Xharness.Targets
BundleIdentifier = info_plist.GetCFBundleIdentifier ();
info_plist.SetMinimumOSVersion (GetMinimumOSVersion (info_plist.GetMinimumOSVersion ()));
info_plist.SetUIDeviceFamily (UIDeviceFamily);
- Harness.Save (info_plist, target_info_plist);
+ info_plist.Save (target_info_plist, Harness);
}
}
}
diff --git a/tests/xharness/TestProject.cs b/tests/xharness/TestProject.cs
index 1166d1b1f8..b3fb7bc6a0 100644
--- a/tests/xharness/TestProject.cs
+++ b/tests/xharness/TestProject.cs
@@ -1,12 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
using System.Xml;
using Xharness.Jenkins.TestTasks;
using Microsoft.DotNet.XHarness.iOS.Shared.Utilities;
-using Microsoft.DotNet.XHarness.iOS.Shared.Hardware;
namespace Xharness {
public class TestProject
@@ -40,42 +38,6 @@ namespace Xharness {
IsExecutableProject = isExecutableProject;
}
- public TestProject AsTvOSProject ()
- {
- var clone = Clone ();
- clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), System.IO.Path.GetFileNameWithoutExtension (Path) + "-tvos" + System.IO.Path.GetExtension (Path));
- return clone;
- }
-
- public TestProject AsWatchOSProject ()
- {
- var clone = Clone ();
- var fileName = System.IO.Path.GetFileNameWithoutExtension (Path);
- clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), fileName + (fileName.Contains("-watchos")?"":"-watchos") + System.IO.Path.GetExtension (Path));
- return clone;
- }
-
- public TestProject AsTodayExtensionProject ()
- {
- var clone = Clone ();
- clone.Path = System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), System.IO.Path.GetFileNameWithoutExtension (Path) + "-today" + System.IO.Path.GetExtension (Path));
- return clone;
- }
-
- // Get the referenced today extension project (if any)
- public TestProject GetTodayExtension ()
- {
- var extensions = Xml.GetExtensionProjectReferences ().ToArray ();
- if (!extensions.Any ())
- return null;
- if (extensions.Count () != 1)
- throw new NotImplementedException ();
- return new TestProject
- {
- Path = System.IO.Path.GetFullPath (System.IO.Path.Combine (System.IO.Path.GetDirectoryName (Path), extensions.First ().Replace ('\\', '/'))),
- };
- }
-
public XmlDocument Xml {
get {
if (xml == null) {
@@ -86,20 +48,6 @@ namespace Xharness {
}
}
- public bool IsBclTest {
- get {
- return Path.Contains ("bcl-test");
- }
- }
-
- public bool IsMonotouch => Name.Contains ("monotouch");
-
- public bool IsBclxUnit => IsBclTest && (Name.Contains ("xUnit") || IsMscorlib);
-
-
- public bool IsMscorlib => Name.Contains ("mscorlib");
-
-
public virtual TestProject Clone ()
{
TestProject rv = (TestProject) Activator.CreateInstance (GetType ());
@@ -159,79 +107,5 @@ namespace Xharness {
}
}
- public class iOSTestProject : TestProject
- {
- public bool SkipiOSVariation;
- public bool SkipwatchOSVariation; // skip both
- public bool SkipwatchOSARM64_32Variation;
- public bool SkipwatchOS32Variation;
- public bool SkiptvOSVariation;
- public bool BuildOnly;
-
- public iOSTestProject ()
- {
- }
-
- public iOSTestProject (string path, bool isExecutableProject = true)
- : base (path, isExecutableProject)
- {
- Name = System.IO.Path.GetFileNameWithoutExtension (path);
- }
-
- public bool IsSupported (DevicePlatform devicePlatform, string productVersion)
- {
- if (MonoNativeInfo == null)
- return true;
- var min_version = MonoNativeHelper.GetMinimumOSVersion (devicePlatform, MonoNativeInfo.Flavor);
- return Version.Parse (productVersion) >= Version.Parse (min_version);
- }
- }
-
- [Flags]
- public enum MacFlavors {
- Modern = 1, // Xamarin.Mac/Modern app
- Full = 2, // Xamarin.Mac/Full app
- System = 4, // Xamarin.Mac/System app
- Console = 8, // Console executable
- }
-
- public class MacTestProject : TestProject
- {
- public MacFlavors TargetFrameworkFlavors;
-
- public bool GenerateFull => GenerateVariations && (TargetFrameworkFlavors & MacFlavors.Full) == MacFlavors.Full;
- public bool GenerateSystem => GenerateVariations && (TargetFrameworkFlavors & MacFlavors.System) == MacFlavors.System;
-
- public bool GenerateVariations {
- get {
- // If a bitwise combination of flavors, then we're generating variations
- return TargetFrameworkFlavors != MacFlavors.Modern && TargetFrameworkFlavors != MacFlavors.Full && TargetFrameworkFlavors != MacFlavors.System && TargetFrameworkFlavors != MacFlavors.Console;
- }
- }
-
- public string Platform = "x86";
-
- public MacTestProject () : base ()
- {
- }
-
- public MacTestProject (string path, bool isExecutableProject = true, MacFlavors targetFrameworkFlavor = MacFlavors.Full | MacFlavors.Modern) : base (path, isExecutableProject)
- {
- TargetFrameworkFlavors = targetFrameworkFlavor;
- }
-
- public override TestProject Clone()
- {
- var rv = (MacTestProject) base.Clone ();
- rv.TargetFrameworkFlavors = TargetFrameworkFlavors;
- rv.Platform = Platform;
- return rv;
- }
-
- public override string ToString ()
- {
- return base.ToString () + " (" + TargetFrameworkFlavors.ToString () + ")";
- }
- }
}
diff --git a/tests/xharness/TestProjectExtensions.cs b/tests/xharness/TestProjectExtensions.cs
new file mode 100644
index 0000000000..4a69c1dd2f
--- /dev/null
+++ b/tests/xharness/TestProjectExtensions.cs
@@ -0,0 +1,55 @@
+using System;
+using System.IO;
+using System.Linq;
+using Microsoft.DotNet.XHarness.iOS.Shared.Utilities;
+
+namespace Xharness {
+ // particular methods used within xamarin-macios
+ public static class TestProjectExtensions {
+
+ public static bool IsBclTest (this TestProject self) => self.Path.Contains ("bcl-test");
+
+ public static bool IsMonotouch (this TestProject self) => self.Name.Contains ("monotouch");
+
+ public static bool IsBclxUnit (this TestProject self)
+ => self.IsBclTest () && (self.Name.Contains ("xUnit") || self.IsMscorlib ());
+
+ public static bool IsMscorlib (this TestProject self) => self.Name.Contains ("mscorlib");
+
+ public static TestProject AsTvOSProject (this TestProject self)
+ {
+ var clone = self.Clone ();
+ clone.Path = Path.Combine (Path.GetDirectoryName (self.Path), Path.GetFileNameWithoutExtension (self.Path) + "-tvos" + Path.GetExtension (self.Path));
+ return clone;
+ }
+
+ public static TestProject AsWatchOSProject (this TestProject self)
+ {
+ var clone = self.Clone ();
+ var fileName = Path.GetFileNameWithoutExtension (self.Path);
+ clone.Path = Path.Combine (Path.GetDirectoryName (self.Path), fileName + (fileName.Contains("-watchos")?"":"-watchos") + Path.GetExtension (self.Path));
+ return clone;
+ }
+
+ public static TestProject AsTodayExtensionProject (this TestProject self)
+ {
+ var clone = self.Clone ();
+ clone.Path = Path.Combine (Path.GetDirectoryName (self.Path), Path.GetFileNameWithoutExtension (self.Path) + "-today" + Path.GetExtension (self.Path));
+ return clone;
+ }
+
+ // Get the referenced today extension project (if any)
+ public static TestProject GetTodayExtension (this TestProject self)
+ {
+ var extensions = self.Xml.GetExtensionProjectReferences ().ToArray ();
+ if (!extensions.Any ())
+ return null;
+ if (extensions.Count () != 1)
+ throw new NotImplementedException ();
+ return new TestProject
+ {
+ Path = Path.GetFullPath (Path.Combine (Path.GetDirectoryName (self.Path), extensions.First ().Replace ('\\', '/'))),
+ };
+ }
+ }
+}
diff --git a/tests/xharness/XmlDocumentExtensions.cs b/tests/xharness/XmlDocumentExtensions.cs
new file mode 100644
index 0000000000..6d89860cf3
--- /dev/null
+++ b/tests/xharness/XmlDocumentExtensions.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+using System.Xml;
+
+namespace Xharness {
+ public static class XmlDocumentExtensions {
+
+ public static void Save (this XmlDocument doc, string path, IHarness harness)
+ {
+ if (!File.Exists (path)) {
+ doc.Save (path);
+ harness.Log (1, "Created {0}", path);
+ } else {
+ var tmpPath = path + ".tmp";
+ doc.Save (tmpPath);
+ var existing = File.ReadAllText (path);
+ var updated = File.ReadAllText (tmpPath);
+
+ if (existing == updated) {
+ File.Delete (tmpPath);
+ harness.Log (1, "Not saved {0}, no change", path);
+ } else {
+ File.Delete (path);
+ File.Move (tmpPath, path);
+ harness.Log (1, "Updated {0}", path);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/xharness/iOSTestProject.cs b/tests/xharness/iOSTestProject.cs
new file mode 100644
index 0000000000..a369f7ed9b
--- /dev/null
+++ b/tests/xharness/iOSTestProject.cs
@@ -0,0 +1,33 @@
+using System;
+using Microsoft.DotNet.XHarness.iOS.Shared.Hardware;
+
+namespace Xharness {
+
+ public class iOSTestProject : TestProject
+ {
+ public bool SkipiOSVariation;
+ public bool SkipwatchOSVariation; // skip both
+ public bool SkipwatchOSARM64_32Variation;
+ public bool SkipwatchOS32Variation;
+ public bool SkiptvOSVariation;
+ public bool BuildOnly;
+
+ public iOSTestProject ()
+ {
+ }
+
+ public iOSTestProject (string path, bool isExecutableProject = true)
+ : base (path, isExecutableProject)
+ {
+ Name = System.IO.Path.GetFileNameWithoutExtension (path);
+ }
+
+ public bool IsSupported (DevicePlatform devicePlatform, string productVersion)
+ {
+ if (MonoNativeInfo == null)
+ return true;
+ var min_version = MonoNativeHelper.GetMinimumOSVersion (devicePlatform, MonoNativeInfo.Flavor);
+ return Version.Parse (productVersion) >= Version.Parse (min_version);
+ }
+ }
+}
diff --git a/tests/xharness/xharness.csproj b/tests/xharness/xharness.csproj
index 20c9fc538e..3263be598f 100644
--- a/tests/xharness/xharness.csproj
+++ b/tests/xharness/xharness.csproj
@@ -134,6 +134,10 @@
+
+
+
+