コード例 #1
0
        public void SetUp()
        {
            taskContext = new JoinableTaskContext();
            mockMemoryMappedFileFactory = Substitute.For <MemoryMappedFileFactory>();
            transportSessionFactory     = new LldbTransportSession.Factory(mockMemoryMappedFileFactory);
            mockManagedProcessFactory   = Substitute.For <ManagedProcess.Factory>();
            mockGrpcCallInvoker         = Substitute.ForPartsOf <PipeCallInvoker>(_numGrpcPipePairs);
            mockGrpcCallInvokerFactory  = Substitute.For <PipeCallInvokerFactory>();
            mockGrpcCallInvokerFactory.Create().Returns(mockGrpcCallInvoker);
            mockGrpcConnectionFactory = Substitute.For <GrpcConnectionFactory>();
            optionPageGrid            = Substitute.For <IExtensionOptions>();
            service = new YetiVSIService(optionPageGrid);
            var mockVsOutputWindow = Substitute.For <IVsOutputWindow>();

            mockDialogUtil     = Substitute.For <IDialogUtil>();
            yetiDebugTransport = new YetiDebugTransport(taskContext, transportSessionFactory,
                                                        mockGrpcCallInvokerFactory,
                                                        mockGrpcConnectionFactory,
                                                        onAsyncRpcCompleted: null,
                                                        managedProcessFactory:
                                                        mockManagedProcessFactory,
                                                        dialogUtil: mockDialogUtil,
                                                        vsOutputWindow: mockVsOutputWindow,
                                                        yetiVSIService: service);

            abortError = null;
            yetiDebugTransport.OnStop += e => { abortError = e; };
        }
コード例 #2
0
 public ServerInfo(PipeServiceBinder server, PipeCallInvoker callInvoker,
                   GrpcConnection connection, RemoteObjectStores stores,
                   LldbMockFactories mockFactories)
 {
     Server        = server;
     CallInvoker   = callInvoker;
     Connection    = connection;
     Stores        = stores;
     MockFactories = mockFactories;
 }
コード例 #3
0
 // Exits and disposes of all processes, the TransportSession, and GrpcConnection.
 public void Stop(ExitReason exitReason)
 {
     lock (thisLock)
     {
         // Stop the grpc connection first because it depends on the the grpc server process
         // that is managed by the process manager.
         grpcConnection?.Shutdown();
         grpcConnection = null;
         grpcCallInvoker?.Dispose();
         grpcCallInvoker = null;
         transportSession?.Dispose();
         transportSession = null;
         processManager?.StopAll(exitReason);
         processManager = null;
     }
 }
コード例 #4
0
        public void SetUp()
        {
            invoker = new PipeCallInvoker(NUM_PIPE_PAIRS);

            clientInPipes    = new AnonymousPipeClientStream[NUM_PIPE_PAIRS];
            clientOutPipes   = new AnonymousPipeClientStream[NUM_PIPE_PAIRS];
            stringMarshaller = new Marshaller <string>((message, context) =>
            {
                byte[] bytes = Encoding.ASCII.GetBytes(message);
                context.SetPayloadLength(bytes.Length);
                context.GetBufferWriter().Write(bytes);
                context.Complete();
            }, context => Encoding.ASCII.GetString(context.PayloadAsReadOnlySequence().ToArray()));

            stringMethod = new Method <string, string>(MethodType.Unary, "ServiceName", "MethodName",
                                                       stringMarshaller, stringMarshaller);
        }
コード例 #5
0
        private ServerInfo CreateServer(
            PipeCallInvokerFactory callInvokerFactory, GrpcConnectionFactory connectionFactory)
        {
            PipeCallInvoker callInvoker = callInvokerFactory.Create();
            GrpcConnection  connection  = connectionFactory.Create(callInvoker);

            string[] inPipeHandles, outPipeHandles;
            callInvoker.GetClientPipeHandles(out inPipeHandles, out outPipeHandles);

            // Note: The client's out handles are the server's in handles and vice versa.
            PipeServiceBinder server = new PipeServiceBinder(outPipeHandles, inPipeHandles);
            var stores        = new RemoteObjectStores();
            var mockFactories = new LldbMockFactories();

            BindServices(server, stores, mockFactories);
            server.Start();
            return(new ServerInfo(server, callInvoker, connection, stores, mockFactories));
        }
コード例 #6
0
        public void SetUp()
        {
            var taskContext = new JoinableTaskContext();
            PipeCallInvokerFactory callInvokerFactory = new PipeCallInvokerFactory();
            PipeCallInvoker        callInvoker        = callInvokerFactory.Create();

            _grpcConnection  = new GrpcConnection(taskContext.Factory, callInvoker);
            _callback        = Substitute.For <IDebugEventCallback2>();
            _debuggerOptions = new YetiVSI.DebuggerOptions.DebuggerOptions
            {
                [DebuggerOption.CLIENT_LOGGING] = DebuggerOptionState.DISABLED
            };
            _libPaths = new HashSet <string> {
                "some/path", "some/other/path", _gameBinary
            };
            _programId   = Guid.Empty;
            _task        = Substitute.For <ICancelable>();
            _process     = new DebugProcessStub(enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM, _pid);
            _fileSystem  = new MockFileSystem();
            _debugEngine = Substitute.For <IDebugEngine3>();
            _gameLaunch  = Substitute.For <IVsiGameLaunch>();
        }
