public void ORDictionary_must_be_able_to_update_ORSet_entry_with_Remove_then_Merge_then_Add() { var m1 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node1, "a", ORSet.Create(_node1, "A")) .SetItem(_node1, "b", ORSet.Create(_node1, "B01").Add(_node1, "B02").Add(_node1, "B03")); var m2 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node2, "c", ORSet.Create(_node2, "C")); var merged1 = m1.Merge(m2); var m3 = merged1.Remove(_node1, "b"); var merged2 = merged1.Merge(m3); Assert.Equal(ImmutableHashSet.Create("A"), merged2["a"].Elements); Assert.DoesNotContain("b", merged2.Entries.Keys); Assert.Equal(ImmutableHashSet.Create("C"), merged2["c"].Elements); var m4 = merged2.SetItem(_node1, "b", ORSet.Create(_node1, "B2")); var m5 = merged2.AddOrUpdate(_node2, "c", ORSet <string> .Empty, old => old.Add(_node2, "C2")) .SetItem(_node2, "b", ORSet.Create(_node2, "B3")); var merged3 = m5.Merge(m4); Assert.Equal(ImmutableHashSet.Create("A"), merged3["a"].Elements); Assert.Equal(ImmutableHashSet.Create("B2", "B3"), merged3["b"].Elements); Assert.Equal(ImmutableHashSet.Create("C", "C2"), merged3["c"].Elements); }
public void ReplicatedDataSerializer_should_serialize_ORDictionary_delta() { CheckSerialization(ORDictionary <string, GSet <string> > .Empty .SetItem(_address1, "a", GSet.Create("A")) .SetItem(_address2, "b", GSet.Create("B")) .Delta); CheckSerialization(ORDictionary <string, GSet <string> > .Empty .SetItem(_address1, "a", GSet.Create("A")) .ResetDelta() .Remove(_address2, "a") .Delta); CheckSerialization(ORDictionary <string, GSet <string> > .Empty .SetItem(_address1, "a", GSet.Create("A")) .Remove(_address2, "a") .Delta); CheckSerialization(ORDictionary <string, ORSet <string> > .Empty .SetItem(_address1, "a", ORSet.Create(_address1, "A")) .SetItem(_address2, "b", ORSet.Create(_address2, "B")) .AddOrUpdate(_address1, "a", ORSet <string> .Empty, old => old.Add(_address1, "C")) .Delta); CheckSerialization(ORDictionary <string, ORSet <string> > .Empty .ResetDelta() .AddOrUpdate(_address1, "a", ORSet <string> .Empty, old => old.Add(_address1, "C")) .Delta); }
public void ORDictionary_must_be_able_to_update_an_entry() { var m1 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node1, "a", ORSet.Create(_node1, "A")) .SetItem(_node1, "b", ORSet.Create(_node1, "B01").Add(_node1, "B02").Add(_node1, "B03")); var m2 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node2, "c", ORSet.Create(_node2, "C")); var merged1 = m1.Merge(m2); var m3 = merged1.AddOrUpdate(_node1, "b", ORSet <string> .Empty, old => old.Clear(_node1).Add(_node1, "B2")); var merged2 = merged1.Merge(m3); merged2["a"].Elements.Should().BeEquivalentTo("A"); merged2["b"].Elements.Should().BeEquivalentTo("B2"); merged2["c"].Elements.Should().BeEquivalentTo("C"); var m4 = merged1.AddOrUpdate(_node2, "b", ORSet <string> .Empty, old => old.Add(_node2, "B3")); var merged3 = m3.Merge(m4); merged3["a"].Elements.Should().BeEquivalentTo("A"); merged3["b"].Elements.Should().BeEquivalentTo("B2", "B3"); merged3["c"].Elements.Should().BeEquivalentTo("C"); }
public void ORDictionary_must_be_able_to_update_ORSet_entry_with_Remove_then_Add() { var m1 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node1, "a", ORSet.Create(_node1, "A01")) .AddOrUpdate(_node1, "a", ORSet <string> .Empty, old => old.Add(_node1, "A02")) .AddOrUpdate(_node1, "a", ORSet <string> .Empty, old => old.Add(_node1, "A03")) .SetItem(_node1, "b", ORSet.Create(_node1, "B01").Add(_node1, "B02").Add(_node1, "B03")); var m2 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node2, "c", ORSet.Create(_node2, "C")); var merged1 = m1.Merge(m2); // note that remove + put work because the new VersionVector version is incremented // from a global counter var m3 = merged1.Remove(_node1, "b").SetItem(_node1, "b", ORSet.Create(_node1, "B2")); var merged2 = merged1.Merge(m3); Assert.Equal(ImmutableHashSet.Create("A01", "A02", "A03"), merged2["a"].Elements); Assert.Equal(ImmutableHashSet.Create("B2"), merged2["b"].Elements); Assert.Equal(ImmutableHashSet.Create("C"), merged2["c"].Elements); var m4 = merged1.AddOrUpdate(_node2, "b", ORSet <string> .Empty, old => old.Add(_node2, "B3")); var merged3 = m3.Merge(m4); Assert.Equal(ImmutableHashSet.Create("A01", "A02", "A03"), merged3["a"].Elements); Assert.Equal(ImmutableHashSet.Create("B2", "B3"), merged3["b"].Elements); Assert.Equal(ImmutableHashSet.Create("C"), merged3["c"].Elements); }
public void ORSet_must_verify_removed_after_merge_2() { var a = ORSet.Create(_node1, "Z"); var b = ORSet.Create(_node2, "Z"); // replicate node3 var c = a; var a2 = a.Remove(_node1, "Z"); // replicate b to node1, now node1 has node2's 'Z' var a3 = a2.Merge(b); a3.Elements.Should().BeEquivalentTo("Z"); // Remove node2's 'Z' var b2 = b.Remove(_node2, "Z"); // Replicate c to node2, now node2 has node1's old 'Z' var b3 = b2.Merge(c); b3.Elements.Should().BeEquivalentTo("Z"); // Merge everytyhing a3.Merge(c).Merge(b3).Elements.Should().BeEmpty(); a3.Merge(b3).Merge(c).Elements.Should().BeEmpty(); c.Merge(a3).Merge(b3).Elements.Should().BeEmpty(); c.Merge(b3).Merge(a3).Elements.Should().BeEmpty(); b3.Merge(c).Merge(a3).Elements.Should().BeEmpty(); b3.Merge(a3).Merge(c).Elements.Should().BeEmpty(); }
public void ORSet_must_verify_removed_after_merge() { // Add Z at node1 replica var a = ORSet.Create(_node1, "Z"); // Replicate it to some node3, i.e. it has dot 'Z'->{node1 -> 1} var c = a; // Remove Z at node1 replica var a2 = a.Remove(_node1, "Z"); // Add Z at node2, a new replica var b = ORSet.Create(_node2, "Z"); // Replicate b to node1, so now node1 has a Z, the one with a Dot of // {node2 -> 1} and version vector of [{node1 -> 1}, {node2 -> 1}] var a3 = b.Merge(a2); a3.Elements.Should().BeEquivalentTo("Z"); // Remove the 'Z' at node2 replica var b2 = b.Remove(_node2, "Z"); // Both node3 (c) and node1 (a3) have a 'Z', but when they merge, there should be // no 'Z' as node3 (c)'s has been removed by node1 and node1 (a3)'s has been removed by // node2 c.Elements.Should().BeEquivalentTo("Z"); a3.Elements.Should().BeEquivalentTo("Z"); b2.Elements.Should().BeEmpty(); a3.Merge(c).Merge(b2).Elements.Should().BeEmpty(); a3.Merge(b2).Merge(c).Elements.Should().BeEmpty(); c.Merge(a3).Merge(b2).Elements.Should().BeEmpty(); c.Merge(b2).Merge(a3).Elements.Should().BeEmpty(); b2.Merge(c).Merge(a3).Elements.Should().BeEmpty(); b2.Merge(a3).Merge(c).Elements.Should().BeEmpty(); }
public void A_ORDictionary_should_be_able_to_update_an_entry() { var m1 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node1, "a", ORSet.Create(_node1, "A")) .SetItem(_node1, "b", ORSet.Create(_node1, "B01").Add(_node1, "B02").Add(_node1, "B03")); var m2 = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node2, "c", ORSet.Create(_node2, "C")); var merged1 = m1.Merge(m2); var m3 = merged1.AddOrUpdate(_node1, "b", ORSet <string> .Empty, old => old.Clear(_node1).Add(_node1, "B2")); var merged2 = merged1.Merge(m3); Assert.Equal(ImmutableHashSet.Create("A"), merged2["a"].Elements); Assert.Equal(ImmutableHashSet.Create("B2"), merged2["b"].Elements); Assert.Equal(ImmutableHashSet.Create("C"), merged2["c"].Elements); var m4 = merged1.AddOrUpdate(_node2, "b", ORSet <string> .Empty, old => old.Add(_node2, "B3")); var merged3 = m3.Merge(m4); Assert.Equal(ImmutableHashSet.Create("A"), merged3["a"].Elements); Assert.Equal(ImmutableHashSet.Create("B2", "B3"), merged3["b"].Elements); Assert.Equal(ImmutableHashSet.Create("C"), merged3["c"].Elements); }
public void ORDictionary_must_not_allow_SetItem_for_ORSet_elements_type() { var m = ORDictionary <string, ORSet <string> > .Empty .SetItem(_node1, "a", ORSet.Create(_node1, "A")); Assert.Throws <ArgumentException>(() => m.SetItem(_node1, "a", ORSet.Create(_node1, "B"))); }
public void ORSet_must_verify_disjoint_Merge() { var a1 = ORSet.Create(_node1, "bar"); var b1 = ORSet.Create(_node2, "baz"); var c = a1.Merge(b1); var a2 = a1.Remove(_node1, "bar"); var d = a2.Merge(c); d.Elements.Should().BeEquivalentTo("baz"); }
public void ORDictionary_must_have_usual_anomalies_for_remove_with_update_scenario() { // please note that the current ORMultiMap has the same anomaly // because the condition of keeping global vvector is violated // by removal of the whole entry for the removed key "b" which results in removal of it's value's vvector var m1 = ORDictionary.Create(_node1, "a", ORSet.Create(_node1, "A")).SetItem(_node1, "b", ORSet.Create(_node1, "B")); var m2 = ORDictionary.Create(_node2, "c", ORSet.Create(_node2, "C")); // m1 - node1 gets the update from m2 var merged1 = m1.Merge(m2); // m2 - node2 gets the update from m1 var merged2 = m2.Merge(m1); // RACE CONDITION ahead! var m3 = merged1.ResetDelta().Remove(_node1, "b"); // let's imagine that m3 (node1) update gets propagated here (full state or delta - doesn't matter) // and is in flight, but in the meantime, an element is being added somewhere else (m4 - node2) // and the update is propagated before the update from node1 is merged var m4 = merged2.ResetDelta().AddOrUpdate(_node2, "b", ORSet <string> .Empty, x => x.Add(_node2, "B2")); // and later merged on node1 var merged3 = m3.Merge(m4); // and the other way round... var merged4 = m4.Merge(m3); // result - the element "B" is kept on both sides... merged3.Entries["a"].Elements.Should().BeEquivalentTo("A"); merged3.Entries["b"].Elements.Should().BeEquivalentTo("B", "B2"); merged3.Entries["c"].Elements.Should().BeEquivalentTo("C"); merged4.Entries["a"].Elements.Should().BeEquivalentTo("A"); merged4.Entries["b"].Elements.Should().BeEquivalentTo("B", "B2"); merged4.Entries["c"].Elements.Should().BeEquivalentTo("C"); // but if the timing was slightly different, so that the update from node1 // would get merged just before update on node2: var merged5 = m2.Merge(m3) .ResetDelta() .AddOrUpdate(_node2, "b", ORSet <string> .Empty, x => x.Add(_node2, "B2")); // the update propagated ... and merged on node1: var merged6 = m3.Merge(merged5); // then the outcome is different... because the vvector of value("b") was lost... merged5.Entries["a"].Elements.Should().BeEquivalentTo("A"); // this time it's different... merged5.Entries["b"].Elements.Should().BeEquivalentTo("B2"); merged5.Entries["c"].Elements.Should().BeEquivalentTo("C"); merged6.Entries["a"].Elements.Should().BeEquivalentTo("A"); // this time it's different... merged6.Entries["b"].Elements.Should().BeEquivalentTo("B2"); merged6.Entries["c"].Elements.Should().BeEquivalentTo("C"); }
public void ORDictionary_must_not_have_anomalies_for_remove_with_update_scenario_and_deltas_7() { var m1 = ORDictionary.Create(_node1, "a", ORSet.Create(_node1, "A")) .SetItem(_node1, "b", ORSet.Create(_node1, "B1")) .Remove(_node1, "b"); var m2 = ORDictionary.Create(_node1, "a", ORSet.Create(_node1, "A")) .SetItem(_node1, "b", ORSet.Create(_node1, "B2")); var m2d = m2.ResetDelta().Remove(_node1, "b"); var m2u = m2.ResetDelta() .AddOrUpdate(_node1, "b", ORSet <string> .Empty, x => x.Add(_node1, "B3")) .AddOrUpdate(_node2, "b", ORSet <string> .Empty, x => x.Add(_node2, "B4")); var merged1 = m1.Merge(m2d).MergeDelta(m2u.Delta); merged1.Entries["a"].Elements.Should().BeEquivalentTo("A"); // note that B1 is lost as it was added and removed earlier in timeline than B2 merged1.Entries["b"].Elements.Should().BeEquivalentTo("B2", "B3", "B4"); }
public void ReplicatedDataSerializer_should_serialize_ORSet() { CheckSerialization(ORSet <string> .Empty); CheckSerialization(ORSet.Create(_address1, "a")); CheckSerialization(ORSet.Create(_address1, "a").Add(_address2, "a")); CheckSerialization(ORSet.Create(_address1, "a").Remove(_address2, "a")); CheckSerialization(ORSet.Create(_address1, "a").Add(_address2, "b").Remove(_address1, "a")); CheckSerialization(ORSet.Create(_address1, 1).Add(_address2, 2)); CheckSerialization(ORSet.Create(_address1, 1L).Add(_address2, 2L)); CheckSerialization(ORSet.Create <object>(_address1, "a").Add(_address2, 2).Add(_address3, 3L).Add(_address3, _address3)); var s1 = ORSet.Create(_address1, "a").Add(_address2, "b"); var s2 = ORSet.Create(_address2, "b").Add(_address1, "a"); CheckSameContent(s1.Merge(s2), s2.Merge(s1)); var s3 = ORSet.Create <object>(_address1, "a").Add(_address2, 17).Remove(_address3, 17); var s4 = ORSet.Create <object>(_address2, 17).Remove(_address3, 17).Add(_address1, "a"); CheckSameContent(s3.Merge(s4), s4.Merge(s3)); }
public void ORDictionary_must_not_have_anomalies_for_remove_with_update_scenario_and_deltas_6() { var m1 = ORDictionary.Create(_node1, "a", ORSet.Create(_node1, "A")).SetItem(_node1, "b", ORSet.Create(_node1, "B")); var m2 = ORDictionary.Create(_node2, "b", ORSet.Create(_node2, "B3")); var merged1 = m1.Merge(m2); var m3 = merged1.ResetDelta().Remove(_node1, "b"); var m4 = merged1.ResetDelta().Remove(_node2, "b") .AddOrUpdate(_node2, "b", ORSet <string> .Empty, x => x.Add(_node2, "B1")) .AddOrUpdate(_node2, "b", ORSet <string> .Empty, x => x.Add(_node2, "B2")); var merged2 = m3.Merge(m4); merged2.Entries["a"].Elements.Should().BeEquivalentTo("A"); // note that B is not included, because it was removed in both timelines merged2.Entries["b"].Elements.Should().BeEquivalentTo("B1", "B2"); var merged3 = m3.MergeDelta(m4.Delta); merged3.Entries["a"].Elements.Should().BeEquivalentTo("A"); // note that B is not included, because it was removed in both timelines merged3.Entries["b"].Elements.Should().BeEquivalentTo("B1", "B2"); }