package org.jgroups.tests; import org.jgroups.Global; import org.jgroups.util.SeqnoList; import org.jgroups.util.Table; import org.jgroups.util.Util; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; /** Tests {@link org.jgroups.util.Table<Integer>} * @author Bela Ban */ @Test(groups=Global.FUNCTIONAL,sequential=false) public class TableTest { public static void testCreation() { Table<Integer> table=new Table<Integer>(3, 10, 0); System.out.println("table = " + table); int size=table.size(); assert size == 0; assert table.get(15) == null; assertIndices(table, 0, 0, 0); } public void testAdd() { Table<Integer> buf=new Table<Integer>(3, 10, 0); buf.add(1, 322649); buf.add(2, 100000); System.out.println("buf = " + buf); assert buf.size() == 2; } public static void testAddition() { Table<Integer> table=new Table<Integer>(3, 10, 0); assert !table.add(0, 0); addAndGet(table, 1); addAndGet(table, 5); addAndGet(table, 9); addAndGet(table, 10); addAndGet(table, 11); addAndGet(table, 19); addAndGet(table, 20); addAndGet(table, 29); System.out.println("table: " + table.dump()); assert table.size() == 8; int size=table.computeSize(); assert size == 8; assert table.size() == table.computeSize(); assert table.capacity() == 30; assertIndices(table, 0, 0, 29); } public static void testAdditionWithOffset() { Table<Integer> table=new Table<Integer>(3, 10, 100); addAndGet(table, 101); addAndGet(table, 105); addAndGet(table, 109); addAndGet(table, 110); addAndGet(table, 111); addAndGet(table, 119); addAndGet(table, 120); addAndGet(table, 129); System.out.println("table: " + table.dump()); assert table.size() == 8; assert table.capacity() == 30; assertIndices(table, 100, 100, 129); } public static void testAdditionWithOffset2() { Table<Integer> table=new Table<Integer>(3, 10, 2); addAndGet(table, 1000); addAndGet(table, 1001); table.compact(); addAndGet(table, 1005); addAndGet(table, 1009); addAndGet(table, 1010); addAndGet(table, 1011); addAndGet(table, 1019); addAndGet(table, 1020); addAndGet(table, 1029); System.out.println("table: " + table.dump()); assert table.size() == 9; assertIndices(table, 2, 2, 1029); } public void testAddWithWrapAround() { Table<Integer> buf=new Table<Integer>(3, 10, 5); for(int i=6; i <=15; i++) assert buf.add(i, i) : "addition of seqno " + i + " failed"; System.out.println("buf = " + buf); for(int i=0; i < 3; i++) { Integer val=buf.remove(false); System.out.println("removed " + val); assert val != null; } System.out.println("buf = " + buf); long low=buf.getLow(); buf.purge(8); System.out.println("buf = " + buf); assert buf.getLow() == 8; for(long i=low; i <= 8; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; for(int i=16; i <= 18; i++) assert buf.add(i, i); System.out.println("buf = " + buf); while(buf.remove(false) != null) ; System.out.println("buf = " + buf); assert buf.isEmpty(); assert buf.getNumMissing() == 0; low=buf.getLow(); buf.purge(18); assert buf.getLow() == 18; for(long i=low; i <= 18; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; } public void testAddWithWrapAroundAndRemoveMany() { Table<Integer> buf=new Table<Integer>(3, 10, 5); for(int i=6; i <=15; i++) assert buf.add(i, i) : "addition of seqno " + i + " failed"; System.out.println("buf = " + buf); List<Integer> removed=buf.removeMany(true, 3); System.out.println("removed " + removed); System.out.println("buf = " + buf); for(int i: removed) assert buf._get(i) == null; assertIndices(buf, 8, 8, 15); for(int i=16; i <= 18; i++) assert buf.add(i, i); System.out.println("buf = " + buf); removed=buf.removeMany(true, 0); System.out.println("buf = " + buf); System.out.println("removed = " + removed); assert removed.size() == 10; for(int i: removed) assert buf._get(i) == null; assert buf.isEmpty(); assert buf.getNumMissing() == 0; assertIndices(buf, 18, 18, 18); } public void testAddMissing() { Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,4,5,6)) buf.add(i, i); System.out.println("buf = " + buf); assert buf.size() == 5 && buf.getNumMissing() == 1; Integer num=buf.remove(); assert num == 1; num=buf.remove(); assert num == 2; num=buf.remove(); assert num == null; buf.add(3, 3); System.out.println("buf = " + buf); assert buf.size() == 4 && buf.getNumMissing() == 0; for(int i=3; i <= 6; i++) { num=buf.remove(); System.out.println("buf = " + buf); assert num == i; } num=buf.remove(); assert num == null; } public static void testDuplicateAddition() { Table<Integer> table=new Table<Integer>(3, 10, 0); addAndGet(table, 1); addAndGet(table, 5); addAndGet(table, 9); addAndGet(table, 10); assert !table.add(5,5); assert table.get(5) == 5; assert table.size() == 4; assertIndices(table, 0, 0, 10); } public void testAddWithInvalidSeqno() { Table<Integer> buf=new Table<Integer>(3, 10, 20); boolean success=buf.add(10, 0); assert !success; success=buf.add(20, 0); assert !success; assert buf.isEmpty(); } /** * Runs NUM adder threads, each adder adds 1 (unique) seqno. When all adders are done, we should have * NUM elements in the table. */ public void testConcurrentAdd() { final int NUM=100; final Table<Integer> buf=new Table<Integer>(3, 10, 0); CountDownLatch latch=new CountDownLatch(1); Adder[] adders=new Adder[NUM]; for(int i=0; i < adders.length; i++) { adders[i]=new Adder(latch, i+1, buf); adders[i].start(); } System.out.println("starting threads"); latch.countDown(); System.out.print("waiting for threads to be done: "); for(Adder adder: adders) { try { adder.join(); } catch(InterruptedException e) { e.printStackTrace(); } } System.out.println("OK"); System.out.println("buf = " + buf); assert buf.size() == NUM; } /** * Creates a table and fills it to capacity. Then starts a number of adder threads, each trying to add a * seqno, blocking until there is more space. Each adder will block until the remover removes elements, so the * adder threads get unblocked and can then add their elements to the buffer. */ public void testConcurrentAddAndRemove() throws Exception { final int NUM=5; final Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i=1; i <= 10; i++) buf.add(i, i); // fill the buffer, add() will block now CountDownLatch latch=new CountDownLatch(1); Adder[] adders=new Adder[NUM]; for(int i=0; i < adders.length; i++) { adders[i]=new Adder(latch, i+11, buf); adders[i].start(); } System.out.println("releasing threads"); latch.countDown(); System.out.print("waiting for threads to be done: "); Thread remover=new Thread("Remover") { public void run() { Util.sleep(2000); List<Integer> list=buf.removeMany(true, 5); System.out.println("\nremover: removed = " + list); } }; remover.start(); for(Adder adder: adders) { try { adder.join(); } catch(InterruptedException e) { e.printStackTrace(); } } remover.join(); System.out.println("OK"); System.out.println("buf = " + buf); assert buf.size() == 10; assertIndices(buf, 5, 5, 15); List<Integer> list=buf.removeMany(true, 0); System.out.println("removed = " + list); assert list.size() == 10; for(int i=6; i <=15; i++) assert list.contains(i); assertIndices(buf, 15, 15, 15); } public void testIndex() { Table<Integer> buf=new Table<Integer>(3, 10, 5); assert buf.getHighestDelivered() == 5; assert buf.getHighestReceived() == 5; buf.add(6,6); buf.add(7,7); buf.remove(false); buf.remove(false); long low=buf.getLow(); assert low == 5; buf.purge(4); buf.purge(5); buf.purge(6); buf.purge(7); System.out.println("buf = " + buf); for(long i=low; i <= 7; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; } public void testIndexWithRemoveMany() { Table<Integer> buf=new Table<Integer>(3, 10, 5); assert buf.getHighestDelivered() == 5; assert buf.getHighestReceived() == 5; buf.add(6,6); buf.add(7,7); long low=buf.getLow(); buf.removeMany(true,0); System.out.println("buf = " + buf); for(long i=low; i <= 7; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; assertIndices(buf, 7, 7, 7); } public static void testComputeSize() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(1,2,3,4,5,6,7,8,9,10)) table.add(num, num); System.out.println("table = " + table); assert table.computeSize() == 10; table.removeMany(false, 3); System.out.println("table = " + table); assert table.computeSize() == 7; table.removeMany(true, 4); System.out.println("table = " + table); assert table.computeSize() == table.size(); assert table.computeSize() == 3; } public static void testComputeSize2() { Table<Integer> table=new Table<Integer>(3, 10, 0); table.add(1, 1); System.out.println("table = " + table); assert table.computeSize() == table.size(); assert table.computeSize() == 1; table.remove(false); System.out.println("table = " + table); assert table.computeSize() == table.size(); assert table.computeSize() == 0; } public static void testRemove() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 9; i++) table.add(i,i); table.add(20, 20); System.out.println("table = " + table); assert table.size() == 10; assertIndices(table, 0, 0, 20); int num_null_msgs=table.getNumMissing(); System.out.println("num_null_msgs = " + num_null_msgs); assert num_null_msgs == 10; for(long i=1; i <= 10; i++) // 10 is missing table.remove(); System.out.println("table = " + table); assert table.size() == 1; assertIndices(table, 9, 9, 20); num_null_msgs=table.getNumMissing(); System.out.println("num_null_msgs = " + num_null_msgs); assert num_null_msgs == 10; } public void testRemove2() { final Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,3,4,5)) buf.add(i, i); System.out.println("buf = " + buf); assertIndices(buf, 0, 0, 5); Integer el=buf.remove(true); System.out.println("el = " + el); assert el.equals(1); el=buf.remove(false); // not encouraged ! nullify should always be true or false System.out.println("el = " + el); assert el.equals(2); el=buf.remove(true); System.out.println("el = " + el); assert el.equals(3); } public static void testRemoveMany() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int seqno: Arrays.asList(1,2,3,4,5,7,8,9,10)) table.add(seqno, seqno); System.out.println("table = " + table); assertIndices(table, 0, 0, 10); List<Integer> list=table.removeMany(true,4); System.out.println("list=" + list + ", table=" + table); assert table.size() == 5 && table.getNumMissing() == 1; assert list != null && list.size() == 4; for(int num: Arrays.asList(1,2,3,4)) assert list.contains(num); assertIndices(table, 4, 4, 10); } public void testRemoveMany2() { Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,3,4,5,6,7,9,10)) buf.add(i, i); List<Integer> list=buf.removeMany(false,3); System.out.println("list = " + list); assert list != null && list.size() == 3; list=buf.removeMany(false, 0); System.out.println("list = " + list); assert list != null && list.size() == 4; list=buf.removeMany(false, 10); assert list == null; buf.add(8, 8); list=buf.removeMany(false, 0); System.out.println("list = " + list); assert list != null && list.size() == 3; } public void testRemoveManyWithNulling() { Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,3,4,5,6,7,9,10)) buf.add(i, i); List<Integer> list=buf.removeMany(true, 3); System.out.println("list = " + list); assert list != null && list.size() == 3; for(int i: list) assert buf._get(i) == null; list=buf.removeMany(true, 0); System.out.println("list = " + list); assert list != null && list.size() == 4; for(int i: list) assert buf._get(i) == null; list=buf.removeMany(false, 10); assert list == null; buf.add(8, 8); list=buf.removeMany(true, 0); System.out.println("list = " + list); assert list != null && list.size() == 3; for(int i: list) assert buf._get(i) == null; } public static void testRemoveManyWithWrapping() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int seqno: Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20)) table.add(seqno, seqno); System.out.println("table = " + table); assertIndices(table, 0, 0, 20); assert table.size() == 18 && table.getNumMissing() == 2; List<Integer> list=table.removeMany(true, 0); assert list.size() == 12; assertIndices(table, 12, 12, 20); assert table.size() == 6 && table.getNumMissing() == 2; table.purge(12); assertIndices(table, 12, 12, 20); assert table.size() == 6 && table.getNumMissing() == 2; } public static void testRemoveManyWithWrapping2() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int seqno: Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,18,19,20)) table.add(seqno, seqno); System.out.println("table = " + table); assertIndices(table, 0, 0, 20); assert table.size() == 18 && table.getNumMissing() == 2; List<Integer> list=table.removeMany(false,0); assert list.size() == 12; assertIndices(table, 0, 12, 20); assert table.size() == 6 && table.getNumMissing() == 2; table.purge(12); assertIndices(table, 12, 12, 20); assert table.size() == 6 && table.getNumMissing() == 2; } public static void testForEach() { class MyVisitor<T> implements Table.Visitor<T> { List<int[]> list=new ArrayList<int[]>(20); public boolean visit(long seqno, T element, int row, int column) { System.out.println("#" + seqno + ": " + element + ", row=" + row + ", column=" + column); list.add(new int[]{row,column}); return true; } } MyVisitor<Integer> visitor=new MyVisitor<Integer>(); Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <=20; i++) table.add(i, i); System.out.println("table = " + table); table.forEach(table.getLow()+1, table.getHighestReceived()-1, visitor); int count=1; for(int[] pair: visitor.list) { int row=pair[0], column=pair[1]; if(count < 10) { assert row == 0; assert column == count; } else { assert row == 1; assert column == count - 10; } count++; } } public void testGet() { final Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,3,4,5)) buf.add(i, i); assert buf.get(0) == null; assert buf.get(1) == 1; assert buf.get(10) == null; assert buf.get(5) == 5; assert buf.get(6) == null; } public void testGetList() { final Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i: Arrays.asList(1,2,3,4,5)) buf.add(i, i); List<Integer> elements=buf.get(3,5); System.out.println("elements = " + elements); assert elements != null && elements.size() == 3; assert elements.contains(3) && elements.contains(4) && elements.contains(5); elements=buf.get(4, 10); System.out.println("elements = " + elements); assert elements != null && elements.size() == 2; assert elements.contains(4) && elements.contains(5); elements=buf.get(10, 20); assert elements == null; } public static void testGetNullMessages() { Table<Integer> table=new Table<Integer>(3, 10, 0); table.add(1, 1); table.add(100, 100); System.out.println("table = " + table); int num_null_elements=table.getNumMissing(); assert num_null_elements == 98; // [2 .. 99] table.add(50,50); System.out.println("table = " + table); assert table.size() == 3; assert table.getNumMissing() == 97; } public static void testGetNullMessages2() { Table<Integer> table=new Table<Integer>(1, 10, 0); table.add(1, 1); table.add(5, 5); System.out.println("table = " + table); int num_null_elements=table.getNumMissing(); assert num_null_elements == 3; // [2 .. 4] table.add(10,10); System.out.println("table = " + table); assert table.size() == 3; assert table.getNumMissing() == 7; table.add(14,14); System.out.println("table = " + table); assert table.size() == 4; assert table.getNumMissing() == 10; while(table.remove() != null) ; System.out.println("table = " + table); assert table.size() == 3; assert table.getNumMissing() == 10; } public static void testGetMissing() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(2,4,6,8)) table.add(num, num); System.out.println("table = " + table); SeqnoList missing=table.getMissing(); System.out.println("missing=" + missing); assert missing.size() == 4; assert table.getNumMissing() == 4; } public static void testGetMissing2() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(3,4,5)) table.add(num, num); System.out.println("table = " + table); SeqnoList missing=table.getMissing(); System.out.println("missing=" + missing); assert missing.size() == 2; // the range [1-2] assert table.getNumMissing() == 2; } public static void testGetMissing3() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(8)) table.add(num, num); System.out.println("table = " + table); SeqnoList missing=table.getMissing(); System.out.println("missing=" + missing); assert missing.size() == 7; assert table.getNumMissing() == 7; } public void testGetMissing4() { Table<Integer> buf=new Table<Integer>(3, 30, 0); for(int i: Arrays.asList(2,5,10,11,12,13,15,20,28,30)) buf.add(i, i); System.out.println("buf = " + buf); int missing=buf.getNumMissing(); assert missing == 20; System.out.println("missing=" + missing); SeqnoList missing_list=buf.getMissing(); System.out.println("missing_list = " + missing_list); assert missing_list.size() == missing; } public void testGetMissing5() { Table<Integer> buf=new Table<Integer>(3, 10, 0); buf.add(1,1); SeqnoList missing=buf.getMissing(); System.out.println("missing = " + missing); assert missing == null && buf.getNumMissing() == 0; buf=new Table<Integer>(3, 10, 0); buf.add(10,10); missing=buf.getMissing(); System.out.println("missing = " + missing); assert buf.getNumMissing() == missing.size(); buf=new Table<Integer>(3, 10, 0); buf.add(5,5); missing=buf.getMissing(); System.out.println("missing = " + missing); assert buf.getNumMissing() == missing.size(); buf=new Table<Integer>(3, 10, 0); buf.add(5,5); buf.add(7,7); missing=buf.getMissing(); System.out.println("missing = " + missing); assert missing.size() == 5; assert buf.getNumMissing() == missing.size(); } public static void testGetMissingLast() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(1,2,3,4,5,6,8)) table.add(num, num); System.out.println("table = " + table); SeqnoList missing=table.getMissing(); System.out.println("missing=" + missing); assert missing.size() == 1; assert table.getNumMissing() == 1; } public static void testGetMissingFirst() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int num: Arrays.asList(2,3,4,5)) table.add(num, num); System.out.println("table = " + table); SeqnoList missing=table.getMissing(); System.out.println("missing=" + missing); assert missing.size() == 1; assert table.getNumMissing() == 1; } public static void testMassAddition() { Table<Integer> table=new Table<Integer>(3, 10, 0); final int NUM_ELEMENTS=10005; for(int i=1; i <= NUM_ELEMENTS; i++) table.add(i, i); System.out.println("table = " + table); assert table.size() == NUM_ELEMENTS; assert table.capacity() == 10010; assertIndices(table, 0, 0, NUM_ELEMENTS); assert table.getNumMissing() == 0; } public static void testResize() { Table<Integer> table=new Table<Integer>(3, 10, 0); assert table.capacity() == 30; addAndGet(table, 30); addAndGet(table, 35); assert table.capacity() == 40; addAndGet(table, 500); assert table.capacity() == 510; addAndGet(table, 515); assert table.capacity() == 520; } public void testResizeWithPurge() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 100; i++) addAndGet(table, i); System.out.println("table: " + table); // now remove 60 messages for(int i=1; i <= 60; i++) { Integer num=table.remove(); assert num != null && num.intValue() == i; } System.out.println("table after removal of seqno 60: " + table); table.purge(50); System.out.println("now triggering a resize() by addition of seqno=120"); addAndGet(table, 120); } public void testResizeWithPurgeAndGetOfNonExistingElement() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 50; i++) addAndGet(table, i); System.out.println("table: " + table); assertIndices(table, 0, 0, 50); assert table.size() == 50 && table.getNumMissing() == 0; // now remove 15 messages for(long i=1; i <= 15; i++) { Integer num=table.remove(false); assert num != null && num.intValue() == i; } System.out.println("table after removal of seqno 15: " + table); assertIndices(table, 0, 15, 50); assert table.size() == 35 && table.getNumMissing() == 0; table.purge(15); System.out.println("now triggering a resize() by addition of seqno=55"); addAndGet(table, 55); assertIndices(table, 15, 15, 55); assert table.size() == 36 && table.getNumMissing() == 4; // now we have elements 40-49 in row 1 and 55 in row 2: List<Integer> list=new ArrayList<Integer>(20); for(int i=16; i < 50; i++) list.add(i); list.add(55); for(long i=table.getOffset(); i < table.capacity() + table.getOffset(); i++) { Integer num=table._get(i); if(num != null) { System.out.println("num=" + num); list.remove(num); } } System.out.println("table:\n" + table.dump()); assert list.isEmpty() : " list: " + Util.print(list); } public void testResizeWithPurge2() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 50; i++) addAndGet(table, i); System.out.println("table = " + table); assert table.size() == 50; assert table.capacity() == 60; assertIndices(table, 0, 0, 50); table.removeMany(false, 43); System.out.println("table = " + table); assertIndices(table, 0, 43, 50); table.purge(43); System.out.println("table = " + table); assertIndices(table, 43, 43, 50); addAndGet(table, 52); assert table.get(43) == null; for(long i=44; i <= 50; i++) { Integer num=table.get(i); assert num != null && num.intValue() == i; } assert table.get(50) != null; assert table.get(51) == null; Integer num=table.get(52); assert num != null && num.intValue() == 52; assert table.get(53) == null; } public static void testMove() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i < 50; i++) addAndGet(table, i); table.removeMany(true, 49); assert table.isEmpty(); addAndGet(table, 50); assert table.size() == 1; assert table.capacity() == 50; } public static void testMove2() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i < 30; i++) table.add(i, i); table.removeMany(true, 23); System.out.println("table = " + table); table.add(35, 35); // triggers a resize() --> move() for(int i=1; i <= 23; i++) assert table._get(i) == null; for(int i=24; i < 30; i++) assert table._get(i) != null; } public static void testMove3() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i < 30; i++) table.add(i, i); table.removeMany(true, 23); System.out.println("table = " + table); table.add(30, 30); // triggers a resize() --> move() for(int i=1; i <= 23; i++) assert table._get(i) == null; for(int i=24; i < 30; i++) assert table._get(i) != null; } public static void testPurge() { Table<Integer> table=new Table<Integer>(5, 10, 0); for(int seqno=1; seqno <= 25; seqno++) table.add(seqno, seqno); int[] seqnos={30,31,32,37,38,39,40,41,42,47,48,49}; for(int seqno: seqnos) table.add(seqno, seqno); System.out.println("table (before remove):\n" + table.dump()); for(int seqno=1; seqno <= 22; seqno++) table.remove(false); System.out.println("\ntable (after remove 22, before purge):\n" + table.dump()); table.purge(22); System.out.println("\ntable: (after purge 22):\n" + table.dump()); assert table.size() == 3 + seqnos.length; assert table.computeSize() == table.size(); } public void testPurge2() { Table<Integer> buf=new Table<Integer>(3, 10, 0); for(int i=1; i <=7; i++) { buf.add(i, i); buf.remove(false); } System.out.println("buf = " + buf); assert buf.isEmpty(); long low=buf.getLow(); buf.purge(3); assert buf.getLow() == 3; for(long i=low; i <= 3; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; buf.purge(6); assert buf._get(6) == null; buf.purge(7); assert buf._get(7) == null; assert buf.getLow() == 7; assert buf.isEmpty(); for(int i=7; i <= 14; i++) { buf.add(i, i); buf.remove(false); } System.out.println("buf = " + buf); assert buf.isEmpty(); low=buf.getLow(); assert low == 7; buf.purge(12); System.out.println("buf = " + buf); assert buf.getLow() == 12; for(long i=low; i <= 12; i++) assert buf._get(i) == null : "message with seqno=" + i + " is not null"; } public void testPurge3() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 100; i++) table.add(i, i); System.out.println("table = " + table); table.removeMany(true, 53); for(int i=54; i <= 100; i++) assert table.get(i) == i; } public void testPurge4() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 100; i++) table.add(i, i); System.out.println("table = " + table); table.removeMany(false, 53); table.purge(53); for(int i=54; i <= 100; i++) assert table.get(i) == i; } public void testPurge5() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 100; i++) table.add(i, i); System.out.println("table = " + table); table.removeMany(false, 0); table.purge(10); for(int i=1; i <= 10; i++) assert table._get(i) == null; for(int i=11; i <= 100; i++) assert table.get(i) == i; table.purge(10); for(int i=11; i <= 100; i++) assert table.get(i) == i; table.purge(50); for(int i=1; i <= 50; i++) assert table._get(i) == null; for(int i=51; i <= 100; i++) assert table.get(i) == i; table.purge(100); for(int i=51; i <= 100; i++) assert table._get(i) == null; } public void testPurgeForce() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 30; i++) table.add(i, i); System.out.println("table = " + table); table.purge(15, true); System.out.println("table = " + table); assertIndices(table, 15, 15, 30); for(int i=1; i <= 15; i++) assert table._get(i) == null; for(int i=16; i<= 30; i++) assert table._get(i) != null; assert table.get(5) == null && table.get(25) != null; table.purge(30, true); System.out.println("table = " + table); assertIndices(table, 30, 30, 30); assert table.isEmpty(); for(int i=1; i <= 30; i++) assert table._get(i) == null; for(int i=31; i <= 40; i++) table.add(i, i); System.out.println("table = " + table); assert table.size() == 10; assertIndices(table, 30, 30, 40); table.purge(50, true); System.out.println("table = " + table); assert table.isEmpty(); assertIndices(table, 40, 40, 40); } public void testCompact() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 80; i++) addAndGet(table, i); assert table.size() == 80; assertIndices(table, 0, 0, 80); List<Integer> list=table.removeMany(false,60); assert list.size() == 60; assert list.get(0) == 1 && list.get(list.size() -1) == 60; assertIndices(table, 0, 60, 80); table.purge(60); assertIndices(table, 60, 60, 80); assert table.size() == 20; table.compact(); assertIndices(table, 60, 60, 80); assert table.size() == 20; assert table.capacity() == 40; } public void testCompact2() { Table<Integer> table=new Table<Integer>(3, 10, 0); for(int i=1; i <= 80; i++) addAndGet(table, i); assert table.size() == 80; for(long i=1; i <= 60; i++) table.remove(); assert table.size() == 20; table.compact(); assert table.size() == 20; assert table.capacity() == 40; } protected static void addAndGet(Table<Integer> table, int seqno) { boolean added=table.add((long)seqno,seqno); assert added; Integer val=table.get(seqno); assert val != null && val == seqno; } protected static <T> void assertIndices(Table<T> table, long low, long hd, long hr) { assert table.getLow() == low : "expected low=" + low + " but was " + table.getLow(); assert table.getHighestDelivered() == hd : "expected hd=" + hd + " but was " + table.getHighestDelivered(); assert table.getHighestReceived() == hr : "expected hr=" + hr + " but was " + table.getHighestReceived(); } protected static class Adder extends Thread { protected final CountDownLatch latch; protected final int seqno; protected final Table<Integer> buf; public Adder(CountDownLatch latch, int seqno, Table<Integer> buf) { this.latch=latch; this.seqno=seqno; this.buf=buf; } public void run() { try { latch.await(); Util.sleepRandom(10, 500); buf.add(seqno, seqno); } catch(InterruptedException e) { e.printStackTrace(); } } } }