* fix(repair): keep RPC progress alive * fix(daemon): propagate DB open failure to FSM and add shutdown cancellation * fix(db): classify FTS5 inverted-index errors as repairable, not transient locks * fix(daemon): clean up stale corrupt files after salvage and suppress optional readiness keys * test(db_recovery): update FTS5 classification test for new transient-lock exclusion * test(gc): add garbage collector unit tests for collection, dry-run, scheduling * test(repair): expand repair manager tests with hash-verified recovery and source ordering * fix(gc): dry-run mode no longer increments blocksDeleted/bytesReclaimed * fix(mock,mcp): add atomic bool for lock consistency, move field assignments * style: fix unnecessary-copy, dead-store, and const-refable findings from Infer * fix(daemon): increase default shutdown timeout from 15s to 120s * fix(daemon): demote non-critical warnings to info (FTS5, VACUUM, WorkCoordinator timeout) * fix(db): re-enable WAL auto-checkpoint to prevent unbounded WAL growth * test(pool): add WAL auto-checkpoint and concurrency coverage for connection pool * test(pool): add exhaustion, stats, lifecycle, and read-only connection pool tests * test(pool): add tagging, WAL journal, reuse, and busy timeout tests * test(metrics): relax session snippet assertion to tolerate stub behavior * fix(test): stabilize sanitizer triage failures * fix(build): wire version and zyp deps * fix(daemon): close TSAN race clusters * fix(test): guard optional zyp dep * fix(test): address PR review findings
106 lines
2.9 KiB
C++
106 lines
2.9 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
|
|
#include <array>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <regex>
|
|
#include <string>
|
|
|
|
namespace {
|
|
|
|
FILE* openPipe(const char* command, const char* mode) {
|
|
#ifdef _WIN32
|
|
return _popen(command, mode);
|
|
#else
|
|
return popen(command, mode);
|
|
#endif
|
|
}
|
|
|
|
int closePipe(FILE* pipe) {
|
|
#ifdef _WIN32
|
|
return _pclose(pipe);
|
|
#else
|
|
return pclose(pipe);
|
|
#endif
|
|
}
|
|
|
|
std::string runCommand(const char* command) {
|
|
std::array<char, 256> buffer{};
|
|
std::string output;
|
|
FILE* pipe = openPipe(command, "r");
|
|
if (!pipe) {
|
|
return {};
|
|
}
|
|
while (fgets(buffer.data(), static_cast<int>(buffer.size()), pipe) != nullptr) {
|
|
output += buffer.data();
|
|
}
|
|
closePipe(pipe);
|
|
while (!output.empty() && (output.back() == '\n' || output.back() == '\r')) {
|
|
output.pop_back();
|
|
}
|
|
return output;
|
|
}
|
|
|
|
std::filesystem::path findGeneratedVersionHeader() {
|
|
if (const char* buildRoot = std::getenv("MESON_BUILD_ROOT")) {
|
|
auto candidate = std::filesystem::path(buildRoot) / "version_generated.h";
|
|
if (std::filesystem::exists(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
std::error_code ec;
|
|
auto cwd = std::filesystem::current_path(ec);
|
|
if (!ec) {
|
|
auto candidate = cwd / "version_generated.h";
|
|
if (std::filesystem::exists(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::string readFile(const std::filesystem::path& path) {
|
|
std::ifstream input(path);
|
|
if (!input) {
|
|
return {};
|
|
}
|
|
return std::string((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>());
|
|
}
|
|
|
|
std::string extractDefine(const std::string& text, const char* name) {
|
|
const std::regex pattern(std::string("#define\\s+") + name + "\\s+\"([^\"]*)\"");
|
|
std::smatch match;
|
|
if (!std::regex_search(text, match, pattern)) {
|
|
return {};
|
|
}
|
|
return match[1].str();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST_CASE("Version header tracks current git commit", "[cli][version]") {
|
|
const auto gitCommit = runCommand("git rev-parse --short=8 HEAD");
|
|
REQUIRE_FALSE(gitCommit.empty());
|
|
|
|
const auto headerPath = findGeneratedVersionHeader();
|
|
REQUIRE_FALSE(headerPath.empty());
|
|
const auto headerText = readFile(headerPath);
|
|
REQUIRE_FALSE(headerText.empty());
|
|
|
|
CHECK(extractDefine(headerText, "YAMS_GIT_COMMIT") == gitCommit);
|
|
}
|
|
|
|
TEST_CASE("Version header uses ISO-8601 build timestamp", "[cli][version]") {
|
|
const auto headerPath = findGeneratedVersionHeader();
|
|
REQUIRE_FALSE(headerPath.empty());
|
|
const auto headerText = readFile(headerPath);
|
|
REQUIRE_FALSE(headerText.empty());
|
|
|
|
const std::string buildTimestamp = extractDefine(headerText, "YAMS_BUILD_TIMESTAMP");
|
|
CHECK(
|
|
std::regex_match(buildTimestamp, std::regex(R"(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$)")));
|
|
}
|