summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2023-01-08 22:31:08 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2023-01-31 21:27:00 +0100
commitc2df0381313ffe5e155b7dc3d6d4c7271a4b73a2 (patch)
tree0f9385be3a08e45045291ed52b692a3579db394d
parented40a224e4256867d5f8c9f7c4c3ea998d4b88ce (diff)
Contact name setting and property lookup
-rw-r--r--include/erebos/contact.h2
-rw-r--r--src/contact.cpp40
-rw-r--r--src/main.cpp27
-rw-r--r--test/contact.test62
4 files changed, 121 insertions, 10 deletions
diff --git a/include/erebos/contact.h b/include/erebos/contact.h
index ef9c3b6..24a4c89 100644
--- a/include/erebos/contact.h
+++ b/include/erebos/contact.h
@@ -32,12 +32,14 @@ public:
optional<Identity> identity() const;
optional<string> customName() const;
+ Contact customName(const Storage & st, const string & name) const;
string name() const;
bool operator==(const Contact &) const;
bool operator!=(const Contact &) const;
vector<Stored<ContactData>> data() const;
+ Digest leastRoot() const;
private:
struct Priv;
diff --git a/src/contact.cpp b/src/contact.cpp
index 796e896..787831c 100644
--- a/src/contact.cpp
+++ b/src/contact.cpp
@@ -2,8 +2,11 @@
#include "identity.h"
+#include <array>
+
using namespace erebos;
+using std::array;
using std::move;
DEFINE_SHARED_TYPE(Set<Contact>,
@@ -34,6 +37,19 @@ optional<string> Contact::customName() const
return p->name;
}
+Contact Contact::customName(const Storage & st, const string & name) const
+{
+ auto cdata = st.store(ContactData {
+ .prev = p->data,
+ .identity = {},
+ .name = name,
+ });
+
+ return Contact(shared_ptr<Contact::Priv>(new Contact::Priv {
+ .data = { cdata },
+ }));
+}
+
string Contact::name() const
{
if (auto cust = customName())
@@ -59,13 +75,33 @@ vector<Stored<ContactData>> Contact::data() const
return p->data;
}
+Digest Contact::leastRoot() const
+{
+ if (p->data.empty())
+ return Digest(array<uint8_t, Digest::size> {});
+
+ vector<Digest> roots;
+ for (const auto & d : p->data)
+ for (const auto & r : d.ref().roots())
+ roots.push_back(r);
+ roots.erase(std::unique(roots.begin(), roots.end()), roots.end());
+ return roots[0];
+}
+
void Contact::Priv::init()
{
std::call_once(initFlag, [this]() {
- // TODO: property lookup
- identity = Identity::load(data[0]->identity);
+ vector<Stored<Signed<IdentityData>>> idata;
+ for (const auto & c : findPropertyComponents<Contact>(data, "identity"))
+ for (const auto & i : c->identity)
+ idata.push_back(i);
+
+ identity = Identity::load(idata);
if (identity)
name = identity->name();
+
+ if (auto opt = findPropertyComponent<Contact>(data, "name"))
+ name = (*opt)->name;
});
}
diff --git a/src/main.cpp b/src/main.cpp
index 12f46ac..edf68d7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -465,7 +465,7 @@ void contactList(const vector<string> &)
};
for (const auto & c : h->behavior().lens<SharedState>().lens<Set<Contact>>().get().view(cmp)) {
ostringstream ss;
- ss << "contact-list-item " << c.name();
+ ss << "contact-list-item " << string(c.leastRoot()) << " " << c.name();
if (auto id = c.identity())
if (auto iname = id->name())
ss << " " << *iname;
@@ -474,6 +474,30 @@ void contactList(const vector<string> &)
printLine("contact-list-done");
}
+void contactSetName(const vector<string> & args)
+{
+ auto id = args.at(0);
+ auto name = args.at(1);
+
+ auto cmp = [](const Contact & x, const Contact & y) {
+ return x.data() < y.data();
+ };
+ for (const auto & c : h->behavior().lens<SharedState>().lens<Set<Contact>>().get().view(cmp)) {
+ if (string(c.leastRoot()) == id) {
+ auto nh = h->update([&] (const Stored<LocalState> & loc) {
+ auto st = loc.ref().storage();
+ auto cc = c.customName(st, name);
+ auto contacts = loc->shared<Set<Contact>>();
+ return st.store(loc->shared<Set<Contact>>(contacts.add(st, cc)));
+ });
+ if (nh)
+ *h = *nh;
+ break;
+ }
+ }
+ printLine("contact-set-name-done");
+}
+
vector<Command> commands = {
{ "store", store },
{ "stored-generation", storedGeneration },
@@ -496,6 +520,7 @@ vector<Command> commands = {
{ "contact-accept", contactAccept },
{ "contact-reject", contactReject },
{ "contact-list", contactList },
+ { "contact-set-name", contactSetName },
};
}
diff --git a/test/contact.test b/test/contact.test
index b0005fd..084dd93 100644
--- a/test/contact.test
+++ b/test/contact.test
@@ -76,12 +76,12 @@ test Contact:
send "contact-list" to p1
expect from p1:
- /contact-list-item Owner2 Owner2/
+ /contact-list-item [a-z0-9#]+ Owner2 Owner2/
/contact-list-(.*)/ capture done1_1
guard done1_1 == "done"
send "contact-list" to p2
expect from p2:
- /contact-list-item Owner1 Owner1/
+ /contact-list-item [a-z0-9#]+ Owner1 Owner1/
/contact-list-(.*)/ capture done1_2
guard done1_2 == "done"
@@ -118,7 +118,7 @@ test Contact:
send "contact-list" to p3
expect from p3:
- /contact-list-item Owner1 Owner1/
+ /contact-list-item [a-z0-9#]+ Owner1 Owner1/
/contact-list-(.*)/ capture done2_3
guard done2_3 == "done"
@@ -129,8 +129,8 @@ test Contact:
send "contact-list" to p4
expect from p4:
- /contact-list-item Owner2 Owner2/
- /contact-list-item Owner3 Owner3/
+ /contact-list-item ([a-z0-9#]+) Owner2 Owner2/ capture c4_2
+ /contact-list-item ([a-z0-9#]+) Owner3 Owner3/ capture c4_3
/contact-list-(.*)/ capture done2_4
guard done2_4 == "done"
@@ -143,7 +143,55 @@ test Contact:
send "contact-list" to p1
expect from p1:
- /contact-list-item Owner2 Owner2/
- /contact-list-item Owner3 Owner3/
+ /contact-list-item ([a-z0-9#]+) Owner2 Owner2/ capture c1_2
+ /contact-list-item ([a-z0-9#]+) Owner3 Owner3/ capture c1_3
/contact-list-(.*)/ capture done2_1
guard done2_1 == "done"
+
+ # Update custom name
+
+ send "contact-set-name $c4_2 Custom2" to p4
+ expect /contact-set-name-done/ from p4
+
+ send "contact-list" to p4
+ expect from p4:
+ /contact-list-item $c4_2 Custom2 Owner2/
+ /contact-list-item $c4_3 Owner3 Owner3/
+ /contact-list-(.*)/ capture done3_4
+ guard done3_4 == "done"
+
+ send "shared-state-get" to p4
+ expect /shared-state-get (.*)/ from p4 capture s4b
+ send "shared-state-wait $s4b" to p1
+ expect /shared-state-wait $s4b/ from p1
+
+ send "contact-list" to p1
+ expect from p1:
+ /contact-list-item $c4_2 Custom2 Owner2/
+ /contact-list-item $c4_3 Owner3 Owner3/
+ /contact-list-(.*)/ capture done3_1
+ guard done3_1 == "done"
+
+ send "contact-set-name $c1_2 Custom2B" to p1
+ expect /contact-set-name-done/ from p1
+ send "contact-set-name $c1_3 Custom3B" to p1
+ expect /contact-set-name-done/ from p1
+
+ send "contact-list" to p1
+ expect from p1:
+ /contact-list-item $c1_2 Custom2B Owner2/
+ /contact-list-item $c1_3 Custom3B Owner3/
+ /contact-list-(.*)/ capture done4_1
+ guard done4_1 == "done"
+
+ send "shared-state-get" to p1
+ expect /shared-state-get (.*)/ from p1 capture s1b
+ send "shared-state-wait $s1b" to p4
+ expect /shared-state-wait $s1b/ from p4
+
+ send "contact-list" to p4
+ expect from p4:
+ /contact-list-item $c4_2 Custom2B Owner2/
+ /contact-list-item $c4_3 Custom3B Owner3/
+ /contact-list-(.*)/ capture done4_4
+ guard done4_4 == "done"