예제 #1
0
        List <ProcessListEntry> GetProcessList(IProcessListRequest request)
        {
            // TODO: Use single cancelable task for both actions
            try
            {
                var enableSshAction = _actionRecorder.CreateToolAction(ActionType.GameletEnableSsh);
                if (!_cancelableTaskFactory
                    .Create(TaskMessages.EnablingSSH,
                            async _ =>
                            await _sshManager.EnableSshAsync(Gamelet, enableSshAction))
                    .RunAndRecord(enableSshAction))
                {
                    return(new List <ProcessListEntry>());
                }
            }
            catch (Exception e) when(e is SshKeyException || e is CloudException)
            {
                Trace.WriteLine(e.ToString());
                _dialogUtil.ShowError(ErrorStrings.FailedToEnableSsh(e.Message), e.ToString());
                return(new List <ProcessListEntry>());
            }

            // TODO: Handle ProcessException
            var processListAction  = _actionRecorder.CreateToolAction(ActionType.ProcessList);
            var queryProcessesTask = _cancelableTaskFactory.Create(
                "Querying instance processes...",
                async() => await request.GetBySshAsync(new SshTarget(Gamelet)));

            queryProcessesTask.RunAndRecord(processListAction);
            return(queryProcessesTask.Result);
        }
예제 #2
0
        void RefreshCoreList()
        {
            if (_instance == null)
            {
                return;
            }

            Cursor = System.Windows.Input.Cursors.Wait;
            try
            {
                var queryTaskTitle = "Querying instance crash dumps...";
                var queryTask      = _cancelableTaskFactory.Create(
                    queryTaskTitle,
                    async() => await _coreListRequest.GetCoreListAsync(new SshTarget(_instance)));

                // Ignore cancelation, and accept the empty result.
                queryTask.RunAndRecord(_actionRecorder, ActionType.CrashDumpList);
                CoreList.ItemsSource = queryTask.Result;
            }
            catch (ProcessException e)
            {
                Trace.WriteLine($"Unable to query instance crash dumps: {e}");
                GameletMessageTextBox.Text = ErrorStrings.ErrorQueryingCoreFiles(e.Message);
                CoreList.ItemsSource       = new List <CoreListEntry>();
            }
            finally
            {
                Cursor = null;
            }
        }
예제 #3
0
        public IVsiGameLaunch CreateLaunch(LaunchParams launchParams)
        {
            IAction            action     = _actionRecorder.CreateToolAction(ActionType.GameLaunchCreate);
            CreateLaunchResult launchRes  = null;
            ICancelableTask    launchTask = _cancelableTaskFactory.Create(
                TaskMessages.LaunchingGame,
                async task => { launchRes = await CreateLaunchAsync(launchParams, task, action); });

            try
            {
                if (!launchTask.RunAndRecord(action))
                {
                    Trace.WriteLine("Launching a game has been canceled by user.");
                    return(null);
                }
            }
            catch (ConfigurationException e)
            {
                _dialogUtil.ShowError(e.Message);
                return(null);
            }
            catch (CloudException e)
            {
                string message = $"{ErrorStrings.CouldNotStartTheGame}{Environment.NewLine}" +
                                 $"{e.Message}{Environment.NewLine}{Environment.NewLine}{ErrorStrings.SeeLogs}";
                _dialogUtil.ShowError(message);
                return(null);
            }

            if (!string.IsNullOrWhiteSpace(launchRes.WarningMessage))
            {
                _dialogUtil.ShowWarning(launchRes.WarningMessage);
            }

            if (!string.IsNullOrWhiteSpace(launchRes.SdkCompatibilityMessage))
            {
                bool showAgain = _dialogUtil.ShowOkNoMoreDisplayWarning(
                    launchRes.SdkCompatibilityMessage, new[]
                {
                    "Tools", "Options", "Stadia SDK", "Game launch",
                    "SDK incompatibility warning"
                });
                if (!showAgain)
                {
                    _vsiService.Options.AddSdkVersionsToHide(launchParams.GameletSdkVersion,
                                                             launchParams.SdkVersion,
                                                             launchParams.GameletName);
                }
            }

            return(launchRes.GameLaunch);
        }
