yams/tests/unit/cli/vector_db_util_catch2_test.cpp

101 lines
2.9 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include <sqlite3.h>
#include <filesystem>
#include <fstream>
#include <optional>
#include <string>
#include <yams/cli/vector_db_util.h>
#include "../../common/test_helpers_catch2.h"
extern "C" int sqlite3_vec_init(sqlite3* db, char** pzErrMsg, const sqlite3_api_routines* pApi);
namespace yams::cli::vecutil {
namespace {
namespace fs = std::filesystem;
struct TempDb {
fs::path dir;
fs::path dbPath;
TempDb() : dir(yams::test::make_temp_dir("yams_vecutil_catch2_")), dbPath(dir / "vectors.db") {
fs::create_directories(dir);
}
~TempDb() {
std::error_code ec;
fs::remove_all(dir, ec);
}
};
void exec(sqlite3* db, const char* sql) {
char* err = nullptr;
const int rc = sqlite3_exec(db, sql, nullptr, nullptr, &err);
INFO(std::string(sql));
INFO(std::string(err ? err : ""));
REQUIRE(rc == SQLITE_OK);
if (err) {
sqlite3_free(err);
}
}
} // namespace
TEST_CASE("vecutil validateVecSchema reports missing database", "[cli][vecutil][catch2]") {
TempDb temp;
const auto result = validateVecSchema(temp.dbPath);
CHECK_FALSE(result.exists);
CHECK_FALSE(result.vec0Available);
CHECK_FALSE(result.schemaValid);
CHECK(result.error == "Database file does not exist");
}
TEST_CASE("vecutil initVecModule validates null handle", "[cli][vecutil][catch2]") {
auto result = initVecModule(nullptr);
REQUIRE_FALSE(result.has_value());
CHECK(result.error().message.find("Null database handle") != std::string::npos);
}
TEST_CASE("vecutil validateVecSchema recognizes vec0 virtual table schema",
"[cli][vecutil][vec0][catch2]") {
TempDb temp;
sqlite3* db = nullptr;
REQUIRE(sqlite3_open(temp.dbPath.string().c_str(), &db) == SQLITE_OK);
REQUIRE(sqlite3_vec_init(db, nullptr, nullptr) == SQLITE_OK);
exec(db, "CREATE VIRTUAL TABLE doc_embeddings USING vec0(embedding float[8])");
sqlite3_close(db);
const auto result = validateVecSchema(temp.dbPath);
CHECK(result.exists);
CHECK(result.vec0Available);
CHECK(result.schemaValid);
CHECK(result.usesVec0);
REQUIRE(result.dimension.has_value());
CHECK(result.dimension.value() == 8);
CHECK(result.ddl.find("USING vec0") != std::string::npos);
}
TEST_CASE("vecutil validateVecSchema flags non-vec0 doc_embeddings schema",
"[cli][vecutil][vec0][catch2]") {
TempDb temp;
sqlite3* db = nullptr;
REQUIRE(sqlite3_open(temp.dbPath.string().c_str(), &db) == SQLITE_OK);
exec(db, "CREATE TABLE doc_embeddings(rowid INTEGER PRIMARY KEY, embedding BLOB)");
sqlite3_close(db);
const auto result = validateVecSchema(temp.dbPath);
CHECK(result.exists);
CHECK(result.vec0Available);
CHECK(result.schemaValid);
CHECK_FALSE(result.usesVec0);
CHECK(result.ddl.find("CREATE TABLE doc_embeddings") != std::string::npos);
}
} // namespace yams::cli::vecutil