Add --record in favor of --log-stdin-stdout-to-stderr.

This should be more useful and can hopefully be adapted to writing tests.
This commit is contained in:
Jacob Dufault 2018-02-06 20:27:30 -08:00
parent 4916c61182
commit 0cfb5391d1
5 changed files with 75 additions and 23 deletions

View File

@ -18,6 +18,7 @@
#include "query.h" #include "query.h"
#include "query_utils.h" #include "query_utils.h"
#include "queue_manager.h" #include "queue_manager.h"
#include "recorder.h"
#include "semantic_highlight_symbol_cache.h" #include "semantic_highlight_symbol_cache.h"
#include "serializer.h" #include "serializer.h"
#include "serializers/json.h" #include "serializers/json.h"
@ -56,9 +57,6 @@ namespace {
std::vector<std::string> kEmptyArgs; std::vector<std::string> kEmptyArgs;
// If true stdout will be printed to stderr.
bool g_log_stdin_stdout_to_stderr = false;
// This function returns true if e2e timing should be displayed for the given // This function returns true if e2e timing should be displayed for the given
// IpcId. // IpcId.
bool ShouldDisplayIpcTiming(IpcId id) { bool ShouldDisplayIpcTiming(IpcId id) {
@ -96,8 +94,8 @@ Other command line options:
--init <initializationOptions> --init <initializationOptions>
Override client provided initialization options Override client provided initialization options
https://github.com/cquery-project/cquery/wiki/Initialization-options https://github.com/cquery-project/cquery/wiki/Initialization-options
--log-stdin-stdout-to-stderr --record <path>
Print stdin (requests) and stdout (responses) to stderr Writes stdin to <path>.in and stdout to <path>.out
--log-file <path> Logging file for diagnostics --log-file <path> Logging file for diagnostics
--log-all-to-stderr Write all log messages to STDERR. --log-all-to-stderr Write all log messages to STDERR.
--wait-for-input Wait for an '[Enter]' before exiting --wait-for-input Wait for an '[Enter]' before exiting
@ -273,8 +271,7 @@ void LaunchStdinLoop(Config* config,
while (true) { while (true) {
std::unique_ptr<BaseIpcMessage> message; std::unique_ptr<BaseIpcMessage> message;
optional<std::string> err = optional<std::string> err =
MessageRegistry::instance()->ReadMessageFromStdin( MessageRegistry::instance()->ReadMessageFromStdin(&message);
g_log_stdin_stdout_to_stderr, &message);
// Message parsing can fail if we don't recognize the method. // Message parsing can fail if we don't recognize the method.
if (err) { if (err) {
@ -381,10 +378,7 @@ void LaunchStdoutThread(std::unordered_map<IpcId, Timer>* request_times,
std::string(IpcIdToString(message.id))); std::string(IpcIdToString(message.id)));
} }
if (g_log_stdin_stdout_to_stderr) { RecordOutput(message.content);
std::cerr << "[COUT] |" << message.content << "|\n";
std::cerr.flush();
}
std::cout << message.content; std::cout << message.content;
std::cout.flush(); std::cout.flush();
@ -460,8 +454,8 @@ int main(int argc, char** argv) {
loguru::Verbosity_MAX); loguru::Verbosity_MAX);
} }
if (HasOption(options, "--log-stdin-stdout-to-stderr")) if (HasOption(options, "--record"))
g_log_stdin_stdout_to_stderr = true; EnableRecording(options["--record"]);
if (HasOption(options, "--clang-sanity-check")) { if (HasOption(options, "--clang-sanity-check")) {
language_server = false; language_server = false;

View File

@ -1,5 +1,6 @@
#include "language_server_api.h" #include "language_server_api.h"
#include "recorder.h"
#include "serializers/json.h" #include "serializers/json.h"
#include <doctest/doctest.h> #include <doctest/doctest.h>
@ -65,6 +66,8 @@ optional<std::string> ReadJsonRpcContentFrom(
content += *c; content += *c;
} }
RecordInput(content);
return content; return content;
} }
@ -119,7 +122,6 @@ optional<char> ReadCharFromStdinBlocking() {
} }
optional<std::string> MessageRegistry::ReadMessageFromStdin( optional<std::string> MessageRegistry::ReadMessageFromStdin(
bool log_stdin_to_stderr,
std::unique_ptr<BaseIpcMessage>* message) { std::unique_ptr<BaseIpcMessage>* message) {
optional<std::string> content = optional<std::string> content =
ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking); ReadJsonRpcContentFrom(&ReadCharFromStdinBlocking);
@ -128,14 +130,6 @@ optional<std::string> MessageRegistry::ReadMessageFromStdin(
exit(1); exit(1);
} }
if (log_stdin_to_stderr) {
// TODO: This should go inside of ReadJsonRpcContentFrom since it does not
// print the header.
std::string printed = "[CIN] |" + *content + "|\n";
std::cerr << printed;
std::cerr.flush();
}
rapidjson::Document document; rapidjson::Document document;
document.Parse(content->c_str(), content->length()); document.Parse(content->c_str(), content->length());
assert(!document.HasParseError()); assert(!document.HasParseError());

View File

@ -43,7 +43,6 @@ struct MessageRegistry {
std::unordered_map<std::string, Allocator> allocators; std::unordered_map<std::string, Allocator> allocators;
optional<std::string> ReadMessageFromStdin( optional<std::string> ReadMessageFromStdin(
bool log_stdin_to_stderr,
std::unique_ptr<BaseIpcMessage>* message); std::unique_ptr<BaseIpcMessage>* message);
optional<std::string> Parse(Reader& visitor, optional<std::string> Parse(Reader& visitor,
std::unique_ptr<BaseIpcMessage>* message); std::unique_ptr<BaseIpcMessage>* message);

56
src/recorder.cc Normal file
View File

@ -0,0 +1,56 @@
#include "recorder.h"
#include <loguru.hpp>
#include <cassert>
#include <fstream>
namespace {
std::ofstream* g_file_in = nullptr;
std::ofstream* g_file_out = nullptr;
} // namespace
void EnableRecording(std::string path) {
if (path.empty())
path = "cquery";
// We can only call |EnableRecording| once.
assert(!g_file_in && !g_file_out);
// Open the files.
g_file_in = new std::ofstream(path + ".in",
std::ios::out | std::ios::trunc | std::ios::binary);
g_file_out = new std::ofstream(path + ".out",
std::ios::out | std::ios::trunc | std::ios::binary);
// Make sure we can write to the files.
bool bad = false;
if (!g_file_in->good()) {
LOG_S(ERROR) << "record: cannot write to " << path << ".in";
bad = true;
}
if (!g_file_out->good()) {
LOG_S(ERROR) << "record: cannot write to " << path << ".out";
bad = true;
}
if (bad) {
delete g_file_in;
delete g_file_out;
g_file_in = nullptr;
g_file_out = nullptr;
}
}
void RecordInput(std::string_view content) {
if (!g_file_in)
return;
(*g_file_in) << "Content-Length: " << content.size() << "\r\n\r\n" << content;
(*g_file_in).flush();
}
void RecordOutput(std::string_view content) {
if (!g_file_out)
return;
(*g_file_out) << content;
(*g_file_out).flush();
}

9
src/recorder.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include <string_view.h>
#include <string>
void EnableRecording(std::string path);
void RecordInput(std::string_view content);
void RecordOutput(std::string_view content);