예제 #4
0
        public int AddPort(IDebugPortRequest2 request, out IDebugPort2 port)
        {
            var debugSessionMetrics = new DebugSessionMetrics(_metrics);

            debugSessionMetrics.UseNewDebugSessionId();
            var actionRecorder = new ActionRecorder(debugSessionMetrics);

            port = null;

            if (request.GetPortName(out string gameletIdOrName) != VSConstants.S_OK)
            {
                return(VSConstants.E_FAIL);
            }

            var action        = actionRecorder.CreateToolAction(ActionType.GameletGet);
            var gameletClient = _gameletClientFactory.Create(_cloudRunner.Intercept(action));
            var gameletTask   = _cancelableTaskFactory.Create(
                "Querying instance...",
                async() => await gameletClient.LoadByNameOrIdAsync(gameletIdOrName));

            try
            {
                gameletTask.RunAndRecord(action);
            }
            catch (CloudException e)
            {
                Trace.WriteLine(e.ToString());
                _dialogUtil.ShowError(e.Message);
                return(VSConstants.S_OK);
            }

            var debugPort = _debugPortFactory.Create(gameletTask.Result, this,
                                                     debugSessionMetrics.DebugSessionId);

            _ports.Add(debugPort);
            port = debugPort;
            return(VSConstants.S_OK);
        }
예제 #5
0
        /// <summary>
        /// Stop a gamelet and wait for it to return to the reserved state.
        /// </summary>
        Gamelet StopGamelet(Gamelet gamelet)
        {
            IAction         action   = _actionRecorder.CreateToolAction(ActionType.GameletStop);
            ICancelableTask stopTask =
                _cancelableTaskFactory.Create(TaskMessages.WaitingForGameStop, async(task) => {
                IGameletClient gameletClient =
                    _gameletClientFactory.Create(_runner.Intercept(action));
                try
                {
                    await gameletClient.StopGameAsync(gamelet.Id);
                }
                catch (CloudException e) when((e.InnerException as RpcException)
                                              ?.StatusCode == StatusCode.FailedPrecondition)
                {
                    // FailedPreconditions likely means there is no game session to stop.
                    // For details see (internal).
                    Trace.WriteLine("Potential race condition while stopping game; " +
                                    $"ignoring RPC error: {e.InnerException.Message}");
                }
                while (!task.IsCanceled)
                {
                    gamelet = await gameletClient.GetGameletByNameAsync(gamelet.Name);
                    if (gamelet.State == GameletState.Reserved)
                    {
                        break;
                    }
                    await Task.Delay(1000);
                }
            });

            if (stopTask.RunAndRecord(action))
            {
                return(gamelet);
            }
            return(null);
        }
예제 #6
0
        public void WaitUntilGameLaunchedTest(GameLaunchState[] launchStates, int[] stateRepeat,
                                              bool launchResult, EndReason?endReason = null,
                                              bool isDevResumeOfferEnabled           = false)
        {
            _target = GetGameLaunch(isDevResumeOfferEnabled);
            Func <ICancelable, Task> currentTask = null;
            var action = Substitute.For <IAction>();
            DeveloperLogEvent devEvent = SetupUpdateEvent(action);

            _actionRecorder.CreateToolAction(ActionType.GameLaunchWaitForStart).Returns(action);
            var cancelable = Substitute.For <ICancelableTask>();

            action.Record(Arg.Any <Func <bool> >()).Returns(callInfo =>
            {
                new JoinableTaskFactory(new JoinableTaskContext()).Run(
                    () => currentTask(new NothingToCancel()));
                return(true);
            });
            _cancelableTaskFactory.Create(
                TaskMessages.LaunchingGame, Arg.Any <Func <ICancelable, Task> >()).Returns(callInfo =>
            {
                currentTask = callInfo.Arg <Func <ICancelable, Task> >();
                return(cancelable);
            });
            List <GameLaunchState> statusSequence = launchStates
                                                    .Select((state, i) => Enumerable.Repeat(state, stateRepeat[i]))
                                                    .SelectMany(states => states).ToList();

            Task <GgpGrpc.Models.GameLaunch>[] launches = statusSequence.Select(
                (state, i) => Task.FromResult(GetGameLaunch(state, i == statusSequence.Count - 1
                                                                ? endReason
                                                                : null))).ToArray();
            _gameletClient.GetGameLaunchStateAsync(_launchName, action)
            .Returns(launches[0], launches.Skip(1).ToArray());

            bool launched = _target.WaitUntilGameLaunched();

            Assert.That(launched, Is.EqualTo(launchResult));
            if (!launchResult)
            {
                _dialogUtil.Received(1).ShowError(Arg.Any <string>());
            }

            Assert.That(devEvent.GameLaunchData.LaunchId, Is.EqualTo(_launchId));
            Assert.That(devEvent.GameLaunchData.EndReason, Is.EqualTo((int?)endReason));
            action.Received(1).Record(Arg.Any <Func <bool> >());
        }
