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; }; }
public ServerInfo(PipeServiceBinder server, PipeCallInvoker callInvoker, GrpcConnection connection, RemoteObjectStores stores, LldbMockFactories mockFactories) { Server = server; CallInvoker = callInvoker; Connection = connection; Stores = stores; MockFactories = mockFactories; }
// 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; } }
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); }
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)); }
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>(); }
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)); }