diff options
| -rw-r--r-- | include/erebos/contact.h | 2 | ||||
| -rw-r--r-- | src/contact.cpp | 40 | ||||
| -rw-r--r-- | src/main.cpp | 27 | ||||
| -rw-r--r-- | test/contact.test | 62 | 
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" |