Index: ClangdLSPServer.h =================================================================== --- ClangdLSPServer.h +++ ClangdLSPServer.h @@ -43,7 +43,7 @@ /// each instance of ClangdLSPServer. /// /// \return Whether we received a 'shutdown' request before an 'exit' request. - bool run(std::FILE *In, + bool run(std::FILE *In, bool TestMode, JSONStreamStyle InputStyle = JSONStreamStyle::Standard); private: Index: ClangdLSPServer.cpp =================================================================== --- ClangdLSPServer.cpp +++ ClangdLSPServer.cpp @@ -447,7 +447,8 @@ CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()), Server(CDB.getCDB(), FSProvider, /*DiagConsumer=*/*this, Opts) {} -bool ClangdLSPServer::run(std::FILE *In, JSONStreamStyle InputStyle) { +bool ClangdLSPServer::run(std::FILE *In, bool TestMode, + JSONStreamStyle InputStyle) { assert(!IsDone && "Run was called before"); // Set up JSONRPCDispatcher. @@ -457,7 +458,7 @@ registerCallbackHandlers(Dispatcher, /*Callbacks=*/*this); // Run the Language Server loop. - runLanguageServerLoop(In, Out, InputStyle, Dispatcher, IsDone); + runLanguageServerLoop(In, Out, InputStyle, Dispatcher, IsDone, TestMode); // Make sure IsDone is set to true after this method exits to ensure assertion // at the start of the method fires if it's ever executed again. Index: JSONRPCDispatcher.h =================================================================== --- JSONRPCDispatcher.h +++ JSONRPCDispatcher.h @@ -109,7 +109,8 @@ /// with signals, which are sent by debuggers on some OSs. void runLanguageServerLoop(std::FILE *In, JSONOutput &Out, JSONStreamStyle InputStyle, - JSONRPCDispatcher &Dispatcher, bool &IsDone); + JSONRPCDispatcher &Dispatcher, bool &IsDone, + bool TestMode); } // namespace clangd } // namespace clang Index: JSONRPCDispatcher.cpp =================================================================== --- JSONRPCDispatcher.cpp +++ JSONRPCDispatcher.cpp @@ -342,8 +342,8 @@ // The C APIs seem to be clearer in this respect. void clangd::runLanguageServerLoop(std::FILE *In, JSONOutput &Out, JSONStreamStyle InputStyle, - JSONRPCDispatcher &Dispatcher, - bool &IsDone) { + JSONRPCDispatcher &Dispatcher, bool &IsDone, + bool TestMode) { auto &ReadMessage = (InputStyle == Delimited) ? readDelimitedMessage : readStandardMessage; while (!IsDone && !feof(In)) { @@ -362,6 +362,8 @@ // Parse error. Log the raw message. vlog("<<< {0}\n", *JSON); elog("JSON parse error: {0}", llvm::toString(Doc.takeError())); + if (TestMode) + exit(EXIT_FAILURE); } } } Index: tool/ClangdMain.cpp =================================================================== --- tool/ClangdMain.cpp +++ tool/ClangdMain.cpp @@ -308,5 +308,6 @@ llvm::set_thread_name("clangd.main"); // Change stdin to binary to not lose \r\n on windows. llvm::sys::ChangeStdinToBinary(); - return LSPServer.run(stdin, InputStyle) ? 0 : NoShutdownRequestErrorCode; + return LSPServer.run(stdin, Test, InputStyle) ? 0 + : NoShutdownRequestErrorCode; }