build(docs): add cmake target for docs (#2748)

This commit is contained in:
ReenigneArcher 2024-06-24 12:12:31 -04:00 committed by GitHub
commit 4683bcaf36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 176 additions and 315 deletions

View file

@ -3,9 +3,6 @@ cmake_minimum_required(VERSION 3.13)
project(test_sunshine)
set(PYTHON_PREFERRED_VERSION 3.11)
set(PYTHON_MINIMUM_VERSION 3.9)
include_directories("${CMAKE_SOURCE_DIR}")
enable_testing()
@ -38,55 +35,6 @@ endif ()
set(TEST_DEFINITIONS) # list will be appended as needed
# IF option TESTS_ENABLE_PYTHON_TESTS is ON, then we need to find python
if (TESTS_ENABLE_PYTHON_TESTS)
if (NOT DEFINED TESTS_PYTHON_EXECUTABLE)
# python is required for doc tests
# https://github.com/actions/setup-python/issues/121#issuecomment-777748504
if (POLICY CMP0094) # https://cmake.org/cmake/help/latest/policy/CMP0094.html
cmake_policy(SET CMP0094 NEW) # FindPython should return the first matching Python
endif ()
# needed on GitHub Actions CI: actions/setup-python does not touch registry/frameworks on Windows/macOS
# this mirrors PythonInterp behavior which did not consult registry/frameworks first
if (NOT DEFINED Python_FIND_REGISTRY)
set(Python_FIND_REGISTRY "LAST") # cmake-lint: disable=C0103
endif ()
if (NOT DEFINED Python_FIND_FRAMEWORK)
set(Python_FIND_FRAMEWORK "LAST") # cmake-lint: disable=C0103
endif ()
# first, try to find preferred version of python
find_package(Python ${PYTHON_PREFERRED_VERSION} EXACT COMPONENTS Interpreter)
if (Python_FOUND)
message(STATUS
"Preferred Python ${PYTHON_PREFERRED_VERSION} found, tests dependent on Python will be enabled")
else ()
# fallback to minimum version
find_package(Python ${PYTHON_MINIMUM_VERSION} COMPONENTS Interpreter)
endif ()
if (Python_FOUND)
message(STATUS "Python found, tests dependent on Python will be enabled")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=1)
list(APPEND TEST_DEFINITIONS TESTS_PYTHON_EXECUTABLE="${Python_EXECUTABLE}")
else ()
message(SEND_ERROR "Python not found, tests dependent on Python will be disabled")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=0)
endif ()
else()
message(STATUS "Python executable is set to ${TESTS_PYTHON_EXECUTABLE}")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=1)
list(APPEND TEST_DEFINITIONS TESTS_PYTHON_EXECUTABLE="${TESTS_PYTHON_EXECUTABLE}")
endif()
else ()
message(STATUS "Python tests are disabled by 'TESTS_ENABLE_PYTHON_TESTS' option")
list(APPEND TEST_DEFINITIONS TESTS_ENABLE_VENV_TESTS=0)
endif ()
list(APPEND TEST_DEFINITIONS TESTS_SOURCE_DIR="${CMAKE_SOURCE_DIR}") # add source directory to TEST_DEFINITIONS
list(APPEND TEST_DEFINITIONS TESTS_DOCS_DIR="${CMAKE_SOURCE_DIR}/docs") # add docs directory to TEST_DEFINITIONS
# make sure TESTS_SOFTWARE_ENCODER_UNAVAILABLE is set to "fail" or "skip"
if (NOT (TESTS_SOFTWARE_ENCODER_UNAVAILABLE STREQUAL "fail" OR TESTS_SOFTWARE_ENCODER_UNAVAILABLE STREQUAL "skip"))
set(TESTS_SOFTWARE_ENCODER_UNAVAILABLE "fail")

View file

