This commit is contained in:
2026-08-08 22:39:18 +08:00
parent d1cff37a2a
commit 464f3a166a
22 changed files with 510 additions and 54 deletions
+47 -3
View File
@@ -6,12 +6,18 @@
#include <utility>
#include <vector>
namespace drogon_test {
struct Config {
std::string name{"default"};
};
struct Status {
std::string user;
};
struct Config {
std::string name{"default"};
Status status() {
if(name == "status-error") {
throw std::runtime_error("item status failed");
}
return Status{name};
}
};
}
namespace adminive {
template <>
@@ -76,6 +82,27 @@ int main() {
});
ADMINIVE_CHECK(response->status == drogon::k200OK);
ADMINIVE_CHECK(Json::parse(response->body).at("data").at("kind") == "form");
adminive::Drogon_Bind_Options nonstd_options = options;
nonstd_options.context_factory = [](const drogon::HttpRequestPtr&) -> adminive::Request_Context {
throw 7;
};
adminive::Drogon_Resource<drogon_test::Config, Json> nonstd_resource(config, "/context-error");
nonstd_resource.bind(app, nonstd_options);
adminive::Drogon_Status_Resource<drogon_test::Status, Json> nonstd_status("/status-context-error", [](const adminive::Request_Context&) {
return drogon_test::Status{};
});
nonstd_status.bind(app, nonstd_options);
response.reset();
app.handle("/context-error/data", drogon::Post, request, [&response](const drogon::HttpResponsePtr& value) {
response = value;
});
ADMINIVE_CHECK(response->status == drogon::k500InternalServerError);
response.reset();
app.handle("/status-context-error/data", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
response = value;
});
ADMINIVE_CHECK(response->status == drogon::k500InternalServerError);
ADMINIVE_CHECK(tasks.empty());
request->body = R"({"name":"updated"})";
request->user = "wyc";
response.reset();
@@ -114,6 +141,7 @@ int main() {
});
ADMINIVE_CHECK(response->status == drogon::k200OK);
adminive::Drogon_Collection_Resource<drogon_test::Config, Json> collection("/configs", {drogon_test::Config{"first"}});
collection.register_status<&drogon_test::Config::status>(25);
collection.bind(app, options);
response.reset();
app.handle("/configs/view", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
@@ -174,6 +202,22 @@ int main() {
tasks.erase(tasks.begin());
ADMINIVE_CHECK(response->status == drogon::k200OK);
ADMINIVE_CHECK(Json::parse(response->body).at("data").at("name") == "changed");
request->body = R"({"name":"status-error"})";
response.reset();
app.handle("/configs/2", drogon::Patch, request, [&response](const drogon::HttpResponsePtr& value) {
response = value;
});
tasks.front()();
tasks.erase(tasks.begin());
ADMINIVE_CHECK(response->status == drogon::k200OK);
response.reset();
app.handle("/configs/2/status", drogon::Get, request, [&response](const drogon::HttpResponsePtr& value) {
response = value;
});
ADMINIVE_CHECK(!response);
tasks.front()();
tasks.erase(tasks.begin());
ADMINIVE_CHECK(response->status == drogon::k500InternalServerError);
response.reset();
app.handle("/configs/1", drogon::Delete, request, [&response](const drogon::HttpResponsePtr& value) {
response = value;
@@ -23,6 +23,9 @@ struct Row {
bool enabled{true};
int score{};
Item_Status status() {
if(name == "status-error") {
throw std::runtime_error("item status failed");
}
return {};
}
};
@@ -103,6 +106,9 @@ int main() {
if(user == "context-error") {
throw std::runtime_error("context failed");
}
if(user == "context-unknown") {
throw 7;
}
adminive::Request_Context context;
context.user = user;
context.request_id = request.get_header_value("X-Request-Id");
@@ -132,7 +138,9 @@ int main() {
ADMINIVE_CHECK(committed_request_id == "request-42");
ADMINIVE_CHECK(committed_remote == "127.0.0.1");
httplib::Headers context_error_headers{{"X-User", "context-error"}};
httplib::Headers context_unknown_headers{{"X-User", "context-unknown"}};
check_status(client.Post("/config/data", context_error_headers, R"({"name":"not-applied"})", "application/json"), 500);
check_status(client.Post("/config/data", context_unknown_headers, R"({"name":"not-applied"})", "application/json"), 500);
ADMINIVE_CHECK(config.name == "updated");
check_status(client.Get("/status/descriptor"), 200);
check_status(client.Get("/status/amis"), 200);
@@ -140,6 +148,7 @@ int main() {
httplib::Headers status_error_headers{{"X-User", "status-error"}};
check_status(client.Get("/status/data", status_error_headers), 500);
check_status(client.Get("/status/data", context_error_headers), 500);
check_status(client.Get("/status/data", context_unknown_headers), 500);
ADMINIVE_CHECK(body_json(client.Get("/rows/descriptor")).at("data").at("name") == "httplib_row");
ADMINIVE_CHECK(body_json(client.Get("/rows/view")).at("data").at("kind") == "table");
ADMINIVE_CHECK(body_json(client.Get("/rows?perPage=2&page=1&orderBy=score&orderDir=desc")).at("data").at("items").at(0).at("name") == "beta");
@@ -157,6 +166,8 @@ int main() {
ADMINIVE_CHECK(body_json(client.Get(("/rows/" + std::to_string(created_id)).c_str())).at("data").at("score") == 81);
check_status(client.Patch(("/rows/" + std::to_string(created_id)).c_str(), R"({"name":"delta-patched"})", "application/json"), 200);
ADMINIVE_CHECK(body_json(client.Get(("/rows/" + std::to_string(created_id) + "/status").c_str())).at("data").at("state").at("value") == "ready");
check_status(client.Patch(("/rows/" + std::to_string(created_id)).c_str(), R"({"name":"status-error"})", "application/json"), 200);
check_status(client.Get(("/rows/" + std::to_string(created_id) + "/status").c_str()), 500);
check_status(client.Post("/rows/order", R"({"ids":[3,2,1]})", "application/json"), 200);
ADMINIVE_CHECK(body_json(client.Get("/rows?orderBy=id&orderDir=asc")).at("data").at("total") == 4);
check_status(client.Delete(("/rows/" + std::to_string(created_id)).c_str()), 200);
@@ -0,0 +1,55 @@
#include "adminive/adapters/drogon.hpp"
#include "adminive/adapters/nlohmann_json.hpp"
#include "adminive_test.hpp"
#include <string>
namespace real_drogon_test {
struct Status {
std::string state{"ready"};
};
struct Config {
std::string name{"real"};
Status status() {
return {};
}
};
}
namespace adminive {
template <>
struct Type_Descriptor<real_drogon_test::Status> {
static auto get() {
using T = real_drogon_test::Status;
return object<T>("real_drogon_status", ADMINIVE_FIELD(T, state));
}
};
template <>
struct Type_Descriptor<real_drogon_test::Config> {
static auto get() {
using T = real_drogon_test::Config;
return object<T>("real_drogon_config", ADMINIVE_FIELD(T, name).editable().creatable());
}
};
template <>
struct Type_View_Descriptor<real_drogon_test::Config> {
static Table_View table() {
using T = real_drogon_test::Config;
return table_view<T>(column<&T::name>("Name").sort().search());
}
};
}
int main() {
using Json = nlohmann::json;
auto& app = drogon::app();
real_drogon_test::Config config;
adminive::Drogon_Resource<real_drogon_test::Config, Json> resource(config, "/real/config");
resource.bind(app);
adminive::Drogon_Status_Resource<real_drogon_test::Status, Json> status("/real/status", [](const adminive::Request_Context&) {
return real_drogon_test::Status{};
});
status.bind(app);
adminive::Drogon_Collection_Resource<real_drogon_test::Config, Json> collection("/real/configs", {config});
collection.register_status<&real_drogon_test::Config::status>();
collection.bind(app);
ADMINIVE_CHECK(resource.view_schema().at("kind") == "form");
ADMINIVE_CHECK(collection.view_schema().at("kind") == "table");
return 0;
}
@@ -217,6 +217,12 @@ int main() {
query.order_dir = "sideways";
response = collection.list_response(query);
ADMINIVE_CHECK(response.status == 400);
response = collection.create_response("{");
ADMINIVE_CHECK(response.status == 400);
response = collection.update_response(1, "{");
ADMINIVE_CHECK(response.status == 400);
response = collection.reorder_response(R"({"ids":["invalid"]})");
ADMINIVE_CHECK(response.status == 400);
bool invalid_manifest{};
try {
adminive::to_composition_manifest_json<Json>(frontend_composition, {adminive::Composition_Slot_Contract{"left", "amis_schema", {}, {}, {}, {}}}, {{"left", Json{{"type", "tpl"}}}});