#define DROGON_TEST_MAIN #include #include #include #include "common/GeoJson.h" #include "common/Crypto.h" #include "common/Validation.h" #include "repositories/Sql.h" #include using namespace drogon; namespace { std::pair sendRequest(const HttpRequestPtr &request) { auto client = HttpClient::newHttpClient("http://127.0.0.1:15555", app().getLoop()); auto promise = std::make_shared>>(); auto future = promise->get_future(); client->sendRequest( request, [promise](ReqResult result, const HttpResponsePtr &response) { promise->set_value({result, response}); }); return future.get(); } } // namespace DROGON_TEST(HealthEndpoint) { auto request = HttpRequest::newHttpRequest(); request->setMethod(Get); request->setPath("/api/v1/health"); auto [result, response] = sendRequest(request); REQUIRE(result == ReqResult::Ok); REQUIRE(response != nullptr); CHECK(response->getStatusCode() == k200OK); REQUIRE(response->getJsonObject() != nullptr); CHECK((*response->getJsonObject())["status"].asString() == "ok"); CHECK((*response->getJsonObject())["service"].asString() == "visione-backend"); } DROGON_TEST(ValidationRejectsMalformedIdentity) { CHECK(visione::validation::isValidEmail("mario.rossi@example.com")); CHECK(!visione::validation::isValidEmail("not-an-email")); CHECK(visione::validation::isValidFiscalCode("RSSMRA80A01H501U")); CHECK(visione::validation::isValidFiscalCode("VSSGNR94M08A662P")); CHECK(!visione::validation::isValidFiscalCode("short")); CHECK(!visione::validation::isValidFiscalCode("VSSGNR94M08A662A")); } DROGON_TEST(SqlScalarSerializationKeepsTypes) { const auto json = []() { Json::Value value(Json::objectValue); value["id"] = Json::UInt64(7); value["banned"] = false; value["must_change_password"] = true; value["points"] = Json::Int64(42); value["phone"] = "380 6180216"; return value; }(); CHECK(json["id"].isUInt64()); CHECK(json["banned"].isBool()); CHECK(json["must_change_password"].isBool()); CHECK(json["points"].isInt64()); CHECK(json["phone"].isString()); } DROGON_TEST(GeoJsonMatchesPointInsidePolygon) { Json::Value polygon; polygon["type"] = "Polygon"; Json::Value ring(Json::arrayValue); Json::Value a(Json::arrayValue); a.append(12.0); a.append(41.0); Json::Value b(Json::arrayValue); b.append(13.0); b.append(41.0); Json::Value c(Json::arrayValue); c.append(13.0); c.append(42.0); Json::Value d(Json::arrayValue); d.append(12.0); d.append(42.0); ring.append(a); ring.append(b); ring.append(c); ring.append(d); ring.append(a); polygon["coordinates"].append(ring); CHECK(visione::geojson::pointInPolygon(41.5, 12.5, polygon)); CHECK(!visione::geojson::pointInPolygon(43.0, 12.5, polygon)); } DROGON_TEST(PasswordHashSupportsPbkdf2Only) { const auto hash = visione::crypto::hashPassword("CorrectHorse123!"); CHECK(hash.rfind("pbkdf2_sha256$", 0) == 0); CHECK(visione::crypto::verifyPassword("CorrectHorse123!", hash)); CHECK(!visione::crypto::verifyPassword("wrong", hash)); const std::string legacy = "sha256$local-dev-salt$CD4FF6AC8C9685D08E55AF693970F15F9BFCD4C0DC9F4D3001D202C9DB00291F"; CHECK(!visione::crypto::verifyPassword("ChangeMe123!", legacy)); } int main(int argc, char **argv) { std::promise startedPromise; auto startedFuture = startedPromise.get_future(); app().addListener("127.0.0.1", 15555); std::thread serverThread([&startedPromise]() { app().getLoop()->queueInLoop([&startedPromise]() { startedPromise.set_value(); }); app().run(); }); startedFuture.get(); const int status = test::run(argc, argv); app().getLoop()->queueInLoop([]() { app().quit(); }); serverThread.join(); return status; }