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
19 changes: 19 additions & 0 deletions tests/cpp/test_testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

// standard includes
#include <cstdio>
#include <iostream>
#include <optional>
#include <string>
Expand All @@ -21,6 +22,8 @@ namespace {
using BaseTest::isOutputSuppressed;
using BaseTest::isSystemTest;
using BaseTest::skipTest;
using BaseTest::stderrBuffer;
using BaseTest::stdoutBuffer;
};

class EnvGuard {
Expand Down Expand Up @@ -67,6 +70,15 @@ namespace {
}
};

class StdioCaptureFixture: public TestableBaseTest {
protected:
void TearDown() override {
BaseTest::TearDown();
EXPECT_EQ(stdoutBuffer().str(), "captured stdout");
EXPECT_EQ(stderrBuffer().str(), "captured stderr");
}
};

class TestableBufferedTestEventListener: public BufferedTestEventListener {
public:
using BufferedTestEventListener::clearBufferedTestOutput;
Expand All @@ -86,6 +98,13 @@ TEST(TestingSupportTest, DefaultTestMacroUsesBaseFixture) {
EXPECT_EQ(cerrBuffer().str(), "captured cerr");
}

TEST_F(StdioCaptureFixture, CapturesStdoutAndStderr) {
std::printf("captured stdout");
std::fprintf(stderr, "captured stderr");
std::fflush(stdout);
std::fflush(stderr);
}

TEST(TestingSupportTest, ArgumentMatchingCanReturnFullArgument) {
EXPECT_TRUE(getArgWithMatchingPattern("--gtest_", false).has_value());
}
Expand Down
19 changes: 18 additions & 1 deletion tests/support/include/lizardbyte/common/testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace lizardbyte::common::testing {
/**
* @brief Base class used by default for shared tests.
*
* ``cout`` and ``cerr`` are redirected during tests and printed when a test fails.
* ``cout``, ``cerr``, ``stdout``, and ``stderr`` are redirected during tests and printed when a test fails.
*/
class BaseTest: public ::testing::Test {
protected:
Expand Down Expand Up @@ -85,12 +85,29 @@ namespace lizardbyte::common::testing {
*/
[[nodiscard]] std::stringstream &cerrBuffer();

/**
* @brief Get captured stdout.
* @return Captured stdout stream.
*/
[[nodiscard]] std::stringstream &stdoutBuffer();

/**
* @brief Get captured stderr.
* @return Captured stderr stream.
*/
[[nodiscard]] std::stringstream &stderrBuffer();

private:
std::stringstream cout_buffer_; /**< Stores cout while output is suppressed. */
std::stringstream cerr_buffer_; /**< Stores cerr while output is suppressed. */
std::stringstream stdout_buffer_; /**< Stores stdout while output is suppressed. */
std::stringstream stderr_buffer_; /**< Stores stderr while output is suppressed. */
std::streambuf *cout_streambuf_ {nullptr}; /**< Original cout stream buffer. */
std::streambuf *cerr_streambuf_ {nullptr}; /**< Original cerr stream buffer. */
bool test_skipped_at_setup_ {false}; /**< True when SetUp skipped before redirection. */
bool output_suppressed_ {false}; /**< True when output capture was enabled in SetUp. */
bool stdout_capture_active_ {false}; /**< True when GoogleTest stdout capture is active. */
bool stderr_capture_active_ {false}; /**< True when GoogleTest stderr capture is active. */
};

/**
Expand Down
54 changes: 51 additions & 3 deletions tests/support/testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
*/

// standard includes
#include <cstdio>
#include <iostream>
#include <iterator>
#include <regex>

// lib includes
#include <gtest/internal/gtest-port.h>

// platform includes
#if defined(__linux__)
#include <unistd.h>
Expand All @@ -19,17 +23,32 @@

namespace lizardbyte::common::testing {
void BaseTest::SetUp() {
test_skipped_at_setup_ = false;
output_suppressed_ = false;
stdout_capture_active_ = false;
stderr_capture_active_ = false;

cout_buffer_.str({});
cout_buffer_.clear();
cerr_buffer_.str({});
cerr_buffer_.clear();
stdout_buffer_.str({});
stdout_buffer_.clear();
stderr_buffer_.str({});
stderr_buffer_.clear();

if (const auto skip_reason {skipTest()}; !skip_reason.empty()) {
test_skipped_at_setup_ = true;
GTEST_SKIP() << skip_reason;
}

if (isOutputSuppressed()) {
output_suppressed_ = isOutputSuppressed();
if (output_suppressed_) {
::testing::internal::CaptureStdout();
stdout_capture_active_ = true;
::testing::internal::CaptureStderr();
stderr_capture_active_ = true;

cout_streambuf_ = std::cout.rdbuf();
cerr_streambuf_ = std::cerr.rdbuf();
std::cout.rdbuf(cout_buffer_.rdbuf());
Expand All @@ -42,7 +61,12 @@ namespace lizardbyte::common::testing {
return;
}

if (isOutputSuppressed()) {
if (output_suppressed_) {
std::cout.flush();
std::cerr.flush();
std::fflush(stdout);
std::fflush(stderr);

if (cout_streambuf_ != nullptr) {
std::cout.rdbuf(cout_streambuf_);
cout_streambuf_ = nullptr;
Expand All @@ -53,6 +77,16 @@ namespace lizardbyte::common::testing {
cerr_streambuf_ = nullptr;
}

if (stdout_capture_active_) {
stdout_buffer_ << ::testing::internal::GetCapturedStdout();
stdout_capture_active_ = false;
}

if (stderr_capture_active_) {
stderr_buffer_ << ::testing::internal::GetCapturedStderr();
stderr_capture_active_ = false;
}

const auto *test_info = ::testing::UnitTest::GetInstance()->current_test_info();
if (test_info != nullptr && test_info->result()->Failed()) {
std::cout << std::endl
Expand All @@ -61,8 +95,14 @@ namespace lizardbyte::common::testing {
<< "Captured cout:" << std::endl
<< cout_buffer_.str() << std::endl
<< "Captured cerr:" << std::endl
<< cerr_buffer_.str() << std::endl;
<< cerr_buffer_.str() << std::endl
<< "Captured stdout:" << std::endl
<< stdout_buffer_.str() << std::endl
<< "Captured stderr:" << std::endl
<< stderr_buffer_.str() << std::endl;
}

output_suppressed_ = false;
}
}

Expand Down Expand Up @@ -112,6 +152,14 @@ namespace lizardbyte::common::testing {
return cerr_buffer_;
}

std::stringstream &BaseTest::stdoutBuffer() {
return stdout_buffer_;
}

std::stringstream &BaseTest::stderrBuffer() {
return stderr_buffer_;
}

void LinuxTest::SetUp() {
#if !defined(__linux__)
GTEST_SKIP() << "Skipping, this test is for Linux only.";
Expand Down
Loading