@ -1,36 +0,0 @@
#include <tests/conftest.cpp>
class DocsTests: public DocsTestFixture, public ::testing::WithParamInterface<std::tuple<const char *, const char *>> {};
INSTANTIATE_TEST_SUITE_P(
DocFormats,
DocsTests,
::testing::Values(
std::make_tuple("html", "index.html"),
std::make_tuple("epub", "Sunshine.epub")));
TEST_P(DocsTests, MakeDocs) {
auto params = GetParam();
std::string format = std::get<0>(params);
std::string expected_filename = std::get<1>(params);
std::filesystem::path expected_file = std::filesystem::current_path() / "build" / format / expected_filename;
std::string command = "make " + format;
int status = BaseTest::exec(command.c_str());
EXPECT_EQ(status, 0);
EXPECT_TRUE(std::filesystem::exists(expected_file));
}
class DocsRstTests: public DocsPythonVenvTest, public ::testing::WithParamInterface<std::filesystem::path> {};
INSTANTIATE_TEST_SUITE_P(
RstFiles,
DocsRstTests,
::testing::Values(
std::filesystem::path(TESTS_DOCS_DIR),
std::filesystem::path(TESTS_SOURCE_DIR) / "README.rst"));
TEST_P(DocsRstTests, RstCheckDocs) {
std::filesystem::path docs_dir = GetParam();
std::string command = "rstcheck -r " + docs_dir.string();
int status = BaseTest::exec(command.c_str());
EXPECT_EQ(status, 0);
}

View file

