Exemple #1
0
 protected async Task <ExitCode> OrchestrateOperation(
     TestTargetOs target,
     string?deviceName,
     bool includeWirelessDevices,
     bool resetSimulator,
     bool enableLldb,
     GetAppBundleInfoFunc getAppBundle,
     ExecuteMacCatalystAppFunc executeMacCatalystApp,
     ExecuteAppFunc executeApp,
     CancellationToken cancellationToken)
 {
     try
     {
         return(await OrchestrateOperationInternal(
                    target,
                    deviceName,
                    includeWirelessDevices,
                    resetSimulator,
                    enableLldb,
                    getAppBundle,
                    executeMacCatalystApp,
                    executeApp,
                    cancellationToken));
     }
     catch (OperationCanceledException e)
     {
         _logger.LogDebug(e.ToString());
         return(ExitCode.APP_LAUNCH_TIMEOUT);
     }
 }
Exemple #2
0
    private async Task <ExitCode> OrchestrateOperationInternal(
        TestTargetOs target,
        string?deviceName,
        bool includeWirelessDevices,
        bool resetSimulator,
        bool enableLldb,
        GetAppBundleInfoFunc getAppBundle,
        ExecuteMacCatalystAppFunc executeMacCatalystApp,
        ExecuteAppFunc executeApp,
        CancellationToken cancellationToken)
    {
        _lldbFileCreated = false;
        var isLldbEnabled = IsLldbEnabled();

        if (isLldbEnabled && !enableLldb)
        {
            // the file is present, but the user did not set it, warn him about it
            _logger.LogWarning("Lldb will be used since '~/.mtouch-launch-with-lldb' was found in the system but it was not created by xharness.");
        }
        else if (enableLldb)
        {
            if (!File.Exists(s_mlaunchLldbConfigFile))
            {
                // create empty file
                File.WriteAllText(s_mlaunchLldbConfigFile, string.Empty);
                _lldbFileCreated = true;
            }
        }

        if (includeWirelessDevices && target.Platform.IsSimulator())
        {
            _logger.LogWarning("Including wireless devices while targeting a simulator has no effect");
        }

        if (resetSimulator && !target.Platform.IsSimulator())
        {
            _logger.LogWarning("Targeting device but requesting simulator reset has no effect");
            resetSimulator = false;
        }

        ExitCode             exitCode;
        IDevice              device;
        IDevice?             companionDevice;
        AppBundleInformation appBundleInfo;

        if (target.Platform == TestTarget.MacCatalyst)
        {
            try
            {
                appBundleInfo = await getAppBundle(target, null !, cancellationToken);
            }
            catch (Exception e)
            {
                cancellationToken.ThrowIfCancellationRequested();
                _logger.LogError(e.Message);
                return(ExitCode.PACKAGE_NOT_FOUND);
            }

            try
            {
                return(await executeMacCatalystApp(appBundleInfo));
            }
            catch (Exception e)
            {
                var message = new StringBuilder().AppendLine("Application run failed:");
                exitCode = ExitCode.APP_LAUNCH_FAILURE;

                if (_errorKnowledgeBase.IsKnownTestIssue(_mainLog, out var failure))
                {
                    message.Append(failure.HumanMessage);
                    if (failure.IssueLink != null)
                    {
                        message.AppendLine($" Find more information at {failure.IssueLink}");
                    }

                    if (failure.SuggestedExitCode.HasValue)
                    {
                        exitCode = (ExitCode)failure.SuggestedExitCode.Value;
                    }
                }
                else
                {
                    message.AppendLine(e.ToString());
                }

                _logger.LogError(message.ToString());

                return(exitCode);
            }
        }

        try
        {
            _logger.LogInformation($"Looking for available {target.AsString()} {(target.Platform.IsSimulator() ? "simulators" : "devices")}..");

            var finderLogName = $"list-{target.AsString()}-{_helpers.Timestamp}.log";
            using var finderLog = _logs.Create(finderLogName, "DeviceList", true);

            _mainLog.WriteLine(
                $"Looking for available {target.AsString()} {(target.Platform.IsSimulator() ? "simulators" : "devices")}. " +
                $"Storing logs into {finderLogName}");

            (device, companionDevice) = await _deviceFinder.FindDevice(target, deviceName, finderLog, includeWirelessDevices, cancellationToken);

            _logger.LogInformation($"Found {(target.Platform.IsSimulator() ? "simulator" : "physical")} device '{device.Name}'");

            if (companionDevice != null)
            {
                _logger.LogInformation($"Found companion {(target.Platform.IsSimulator() ? "simulator" : "physical")} device '{companionDevice.Name}'");
            }
        }
        catch (NoDeviceFoundException e)
        {
            _logger.LogError(e.Message);
            return(ExitCode.DEVICE_NOT_FOUND);
        }

        cancellationToken.ThrowIfCancellationRequested();

        try
        {
            appBundleInfo = await getAppBundle(target, device, cancellationToken);
        }
        catch (Exception e)
        {
            cancellationToken.ThrowIfCancellationRequested();
            _logger.LogError(e.Message);
            return(ExitCode.PACKAGE_NOT_FOUND);
        }

        cancellationToken.ThrowIfCancellationRequested();

        if (target.Platform.IsSimulator() && resetSimulator)
        {
            try
            {
                var simulator = (ISimulatorDevice)device;
                var bundleIds = appBundleInfo.BundleIdentifier == string.Empty ? Array.Empty <string>() : new[] { appBundleInfo.BundleIdentifier };

                _logger.LogInformation($"Reseting simulator '{device.Name}'");
                await simulator.PrepareSimulator(_mainLog, bundleIds);

                if (companionDevice != null)
                {
                    _logger.LogInformation($"Reseting companion simulator '{companionDevice.Name}'");
                    var companionSimulator = (ISimulatorDevice)companionDevice;
                    await companionSimulator.PrepareSimulator(_mainLog, bundleIds);
                }

                _logger.LogInformation("Simulator reset finished");
            }
            catch (Exception e)
            {
                _logger.LogError($"Failed to reset simulator: " + Environment.NewLine + e);
                return(ExitCode.SIMULATOR_FAILURE);
            }
        }

        cancellationToken.ThrowIfCancellationRequested();

        // Note down the actual test target
        // For simulators (e.g. "iOS 13.4"), we strip the iOS part and keep the version only, for devices there's no OS
        _diagnosticsData.TargetOS = target.Platform.IsSimulator() ? device.OSVersion.Split(' ', 2).Last() : device.OSVersion;
        _diagnosticsData.Device   = device.Name ?? device.UDID;

        // Uninstall the app first to get a clean state
        if (!resetSimulator)
        {
            await UninstallApp(target.Platform, appBundleInfo.BundleIdentifier, device, isPreparation : true, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();
        }

        exitCode = await InstallApp(appBundleInfo, device, target, cancellationToken);

        if (exitCode != ExitCode.SUCCESS)
        {
            _logger.LogInformation($"Cleaning up the failed installation from '{device.Name}'");

            var uninstallResult = await UninstallApp(target.Platform, appBundleInfo.BundleIdentifier, device, isPreparation : false, new CancellationToken());

            if (uninstallResult == ExitCode.SIMULATOR_FAILURE)
            {
                // Sometimes the simulator gets in a bad shape and we won't be able to install the app, we can tell here
                return(ExitCode.SIMULATOR_FAILURE);
            }

            return(exitCode);
        }

        try
        {
            exitCode = await executeApp(appBundleInfo, device, companionDevice);
        }
        catch (Exception e)
        {
            exitCode = ExitCode.GENERAL_FAILURE;

            var message = new StringBuilder().AppendLine("Application run failed:");

            if (_errorKnowledgeBase.IsKnownTestIssue(_mainLog, out var failure))
            {
                message.Append(failure.HumanMessage);
                if (failure.IssueLink != null)
                {
                    message.AppendLine($" Find more information at {failure.IssueLink}");
                }

                if (failure.SuggestedExitCode.HasValue)
                {
                    exitCode = (ExitCode)failure.SuggestedExitCode.Value;
                }
            }
            else
            {
                message.AppendLine(e.ToString());
            }

            _logger.LogError(message.ToString());
        }
        finally
        {
            if (target.Platform.IsSimulator() && resetSimulator)
            {
                await CleanUpSimulators(device, companionDevice);
            }
            else if (device != null) // Do not uninstall if device was cleaned up
            {
                var uninstallResult = await UninstallApp(target.Platform, appBundleInfo.BundleIdentifier, device, false, new CancellationToken());

                // We are able to detect a case when simulator is in a bad shape
                // If it also failed the test/run, we should present that as the failure
                if (uninstallResult == ExitCode.SIMULATOR_FAILURE && exitCode != ExitCode.SUCCESS && exitCode != ExitCode.TESTS_FAILED)
                {
                    exitCode = ExitCode.SIMULATOR_FAILURE;
                }
            }
        }

        return(exitCode);
    }