Exemple #1
0
        public void SetUp()
        {
            _targetPath = "/any/old/target/path";
            var fileSystem = new MockFileSystem();

            fileSystem.AddFile(_targetPath, new MockFileData(""));

            _outputDirectory = Path.GetTempPath();

            _project = Substitute.For <IAsyncProject>();
            _project.GetTargetPathAsync().Returns(_targetPath);
            _project.GetTargetDirectoryAsync().Returns(Path.GetDirectoryName(_targetPath));
            _project.GetTargetFileNameAsync().Returns(Path.GetFileName(_targetPath));
            _project.GetOutputDirectoryAsync().Returns(_outputDirectory);
            _project.GetAbsoluteRootPathAsync().Returns(_testProjectDir);
            _project.GetApplicationAsync().Returns(_testApplicationName);
            _project.GetQueryParamsAsync().Returns(_customQueryParams);

            var sdkConfigFactory = Substitute.For <SdkConfig.Factory>();
            var sdkConfig        = new SdkConfig();

            sdkConfig.OrganizationId = _testOrganizationId;
            sdkConfig.ProjectId      = _testProjectId;
            sdkConfigFactory.LoadOrDefault().Returns(sdkConfig);

            _gameletClient = Substitute.For <IGameletClient>();
            var gameletClientFactory = Substitute.For <GameletClient.Factory>();

            gameletClientFactory.Create(Arg.Any <ICloudRunner>()).Returns(_gameletClient);

            var remoteCommand = Substitute.For <IRemoteCommand>();

            _remoteDeploy = Substitute.For <IRemoteDeploy>();
            _dialogUtil   = Substitute.For <IDialogUtil>();

            var credentialManager = Substitute.For <YetiCommon.ICredentialManager>();

            credentialManager.LoadAccount().Returns(_testAccount);

            var cancelableTaskFactory =
                FakeCancelableTask.CreateFactory(new JoinableTaskContext(), false);

            _applicationClient = Substitute.For <IApplicationClient>();
            var application = new Application
            {
                Id = _testApplicationId, Name = _testApplicationName
            };

            _applicationClient.LoadByNameOrIdAsync(_testApplicationName)
            .Returns(Task.FromResult(application));
            var applicationClientFactory = Substitute.For <ApplicationClient.Factory>();

            applicationClientFactory.Create(Arg.Any <ICloudRunner>()).Returns(_applicationClient);

            _testAccountClientFactory = Substitute.For <TestAccountClient.Factory>();
            var testAccount = new TestAccount()
            {
                Name = $"organizations/{_testOrganizationId}" +
                       $"/projects/{_testProjectId}/testAccounts/{_testTestAccountId}"
            };
            var testAccountClient = Substitute.For <ITestAccountClient>();

            testAccountClient
            .LoadByIdOrGamerTagAsync(_testOrganizationId, _testProjectId, _testTestAccountId)
            .Returns(new List <TestAccount> {
                testAccount
            });
            _testAccountClientFactory.Create(Arg.Any <ICloudRunner>()).Returns(testAccountClient);

            Substitute.For <IExtensionOptions>();

            _yetiVsiService = Substitute.For <IYetiVSIService>();
            var options         = Substitute.For <IExtensionOptions>();
            var debuggerOptions = new YetiVSI.DebuggerOptions.DebuggerOptions();

            _yetiVsiService.DebuggerOptions.Returns(debuggerOptions);
            options.LaunchGameApiFlow.Returns(LaunchGameApiFlow.DISABLED);
            _yetiVsiService.Options.Returns(options);
            _metrics = Substitute.For <IMetrics>();
            _metrics.NewDebugSessionId().Returns(_testDebugSessionId);
            var debugMetrics = new DebugSessionMetrics(_metrics);
            var cloudRunner  = new CloudRunner(sdkConfigFactory, credentialManager,
                                               new CloudConnection(), new GgpSDKUtil());

            _gameletSelector        = Substitute.For <IGameletSelector>();
            _gameletSelectorFactory = Substitute.For <IGameletSelectorFactory>();
            _gameletSelectorFactory.Create(Arg.Any <bool>(), Arg.Any <ActionRecorder>())
            .Returns(_gameletSelector);
            var serializer = new JsonUtil();

            _launchCommandFormatter = new ChromeClientLaunchCommandFormatter(serializer);
            _paramsFactory          = new YetiVSI.DebugEngine.DebugEngine.Params.Factory(serializer);

            _gameLauncher = Substitute.For <IGameLauncher>();
            _gameLauncher.LaunchGameApiEnabled.Returns(false);
            _gameLaunch = Substitute.For <IVsiGameLaunch>();
            _gameLaunch.LaunchName.Returns("launch_name");
            _ggpDebugQueryTarget = new GgpDebugQueryTarget(fileSystem, sdkConfigFactory,
                                                           gameletClientFactory,
                                                           applicationClientFactory,
                                                           cancelableTaskFactory, _dialogUtil,
                                                           _remoteDeploy, debugMetrics,
                                                           credentialManager,
                                                           _testAccountClientFactory,
                                                           _gameletSelectorFactory, cloudRunner,
                                                           _sdkVersion, _launchCommandFormatter,
                                                           _paramsFactory, _yetiVsiService,
                                                           _gameLauncher);
        }
        public async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync(
            IAsyncProject project, DebugLaunchOptions launchOptions)
        {
            try
            {
                // Make sure we can find the target executable.
                var targetPath = await project.GetTargetPathAsync();

                if (!_fileSystem.File.Exists(targetPath))
                {
                    Trace.WriteLine($"Unable to find target executable: {targetPath}");
                    _dialogUtil.ShowError(ErrorStrings.UnableToFindTargetExecutable(targetPath));
                    return(new IDebugLaunchSettings[] { });
                }

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

                var targetFileName = await project.GetTargetFileNameAsync();

                var gameletCommand = (targetFileName + " " +
                                      await project.GetGameletLaunchArgumentsAsync()).Trim();

                var launchParams = new LaunchParams()
                {
                    Cmd       = gameletCommand,
                    RenderDoc = await project.GetLaunchRenderDocAsync(),
                    Rgp       = await project.GetLaunchRgpAsync(),
                    SurfaceEnforcementMode = await project.GetSurfaceEnforcementAsync(),
                    VulkanDriverVariant    = await project.GetVulkanDriverVariantAsync(),
                    QueryParams            = await project.GetQueryParamsAsync(),
                    Endpoint = await project.GetEndpointAsync()
                };

                if (_sdkVersion != null && !string.IsNullOrEmpty(_sdkVersion.ToString()))
                {
                    launchParams.SdkVersion = _sdkVersion.ToString();
                }

                if (!TrySetupQueries(project, actionRecorder,
                                     out SetupQueriesResult setupQueriesResult))
                {
                    return(new IDebugLaunchSettings[] { });
                }

                launchParams.ApplicationName = setupQueriesResult.Application.Name;
                launchParams.ApplicationId   = setupQueriesResult.Application.Id;
                if (setupQueriesResult.TestAccount != null)
                {
                    launchParams.TestAccount          = setupQueriesResult.TestAccount.Name;
                    launchParams.TestAccountGamerName =
                        setupQueriesResult.TestAccount.GamerStadiaName;
                }

                DeployOnLaunchSetting deployOnLaunchAsync = await project.GetDeployOnLaunchAsync();

                launchParams.Account = _credentialManager.LoadAccount();

                // TODO: Enable PlayerEndpoint Launches for non-internal usage in VS.
                if (launchParams.Endpoint == StadiaEndpoint.PlayerEndpoint &&
                    launchParams.Account != null &&
                    !launchParams.Account.EndsWith("@sparklingsunset.com") &&
                    !launchParams.Account.EndsWith("@subtlesunset.com"))
                {
                    throw new NotImplementedException(
                              "Player Endpoints are not yet supported, please select " +
                              "Test Client in the Project Properties instead.");
                }

                // TODO: Enable launch on any endpoint for external accounts.
                if (launchParams.Endpoint == StadiaEndpoint.AnyEndpoint &&
                    launchParams.Account != null &&
                    !launchParams.Account.EndsWith("@sparklingsunset.com") &&
                    !launchParams.Account.EndsWith("@subtlesunset.com"))
                {
                    throw new NotImplementedException(
                              "Launch on any player endpoint is not supported yet, please select " +
                              "another endpoint in the Project Properties instead.");
                }

                bool launchGameApiEnabled =
                    _yetiVsiService.Options.LaunchGameApiFlow == LaunchGameApiFlow.ENABLED;
                IGameletSelector gameletSelector =
                    _gameletSelectorFactory.Create(launchGameApiEnabled, actionRecorder);
                if (!gameletSelector.TrySelectAndPrepareGamelet(
                        targetPath, deployOnLaunchAsync, setupQueriesResult.Gamelets,
                        setupQueriesResult.TestAccount, launchParams.Account, out Gamelet gamelet))
                {
                    return(new IDebugLaunchSettings[] { });
                }

                launchParams.GameletName            = gamelet.Name;
                launchParams.PoolId                 = gamelet.PoolId;
                launchParams.GameletSdkVersion      = gamelet.GameletVersions.DevToolingVersion;
                launchParams.GameletEnvironmentVars =
                    await project.GetGameletEnvironmentVariablesAsync();

                // Prepare for debug launch using these settings.
                var debugLaunchSettings = new DebugLaunchSettings(launchOptions);
                debugLaunchSettings.Environment["PATH"] = await project.GetExecutablePathAsync();

                debugLaunchSettings.LaunchOperation  = DebugLaunchOperation.CreateProcess;
                debugLaunchSettings.CurrentDirectory = await project.GetAbsoluteRootPathAsync();

                if (!launchOptions.HasFlag(DebugLaunchOptions.NoDebug))
                {
                    var parameters = _paramsFactory.Create();
                    parameters.TargetIp         = new SshTarget(gamelet).GetString();
                    parameters.DebugSessionId   = _metrics.DebugSessionId;
                    debugLaunchSettings.Options = _paramsFactory.Serialize(parameters);
                }

                IAction action     = actionRecorder.CreateToolAction(ActionType.RemoteDeploy);
                bool    isDeployed = _cancelableTaskFactory.Create(
                    TaskMessages.DeployingExecutable, async task =>
                {
                    await _remoteDeploy.DeployGameExecutableAsync(
                        project, new SshTarget(gamelet), task, action);
                    task.Progress.Report(TaskMessages.CustomDeployCommand);
                    await _remoteDeploy.ExecuteCustomCommandAsync(project, gamelet, action);
                }).RunAndRecord(action);

                if (!isDeployed)
                {
                    return(new IDebugLaunchSettings[] { });
                }

                if (launchOptions.HasFlag(DebugLaunchOptions.NoDebug))
                {
                    if (_gameLauncher.LaunchGameApiEnabled ||
                        launchParams.Endpoint == StadiaEndpoint.PlayerEndpoint ||
                        launchParams.Endpoint == StadiaEndpoint.AnyEndpoint)
                    {
                        IVsiGameLaunch launch = _gameLauncher.CreateLaunch(launchParams);
                        if (launch != null)
                        {
                            debugLaunchSettings.Arguments =
                                _launchCommandFormatter.CreateWithLaunchName(
                                    launchParams, launch.LaunchName);
                        }
                        else
                        {
                            Trace.WriteLine("Unable to retrieve launch name from the launch api.");
                            return(new IDebugLaunchSettings[] { });
                        }
                    }
                    else
                    {
                        debugLaunchSettings.Arguments =
                            _launchCommandFormatter.CreateFromParams(launchParams);
                    }

                    debugLaunchSettings.Executable =
                        Path.Combine(Environment.SystemDirectory, YetiConstants.Command);

                    debugLaunchSettings.LaunchOptions = DebugLaunchOptions.NoDebug |
                                                        DebugLaunchOptions.MergeEnvironment;
                }
                else
                {
                    if (_yetiVsiService.DebuggerOptions[DebuggerOption.SKIP_WAIT_LAUNCH] ==
                        DebuggerOptionState.DISABLED)
                    {
                        launchParams.Debug = true;
                    }

                    // TODO: This should really be the game_client executable, since
                    // the args we pass are for game_client as well.  We just need to find another
                    // way to pass the game executable.
                    debugLaunchSettings.Executable            = targetPath;
                    debugLaunchSettings.LaunchDebugEngineGuid = YetiConstants.DebugEngineGuid;
                    debugLaunchSettings.Arguments             =
                        _launchCommandFormatter.EncodeLaunchParams(launchParams);
                    debugLaunchSettings.LaunchOptions = DebugLaunchOptions.MergeEnvironment;
                }

                return(new IDebugLaunchSettings[] { debugLaunchSettings });
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.ToString());
                _dialogUtil.ShowError(e.Message, e.ToString());
                return(new IDebugLaunchSettings[] { });
            }
        }