diff --git a/tests/xharness/AppBundleInformationParser.cs b/tests/xharness/AppBundleInformationParser.cs new file mode 100644 index 0000000000..b19e2f8440 --- /dev/null +++ b/tests/xharness/AppBundleInformationParser.cs @@ -0,0 +1,64 @@ +using System.IO; +using System.Xml; +using Xharness.Utilities; + +namespace Xharness { + + public class AppBundleInformation { + public string AppName { get; } + public string BundleIdentifier { get; } + public string AppPath { get; } + public string LaunchAppPath { get; } + public Extension? Extension { get; } + + public AppBundleInformation (string appName, string bundleIdentifier, string appPath, string launchAppPath, Extension? extension) + { + AppName = appName; + BundleIdentifier = bundleIdentifier; + AppPath = appPath; + LaunchAppPath = launchAppPath; + Extension = extension; + } + } + + public interface IAppBundleInformationParser { + AppBundleInformation ParseFromProject (string projectFilePath, TestTarget target, string buildConfiguration); + } + + public class AppBundleInformationParser : IAppBundleInformationParser { + public AppBundleInformation ParseFromProject (string projectFilePath, TestTarget target, string buildConfiguration) + { + var csproj = new XmlDocument (); + csproj.LoadWithoutNetworkAccess (projectFilePath); + + string appName = csproj.GetAssemblyName (); + string info_plist_path = csproj.GetInfoPListInclude (); + + var info_plist = new XmlDocument (); + string plistPath = Path.Combine (Path.GetDirectoryName (projectFilePath), info_plist_path.Replace ('\\', Path.DirectorySeparatorChar)); + info_plist.LoadWithoutNetworkAccess (plistPath); + + string bundleIdentifier = info_plist.GetCFBundleIdentifier (); + + Extension? extension = null; + string extensionPointIdentifier = info_plist.GetNSExtensionPointIdentifier (); + if (!string.IsNullOrEmpty (extensionPointIdentifier)) + extension = extensionPointIdentifier.ParseFromNSExtensionPointIdentifier (); + + var platform = target.IsSimulator () ? "iPhoneSimulator" : "iPhone"; + + string appPath = Path.Combine (Path.GetDirectoryName (projectFilePath), + csproj.GetOutputPath (platform, buildConfiguration).Replace ('\\', Path.DirectorySeparatorChar), + appName + (extension != null ? ".appex" : ".app")); + + if (!Directory.Exists (appPath)) + throw new DirectoryNotFoundException ($"The app bundle directory `{appPath}` does not exist"); + + string launchAppPath = (target.ToRunMode () == RunMode.WatchOS) + ? Directory.GetDirectories (Path.Combine (appPath, "Watch"), "*.app") [0] + : appPath; + + return new AppBundleInformation (appName, bundleIdentifier, appPath, launchAppPath, extension); + } + } +} diff --git a/tests/xharness/AppRunner.cs b/tests/xharness/AppRunner.cs index e361da0d85..9e81d06ae6 100644 --- a/tests/xharness/AppRunner.cs +++ b/tests/xharness/AppRunner.cs @@ -16,38 +16,6 @@ using Xharness.Utilities; namespace Xharness { - public enum RunMode { - Sim32, - Sim64, - Classic, - iOS, - TvOS, - WatchOS, - } - - public enum Extension - { - WatchKit2, - TodayExtension, - } - - public class AppInformation { - public string AppName { get; } - public string BundleIdentifier { get; } - public string AppPath { get; } - public string LaunchAppPath { get; } - public Extension? Extension { get; } - - public AppInformation (string appName, string bundleIdentifier, string appPath, string launchAppPath, Extension? extension) - { - AppName = appName; - BundleIdentifier = bundleIdentifier; - AppPath = appPath; - LaunchAppPath = launchAppPath; - Extension = extension; - } - } - class AppRunner { readonly IProcessManager processManager; @@ -59,12 +27,10 @@ namespace Xharness { readonly IDeviceLogCapturerFactory deviceLogCapturerFactory; readonly IResultParser resultParser; - readonly RunMode mode; + readonly RunMode runMode; readonly bool isSimulator; - readonly AppRunnerTarget target; - readonly string projectFilePath; + readonly TestTarget target; readonly IHarness harness; - readonly string buildConfiguration; readonly string variation; readonly double timeoutMultiplier; readonly BuildToolTask buildTask; @@ -82,7 +48,7 @@ namespace Xharness { bool IsExtension => AppInformation.Extension.HasValue; - public AppInformation AppInformation { get; } + public AppBundleInformation AppInformation { get; } public TestExecutingResult Result { get; private set; } @@ -93,6 +59,7 @@ namespace Xharness { public ILogs Logs { get; } public AppRunner (IProcessManager processManager, + IAppBundleInformationParser appBundleInformationParser, ISimulatorsLoaderFactory simulatorsFactory, ISimpleListenerFactory simpleListenerFactory, IDeviceLoaderFactory devicesFactory, @@ -100,7 +67,7 @@ namespace Xharness { ICaptureLogFactory captureLogFactory, IDeviceLogCapturerFactory deviceLogCapturerFactory, IResultParser resultParser, - AppRunnerTarget target, + TestTarget target, IHarness harness, ILog mainLog, ILogs logs, @@ -114,6 +81,9 @@ namespace Xharness { string variation = null, BuildToolTask buildTask = null) { + if (appBundleInformationParser is null) + throw new ArgumentNullException (nameof (appBundleInformationParser)); + this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager)); this.simulatorsLoaderFactory = simulatorsFactory ?? throw new ArgumentNullException (nameof (simulatorsFactory)); this.listenerFactory = simpleListenerFactory ?? throw new ArgumentNullException (nameof (simpleListenerFactory)); @@ -124,9 +94,7 @@ namespace Xharness { this.resultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser)); this.harness = harness ?? throw new ArgumentNullException (nameof (harness)); this.MainLog = mainLog ?? throw new ArgumentNullException (nameof (mainLog)); - this.projectFilePath = projectFilePath ?? throw new ArgumentNullException (nameof (projectFilePath)); this.Logs = logs ?? throw new ArgumentNullException (nameof (logs)); - this.buildConfiguration = buildConfiguration ?? throw new ArgumentNullException (nameof (buildConfiguration)); this.timeoutMultiplier = timeoutMultiplier; this.deviceName = deviceName; this.companionDeviceName = companionDeviceName; @@ -136,41 +104,9 @@ namespace Xharness { this.buildTask = buildTask; this.target = target; - mode = target.ToRunMode (); + runMode = target.ToRunMode (); isSimulator = target.IsSimulator (); - AppInformation = Initialize (); - } - - AppInformation Initialize () - { - var csproj = new XmlDocument (); - csproj.LoadWithoutNetworkAccess (projectFilePath); - string appName = csproj.GetAssemblyName (); - string info_plist_path = csproj.GetInfoPListInclude (); - - var info_plist = new XmlDocument (); - string plistPath = Path.Combine (Path.GetDirectoryName (projectFilePath), info_plist_path.Replace ('\\', Path.DirectorySeparatorChar)); - info_plist.LoadWithoutNetworkAccess (plistPath); - - string bundleIdentifier = info_plist.GetCFBundleIdentifier (); - - Extension? extension = null; - string extensionPointIdentifier = info_plist.GetNSExtensionPointIdentifier (); - if (!string.IsNullOrEmpty (extensionPointIdentifier)) - extension = extensionPointIdentifier.ParseFromNSExtensionPointIdentifier (); - - string appPath = Path.Combine (Path.GetDirectoryName (projectFilePath), - csproj.GetOutputPath (isSimulator ? "iPhoneSimulator" : "iPhone", buildConfiguration).Replace ('\\', Path.DirectorySeparatorChar), - appName + (extension != null ? ".appex" : ".app")); - - if (!Directory.Exists (appPath)) - throw new Exception (string.Format ("The app directory {0} does not exist. This is probably a bug in the test harness.", appPath)); - - string launchAppPath = mode == RunMode.WatchOS - ? Directory.GetDirectories (Path.Combine (appPath, "Watch"), "*.app") [0] - : appPath; - - return new AppInformation (appName, bundleIdentifier, appPath, launchAppPath, extension); + AppInformation = appBundleInformationParser.ParseFromProject (projectFilePath, target, buildConfiguration); } async Task FindSimulatorAsync () @@ -201,7 +137,7 @@ namespace Xharness { }).Wait (); DeviceClass [] deviceClasses; - switch (mode) { + switch (runMode) { case RunMode.iOS: deviceClasses = new [] { DeviceClass.iPhone, DeviceClass.iPad, DeviceClass.iPod }; break; @@ -212,7 +148,7 @@ namespace Xharness { deviceClasses = new [] { DeviceClass.AppleTV }; // Untested break; default: - throw new ArgumentException (nameof(mode)); + throw new ArgumentException (nameof(runMode)); } var selected = devs.ConnectedDevices.Where ((v) => deviceClasses.Contains (v.DeviceClass) && v.IsUsableForDebugging != false); @@ -236,7 +172,7 @@ namespace Xharness { deviceName = selected_data.Name; - if (mode == RunMode.WatchOS) + if (runMode == RunMode.WatchOS) companionDeviceName = devs.FindCompanionDevice (MainLog, selected_data).Name; } @@ -261,7 +197,7 @@ namespace Xharness { args.Add (AppInformation.AppPath); AddDeviceName (args, companionDeviceName ?? deviceName); - if (mode == RunMode.WatchOS) { + if (runMode == RunMode.WatchOS) { args.Add ("--device"); args.Add ("ios,watchos"); } @@ -294,7 +230,7 @@ namespace Xharness { return await processManager.ExecuteCommandAsync (harness.MlaunchPath, args, MainLog, TimeSpan.FromMinutes (1)); } - (string resultLine, bool failed, bool crashed) ParseResult (AppInformation appInfo, string test_log_path, bool timed_out, out bool crashed) + (string resultLine, bool failed, bool crashed) ParseResult (AppBundleInformation appInfo, string test_log_path, bool timed_out, out bool crashed) { crashed = false; if (!File.Exists (test_log_path)) { @@ -366,10 +302,10 @@ namespace Xharness { MainLog.WriteLine (new string ('#', 10)); MainLog.WriteLine ("End of xml results."); if (timed_out) { - WrenchLog.WriteLine ($"AddSummary: {mode} timed out
"); + WrenchLog.WriteLine ($"AddSummary: {runMode} timed out
"); return parseResult; } else { - WrenchLog.WriteLine ($"AddSummary: {mode} crashed
"); + WrenchLog.WriteLine ($"AddSummary: {runMode} crashed
"); MainLog.WriteLine ("Test run crashed"); crashed = true; parseResult.crashed = true; @@ -400,26 +336,26 @@ namespace Xharness { } } - public bool TestsSucceeded (AppInformation appInfo, string test_log_path, bool timed_out, out bool crashed) + public bool TestsSucceeded (AppBundleInformation appInfo, string test_log_path, bool timed_out, out bool crashed) { var (resultLine, failed, crashed_out) = ParseResult (appInfo, test_log_path, timed_out, out crashed); // read the parsed logs in a human readable way if (resultLine != null) { var tests_run = resultLine.Replace ("Tests run: ", ""); if (failed) { - WrenchLog.WriteLine ("AddSummary: {0} failed: {1}
", mode, tests_run); + WrenchLog.WriteLine ("AddSummary: {0} failed: {1}
", runMode, tests_run); MainLog.WriteLine ("Test run failed"); return false; } else { - WrenchLog.WriteLine ("AddSummary: {0} succeeded: {1}
", mode, tests_run); + WrenchLog.WriteLine ("AddSummary: {0} succeeded: {1}
", runMode, tests_run); MainLog.WriteLine ("Test run succeeded"); return true; } } else if (timed_out) { - WrenchLog.WriteLine ("AddSummary: {0} timed out
", mode); + WrenchLog.WriteLine ("AddSummary: {0} timed out
", runMode); return false; } else { - WrenchLog.WriteLine ("AddSummary: {0} crashed
", mode); + WrenchLog.WriteLine ("AddSummary: {0} crashed
", runMode); MainLog.WriteLine ("Test run crashed"); crashed = true; return false; @@ -480,8 +416,8 @@ namespace Xharness { args.Add ($"-setenv=NUNIT_HOSTNAME={ips}"); } - var listener_log = Logs.Create ($"test-{mode.ToString().ToLower()}-{Helpers.Timestamp}.log", LogType.TestLog.ToString (), timestamp: !useXmlOutput); - var (transport, listener, listenerTmpFile) = listenerFactory.Create (mode, MainLog, listener_log, isSimulator, true, useXmlOutput); + var listener_log = Logs.Create ($"test-{runMode.ToString().ToLower()}-{Helpers.Timestamp}.log", LogType.TestLog.ToString (), timestamp: !useXmlOutput); + var (transport, listener, listenerTmpFile) = listenerFactory.Create (runMode, MainLog, listener_log, isSimulator, true, useXmlOutput); args.Add ($"-argument=-app-arg:-transport:{transport}"); args.Add ($"-setenv=NUNIT_TRANSPORT={transport.ToString ().ToUpper ()}"); @@ -549,7 +485,7 @@ namespace Xharness { if (!await FindSimulatorAsync ()) return 1; - if (mode != RunMode.WatchOS) { + if (runMode != RunMode.WatchOS) { var stderr_tty = harness.GetStandardErrorTty (); if (!string.IsNullOrEmpty (stderr_tty)) { args.Add ($"--stdout={stderr_tty}"); @@ -581,7 +517,7 @@ namespace Xharness { WrenchLog.WriteLine ("AddFile: {0}", log.FullPath); } - MainLog.WriteLine ("*** Executing {0}/{1} in the simulator ***", AppInformation.AppName, mode); + MainLog.WriteLine ("*** Executing {0}/{1} in the simulator ***", AppInformation.AppName, runMode); if (EnsureCleanSimulatorState) { foreach (var sim in simulators) @@ -652,9 +588,9 @@ namespace Xharness { log.StopCapture (); } else { - MainLog.WriteLine ("*** Executing {0}/{1} on device '{2}' ***", AppInformation.AppName, mode, deviceName); + MainLog.WriteLine ("*** Executing {0}/{1} on device '{2}' ***", AppInformation.AppName, runMode, deviceName); - if (mode == RunMode.WatchOS) { + if (runMode == RunMode.WatchOS) { args.Add ("--attach-native-debugger"); // this prevents the watch from backgrounding the app. } else { args.Add ("--wait-for-exit"); @@ -724,15 +660,15 @@ namespace Xharness { WrenchLog.WriteLine ("AddFile: {0}", listener_log.FullPath); success = TestsSucceeded (AppInformation, listener_log.FullPath, timed_out, out crashed); } else if (timed_out) { - WrenchLog.WriteLine ("AddSummary: {0} never launched
", mode); + WrenchLog.WriteLine ("AddSummary: {0} never launched
", runMode); MainLog.WriteLine ("Test run never launched"); success = false; } else if (launch_failure) { - WrenchLog.WriteLine ("AddSummary: {0} failed to launch
", mode); + WrenchLog.WriteLine ("AddSummary: {0} failed to launch
", runMode); MainLog.WriteLine ("Test run failed to launch"); success = false; } else { - WrenchLog.WriteLine ("AddSummary: {0} crashed at startup (no log)
", mode); + WrenchLog.WriteLine ("AddSummary: {0} crashed at startup (no log)
", runMode); MainLog.WriteLine ("Test run crashed before it started (no log file produced)"); crashed = true; success = false; diff --git a/tests/xharness/AppRunnerTarget.cs b/tests/xharness/AppRunnerTarget.cs deleted file mode 100644 index 47177f4d75..0000000000 --- a/tests/xharness/AppRunnerTarget.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; - -namespace Xharness { - public enum AppRunnerTarget { - None, - Simulator_iOS, - Simulator_iOS32, - Simulator_iOS64, - Simulator_tvOS, - Simulator_watchOS, - Device_iOS, - Device_tvOS, - Device_watchOS, - } - - public static class AppRunnerTargetExtensions { - public static RunMode ToRunMode (this AppRunnerTarget target) => target switch - { - AppRunnerTarget.Simulator_iOS => RunMode.Classic, - AppRunnerTarget.Simulator_iOS32 => RunMode.Sim32, - AppRunnerTarget.Simulator_iOS64 => RunMode.Sim64, - AppRunnerTarget.Simulator_tvOS => RunMode.TvOS, - AppRunnerTarget.Simulator_watchOS => RunMode.WatchOS, - AppRunnerTarget.Device_iOS => RunMode.iOS, - AppRunnerTarget.Device_tvOS => RunMode.TvOS, - AppRunnerTarget.Device_watchOS => RunMode.WatchOS, - _ => throw new ArgumentOutOfRangeException ($"Unknown target: {target}"), - }; - - public static bool IsSimulator (this AppRunnerTarget target) => target switch - { - AppRunnerTarget.Simulator_iOS => true, - AppRunnerTarget.Simulator_iOS32 => true, - AppRunnerTarget.Simulator_iOS64 => true, - AppRunnerTarget.Simulator_tvOS => true, - AppRunnerTarget.Simulator_watchOS => true, - AppRunnerTarget.Device_iOS => false, - AppRunnerTarget.Device_tvOS => false, - AppRunnerTarget.Device_watchOS => false, - _ => throw new ArgumentOutOfRangeException ($"Unknown target: {target}"), - }; - } -} diff --git a/tests/xharness/Extension.cs b/tests/xharness/Extension.cs new file mode 100644 index 0000000000..0588e797a7 --- /dev/null +++ b/tests/xharness/Extension.cs @@ -0,0 +1,7 @@ +namespace Xharness { + public enum Extension + { + WatchKit2, + TodayExtension, + } +} diff --git a/tests/xharness/Hardware/ISimulatorDevice.cs b/tests/xharness/Hardware/ISimulatorDevice.cs index b97508bbd7..543180ea18 100644 --- a/tests/xharness/Hardware/ISimulatorDevice.cs +++ b/tests/xharness/Hardware/ISimulatorDevice.cs @@ -51,9 +51,9 @@ namespace Xharness.Hardware { IEnumerable SupportedDeviceTypes { get; } IEnumerable AvailableDevices { get; } IEnumerable AvailableDevicePairs { get; } - Task FindAsync (AppRunnerTarget target, ILog log, bool create_if_needed = true, bool min_version = false); + Task FindAsync (TestTarget target, ILog log, bool create_if_needed = true, bool min_version = false); ISimulatorDevice FindCompanionDevice (ILog log, ISimulatorDevice device); - IEnumerable SelectDevices (AppRunnerTarget target, ILog log, bool min_version); + IEnumerable SelectDevices (TestTarget target, ILog log, bool min_version); } } diff --git a/tests/xharness/Hardware/Simulators.cs b/tests/xharness/Hardware/Simulators.cs index 4021804703..8965b64273 100644 --- a/tests/xharness/Hardware/Simulators.cs +++ b/tests/xharness/Hardware/Simulators.cs @@ -259,7 +259,7 @@ namespace Xharness.Hardware { return pairs.FirstOrDefault (); } - public async Task FindAsync (AppRunnerTarget target, ILog log, bool create_if_needed = true, bool min_version = false) + public async Task FindAsync (TestTarget target, ILog log, bool create_if_needed = true, bool min_version = false) { ISimulatorDevice [] simulators = null; @@ -269,23 +269,23 @@ namespace Xharness.Hardware { string companion_runtime = null; switch (target) { - case AppRunnerTarget.Simulator_iOS32: + case TestTarget.Simulator_iOS32: simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-5"; simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + (min_version ? SdkVersions.MiniOSSimulator : "10-3").Replace ('.', '-'); break; - case AppRunnerTarget.Simulator_iOS64: + case TestTarget.Simulator_iOS64: simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType." + (min_version ? "iPhone-6" : "iPhone-X"); simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + (min_version ? SdkVersions.MiniOSSimulator : SdkVersions.MaxiOSSimulator).Replace ('.', '-'); break; - case AppRunnerTarget.Simulator_iOS: + case TestTarget.Simulator_iOS: simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.iPhone-5"; simulator_runtime = "com.apple.CoreSimulator.SimRuntime.iOS-" + (min_version ? SdkVersions.MiniOSSimulator : SdkVersions.MaxiOSSimulator).Replace ('.', '-'); break; - case AppRunnerTarget.Simulator_tvOS: + case TestTarget.Simulator_tvOS: simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType.Apple-TV-1080p"; simulator_runtime = "com.apple.CoreSimulator.SimRuntime.tvOS-" + (min_version ? SdkVersions.MinTVOSSimulator : SdkVersions.MaxTVOSSimulator).Replace ('.', '-'); break; - case AppRunnerTarget.Simulator_watchOS: + case TestTarget.Simulator_watchOS: simulator_devicetype = "com.apple.CoreSimulator.SimDeviceType." + (min_version ? "Apple-Watch-38mm" : "Apple-Watch-Series-3-38mm"); simulator_runtime = "com.apple.CoreSimulator.SimRuntime.watchOS-" + (min_version ? SdkVersions.MinWatchOSSimulator : SdkVersions.MaxWatchOSSimulator).Replace ('.', '-'); companion_devicetype = "com.apple.CoreSimulator.SimDeviceType." + (min_version ? "iPhone-6" : "iPhone-X"); @@ -341,7 +341,7 @@ namespace Xharness.Hardware { return available_devices.Single ((v) => v.UDID == pair.Companion); } - public IEnumerable SelectDevices (AppRunnerTarget target, ILog log, bool min_version) + public IEnumerable SelectDevices (TestTarget target, ILog log, bool min_version) { return new SimulatorEnumerable { Simulators = this, @@ -365,7 +365,7 @@ namespace Xharness.Hardware { class SimulatorEnumerable : IEnumerable, IAsyncEnumerable { public Simulators Simulators; - public AppRunnerTarget Target; + public TestTarget Target; public bool MinVersion; public ILog Log; readonly object lock_obj = new object (); diff --git a/tests/xharness/Harness.cs b/tests/xharness/Harness.cs index 950bc544e6..8b2da9770b 100644 --- a/tests/xharness/Harness.cs +++ b/tests/xharness/Harness.cs @@ -40,7 +40,7 @@ namespace Xharness public string PeriodicCommandArguments { get; set; } public TimeSpan PeriodicCommandInterval { get; set; } public string SdkRoot { get; set; } - public AppRunnerTarget Target { get; set; } + public TestTarget Target { get; set; } public double TimeoutInMinutes { get; set; } = 15; public bool UseSystemXamarinIOSMac { get; set; } public int Verbosity { get; set; } @@ -102,7 +102,7 @@ namespace Xharness } public class Harness : IHarness { - readonly AppRunnerTarget target; + readonly TestTarget target; readonly string buildConfiguration = "Debug"; public HarnessAction Action { get; } @@ -605,6 +605,7 @@ namespace Xharness foreach (var project in IOSTestProjects) { var runner = new AppRunner (ProcessManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (this, ProcessManager), new SimpleListenerFactory (), new DeviceLoaderFactory (this, ProcessManager), @@ -635,6 +636,7 @@ namespace Xharness foreach (var project in IOSTestProjects) { var runner = new AppRunner (ProcessManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (this, ProcessManager), new SimpleListenerFactory (), new DeviceLoaderFactory (this, ProcessManager), @@ -663,6 +665,7 @@ namespace Xharness foreach (var project in IOSTestProjects) { var runner = new AppRunner (ProcessManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (this, ProcessManager), new SimpleListenerFactory (), new DeviceLoaderFactory (this, ProcessManager), diff --git a/tests/xharness/Jenkins/Jenkins.cs b/tests/xharness/Jenkins/Jenkins.cs index ea53cab292..5e6ba01bf2 100644 --- a/tests/xharness/Jenkins/Jenkins.cs +++ b/tests/xharness/Jenkins/Jenkins.cs @@ -154,22 +154,22 @@ namespace Xharness.Jenkins return Task.WhenAll (devs, sims); } - AppRunnerTarget[] GetAppRunnerTargets (TestPlatform platform) + TestTarget[] GetAppRunnerTargets (TestPlatform platform) { switch (platform) { case TestPlatform.tvOS: - return new AppRunnerTarget [] { AppRunnerTarget.Simulator_tvOS }; + return new TestTarget [] { TestTarget.Simulator_tvOS }; case TestPlatform.watchOS: case TestPlatform.watchOS_32: case TestPlatform.watchOS_64_32: - return new AppRunnerTarget [] { AppRunnerTarget.Simulator_watchOS }; + return new TestTarget [] { TestTarget.Simulator_watchOS }; case TestPlatform.iOS_Unified: - return new AppRunnerTarget [] { AppRunnerTarget.Simulator_iOS32, AppRunnerTarget.Simulator_iOS64 }; + return new TestTarget [] { TestTarget.Simulator_iOS32, TestTarget.Simulator_iOS64 }; case TestPlatform.iOS_Unified32: - return new AppRunnerTarget [] { AppRunnerTarget.Simulator_iOS32 }; + return new TestTarget [] { TestTarget.Simulator_iOS32 }; case TestPlatform.iOS_Unified64: case TestPlatform.iOS_TodayExtension64: - return new AppRunnerTarget [] { AppRunnerTarget.Simulator_iOS64 }; + return new TestTarget [] { TestTarget.Simulator_iOS64 }; default: throw new NotImplementedException (platform.ToString ()); } @@ -199,7 +199,7 @@ namespace Xharness.Jenkins { var runtasks = new List (); - AppRunnerTarget [] targets = GetAppRunnerTargets (buildTask.Platform); + TestTarget [] targets = GetAppRunnerTargets (buildTask.Platform); TestPlatform [] platforms; bool [] ignored; @@ -217,7 +217,7 @@ namespace Xharness.Jenkins ignored = new [] { !IncludeiOS32, false}; break; case TestPlatform.iOS_TodayExtension64: - targets = new AppRunnerTarget[] { AppRunnerTarget.Simulator_iOS64 }; + targets = new TestTarget[] { TestTarget.Simulator_iOS64 }; platforms = new TestPlatform[] { TestPlatform.iOS_TodayExtension64 }; ignored = new [] { false }; break; diff --git a/tests/xharness/Jenkins/TestTasks/RunDeviceTask.cs b/tests/xharness/Jenkins/TestTasks/RunDeviceTask.cs index 5206126599..8ef9f5c74a 100644 --- a/tests/xharness/Jenkins/TestTasks/RunDeviceTask.cs +++ b/tests/xharness/Jenkins/TestTasks/RunDeviceTask.cs @@ -48,18 +48,18 @@ namespace Xharness.Jenkins.TestTasks case TestPlatform.iOS_Unified: case TestPlatform.iOS_Unified32: case TestPlatform.iOS_Unified64: - AppRunnerTarget = AppRunnerTarget.Device_iOS; + AppRunnerTarget = TestTarget.Device_iOS; break; case TestPlatform.iOS_TodayExtension64: - AppRunnerTarget = AppRunnerTarget.Device_iOS; + AppRunnerTarget = TestTarget.Device_iOS; break; case TestPlatform.tvOS: - AppRunnerTarget = AppRunnerTarget.Device_tvOS; + AppRunnerTarget = TestTarget.Device_tvOS; break; case TestPlatform.watchOS: case TestPlatform.watchOS_32: case TestPlatform.watchOS_64_32: - AppRunnerTarget = AppRunnerTarget.Device_watchOS; + AppRunnerTarget = TestTarget.Device_watchOS; break; default: throw new NotImplementedException (); @@ -82,6 +82,7 @@ namespace Xharness.Jenkins.TestTasks Jenkins.MainLog.WriteLine ("Acquired device '{0}' for '{1}'", Device.Name, ProjectFile); runner = new AppRunner (processManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (Harness, processManager), new SimpleListenerFactory (), new DeviceLoaderFactory (Harness, processManager), @@ -148,6 +149,7 @@ namespace Xharness.Jenkins.TestTasks // will do both of these things, preparing the device for launching the today extension). AppRunner todayRunner = new AppRunner (processManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (Harness, processManager), new SimpleListenerFactory (), new DeviceLoaderFactory (Harness, processManager), diff --git a/tests/xharness/Jenkins/TestTasks/RunSimulatorTask.cs b/tests/xharness/Jenkins/TestTasks/RunSimulatorTask.cs index ff0d517467..bf11ca8a83 100644 --- a/tests/xharness/Jenkins/TestTasks/RunSimulatorTask.cs +++ b/tests/xharness/Jenkins/TestTasks/RunSimulatorTask.cs @@ -34,11 +34,11 @@ namespace Xharness.Jenkins.TestTasks { var project = Path.GetFileNameWithoutExtension (ProjectFile); if (project.EndsWith ("-tvos", StringComparison.Ordinal)) { - AppRunnerTarget = AppRunnerTarget.Simulator_tvOS; + AppRunnerTarget = TestTarget.Simulator_tvOS; } else if (project.EndsWith ("-watchos", StringComparison.Ordinal)) { - AppRunnerTarget = AppRunnerTarget.Simulator_watchOS; + AppRunnerTarget = TestTarget.Simulator_watchOS; } else { - AppRunnerTarget = AppRunnerTarget.Simulator_iOS; + AppRunnerTarget = TestTarget.Simulator_iOS; } this.simulators = simulators ?? throw new ArgumentNullException (nameof (simulators)); @@ -78,6 +78,7 @@ namespace Xharness.Jenkins.TestTasks var clean_state = false;//Platform == TestPlatform.watchOS; runner = new AppRunner (processManager, + new AppBundleInformationParser (), new SimulatorsLoaderFactory (Harness, processManager), new SimpleListenerFactory (), new DeviceLoaderFactory (Harness, processManager), diff --git a/tests/xharness/Jenkins/TestTasks/RunXITask.cs b/tests/xharness/Jenkins/TestTasks/RunXITask.cs index bcc8f205bc..4cb0bf9e50 100644 --- a/tests/xharness/Jenkins/TestTasks/RunXITask.cs +++ b/tests/xharness/Jenkins/TestTasks/RunXITask.cs @@ -11,7 +11,7 @@ namespace Xharness.Jenkins.TestTasks { abstract class RunXITask : RunTestTask where TDevice : class, IDevice { - public AppRunnerTarget AppRunnerTarget; + public TestTarget AppRunnerTarget; protected AppRunner runner; protected AppRunner additional_runner; diff --git a/tests/xharness/RunMode.cs b/tests/xharness/RunMode.cs new file mode 100644 index 0000000000..4b75bd83c0 --- /dev/null +++ b/tests/xharness/RunMode.cs @@ -0,0 +1,10 @@ +namespace Xharness { + public enum RunMode { + Sim32, + Sim64, + Classic, + iOS, + TvOS, + WatchOS, + } +} diff --git a/tests/xharness/TestTarget.cs b/tests/xharness/TestTarget.cs new file mode 100644 index 0000000000..2900c6447b --- /dev/null +++ b/tests/xharness/TestTarget.cs @@ -0,0 +1,43 @@ +using System; + +namespace Xharness { + public enum TestTarget { + None, + Simulator_iOS, + Simulator_iOS32, + Simulator_iOS64, + Simulator_tvOS, + Simulator_watchOS, + Device_iOS, + Device_tvOS, + Device_watchOS, + } + + public static class TestTargetExtensions { + public static RunMode ToRunMode (this TestTarget target) => target switch + { + TestTarget.Simulator_iOS => RunMode.Classic, + TestTarget.Simulator_iOS32 => RunMode.Sim32, + TestTarget.Simulator_iOS64 => RunMode.Sim64, + TestTarget.Simulator_tvOS => RunMode.TvOS, + TestTarget.Simulator_watchOS => RunMode.WatchOS, + TestTarget.Device_iOS => RunMode.iOS, + TestTarget.Device_tvOS => RunMode.TvOS, + TestTarget.Device_watchOS => RunMode.WatchOS, + _ => throw new ArgumentOutOfRangeException ($"Unknown target: {target}"), + }; + + public static bool IsSimulator (this TestTarget target) => target switch + { + TestTarget.Simulator_iOS => true, + TestTarget.Simulator_iOS32 => true, + TestTarget.Simulator_iOS64 => true, + TestTarget.Simulator_tvOS => true, + TestTarget.Simulator_watchOS => true, + TestTarget.Device_iOS => false, + TestTarget.Device_tvOS => false, + TestTarget.Device_watchOS => false, + _ => throw new ArgumentOutOfRangeException ($"Unknown target: {target}"), + }; + } +} diff --git a/tests/xharness/Utilities/Extensions.cs b/tests/xharness/Utilities/Extensions.cs index 1ffd9089ef..96be504d6c 100644 --- a/tests/xharness/Utilities/Extensions.cs +++ b/tests/xharness/Utilities/Extensions.cs @@ -5,54 +5,54 @@ using System.Threading.Tasks; namespace Xharness.Utilities { public static class Extensions { - public static string AsString (this AppRunnerTarget @this) + public static string AsString (this TestTarget @this) { switch (@this) { - case AppRunnerTarget.None: + case TestTarget.None: return null; - case AppRunnerTarget.Device_iOS: + case TestTarget.Device_iOS: return "ios-device"; - case AppRunnerTarget.Device_tvOS: + case TestTarget.Device_tvOS: return "tvos-device"; - case AppRunnerTarget.Device_watchOS: + case TestTarget.Device_watchOS: return "watchos-device"; - case AppRunnerTarget.Simulator_iOS: + case TestTarget.Simulator_iOS: return "ios-simulator"; - case AppRunnerTarget.Simulator_iOS32: + case TestTarget.Simulator_iOS32: return "ios-simulator-32"; - case AppRunnerTarget.Simulator_iOS64: + case TestTarget.Simulator_iOS64: return "ios-simulator-64"; - case AppRunnerTarget.Simulator_tvOS: + case TestTarget.Simulator_tvOS: return "tvos-simulator"; - case AppRunnerTarget.Simulator_watchOS: + case TestTarget.Simulator_watchOS: return "watchos-simulator"; default: throw new NotImplementedException (); } } - public static AppRunnerTarget ParseAsAppRunnerTarget (this string @this) + public static TestTarget ParseAsAppRunnerTarget (this string @this) { switch (@this) { case "ios-device": - return AppRunnerTarget.Device_iOS; + return TestTarget.Device_iOS; case "tvos-device": - return AppRunnerTarget.Device_tvOS; + return TestTarget.Device_tvOS; case "watchos-device": - return AppRunnerTarget.Device_watchOS; + return TestTarget.Device_watchOS; case "ios-simulator": - return AppRunnerTarget.Simulator_iOS; + return TestTarget.Simulator_iOS; case "ios-simulator-32": - return AppRunnerTarget.Simulator_iOS32; + return TestTarget.Simulator_iOS32; case "ios-simulator-64": - return AppRunnerTarget.Simulator_iOS64; + return TestTarget.Simulator_iOS64; case "tvos-simulator": - return AppRunnerTarget.Simulator_tvOS; + return TestTarget.Simulator_tvOS; case "watchos-simulator": - return AppRunnerTarget.Simulator_watchOS; + return TestTarget.Simulator_watchOS; case null: case "": - return AppRunnerTarget.None; + return TestTarget.None; default: throw new NotImplementedException (@this); } diff --git a/tests/xharness/Xharness.Tests/Hardware/Tests/SimulatorsTest.cs b/tests/xharness/Xharness.Tests/Hardware/Tests/SimulatorsTest.cs index 1d9cc0123c..14e7f5dc13 100644 --- a/tests/xharness/Xharness.Tests/Hardware/Tests/SimulatorsTest.cs +++ b/tests/xharness/Xharness.Tests/Hardware/Tests/SimulatorsTest.cs @@ -134,11 +134,11 @@ namespace Xharness.Tests.Hardware.Tests { Assert.AreEqual (75, simulators.AvailableDevices.Count()); } - [TestCase (AppRunnerTarget.Simulator_iOS64, 1)] - [TestCase (AppRunnerTarget.Simulator_iOS32, 1)] - [TestCase (AppRunnerTarget.Simulator_tvOS, 1)] - [TestCase (AppRunnerTarget.Simulator_watchOS, 2)] - public async Task FindAsyncDoNotCreateTest (AppRunnerTarget target, int expected) + [TestCase (TestTarget.Simulator_iOS64, 1)] + [TestCase (TestTarget.Simulator_iOS32, 1)] + [TestCase (TestTarget.Simulator_tvOS, 1)] + [TestCase (TestTarget.Simulator_watchOS, 2)] + public async Task FindAsyncDoNotCreateTest (TestTarget target, int expected) { string processPath = null; MlaunchArguments passedArguments = null; diff --git a/tests/xharness/Xharness.Tests/Tests/AppBundleInformationParserTests.cs b/tests/xharness/Xharness.Tests/Tests/AppBundleInformationParserTests.cs new file mode 100644 index 0000000000..3607f0b65a --- /dev/null +++ b/tests/xharness/Xharness.Tests/Tests/AppBundleInformationParserTests.cs @@ -0,0 +1,41 @@ +using System.IO; +using System.Reflection; +using NUnit.Framework; + +namespace Xharness.Tests { + [TestFixture] + public class AppBundleInformationParserTests { + + const string appName = "com.xamarin.bcltests.SystemXunit"; + + static readonly string outputPath = Path.GetDirectoryName (Assembly.GetAssembly (typeof (AppRunnerTests)).Location); + static readonly string sampleProjectPath = Path.Combine (outputPath, "Samples", "TestProject"); + static readonly string appPath = Path.Combine (sampleProjectPath, "bin", appName + ".app"); + static readonly string projectFilePath = Path.Combine (sampleProjectPath, "SystemXunit.csproj"); + + [SetUp] + public void SetUp () + { + Directory.CreateDirectory (appPath); + } + + [TearDown] + public void TearDown () + { + Directory.Delete (appPath, true); + } + + [Test] + public void InitializeTest () + { + var parser = new AppBundleInformationParser (); + + var info = parser.ParseFromProject (projectFilePath, TestTarget.Simulator_iOS64, "Debug"); + + Assert.AreEqual (appName, info.AppName); + Assert.AreEqual (appPath, info.AppPath); + Assert.AreEqual (appPath, info.LaunchAppPath); + Assert.AreEqual (appName, info.BundleIdentifier); + } + } +} diff --git a/tests/xharness/Xharness.Tests/Tests/AppRunnerTests.cs b/tests/xharness/Xharness.Tests/Tests/AppRunnerTests.cs index 5d94087ceb..d515b2de37 100644 --- a/tests/xharness/Xharness.Tests/Tests/AppRunnerTests.cs +++ b/tests/xharness/Xharness.Tests/Tests/AppRunnerTests.cs @@ -63,6 +63,7 @@ namespace Xharness.Tests { IDeviceLoaderFactory devicesFactory; ISimpleListenerFactory listenerFactory; ICrashSnapshotReporterFactory snapshotReporterFactory; + IAppBundleInformationParser appBundleInformationParser; [SetUp] public void SetUp () @@ -95,15 +96,29 @@ namespace Xharness.Tests { mock4.Setup (m => m.Create (It.IsAny (), It.IsAny (), It.IsAny (), It.IsAny ())).Returns (snapshotReporter.Object); snapshotReporterFactory = mock4.Object; + var mock5 = new Mock (); + mock5 + .Setup (x => x.ParseFromProject (projectFilePath, It.IsAny (), "Debug")) + .Returns (new AppBundleInformation (appName, appName, appPath, appPath, null)); + + appBundleInformationParser = mock5.Object; + mainLog = new Mock (); Directory.CreateDirectory (appPath); } + [TearDown] + public void TearDown () + { + Directory.Delete (appPath, true); + } + [Test] public void InitializeTest () { var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -111,7 +126,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Simulator_iOS64, + TestTarget.Simulator_iOS64, Mock.Of (), mainLog.Object, logs.Object, @@ -128,6 +143,7 @@ namespace Xharness.Tests { public void InstallToSimulatorTest () { var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -135,7 +151,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Simulator_iOS64, + TestTarget.Simulator_iOS64, Mock.Of (), mainLog.Object, logs.Object, @@ -151,6 +167,7 @@ namespace Xharness.Tests { public void UninstallToSimulatorTest () { var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -158,7 +175,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Simulator_iOS64, + TestTarget.Simulator_iOS64, Mock.Of (), mainLog.Object, logs.Object, @@ -174,6 +191,7 @@ namespace Xharness.Tests { public void InstallWhenNoDevicesTest () { var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -181,7 +199,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Device_iOS, + TestTarget.Device_iOS, Mock.Of (), mainLog.Object, logs.Object, @@ -206,6 +224,7 @@ namespace Xharness.Tests { processManager.SetReturnsDefault (Task.FromResult (processResult)); var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -213,7 +232,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Device_iOS, + TestTarget.Device_iOS, harness, mainLog.Object, logs.Object, @@ -259,6 +278,7 @@ namespace Xharness.Tests { processManager.SetReturnsDefault (Task.FromResult (processResult)); var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -266,7 +286,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Device_iOS, + TestTarget.Device_iOS, harness, mainLog.Object, logs.Object, @@ -316,7 +336,7 @@ namespace Xharness.Tests { string simulatorLogPath = Path.Combine (Path.GetTempPath (), "simulator-logs"); simulators - .Setup (x => x.FindAsync (AppRunnerTarget.Simulator_tvOS, mainLog.Object, true, false)) + .Setup (x => x.FindAsync (TestTarget.Simulator_tvOS, mainLog.Object, true, false)) .ReturnsAsync ((ISimulatorDevice []) null); var listenerLogFile = new Mock (); @@ -342,6 +362,7 @@ namespace Xharness.Tests { // Act var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -349,7 +370,7 @@ namespace Xharness.Tests { captureLogFactory.Object, Mock.Of (), Mock.Of (), - AppRunnerTarget.Simulator_tvOS, + TestTarget.Simulator_tvOS, GetMockedHarness (), mainLog.Object, logs.Object, @@ -397,7 +418,7 @@ namespace Xharness.Tests { simulator.SetupGet (x => x.SystemLog).Returns (Path.Combine (simulatorLogPath, "system.log")); simulators - .Setup (x => x.FindAsync (AppRunnerTarget.Simulator_iOS64, mainLog.Object, true, false)) + .Setup (x => x.FindAsync (TestTarget.Simulator_iOS64, mainLog.Object, true, false)) .ReturnsAsync (new ISimulatorDevice [] { simulator.Object }); var testResultFilePath = Path.GetTempFileName (); @@ -450,6 +471,7 @@ namespace Xharness.Tests { // Act var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -457,7 +479,7 @@ namespace Xharness.Tests { captureLogFactory.Object, Mock.Of (), // Use for devices only resultParser.Object, - AppRunnerTarget.Simulator_iOS64, + TestTarget.Simulator_iOS64, harness, mainLog.Object, logs.Object, @@ -513,6 +535,7 @@ namespace Xharness.Tests { // Act var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -520,7 +543,7 @@ namespace Xharness.Tests { Mock.Of (), Mock.Of (), Mock.Of (), - AppRunnerTarget.Device_tvOS, + TestTarget.Device_tvOS, GetMockedHarness (), mainLog.Object, logs.Object, @@ -604,6 +627,7 @@ namespace Xharness.Tests { // Act var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -611,7 +635,7 @@ namespace Xharness.Tests { Mock.Of (), // Used for simulators only deviceLogCapturerFactory.Object, resultParser.Object, - AppRunnerTarget.Device_iOS, + TestTarget.Device_iOS, harness, mainLog.Object, logs.Object, @@ -712,6 +736,7 @@ namespace Xharness.Tests { // Act var appRunner = new AppRunner (processManager.Object, + appBundleInformationParser, simulatorsFactory, listenerFactory, devicesFactory, @@ -719,7 +744,7 @@ namespace Xharness.Tests { Mock.Of (), // Used for simulators only deviceLogCapturerFactory.Object, resultParser.Object, - AppRunnerTarget.Device_iOS, + TestTarget.Device_iOS, harness, mainLog.Object, logs.Object, diff --git a/tests/xharness/Xharness.Tests/Xharness.Tests.csproj b/tests/xharness/Xharness.Tests/Xharness.Tests.csproj index 9bd6e1c7d5..d78c28aa78 100644 --- a/tests/xharness/Xharness.Tests/Xharness.Tests.csproj +++ b/tests/xharness/Xharness.Tests/Xharness.Tests.csproj @@ -58,6 +58,7 @@ + diff --git a/tests/xharness/xharness.csproj b/tests/xharness/xharness.csproj index cfb0f0fb2a..3c8dedbecb 100644 --- a/tests/xharness/xharness.csproj +++ b/tests/xharness/xharness.csproj @@ -73,9 +73,12 @@ + - + + +