修复
This commit is contained in:
@@ -1,13 +1,7 @@
|
||||
#include <structive/property/property.hpp>
|
||||
#include <atomic>
|
||||
#include <barrier>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include "test.hpp"
|
||||
#include <memory>
|
||||
#include <semaphore>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
using namespace structive;
|
||||
struct Test_Tag_Category {};
|
||||
@@ -30,7 +24,6 @@ struct Test_Multi_Attribute {
|
||||
};
|
||||
template <int Value>
|
||||
inline constexpr Test_Multi_Attribute<Value> test_multi{};
|
||||
#define REQUIRE(expression) do { if (!(expression)) { std::fprintf(stderr, "REQUIRE failed: %s:%d: %s\n", __FILE__, __LINE__, #expression); std::abort(); } } while (false)
|
||||
struct Device : Property_Object<Device> {
|
||||
Device() = default;
|
||||
explicit Device(Property_Synchronization synchronization) : Property_Object(std::move(synchronization)) {}
|
||||
@@ -253,6 +246,9 @@ int main() {
|
||||
auto validation = validate_property_value<&Device::temperature>(device.schema(), 500);
|
||||
REQUIRE(validation.has_value());
|
||||
REQUIRE(validation->code == "max_value");
|
||||
device.write<&Device::temperature>(500);
|
||||
REQUIRE(device.read<&Device::temperature>() == 500);
|
||||
device.write<&Device::temperature>(23);
|
||||
REQUIRE(!update_speed_range(device, 200, 100));
|
||||
REQUIRE(device.read<&Device::min_speed>() == 10);
|
||||
REQUIRE(device.read<&Device::max_speed>() == 100);
|
||||
@@ -288,21 +284,6 @@ int main() {
|
||||
non_copyable_visited = true;
|
||||
});
|
||||
REQUIRE(non_copyable_visited);
|
||||
Property_Object_Base& erased = device;
|
||||
REQUIRE(erased.runtime_object_type() == typeid(Device));
|
||||
REQUIRE(erased.runtime_property_count() == 5);
|
||||
int runtime_value = 0;
|
||||
REQUIRE(erased.runtime_read("temperature", &runtime_value, &runtime_read_int) == Runtime_Access_Result::ok);
|
||||
REQUIRE(runtime_value == 23);
|
||||
REQUIRE(erased.runtime_read("immutable_id", &runtime_value, &runtime_read_int) == Runtime_Access_Result::ok);
|
||||
REQUIRE(runtime_value == 7);
|
||||
int runtime_write_value = 35;
|
||||
REQUIRE(erased.runtime_write("temperature", typeid(int), &runtime_write_value) == Runtime_Access_Result::ok);
|
||||
REQUIRE(device.temperature == 35);
|
||||
REQUIRE(erased.runtime_write("immutable_id", typeid(int), &runtime_write_value) == Runtime_Access_Result::not_writable);
|
||||
double wrong_type = 1.0;
|
||||
REQUIRE(erased.runtime_write("temperature", typeid(double), &wrong_type) == Runtime_Access_Result::type_mismatch);
|
||||
REQUIRE(erased.runtime_write("missing", typeid(int), &runtime_write_value) == Runtime_Access_Result::unknown_property);
|
||||
Read_Only_Device read_only_device;
|
||||
REQUIRE(read_only_device.resolved_synchronization().lock_count == 1);
|
||||
REQUIRE(read_only_device.lock_slot<&Read_Only_Device::id>() == Resolved_Synchronization_View::unsynchronized_slot);
|
||||
@@ -314,70 +295,6 @@ int main() {
|
||||
REQUIRE(pure_read_only.lock_slot<&Pure_Read_Only_Device::version>() == Resolved_Synchronization_View::unsynchronized_slot);
|
||||
REQUIRE(pure_read_only.read<&Pure_Read_Only_Device::id>() == 21);
|
||||
REQUIRE(pure_read_only.read<&Pure_Read_Only_Device::version>() == 4);
|
||||
Property_Object_Base& read_only_erased = read_only_device;
|
||||
std::binary_semaphore read_only_done{0};
|
||||
std::jthread read_only_reader;
|
||||
{
|
||||
auto guard = read_only_device.lock_unique<&Read_Only_Device::value>();
|
||||
read_only_reader = std::jthread([&] {
|
||||
int value = 0;
|
||||
REQUIRE(read_only_erased.runtime_read("id", &value, &runtime_read_int) == Runtime_Access_Result::ok);
|
||||
REQUIRE(value == 11);
|
||||
read_only_done.release();
|
||||
});
|
||||
REQUIRE(read_only_done.try_acquire_for(std::chrono::milliseconds(100)));
|
||||
}
|
||||
read_only_reader.join();
|
||||
std::binary_semaphore runtime_blocked_done{0};
|
||||
std::jthread runtime_writer;
|
||||
{
|
||||
auto guard = device.lock_unique<&Device::temperature>();
|
||||
runtime_writer = std::jthread([&] {
|
||||
int value = 36;
|
||||
REQUIRE(erased.runtime_write("temperature", typeid(int), &value) == Runtime_Access_Result::ok);
|
||||
runtime_blocked_done.release();
|
||||
});
|
||||
REQUIRE(!runtime_blocked_done.try_acquire_for(std::chrono::milliseconds(20)));
|
||||
}
|
||||
REQUIRE(runtime_blocked_done.try_acquire_for(std::chrono::seconds(2)));
|
||||
runtime_writer.join();
|
||||
REQUIRE(device.read<&Device::temperature>() == 36);
|
||||
std::binary_semaphore independent_done{0};
|
||||
{
|
||||
auto guard = device.lock_unique({"temperature"});
|
||||
std::jthread writer([&] {
|
||||
device.write<&Device::pressure>(200);
|
||||
independent_done.release();
|
||||
});
|
||||
REQUIRE(independent_done.try_acquire_for(std::chrono::seconds(2)));
|
||||
}
|
||||
bool dynamic_read_only_unique_rejected = false;
|
||||
try {
|
||||
auto guard = device.lock_unique({"immutable_id"});
|
||||
(void) guard;
|
||||
} catch (const std::invalid_argument&) {
|
||||
dynamic_read_only_unique_rejected = true;
|
||||
}
|
||||
REQUIRE(dynamic_read_only_unique_rejected);
|
||||
std::barrier gate(2);
|
||||
std::atomic<int> completed{0};
|
||||
std::jthread first([&] {
|
||||
gate.arrive_and_wait();
|
||||
auto guard = device.lock_unique({"temperature", "pressure"});
|
||||
guard.set<&Device::temperature>(40);
|
||||
guard.set<&Device::pressure>(140);
|
||||
completed.fetch_add(1, std::memory_order_release);
|
||||
});
|
||||
std::jthread second([&] {
|
||||
gate.arrive_and_wait();
|
||||
auto guard = device.lock_unique({"pressure", "temperature"});
|
||||
guard.set<&Device::pressure>(141);
|
||||
guard.set<&Device::temperature>(41);
|
||||
completed.fetch_add(1, std::memory_order_release);
|
||||
});
|
||||
first.join();
|
||||
second.join();
|
||||
REQUIRE(completed.load(std::memory_order_acquire) == 2);
|
||||
Device copied = device;
|
||||
REQUIRE(copied.temperature == device.temperature);
|
||||
copied.write<&Device::temperature>(99);
|
||||
|
||||
Reference in New Issue
Block a user