1.0
This commit is contained in:
162
tests/crypto_smoke_test.cpp
Normal file
162
tests/crypto_smoke_test.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "dps/app.hpp"
|
||||
#include "dps/config.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <zlib.h>
|
||||
|
||||
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<unsigned char> decode_base64(const std::string &text) {
|
||||
std::string normalized = text;
|
||||
while (normalized.size() % 4 != 0) normalized.push_back('=');
|
||||
|
||||
std::vector<unsigned char> decoded((normalized.size() / 4) * 3);
|
||||
const int size = EVP_DecodeBlock(decoded.data(),
|
||||
reinterpret_cast<const unsigned char *>(normalized.data()),
|
||||
static_cast<int>(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<std::size_t>(size) - padding);
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::string gunzip_bytes(const std::vector<unsigned char> &compressed) {
|
||||
z_stream stream{};
|
||||
stream.next_in = const_cast<Bytef *>(reinterpret_cast<const Bytef *>(compressed.data()));
|
||||
stream.avail_in = static_cast<uInt>(compressed.size());
|
||||
|
||||
const int init = inflateInit2(&stream, 15 + 16);
|
||||
assert(init == Z_OK);
|
||||
|
||||
std::string output;
|
||||
std::vector<char> buffer(4096);
|
||||
int ret = Z_OK;
|
||||
while (ret == Z_OK) {
|
||||
stream.next_out = reinterpret_cast<Bytef *>(buffer.data());
|
||||
stream.avail_out = static_cast<uInt>(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;
|
||||
}
|
||||
Reference in New Issue
Block a user