Skip to content

Commit

Permalink
feat: make system tests skipable via env (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
FrogTheFrog authored May 17, 2024
1 parent f7804cc commit 7db4252
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 63 deletions.
2 changes: 1 addition & 1 deletion cmake/Boost_DD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ include_guard(GLOBAL)

find_package(Boost 1.85)
if(NOT Boost_FOUND)
message(STATUS "Boost v1.85.x package not found in system. Falling back to Fetch.")
message(STATUS "Boost v1.85.x package not found in the system. Falling back to FetchContent.")
include(FetchContent)

# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
Expand Down
96 changes: 53 additions & 43 deletions tests/fixtures/fixtures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ BaseTest::BaseTest():

void
BaseTest::SetUp() {
if (const auto skip_reason { skipTest() }; !skip_reason.empty()) {
m_test_skipped_at_setup = true;
GTEST_SKIP() << skip_reason;
}

// todo: only run this one time, instead of every time a test is run
// see: https://stackoverflow.com/questions/2435277/googletest-accessing-the-environment-from-a-test
// get command line args from the test executable
Expand Down Expand Up @@ -38,6 +43,13 @@ BaseTest::SetUp() {

void
BaseTest::TearDown() {
if (m_test_skipped_at_setup) {
// We are not using the IsSkipped() state here. Here we are skipping
// teardown, because we have skipped the setup entirely, but during normal
// skips we still want to do teardown.
return;
}

display_device::Logger::get().setCustomCallback(nullptr); // restore the default callback to avoid potential leaks
std::cout.rdbuf(m_sbuf); // restore cout buffer

Expand Down Expand Up @@ -67,6 +79,28 @@ BaseTest::TearDown() {
}
}

bool
BaseTest::isSystemTest() const {
return false;
}

std::string
BaseTest::skipTest() const {
if (isSystemTest()) {
const static bool is_system_test_skippable {
[]() {
const auto value { getEnv("SKIP_SYSTEM_TESTS") };
return value == "1";
}()
};

if (is_system_test_skippable) {
return "Skipping, this system test is disabled via SKIP_SYSTEM_TESTS=1 env.";
}
}
return {};
}

int
BaseTest::exec(const char *cmd) {
std::array<char, 128> buffer {};
Expand All @@ -81,62 +115,38 @@ BaseTest::exec(const char *cmd) {
while (fgets(buffer.data(), buffer.size(), m_pipe_stderr) != nullptr) {
m_stderr_buffer << buffer.data();
}
int returnCode = pclose(m_pipe_stdout);
int return_code = pclose(m_pipe_stdout);
m_pipe_stdout = nullptr;
if (returnCode != 0) {
if (return_code != 0) {
std::cout << "Error: " << m_stderr_buffer.str() << std::endl
<< "Return code: " << returnCode << std::endl;
<< "Return code: " << return_code << std::endl;
}
return returnCode;
return return_code;
}

void
LinuxTest::SetUp() {
std::string
LinuxTest::skipTest() const {
#ifndef __linux__
GTEST_SKIP_("Skipping, this test is for Linux only.");
return "Skipping, this test is for Linux only.";
#else
return BaseTest::skipTest();
#endif
BaseTest::SetUp();
}

void
LinuxTest::TearDown() {
#ifndef __linux__
// This a noop case to skip the teardown
return;
#endif
BaseTest::TearDown();
}

void
MacOSTest::SetUp() {
#if !defined(__APPLE__) || !defined(__MACH__)
GTEST_SKIP_("Skipping, this test is for macOS only.");
#endif
BaseTest::SetUp();
}

void
MacOSTest::TearDown() {
std::string
MacOSTest::skipTest() const {
#if !defined(__APPLE__) || !defined(__MACH__)
// This a noop case to skip the teardown
return;
return "Skipping, this test is for macOS only.";
#else
return BaseTest::skipTest();
#endif
BaseTest::TearDown();
}

void
WindowsTest::SetUp() {
#ifndef _WIN32
GTEST_SKIP_("Skipping, this test is for Windows only.");
#endif
BaseTest::SetUp();
}

void
WindowsTest::TearDown() {
std::string
WindowsTest::skipTest() const {
#ifndef _WIN32
// This a noop case to skip the teardown
return;
return "Skipping, this test is for Windows only.";
#else
return BaseTest::skipTest();
#endif
BaseTest::TearDown();
}
39 changes: 24 additions & 15 deletions tests/fixtures/fixtures.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ class BaseTest: public ::testing::Test {
void
TearDown() override;

/**
* @brief Check if the test interacts/modifies with the system settings.
* @returns True if it does, false otherwise.
* @note By setting SKIP_SYSTEM_TESTS=1 env, these tests will be skipped (useful during development).
*/
[[nodiscard]] virtual bool
isSystemTest() const;

/**
* @brief Skip the test by specifying the reason.
* @returns A non-empty string (reason) if test needs to be skipped, empty string otherwise.
*/
[[nodiscard]] virtual std::string
skipTest() const;

int
exec(const char *cmd);

Expand All @@ -72,31 +87,25 @@ class BaseTest: public ::testing::Test {
std::streambuf *m_sbuf;
FILE *m_pipe_stdout;
FILE *m_pipe_stderr;

private:
bool m_test_skipped_at_setup { false };
};

class LinuxTest: public BaseTest {
protected:
void
SetUp() override;

void
TearDown() override;
[[nodiscard]] std::string
skipTest() const override;
};

class MacOSTest: public BaseTest {
protected:
void
SetUp() override;

void
TearDown() override;
[[nodiscard]] std::string
skipTest() const override;
};

class WindowsTest: public BaseTest {
protected:
void
SetUp() override;

void
TearDown() override;
[[nodiscard]] std::string
skipTest() const override;
};
11 changes: 11 additions & 0 deletions tests/fixtures/testutils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// header include
#include "testutils.h"

// system includes
#include <cstdlib>

// system includes
#include <iostream>
#include <regex>
Expand All @@ -26,3 +29,11 @@ setEnv(const std::string &name, const std::string &value) {
return setenv(name.c_str(), value.c_str(), 1);
#endif
}

std::optional<std::string>
getEnv(const std::string &name) {
if (const auto value { std::getenv(name.c_str()) }; value) {
return std::string { value };
}
return std::nullopt;
}
17 changes: 13 additions & 4 deletions tests/fixtures/testutils.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
#pragma once

// system includes
#include <optional>
#include <string>

/**
* @brief Test regular expression against string.
* @return True if string matches the regex, false otherwise
* @return True if string matches the regex, false otherwise.
*/
bool
testRegex(const std::string &test_pattern, const std::string &regex_pattern);

/**
* @brief Set an environment variable.
* @param name Name of the environment variable
* @param value Value of the environment variable
* @return 0 on success, non-zero error code on failure
* @param name Name of the environment variable.
* @param value Value of the environment variable.
* @return 0 on success, non-zero error code on failure.
*/
int
setEnv(const std::string &name, const std::string &value);

/**
* @brief Get an environment variable.
* @param name Name of the environment variable.
* @return String value of the variable or an empty optional otherwise.
*/
std::optional<std::string>
getEnv(const std::string &name);
5 changes: 5 additions & 0 deletions tests/unit/windows/test_windisplaydevicetopology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ namespace {
// Test fixture(s) for this file
class WinDisplayDeviceTopology: public BaseTest {
public:
bool
isSystemTest() const override {
return true;
}

std::optional<std::vector<std::string>>
getAvailableDevices() {
const auto all_devices { m_layer->queryDisplayConfig(display_device::QueryType::All) };
Expand Down

0 comments on commit 7db4252

Please sign in to comment.