/** * Replication Benchmarker * https://github.com/score-team/replication-benchmarker/ * Copyright (C) 2013 LORIA / Inria / SCORE Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package crdt.set; import crdt.CRDTMessage; import crdt.Factory; import crdt.PreconditionException; import java.util.*; import static org.junit.Assert.*; /** * * @author score */ public class CrdtSetGeneric<T, L> { public void runTests(Factory<CRDTSet> sf) throws PreconditionException { testadd(sf.create()); testremove(sf.create()); testReadd(sf.create()); testLookupAddThenRemove(sf.create()); testLookupAfterAdd(sf.create()); testApplyAddThenDel(sf.create(), sf.create()); testApplyRemoveConcurrent(sf.create(), sf.create()); testApplyRemoveConcurrent2(sf.create(), sf.create(), sf.create()); } public void testadd(CRDTSet set) throws PreconditionException { set.innerAdd('a'); set.innerAdd(123); set.innerAdd("test"); HashSet s = new HashSet(){{add('a');add('a');add(123);add("test");}}; assertEquals(s, set.lookup()); assertTrue(set.contains('a')); } public void testAddException(CRDTSet set) throws PreconditionException{ set.add('a'); set.add("testString"); set.add('a'); fail("Add element that exists in set not detected"); } public void testremove(CRDTSet set) throws PreconditionException{ set.add('a'); set.add("testString"); set.innerRemove('a'); HashSet s = new HashSet(){{add("testString");}}; assertEquals(s, set.lookup()); assertFalse(set.contains('a')); } public void testRemoveException(CRDTSet set) throws PreconditionException{ set.add('a'); set.remove(123); fail("Delete an element that does not exist in the set not detected"); } /* * test lookup after innerAdd elements * compare lookup of CRDTset with Set of element */ public void testLookupAfterAdd(CRDTSet set) throws PreconditionException{ Set tps2 = new HashSet(); tps2.add('a'); tps2.add("TestString"); tps2.add(123); set.innerAdd('a'); set.innerAdd("TestString"); set.innerAdd(123); assertEquals(tps2, set.lookup()); } /* * test lookup after readd elements * compare lookup of CRDTset with Set of element */ public void testReadd(CRDTSet set) throws PreconditionException{ Set tps2 = new HashSet(); tps2.add('a'); tps2.add('b'); set.innerAdd('a'); set.innerAdd('b'); set.innerRemove('b'); set.innerAdd('b'); assertEquals(tps2, set.lookup()); } /* * test lookup after after innerAdd and innerRemove elements * compare lookup of CRDTset with Set of element */ public void testLookupAddThenRemove(CRDTSet set) throws PreconditionException{ Set tps2 = new HashSet(); tps2.add('a'); tps2.add('b'); set.innerAdd('a'); set.innerAdd("TestString"); set.innerAdd(123); set.innerAdd('b'); set.innerRemove("TestString"); set.innerRemove(123); assertEquals(tps2, set.lookup()); } /* * Test simple applyRemote of two CRDTSet * lookup must be equal * Add --> apply * apply <-- innerRemove */ public void testApplyAddThenDel(CRDTSet set, CRDTSet cs) throws PreconditionException{ CRDTMessage m1 = set.innerAdd('a'); CRDTMessage m2 = set.innerAdd('b'); CRDTMessage m3 = set.innerAdd('c'); cs.applyRemote(m1); cs.applyRemote(m2); cs.applyRemote(m3); assertEquals(set.lookup(), cs.lookup()); CRDTMessage m4 = cs.innerRemove('a'); CRDTMessage m5 = cs.innerRemove('b'); set.applyRemote(m4); set.applyRemote(m5); Set<T> s = new HashSet(){{add('c');}}; assertEquals(s,set.lookup()); assertEquals(set.lookup(), cs.lookup()); } /* * Test Convergence applyRemote * (Add) concurrent with (Add-innerRemove) of the same element * Add --> * <-- innerAdd * <-- innerRemove * then apply */ public Set<T> testApplyConcurAddDel(CRDTSet set1, CRDTSet set2) throws PreconditionException { CRDTMessage m1 = set1.innerAdd('a'); CRDTMessage m2 = set1.innerAdd('b'); m1=m1.concat(m2); CRDTMessage m3 = set2.innerAdd('a'); CRDTMessage m4 = set2.innerRemove('a'); m3=m3.concat(m4); set2.applyRemote(m1); set1.applyRemote(m3); assertEquals(set1.lookup(), set2.lookup()); return (Set<T>) set1.lookup(); } /** * Test Convergence applyRemote * (Add) concurrent with (Add-innerRemove) of the same element * Add --> * <-- innerAdd * <-- innerRemove * then apply */ public Set<T> testApplyConcurAddThenDel(CRDTSet set1, CRDTSet set2) throws PreconditionException { CRDTMessage m1 = set1.innerAdd('a'); CRDTMessage m2 = set2.innerAdd('a'); set1.applyRemote(m2); CRDTMessage m3 = set2.innerRemove('a'); set1.applyRemote(m3); set2.applyRemote(m1); assertEquals(set1.lookup(), set2.lookup()); return (Set<T>) set1.lookup(); } /* * Test Convergence applyRemote * (Add) concurrent with (Add-innerRemove) of the same element * Add --> * <-- innerAdd * applyRemote * <-- innerRemove */ public Set<T> testApplyRemoveAfterConcuAdd(CRDTSet set1, CRDTSet set2) throws PreconditionException { CRDTMessage m1 = set1.innerAdd('a'); CRDTMessage m2 = set2.innerAdd('a'); set2.applyRemote(m1); set1.applyRemote(m2); CRDTMessage m3 = set2.innerRemove('a'); set1.applyRemote(m3); assertEquals(set1.lookup(), set2.lookup()); return (Set<T>)set1.lookup(); } /* * Test Convergence applyRemote * two innerRemove concurrent (delete an element removed) * Add --> apply * <-- innerRemove * innerRemove --> * innerAdd --> */ public void testApplyRemoveConcurrent(CRDTSet set1, CRDTSet set2) throws PreconditionException { CRDTMessage m1 = set1.innerAdd('a'); set2.applyRemote(m1); CRDTMessage m2 = set2.innerRemove('a'); CRDTMessage m3 = set1.innerRemove('a'); set2.applyRemote(m3); set1.applyRemote(m2); assertEquals(set1.lookup(), set2.lookup()); assertEquals(set1.lookup(), new HashSet()); CRDTMessage m4 = set1.innerAdd('a'); set2.applyRemote(m4); Set<T> s = new HashSet(){{add('a');}}; assertEquals(set1.lookup(), set2.lookup()); assertEquals(s, set2.lookup()); } /* * Test Convergence applyRemote * three Replica and replica 3 receive two innerRemove concurrent * P1 : innerAdd --> P2 and P3 * P1 : innerRemove--> P2 and P3 * P2 : innerRemove --> P1 and P3 */ public void testApplyRemoveConcurrent2(CRDTSet set1, CRDTSet set2, CRDTSet set3) throws PreconditionException { CRDTMessage m1 = set1.innerAdd('a'); set2.applyRemote(m1); set3.applyRemote(m1); CRDTMessage m2 = set1.innerRemove('a'); CRDTMessage m3 = set2.innerRemove('a'); set3.applyRemote(m2); set3.applyRemote(m3); set1.applyRemote(m3); set2.applyRemote(m2); assertEquals(set1.lookup(), set2.lookup()); assertEquals(set1.lookup(), set3.lookup()); assertEquals(set1.lookup(), new HashSet()); } }