Files
EVEngine/test/TestPropertyAccess.h

65 lines
2.8 KiB
C++

#pragma once
#include "property_access/PropertyAccess.h"
#include <algorithm>
#include <map>
#include <memory>
#include <utility>
#include <vector>
/** Test-only in-memory authority for the IPropertyAccess contract. */
class TestPropertyAccess final : public eve::property_access::IPropertyAccess {
public:
explicit TestPropertyAccess(eve::property_access::PropertySchema schema = {})
: schema_(std::move(schema)), observers_(std::make_shared<ObserverState>()) {
for (const auto& property : schema_.properties) values_.emplace(property.path, property.defaultValue);
}
const eve::property_access::PropertySchema& schema() const override { return schema_; }
std::optional<eve::Value> read(const std::string& path) const override {
const auto found = values_.find(path);
return found == values_.end() ? std::nullopt : std::optional<eve::Value>(found->second);
}
eve::property_access::WriteResult write(const std::string& path, const eve::Value& value) override {
auto property = schema_.find(path);
if (!property)
return eve::property_access::WriteResult::reject("property_access.property.missing",
"Property is not in the schema");
auto result = eve::property_access::validatePropertyValue(property->get(), value);
if (!result.accepted) return result;
const auto found = values_.find(path);
if (found != values_.end() && found->second == value) return result;
values_[path] = value;
const eve::property_access::PropertyChange change{path, value, ++revision_};
const auto snapshot = observers_->entries;
for (const auto& entry : snapshot)
if (entry.callback) entry.callback(change);
return result;
}
std::uint64_t revision() const override { return revision_; }
eve::Subscription subscribe(ChangeCallback callback) override {
const std::uint64_t id = observers_->nextId++;
observers_->entries.push_back({id, std::move(callback)});
std::weak_ptr<ObserverState> weak = observers_;
return eve::Subscription([weak, id]() {
if (const auto state = weak.lock())
std::erase_if(state->entries, [id](const Entry& entry) { return entry.id == id; });
});
}
private:
struct Entry {
std::uint64_t id;
ChangeCallback callback;
};
struct ObserverState {
std::uint64_t nextId = 1;
std::vector<Entry> entries;
};
eve::property_access::PropertySchema schema_;
std::map<std::string, eve::Value> values_;
std::uint64_t revision_ = 0;
std::shared_ptr<ObserverState> observers_;
};