#include "dps/app.hpp" #include "dps/config.hpp" #include #include #include #include #include #include #include #include #include namespace fs = std::filesystem; namespace { void set_env(const char *name, const char *value) { #ifdef _WIN32 _putenv_s(name, value); #else setenv(name, value, 1); #endif } void clear_env(const char *name) { #ifdef _WIN32 _putenv_s(name, ""); #else unsetenv(name); #endif } std::vector decode_base64(const std::string &text) { std::string normalized = text; while (normalized.size() % 4 != 0) normalized.push_back('='); std::vector decoded((normalized.size() / 4) * 3); const int size = EVP_DecodeBlock(decoded.data(), reinterpret_cast(normalized.data()), static_cast(normalized.size())); assert(size >= 0); std::size_t padding = 0; if (!normalized.empty() && normalized.back() == '=') ++padding; if (normalized.size() > 1 && normalized[normalized.size() - 2] == '=') ++padding; decoded.resize(static_cast(size) - padding); return decoded; } std::string gunzip_bytes(const std::vector &compressed) { z_stream stream{}; stream.next_in = const_cast(reinterpret_cast(compressed.data())); stream.avail_in = static_cast(compressed.size()); const int init = inflateInit2(&stream, 15 + 16); assert(init == Z_OK); std::string output; std::vector buffer(4096); int ret = Z_OK; while (ret == Z_OK) { stream.next_out = reinterpret_cast(buffer.data()); stream.avail_out = static_cast(buffer.size()); ret = inflate(&stream, Z_NO_FLUSH); output.append(buffer.data(), buffer.size() - stream.avail_out); } inflateEnd(&stream); assert(ret == Z_STREAM_END); return output; } void test_crypto() { dps::LegacyCrypto crypto("unit-test-secret"); const std::string password = "P@ssw0rd!"; const std::string hashed = crypto.hash_password(password); assert(!hashed.empty()); assert(hashed.rfind("$2", 0) == 0); assert(crypto.verify_password(password, hashed)); assert(!crypto.verify_password(password, password)); const std::string token = crypto.issue_jwt("tester", 60); assert(!token.empty()); const auto subject = crypto.validate_jwt(token); assert(subject.has_value()); assert(subject.value() == "tester"); assert(!crypto.validate_jwt(token + "broken").has_value()); const std::string gzip_payload = crypto.gzip_base64("{\"hello\":\"world\"}"); assert(!gzip_payload.empty()); const std::string inflated = gunzip_bytes(decode_base64(gzip_payload)); assert(inflated == "{\"hello\":\"world\"}"); const std::string rsa_tool = crypto.rsa_private_encrypt_tool("abc123"); const std::string rsa_script = crypto.rsa_private_encrypt_script("xyz789"); assert(!rsa_tool.empty()); assert(!rsa_script.empty()); assert(rsa_tool != "abc123"); assert(rsa_script != "xyz789"); } void test_config() { const fs::path path = fs::temp_directory_path() / "dps-config-smoke.conf"; { std::ofstream out(path); out << "server.host=0.0.0.0\n"; out << "server.port=8651\n"; out << "server.trust_proxy=true\n"; out << "server.proxy_header=x-real-ip\n"; out << "database.host=127.0.0.1\n"; out << "database.name=rindro\n"; out << "database.user=root\n"; out << "database.password=test\n"; out << "database.ssl_mode=verify_ca\n"; out << "database.ssl_ca=C:/certs/demo-ca.pem\n"; out << "database.plugin_dir=C:/mariadb/plugin\n"; } set_env("DPS_SERVER_HOST", "10.0.0.8"); set_env("DPS_SERVER_PROXY_HEADER", "x-forwarded-for"); set_env("DPS_DB_HOST", "192.168.0.10"); set_env("DPS_DB_USER", "tester"); set_env("DPS_DB_PASSWORD", "secret"); set_env("DPS_DB_NAME", "demo"); set_env("DPS_DB_SSL_MODE", "disable"); set_env("DPS_DB_SSL_CA", "D:/certs/dev-ca.pem"); set_env("DPS_DB_PLUGIN_DIR", "D:/mariadb/plugin"); const dps::AppConfig config = dps::load_config(path.string()); assert(config.server.host == "10.0.0.8"); assert(config.server.port == 8651); assert(config.server.trust_proxy); assert(config.server.proxy_header == "x-forwarded-for"); assert(config.database.host == "192.168.0.10"); assert(config.database.user == "tester"); assert(config.database.password == "secret"); assert(config.database.name == "demo"); assert(config.database.ssl_mode == "disable"); assert(config.database.ssl_ca == "D:/certs/dev-ca.pem"); assert(config.database.plugin_dir == "D:/mariadb/plugin"); clear_env("DPS_SERVER_HOST"); clear_env("DPS_SERVER_PROXY_HEADER"); clear_env("DPS_DB_HOST"); clear_env("DPS_DB_USER"); clear_env("DPS_DB_PASSWORD"); clear_env("DPS_DB_NAME"); clear_env("DPS_DB_SSL_MODE"); clear_env("DPS_DB_SSL_CA"); clear_env("DPS_DB_PLUGIN_DIR"); std::remove(path.string().c_str()); } } // namespace int main() { test_crypto(); test_config(); return 0; }