@ -194,204 +194,3 @@ protected:
private:
std::unique_ptr<platf::deinit_t> deinit_guard;
};
class DocsPythonVenvBase: public virtual BaseTest {
protected:
void
SetUp() override {
#if defined TESTS_ENABLE_VENV_TESTS && TESTS_ENABLE_VENV_TESTS == 0
GTEST_SKIP_("TESTS_ENABLE_VENV_TESTS is disabled by CMake");
#else
std::cout << "DocsPythonVenvTest:: starting Fixture SetUp" << std::endl;
std::string pythonBinDirArray[] = { "bin", "Scripts" };
std::filesystem::path pythonPath = "python";
std::string binPath;
std::string command;
int exit_code;
std::filesystem::path venvPath = ".venv";
std::filesystem::path fullVenvPath = BaseTest::testBinaryDir / venvPath;
// check for existence of venv, and create it if necessary
std::cout << "DocsPythonVenvTest:: checking for venv" << std::endl;
if (!std::filesystem::exists(fullVenvPath)) {
std::cout << "DocsPythonVenvTest:: venv not found" << std::endl;
// create the venv
command = "\"" TESTS_PYTHON_EXECUTABLE "\" -m venv " + fullVenvPath.string();
std::cout << "DocsPythonVenvTest:: trying to create venv with command: " << command << std::endl;
exit_code = BaseTest::exec(command.c_str());
if (exit_code != 0) {
if (!std::filesystem::exists(fullVenvPath)) {
FAIL() << "Command failed: " << command << " with exit code: " << exit_code;
}
else {
// venv command will randomly complain that some files already exist...
std::cout << "DocsPythonVenvTest:: exit code (" << exit_code << ") indicates venv creation failed, but venv exists" << std::endl;
}
}
}
// determine if bin directory is `bin` (Unix) or `Scripts` (Windows)
// cannot assume `Scripts` on Windows, as it could be `bin` if using MSYS2, cygwin, etc.
std::cout << "DocsPythonVenvTest:: checking structure of venv" << std::endl;
for (const std::string &binDir : pythonBinDirArray) {
// check if bin directory exists
if (std::filesystem::exists(fullVenvPath / binDir)) {
binPath = binDir;
std::cout << "DocsPythonVenvTest:: found binPath: " << binPath << std::endl;
break;
}
}
if (binPath.empty()) {
FAIL() << "Python venv not found";
}
// set fullPythonPath and fullPythonBinPath
fullPythonPath = fullVenvPath / binPath / pythonPath;
fullPythonBinPath = fullVenvPath / binPath;
std::cout << "DocsPythonVenvTest:: fullPythonPath: " << fullPythonPath << std::endl;
std::cout << "DocsPythonVenvTest:: fullPythonBinPath: " << fullPythonBinPath << std::endl;
std::filesystem::path requirements_path = std::filesystem::path(TESTS_DOCS_DIR) / "requirements.txt";
// array of commands to run
std::string CommandArray[] = {
"\"" + fullPythonPath.string() + "\" -m pip install -r " + requirements_path.string(),
};
for (const std::string &_command : CommandArray) {
std::cout << "DocsPythonVenvTest:: running command: " << _command << std::endl;
exit_code = BaseTest::exec(_command.c_str());
if (exit_code != 0) {
FAIL() << "Command failed: " << command << " with exit code: " << exit_code;
}
}
// Save the original PATH
originalEnvPath = std::getenv("PATH") ? std::getenv("PATH") : "";
std::cout << "DocsPythonVenvTest:: originalEnvPath: " << originalEnvPath << std::endl;
// Set the temporary PATH
std::string tempPath;
std::string envPathSep;
#ifdef _WIN32
envPathSep = ";";
#else
envPathSep = ":";
#endif
tempPath = fullPythonBinPath.string() + envPathSep + originalEnvPath;
std::cout << "DocsPythonVenvTest:: tempPath: " << tempPath << std::endl;
setEnv("PATH", tempPath);
std::cout << "DocsPythonVenvTest:: finished Fixture SetUp" << std::endl;
#endif
}
void
TearDown() override {
std::cout << "DocsPythonVenvTest:: starting Fixture TearDown" << std::endl;
// Restore the original PATH
if (!originalEnvPath.empty()) {
std::cout << "DocsPythonVenvTest:: restoring originalEnvPath: " << originalEnvPath << std::endl;
setEnv("PATH", originalEnvPath);
}
std::cout << "DocsPythonVenvTest:: finished Fixture TearDown" << std::endl;
}
// functions and variables
std::filesystem::path fullPythonPath;
std::filesystem::path fullPythonBinPath;
std::string originalEnvPath;
};
class DocsPythonVenvTest: public virtual BaseTest, public DocsPythonVenvBase {
protected:
void
SetUp() override {
BaseTest::SetUp();
DocsPythonVenvBase::SetUp();
}
void
TearDown() override {
DocsPythonVenvBase::TearDown();
BaseTest::TearDown();
}
};
class DocsWorkingDirectoryBase: public virtual BaseTest {
protected:
void
SetUp() override {
#if defined TESTS_ENABLE_VENV_TESTS && TESTS_ENABLE_VENV_TESTS == 1
std::cout << "DocsWorkingDirectoryTest:: starting Fixture SetUp" << std::endl;
temp_dir = TESTS_DOCS_DIR;
std::cout << "DocsWorkingDirectoryTest:: temp_dir: " << temp_dir << std::endl;
// change directory to `docs`
original_dir = std::filesystem::current_path(); // save original directory
std::cout << "DocsWorkingDirectoryTest:: original_dir: " << original_dir << std::endl;
std::filesystem::current_path(temp_dir);
std::cout << "DocsWorkingDirectoryTest:: working directory set to: " << std::filesystem::current_path() << std::endl;
std::cout << "DocsWorkingDirectoryTest:: finished Fixture SetUp" << std::endl;
#endif
}
void
TearDown() override {
#if defined TESTS_ENABLE_VENV_TESTS && TESTS_ENABLE_VENV_TESTS == 1
std::cout << "DocsWorkingDirectoryTest:: starting Fixture TearDown" << std::endl;
// change directory back to original
std::filesystem::current_path(original_dir);
std::cout << "DocsWorkingDirectoryTest:: working directory set to: " << std::filesystem::current_path() << std::endl;
std::cout << "DocsWorkingDirectoryTest:: finished Fixture TearDown" << std::endl;
#endif
}
// functions and variables
std::filesystem::path original_dir;
std::filesystem::path temp_dir;
};
class DocsWorkingDirectoryTest: public virtual BaseTest, public DocsWorkingDirectoryBase {
protected:
void
SetUp() override {
BaseTest::SetUp();
DocsWorkingDirectoryBase::SetUp();
}
void
TearDown() override {
DocsWorkingDirectoryBase::TearDown();
BaseTest::TearDown();
}
};
class DocsTestFixture: public virtual BaseTest, public DocsPythonVenvBase, public DocsWorkingDirectoryBase {
protected:
void
SetUp() override {
BaseTest::SetUp();
DocsPythonVenvBase::SetUp();
DocsWorkingDirectoryBase::SetUp();
}
void
TearDown() override {
DocsWorkingDirectoryBase::TearDown();
DocsPythonVenvBase::TearDown();
BaseTest::TearDown();
}
};