76 lines
2.8 KiB
C++
76 lines
2.8 KiB
C++
#include "adminive/adapters/nlohmann_json.hpp"
|
|
#include "adminive/http.hpp"
|
|
#include <cassert>
|
|
#include <string>
|
|
namespace synchronized_test {
|
|
using Json = nlohmann::json;
|
|
struct Section_Config {
|
|
int first{1};
|
|
int second{2};
|
|
};
|
|
struct Root_Config {
|
|
Section_Config section;
|
|
int unrelated{3};
|
|
};
|
|
struct Counting_Lock {
|
|
int depth{};
|
|
int lock_count{};
|
|
int unlock_count{};
|
|
void lock() noexcept {
|
|
++depth;
|
|
++lock_count;
|
|
}
|
|
void unlock() noexcept {
|
|
--depth;
|
|
++unlock_count;
|
|
}
|
|
};
|
|
}
|
|
namespace adminive {
|
|
template <>
|
|
struct Type_Descriptor<synchronized_test::Section_Config> {
|
|
static auto get() {
|
|
using T = synchronized_test::Section_Config;
|
|
return object<T>("section", "Section", ADMINIVE_FIELD(T, first).editable(), ADMINIVE_FIELD(T, second).editable());
|
|
}
|
|
};
|
|
template <>
|
|
struct Type_Descriptor<synchronized_test::Root_Config> {
|
|
static auto get() {
|
|
using T = synchronized_test::Root_Config;
|
|
return object<T>("root", "Root", ADMINIVE_FIELD(T, section).editable(), ADMINIVE_FIELD(T, unrelated).editable());
|
|
}
|
|
};
|
|
}
|
|
int main() {
|
|
using namespace synchronized_test;
|
|
adminive::Synchronized_Value<Root_Config, Counting_Lock> guarded;
|
|
const Json initial = adminive::to_json<Json>(guarded);
|
|
assert(initial.at("section").at("first") == 1);
|
|
assert(guarded.mutex().depth == 0);
|
|
assert(guarded.mutex().lock_count == 1);
|
|
auto section = guarded.member<&Root_Config::section>();
|
|
const Json form = adminive::to_amis_form_schema<Json>(section, "/section/data", "Apply");
|
|
assert(form.at("data").at("first") == 1);
|
|
const auto patch_result = adminive::apply_frontend_patch<Json>(section, Json{{"first", 7}, {"second", 8}});
|
|
assert(patch_result.success);
|
|
assert(section.snapshot().first == 7);
|
|
bool commit_saw_lock{};
|
|
adminive::Resource_Transaction<Section_Config> transaction;
|
|
transaction.commit = [&](const Section_Config& value, const adminive::Request_Context&) {
|
|
commit_saw_lock = guarded.mutex().depth == 1 && value.first == 9 && value.second == 8;
|
|
};
|
|
adminive::Resource_Service<Section_Config, Json, Counting_Lock> service(section, "/section", std::move(transaction));
|
|
const auto response = service.update_response(R"({"first":9})");
|
|
assert(response.status == 200);
|
|
assert(commit_saw_lock);
|
|
assert(section.snapshot().first == 9);
|
|
assert(guarded.mutex().depth == 0);
|
|
adminive::Synchronized_Value<Section_Config, adminive::Empty_Lock> unlocked;
|
|
adminive::Resource_Service<Section_Config, Json, adminive::Empty_Lock> unlocked_service(unlocked, "/unlocked");
|
|
const auto unlocked_response = unlocked_service.update_response(R"({"second":11})");
|
|
assert(unlocked_response.status == 200);
|
|
assert(unlocked.snapshot().second == 11);
|
|
return 0;
|
|
}
|