diff options
-rw-r--r-- | include/erebos/storage.h | 31 | ||||
-rw-r--r-- | test/storage.test | 51 |
2 files changed, 75 insertions, 7 deletions
diff --git a/include/erebos/storage.h b/include/erebos/storage.h index 01aeada..c506dfd 100644 --- a/include/erebos/storage.h +++ b/include/erebos/storage.h @@ -528,6 +528,7 @@ void filterAncestors(std::vector<Stored<T>> & xs) } template<class T> class WatchedHead; +template<class T> class HeadBhv; template<class T> class Head @@ -562,8 +563,13 @@ template<class T> class WatchedHead : public Head<T> { friend class Head<T>; + friend class HeadBhv<T>; + + WatchedHead(const Head<T> & h): + Head<T>(h), watcherId(-1) {} WatchedHead(const Head<T> & h, int watcherId): Head<T>(h), watcherId(watcherId) {} + int watcherId; public: @@ -588,15 +594,26 @@ class HeadBhv : public BhvSource<T> { public: HeadBhv(const Head<T> & head): - whead(head.watch([this] (const Head<T> & cur) { - BhvCurTime ctime; - whead = cur; - BhvImplBase::updated(ctime); - })) {} + whead(head) + {} T get(const BhvCurTime &, const std::monostate &) const { return *whead; } private: + friend class Head<T>; + + void init() + { + whead = whead.watch([wp = weak_ptr<BhvImplBase>(BhvImplBase::shared_from_this()), this] (const Head<T> & cur) { + // make sure this object still exists + if (auto ptr = wp.lock()) { + BhvCurTime ctime; + whead = cur; + BhvImplBase::updated(ctime); + } + }); + } + WatchedHead<T> whead; }; @@ -665,7 +682,9 @@ template<typename T> Bhv<T> Head<T>::behavior() const { auto cur = reload(); - return make_shared<HeadBhv<T>>(cur ? *cur : *this); + auto ret = make_shared<HeadBhv<T>>(cur ? *cur : *this); + ret->init(); + return ret; } template<class T> diff --git a/test/storage.test b/test/storage.test index 17859cc..6267beb 100644 --- a/test/storage.test +++ b/test/storage.test @@ -1,4 +1,4 @@ -test: +test Storage: spawn as p1 # Root finding @@ -150,3 +150,52 @@ test: /stored-set-item $r2_3/ /stored-set-(.*)/ capture done6 guard done6 == "done" + + +test StorageWatcher: + spawn as p1 + spawn as p2 + send "create-identity Device1 Owner" to p1 + send "create-identity Device2" to p2 + send "watch-local-identity" to p1 + send "watch-local-identity" to p2 + send "start-server" to p1 + send "start-server" to p2 + expect from p1: + /local-identity Device1 Owner/ + /peer 1 addr ${p2.node.ip} 29665/ + /peer 1 id Device2/ + expect from p2: + /local-identity Device2/ + /peer 1 addr ${p1.node.ip} 29665/ + /peer 1 id Device1 Owner/ + + local: + send "attach-to 1" to p2 + expect /attach-request 1 ([0-9]*)/ from p1 capture code1 + expect /attach-response 1 ([0-9]*)/ from p2 capture code2 + guard code1 == code2 + + send "attach-accept 1" to p1 + send "attach-accept 1" to p2 + expect /attach-request-done 1/ from p1 + expect /attach-response-done 1/ from p2 + expect /local-identity Device2 Owner/ from p2 + expect /peer 1 id Device2 Owner/ from p1 + + for i in [1..5]: + send "update-local-identity Owner2" to p1 + send "shared-state-get" to p1 + expect /shared-state-get (.*)/ from p1 capture s1 + + send "shared-state-wait $s1" to p2 + expect /shared-state-wait $s1/ from p2 + + send "update-local-identity Owner1" to p1 + send "shared-state-get" to p1 + expect /shared-state-get (.*)/ from p1 capture s2 + + send "shared-state-wait $s1" to p2 + send "shared-state-wait $s2" to p2 + expect /shared-state-wait $s1/ from p2 + expect /shared-state-wait $s2/ from p2 |