public RunDeviceTask(Jenkins jenkins, IHardwareDeviceLoader devices, MSBuildTask buildTask, IProcessManager processManager, ITunnelBore tunnelBore, bool useTcpTunnel, IEnumerable <IHardwareDevice> candidates) : base(jenkins, buildTask, processManager, candidates.OrderBy((v) => v.DebugSpeed)) { TunnelBore = tunnelBore; runDevice = new RunDevice( testTask: this, devices: devices, resourceManager: Jenkins, mainLog: Jenkins.MainLog, deviceLoadLog: Jenkins.DeviceLoadLog, defaultLogDirectory: Jenkins.Harness.LogDirectory, uninstallTestApp: Jenkins.UninstallTestApp, cleanSuccessfulTestRuns: Jenkins.CleanSuccessfulTestRuns, generateXmlFailures: Jenkins.Harness.InCI, inCI: Jenkins.Harness.InCI, useTcpTunnel: useTcpTunnel, xmlResultJargon: Jenkins.Harness.XmlJargon ); }
public Jenkins(IHarness harness, IProcessManager processManager, IResultParser resultParser, ITunnelBore tunnelBore) { this.processManager = processManager ?? throw new ArgumentNullException(nameof(processManager)); this.TunnelBore = tunnelBore ?? throw new ArgumentNullException(nameof(tunnelBore)); Harness = harness ?? throw new ArgumentNullException(nameof(harness)); Simulators = new SimulatorLoader(processManager); Devices = new HardwareDeviceLoader(processManager); testSelector = new TestSelector(this, processManager, new GitHub(harness, processManager)); testVariationsFactory = new TestVariationsFactory(this, processManager); DeviceLoader = new JenkinsDeviceLoader(Simulators, Devices, Logs); resourceManager = new ResourceManager(); xamarinStorageHtmlReportWriter = new HtmlReportWriter(jenkins: this, resourceManager: resourceManager, resultParser: resultParser); // we only care about the vsdrops writer if we are in the CI, locally makes no sense if (harness.InCI && !string.IsNullOrEmpty(Harness.VSDropsUri)) { vsdropsHtmlReportWriter = new HtmlReportWriter(this, resourceManager, resultParser, linksPrefix: Harness.VSDropsUri, embeddedResources: true); } markdownReportWriter = new MarkdownReportWriter(); }
public RunSimulatorTask(Jenkins jenkins, ISimulatorLoader simulators, MSBuildTask buildTask, IProcessManager processManager, ITunnelBore tunnelBore, IEnumerable <ISimulatorDevice> candidates = null) : base(jenkins, buildTask, processManager, candidates) => runSimulator = new RunSimulator(
public async Task RunTestAsync() { mainLog.WriteLine("Running '{0}' on device (candidates: '{1}')", testTask.ProjectFile, string.Join("', '", testTask.Candidates.Select((v) => v.Name).ToArray())); var uninstall_log = testTask.Logs.Create($"uninstall-{Helpers.Timestamp}.log", "Uninstall log"); using (var device_resource = await testTask.NotifyBlockingWaitAsync(resourceManager.GetDeviceResources(testTask.Candidates).AcquireAnyConcurrentAsync())) { try { // Set the device we acquired. testTask.Device = testTask.Candidates.First((d) => d.UDID == device_resource.Resource.Name); if (testTask.Device.DevicePlatform == DevicePlatform.watchOS) { testTask.CompanionDevice = await devices.FindCompanionDevice(deviceLoadLog, testTask.Device); } mainLog.WriteLine("Acquired device '{0}' for '{1}'", testTask.Device.Name, testTask.ProjectFile); ITunnelBore tunnelBore = null; if (useTcpTunnel && testTask.Device.DevicePlatform != DevicePlatform.iOS && testTask.Device.DevicePlatform != DevicePlatform.tvOS) { mainLog.WriteLine("Ignoring request to use a tunnel because it is not supported by the specified platform"); } else if (useTcpTunnel && (testTask.Device.DevicePlatform == DevicePlatform.iOS || testTask.Device.DevicePlatform == DevicePlatform.tvOS)) { tunnelBore = testTask.TunnelBore; mainLog.WriteLine("Using tunnel to communicate with device."); } testTask.Runner = new AppRunner(testTask.ProcessManager, new AppBundleInformationParser(), new SimulatorLoaderFactory(testTask.ProcessManager), new SimpleListenerFactory(tunnelBore), new DeviceLoaderFactory(testTask.ProcessManager), new CrashSnapshotReporterFactory(testTask.ProcessManager), new CaptureLogFactory(), new DeviceLogCapturerFactory(testTask.ProcessManager), new TestReporterFactory(testTask.ProcessManager), testTask.AppRunnerTarget, testTask.Harness, projectFilePath: testTask.ProjectFile, mainLog: uninstall_log, logs: new Logs(testTask.LogDirectory ?? defaultLogDirectory), buildConfiguration: testTask.ProjectConfiguration, deviceName: testTask.Device.Name, companionDeviceName: testTask.CompanionDevice?.Name, timeoutMultiplier: testTask.TimeoutMultiplier, variation: testTask.Variation, buildTask: testTask.BuildTask); await testTask.Runner.InitializeAsync(); // Sometimes devices can't upgrade (depending on what has changed), so make sure to uninstall any existing apps first. if (uninstallTestApp) { testTask.Runner.MainLog = uninstall_log; var uninstall_result = await testTask.Runner.UninstallAsync(); if (!uninstall_result.Succeeded) { mainLog.WriteLine($"Pre-run uninstall failed, exit code: {uninstall_result.ExitCode} (this hopefully won't affect the test result)"); } } else { uninstall_log.WriteLine($"Pre-run uninstall skipped."); } if (!testTask.Failed) { // Install the app InstallLog = new AppInstallMonitorLog(testTask.Logs.Create($"install-{Helpers.Timestamp}.log", "Install log")); try { testTask.Runner.MainLog = this.InstallLog; var install_result = await testTask.Runner.InstallAsync(InstallLog.CancellationToken); if (!install_result.Succeeded) { testTask.FailureMessage = $"Install failed, exit code: {install_result.ExitCode}."; testTask.ExecutionResult = TestExecutingResult.Failed; if (generateXmlFailures) { resultParser.GenerateFailure( testTask.Logs, "install", testTask.Runner.AppInformation.AppName, testTask.Variation, $"AppInstallation on {testTask.Device.Name}", $"Install failed on {testTask.Device.Name}, exit code: {install_result.ExitCode}", InstallLog.FullPath, xmlResultJargon); } } } finally { InstallLog.Dispose(); InstallLog = null; } } if (!testTask.Failed) { // Run the app testTask.Runner.MainLog = testTask.Logs.Create($"run-{testTask.Device.UDID}-{Helpers.Timestamp}.log", "Run log"); await testTask.Runner.RunAsync(); if (!string.IsNullOrEmpty(testTask.Runner.FailureMessage)) { testTask.FailureMessage = testTask.Runner.FailureMessage; } else if (testTask.Runner.Result != TestExecutingResult.Succeeded) { testTask.FailureMessage = testTask.GuessFailureReason(testTask.Runner.MainLog); } if (string.IsNullOrEmpty(testTask.FailureMessage) && errorKnowledgeBase.IsKnownTestIssue(testTask.Runner.MainLog, out var failure)) { testTask.KnownFailure = failure; mainLog.WriteLine($"Test run has a known failure: '{testTask.KnownFailure}'"); } if (testTask.Runner.Result == TestExecutingResult.Succeeded && testTask.Platform == TestPlatform.iOS_TodayExtension64) { // For the today extension, the main app is just a single test. // This is because running the today extension will not wake up the device, // nor will it close & reopen the today app (but launching the main app // will do both of these things, preparing the device for launching the today extension). AppRunner todayRunner = new AppRunner(testTask.ProcessManager, new AppBundleInformationParser(), new SimulatorLoaderFactory(testTask.ProcessManager), new SimpleListenerFactory(tunnelBore), new DeviceLoaderFactory(testTask.ProcessManager), new CrashSnapshotReporterFactory(testTask.ProcessManager), new CaptureLogFactory(), new DeviceLogCapturerFactory(testTask.ProcessManager), new TestReporterFactory(testTask.ProcessManager), testTask.AppRunnerTarget, testTask.Harness, projectFilePath: testTask.ProjectFile, mainLog: testTask.Logs.Create($"extension-run-{testTask.Device.UDID}-{Helpers.Timestamp}.log", "Extension run log"), logs: new Logs(testTask.LogDirectory ?? defaultLogDirectory), buildConfiguration: testTask.ProjectConfiguration, deviceName: testTask.Device.Name, companionDeviceName: testTask.CompanionDevice?.Name, timeoutMultiplier: testTask.TimeoutMultiplier, variation: testTask.Variation, buildTask: testTask.BuildTask); await todayRunner.InitializeAsync(); testTask.AdditionalRunner = todayRunner; await todayRunner.RunAsync(); foreach (var log in todayRunner.Logs.Where((v) => !v.Description.StartsWith("Extension ", StringComparison.Ordinal))) { log.Description = "Extension " + log.Description [0].ToString().ToLower() + log.Description.Substring(1); } testTask.ExecutionResult = todayRunner.Result; if (!string.IsNullOrEmpty(todayRunner.FailureMessage)) { testTask.FailureMessage = todayRunner.FailureMessage; } } else { testTask.ExecutionResult = testTask.Runner.Result; } } } finally { // Uninstall again, so that we don't leave junk behind and fill up the device. if (uninstallTestApp) { testTask.Runner.MainLog = uninstall_log; var uninstall_result = await testTask.Runner.UninstallAsync(); if (!uninstall_result.Succeeded) { mainLog.WriteLine($"Post-run uninstall failed, exit code: {uninstall_result.ExitCode} (this won't affect the test result)"); } } else { uninstall_log.WriteLine($"Post-run uninstall skipped."); } // Also clean up after us locally. if (inCI || cleanSuccessfulTestRuns && testTask.Succeeded) { await testTask.BuildTask.CleanAsync(); } } } }
public SimpleListenerFactory(ITunnelBore tunnelBore = null) => TunnelBore = tunnelBore;
public Jenkins(Harness harness, IProcessManager processManager, IResultParser resultParser, ITunnelBore tunnelBore) { this.processManager = processManager ?? throw new ArgumentNullException(nameof(processManager)); this.TunnelBore = tunnelBore ?? throw new ArgumentNullException(nameof(tunnelBore)); Harness = harness ?? throw new ArgumentNullException(nameof(harness)); Simulators = new SimulatorLoader(processManager); Devices = new HardwareDeviceLoader(processManager); testSelector = new TestSelector(this, processManager, new GitHub(harness, processManager)); testVariationsFactory = new TestVariationsFactory(this, processManager); DeviceLoader = new JenkinsDeviceLoader(Simulators, Devices, Logs); resourceManager = new ResourceManager(); htmlReportWriter = new HtmlReportWriter(jenkins: this, resourceManager: resourceManager, resultParser: resultParser); markdownReportWriter = new MarkdownReportWriter(); }