// Tests for authkit#14 PR 4 — temporal users schema. #include "oatpp-authkit/db/UserDb.hpp" #include "oatpp-authkit/dto/UserDto.hpp" #include "oatpp-authkit/repo/ConcreteUserRepository.hpp" #include "oatpp-authkit/repo/SchemaContract.hpp" #include "oatpp-authkit/repo/TemporalRepository.hpp" #include #include #include #include #define REQUIRE(cond) do { \ if (!(cond)) { std::fprintf(stderr, "REQUIRE failed: %s @ %s:%d\n", \ #cond, __FILE__, __LINE__); std::abort(); } } while (0) namespace { bool contains(const std::string& haystack, const std::string& needle) { return haystack.find(needle) != std::string::npos; } void test_users_temporal_create() { using namespace oatpp_authkit::repo; using namespace oatpp_authkit::db; using namespace oatpp_authkit::dto; std::vector sqls; SqlExec exec = [&](const std::string& sql) { sqls.push_back(sql); }; SchemaBuilder< UserSchema, TemporalRepository>::create("users", exec); // 1 entity table + 3 schema-side indexes + 1 temporal composite index = 5 REQUIRE(sqls.size() == 5); REQUIRE(contains(sqls[0], "CREATE TABLE IF NOT EXISTS users")); REQUIRE(contains(sqls[0], "id TEXT PRIMARY KEY")); REQUIRE(contains(sqls[0], "entity_id TEXT NOT NULL")); REQUIRE(contains(sqls[0], "username TEXT NOT NULL")); REQUIRE(contains(sqls[0], "password_hash TEXT")); REQUIRE(contains(sqls[0], "role TEXT NOT NULL DEFAULT 'editor'")); REQUIRE(contains(sqls[0], "valid_from TEXT NOT NULL DEFAULT ''")); REQUIRE(contains(sqls[0], "valid_until TEXT NOT NULL DEFAULT '9999-12-31T23:59:59Z'")); // is_active and created_at must NOT appear — those are dropped in // the temporal shape (Option B). REQUIRE(!contains(sqls[0], "is_active")); REQUIRE(!contains(sqls[0], "created_at")); REQUIRE(contains(sqls[1], "ix_users_entity_id")); REQUIRE(contains(sqls[2], "ux_users_username_until")); REQUIRE(contains(sqls[2], "(username, valid_until)")); REQUIRE(contains(sqls[3], "ix_users_tls_cert_dn")); REQUIRE(contains(sqls[4], "ux_users_entity_valid_until")); REQUIRE(contains(sqls[4], "(entity_id, valid_until)")); } // ConcreteUserRepository contributes nothing; ensure SchemaBuilder is // idempotent w.r.t. its presence in the parameter pack. void test_concrete_user_repo_no_schema() { using namespace oatpp_authkit::repo; using namespace oatpp_authkit::db; using namespace oatpp_authkit::dto; std::vector with_repo; std::vector without_repo; SchemaBuilder< UserSchema, ConcreteUserRepository, TemporalRepository>::create( "users", [&](const std::string& s){ with_repo.push_back(s); }); SchemaBuilder< UserSchema, TemporalRepository>::create( "users", [&](const std::string& s){ without_repo.push_back(s); }); REQUIRE(with_repo == without_repo); } } // namespace int main() { test_users_temporal_create(); test_concrete_user_repo_no_schema(); std::printf("test_user_schema: OK\n"); return 0; }