This commit is contained in:
2026-08-09 22:47:13 +08:00
parent 1354aa54ba
commit 11407faf86
11 changed files with 85 additions and 143 deletions
+16 -49
View File
@@ -1,14 +1,12 @@
#include <structive/property/property.hpp>
#include "test.hpp"
#include <barrier>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <semaphore>
#include <stdexcept>
#include <string_view>
#include <thread>
using namespace structive;
#define REQUIRE(expression) do { if (!(expression)) { std::fprintf(stderr, "REQUIRE failed: %s:%d: %s\n", __FILE__, __LINE__, #expression); std::abort(); } } while (false)
struct Sync_Device : Property_Object<Sync_Device> {
Sync_Device() = default;
explicit Sync_Device(Property_Synchronization synchronization) : Property_Object(std::move(synchronization)) {}
@@ -32,6 +30,12 @@ struct structive::Type_Descriptor<Sync_Device> {
static Sync_Device with_plan(Synchronization_Plan plan) {
return Sync_Device{property_synchronization(std::move(plan))};
}
template <class Configure>
static void require_invalid_plan(Configure configure) {
Synchronization_Plan plan;
configure(plan);
STRUCTIVE_CHECK_THROWS_AS(with_plan(std::move(plan)), std::invalid_argument);
}
static void test_topology_resolution() {
Sync_Device independent;
auto ro = independent.lock_slot<&Sync_Device::id>();
@@ -67,57 +71,20 @@ static void test_topology_resolution() {
REQUIRE(read_only_grouped.resolved_synchronization().lock_count == 3);
}
static void test_plan_validation() {
bool unknown_thrown = false;
try {
Synchronization_Plan plan;
plan.independent("missing");
auto device = with_plan(std::move(plan));
(void)device;
} catch (const std::invalid_argument&) {
unknown_thrown = true;
}
REQUIRE(unknown_thrown);
bool duplicate_property_thrown = false;
try {
Synchronization_Plan plan;
plan.independent("a").unsynchronized("a");
auto device = with_plan(std::move(plan));
(void)device;
} catch (const std::invalid_argument&) {
duplicate_property_thrown = true;
}
REQUIRE(duplicate_property_thrown);
bool empty_group_thrown = false;
try {
Synchronization_Plan plan;
plan.group("empty", std::span<const std::string_view>{});
auto device = with_plan(std::move(plan));
(void)device;
} catch (const std::invalid_argument&) {
empty_group_thrown = true;
}
REQUIRE(empty_group_thrown);
require_invalid_plan([](auto& plan) { plan.independent("missing"); });
require_invalid_plan([](auto& plan) { plan.independent("a").unsynchronized("a"); });
require_invalid_plan([](auto& plan) { plan.group("empty", {}); });
require_invalid_plan([](auto& plan) { plan.group("same", {"a"}).group("same", {"b"}); });
}
static void test_dynamic_guard_validation() {
Sync_Device device;
bool unknown_thrown = false;
try {
auto guard = device.lock_shared({"missing"});
(void)guard;
} catch (const std::invalid_argument&) {
unknown_thrown = true;
}
REQUIRE(unknown_thrown);
bool read_only_unique_thrown = false;
try {
auto guard = device.lock_unique({"id"});
(void)guard;
} catch (const std::invalid_argument&) {
read_only_unique_thrown = true;
}
REQUIRE(read_only_unique_thrown);
STRUCTIVE_CHECK_THROWS_AS(device.lock_shared({"missing"}), std::invalid_argument);
STRUCTIVE_CHECK_THROWS_AS(device.lock_unique({"id"}), std::invalid_argument);
auto read_guard = device.lock_shared({"id"});
REQUIRE(read_guard.get<"id">() == 1);
STRUCTIVE_CHECK_THROWS_AS(read_guard.get<"a">(), std::logic_error);
auto write_guard = device.lock_unique({"a"});
STRUCTIVE_CHECK_THROWS_AS(write_guard.set<"b">(21), std::logic_error);
}
static void test_independent_and_shared_blocking() {
Sync_Device independent;