コード例 #7
0
        ProcessStartData CreateDebuggerGrpcServerProcessStartData()
        {
            var startInfo = new ProcessStartInfo
            {
                FileName = Path.Combine(YetiConstants.RootDir,
                                        YetiConstants.DebuggerGrpcServerExecutable),
            };

            // (internal): grpcCallInvoker must be created right before the process is created!
            // If it is created before the other processes are created, they'll hold on to the
            // pipes and they won't get closed if the GRPC server shuts down.
            Action <ProcessStartInfo> beforeStart = (processStartInfo) =>
            {
                grpcCallInvoker                   = grpcCallInvokerFactory.Create();
                grpcConnection                    = grpcConnectionFactory.Create(grpcCallInvoker);
                grpcConnection.RpcException      += StopWithException;
                grpcConnection.AsyncRpcCompleted += onAsyncRpcCompleted;

                grpcCallInvoker.GetClientPipeHandles(out string[] inPipeHandles,
                                                     out string[] outPipeHandles);

                // Note: The server's input pipes are the client's output pipes and vice versa.
                processStartInfo.Arguments = $"-i {string.Join(",", outPipeHandles)} " +
                                             $"-o {string.Join(",", inPipeHandles)}";
            };

            // Dispose client handles right after start. This is necessary so that pipes are closed
            // when the server exits.
            Action afterStart = () => { grpcCallInvoker.DisposeLocalCopyOfClientPipeHandles(); };

            var rootDir = YetiConstants.RootDir;

#if USE_LOCAL_PYTHON_AND_TOOLCHAIN
            // This is gated by the <DeployPythonAndToolchainDependencies> project setting to speed
            // up the build.
            var pythonRoot   = File.ReadAllText(Path.Combine(rootDir, "local_python_dir.txt")).Trim();
            var toolchainDir = File.ReadAllText(Path.Combine(rootDir, "local_toolchain_dir.txt"))
                               .Trim();
            var lldbSitePackagesDir = Path.Combine(toolchainDir, "windows", "lib", "site-packages");
            var libLldbDir          = Path.Combine(toolchainDir, "windows", "bin");

            // Quick sanity check that all directories exist.
            var notFoundDir = !Directory.Exists(pythonRoot) ? pythonRoot :
                              !Directory.Exists(lldbSitePackagesDir) ? lldbSitePackagesDir :
                              !Directory.Exists(libLldbDir) ? libLldbDir : null;
            if (!string.IsNullOrEmpty(notFoundDir))
            {
                // Note: This error is only shown to internal VSI devs, not to external devs.
                throw new YetiDebugTransportException(
                          "You have set the <DeployPythonAndToolchainDependencies> project setting to " +
                          $"False to speed up deployment, but the Python/toolchain dir {notFoundDir} " +
                          "moved. Either fix the wrong directory (preferred) or set " +
                          "<DeployPythonAndToolchainDependencies> to False.");
            }
#else
            var pythonRoot          = Path.Combine(rootDir, "Python3");
            var lldbSitePackagesDir = Path.Combine(YetiConstants.LldbDir, "site-packages");
            var libLldbDir          = Path.Combine(YetiConstants.LldbDir, "bin");
#endif

            // Search paths for dLLs.
            startInfo.Environment["PATH"] = string.Join(";", new string[]
            {
                rootDir,
                pythonRoot,
                libLldbDir
            });

            // Search paths for Python files.
            startInfo.Environment["PYTHONPATH"] = string.Join(";", new string[]
            {
                Path.Combine(pythonRoot, "Lib"),
                lldbSitePackagesDir
            });

            // Do not display console windows when launching processes. In our case,
            // we do not want the scp process to show the console window.
            startInfo.Environment["LLDB_LAUNCH_INFERIORS_WITHOUT_CONSOLE"] = "true";

            Trace.WriteLine($"Starting {startInfo.FileName} with" + Environment.NewLine +
                            $"\tPATH={(startInfo.Environment["PATH"])}" + Environment.NewLine +
                            $"\tPYTHONPATH={(startInfo.Environment["PYTHONPATH"])}");

            // Use the directory with the binary as working directory. Normally it doesn't matter,
            // because the server doesn't load any files via relative paths and the dependent DLLs
            // are available via PATH and PYTHONPATH. However when debugging or just running the
            // extension from Visual Studio the working directory is set to the output build
            // directory. The working directory has precedence for loading DLLs, so liblldb.dll is
            // picked up from the build output directory, NOT the deployed extension.
            startInfo.WorkingDirectory = Path.GetDirectoryName(startInfo.FileName);

            // Uncomment to enable GRPC debug logging for DebuggerGrpcServer.exe.
            // This is currently very verbose, and you will most likely want to restrict logging to
            // a subset.
            //
            //lldbGrpcStartInfo.EnvironmentVariables["GRPC_TRACE"] = "all";
            //lldbGrpcStartInfo.EnvironmentVariables["GRPC_VERBOSITY"] = "DEBUG";
            return(new ProcessStartData("lldb grpc server", startInfo, beforeStart: beforeStart,
                                        afterStart: afterStart));
        }