Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 40 additions & 17 deletions src/xinterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,45 @@ namespace xcpp
return "unknown";
}

class SilentStreamRedirectRAII
Comment thread
anutosh491 marked this conversation as resolved.
{
public:

explicit SilentStreamRedirectRAII(bool silent)
: m_silent(silent)
, m_old_cout(silent ? std::cout.rdbuf() : nullptr)
, m_old_cerr(silent ? std::cerr.rdbuf() : nullptr)
{
if (m_silent)
{
std::cout.rdbuf(&m_null);
std::cerr.rdbuf(&m_null);
}
}

~SilentStreamRedirectRAII() noexcept
{
if (m_silent)
{
std::cout.rdbuf(m_old_cout);
std::cerr.rdbuf(m_old_cerr);
}
}

SilentStreamRedirectRAII(const SilentStreamRedirectRAII&) = delete;
SilentStreamRedirectRAII& operator=(const SilentStreamRedirectRAII&) = delete;
SilentStreamRedirectRAII(SilentStreamRedirectRAII&&) = delete;
SilentStreamRedirectRAII& operator=(SilentStreamRedirectRAII&&) = delete;

private:

bool m_silent;
xnull m_null;

std::streambuf* m_old_cout;
std::streambuf* m_old_cerr;
};

interpreter::interpreter(int argc, const char* const* argv) :
xmagics()
, p_cout_strbuf(nullptr)
Expand Down Expand Up @@ -288,16 +327,7 @@ namespace xcpp

// If silent is set to true, temporarily dismiss all std::cerr and
// std::cout outputs resulting from `process_code`.

auto cout_strbuf = std::cout.rdbuf();
auto cerr_strbuf = std::cerr.rdbuf();

if (config.silent)
{
auto null = xnull();
std::cout.rdbuf(&null);
std::cerr.rdbuf(&null);
}
SilentStreamRedirectRAII silent_guard(config.silent);

std::string err;

Expand Down Expand Up @@ -331,13 +361,6 @@ namespace xcpp
std::cout << std::flush;
std::cerr << std::flush;

// Reset non-silent output buffers
if (config.silent)
{
std::cout.rdbuf(cout_strbuf);
std::cerr.rdbuf(cerr_strbuf);
}

// Depending of error level, publish execution result or execution
// error, and compose execute_reply message.
if (errorlevel)
Expand Down
38 changes: 38 additions & 0 deletions test/test_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1229,3 +1229,41 @@ TEST_SUITE("mime_bundle_repr")
REQUIRE(res == expected);
}
}

#if !defined(__EMSCRIPTEN__)
// TODO: Currently any test added to this file will fail for the wasm build saying memory access out of bounds.
Comment thread
anutosh491 marked this conversation as resolved.
TEST_CASE("Silent mode restores std::cout and std::cerr buffers")
{
std::vector<const char*> Args = {};
xcpp::interpreter interpreter((int)Args.size(), Args.data());

auto* cout_before = std::cout.rdbuf();
auto* cerr_before = std::cerr.rdbuf();

xeus::execute_request_config config;
config.silent = true;
config.store_history = false;
config.allow_stdin = false;

nl::json header = nl::json::object();
xeus::xrequest_context::guid_list id = {};
xeus::xrequest_context context(header, id);

std::promise<nl::json> promise;
auto callback = [&promise](nl::json result) { promise.set_value(result); };

std::string code = R"(
#include <iostream>
std::cout << "hidden stdout\n";
std::cerr << "hidden stderr\n";
)";

interpreter.execute_request(context, callback, code, config, nl::json::object());

auto reply = promise.get_future().get();
REQUIRE(reply["status"] == "ok");

REQUIRE(std::cout.rdbuf() == cout_before);
REQUIRE(std::cerr.rdbuf() == cerr_before);
}
#endif
Loading