예제 #7
0
        public void LoadSymbolsSendsEvent()
        {
            var action = Substitute.For <IAction>();

            action.Record(Arg.Any <Func <bool> >()).Returns(true);
            _mockActionRecorder.CreateToolAction(ActionType.DebugModuleLoadSymbols).Returns(action);

            var task = Substitute.For <ICancelableTask <int> >();

            task.Result.Returns(VSConstants.S_OK);
            _mockCancelableTaskFactory.Create(Arg.Any <string>(), Arg.Any <Func <ICancelable, int> >())
            .Returns(task);

            _debugModule.LoadSymbols();

            _mockEngineHandler.Received(1).SendEvent(
                Arg.Is <DebugEvent>(e => e is IDebugSymbolSearchEvent2), _mockDebugProgram,
                (IDebugThread2)null);
        }
예제 #8
0
        public bool WaitUntilGameLaunched()
        {
            IAction         action = _actionRecorder.CreateToolAction(ActionType.GameLaunchWaitForStart);
            ICancelableTask pollForLaunchStatusTask = _cancelableTaskFactory.Create(
                TaskMessages.LaunchingGame,
                async task => await PollForLaunchStatusAsync(task, action));

            try
            {
                if (!pollForLaunchStatusTask.RunAndRecord(action))
                {
                    Trace.WriteLine("Polling for the launch status has been canceled by user.");
                    return(false);
                }
            }
            catch (Exception e) when(e is TimeoutException || e is GameLaunchFailError)
            {
                Trace.WriteLine(e.Message);
                _dialogUtil.ShowError(e.Message);
                return(false);
            }

            return(true);
        }
예제 #9
0
        public int LoadSymbols()
        {
            IAction action = _actionRecorder.CreateToolAction(ActionType.DebugModuleLoadSymbols);

            ICancelableTask <int> loadSymbolsTask = _cancelableTaskFactory.Create(
                "Loading symbols...",
                task => _moduleFileLoader.LoadModuleFilesAsync(new[] { _lldbModule }, task,
                                                               _moduleFileLoadRecorderFactory.Create(
                                                                   action)));

            if (!loadSymbolsTask.RunAndRecord(action))
            {
                return(VSConstants.E_ABORT);
            }

            _engineHandler.OnSymbolsLoaded(Self, ModuleName, null,
                                           loadSymbolsTask.Result == VSConstants.S_OK, _program);
            // Returning E_FAIL causes Visual Studio to show a file dialog when attached
            // to a running program or crash dump. This dialog can only be used to select PDB
            // files.
            return(loadSymbolsTask.Result == VSConstants.E_FAIL
                ? VSConstants.S_OK
                : loadSymbolsTask.Result);
        }
예제 #10
0
        public void RunComplete()
        {
            bool ranToCompletion = false;
            var  task            = taskFactory.Create(Text, t => {
                t.ThrowIfCancellationRequested();
                ranToCompletion = true;
            });

            Assert.IsTrue(task.Run());

            Assert.IsFalse(task.IsCanceled);
            Assert.IsTrue(ranToCompletion);
        }