package org.cliffc.high_scale_lib; import junit.framework.TestCase; import java.io.*; import java.util.Iterator; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class NonBlockingSetIntTest extends TestCase { public void testDerp() { NonBlockingSetInt a = new NonBlockingSetInt(); NonBlockingSetInt b = new NonBlockingSetInt(); a.add(1213446); NonBlockingSetInt c = a.union(b); } public void testSetOperations() { // add values to the following bitsets // 'a' will get all values divisible by 63 // 'b' will get the rest // this ensures that one NBSI will have the largest bit array, while the other // will have the largest recursive bitset used to store values for every 64th bit // this exercises that the constructor building a blank NBSI to hold bitwise operations // on two others is sized appropriately initially NonBlockingSetInt a = new NonBlockingSetInt(); NonBlockingSetInt b = new NonBlockingSetInt(); NonBlockingSetInt empty = new NonBlockingSetInt(); int max = 20000000; for(int i = 0; i < max; i++) { NonBlockingSetInt t = (i&63) == 63 ? a : b; t.add(i); assertTrue(t.contains(i)); } // c should contain the empty set since a and b are disjoint NonBlockingSetInt c = a.intersect(b); NonBlockingSetInt d = b.intersect(a); for(int i = 0; i < max; i++) { assertFalse(c.contains(i)); assertFalse(d.contains(i)); } c = a.union(b); d = b.union(a); for(int i = 0; i < max; i++) { assertTrue(c.contains(i)); assertTrue(d.contains(i)); } c = a.union(empty); d = empty.union(a); IntIterator itr = a.intIterator(); while(itr.hasNext()) { int next = itr.next(); assertTrue(c.contains(next)); assertTrue(d.contains(next)); } itr = b.intIterator(); while(itr.hasNext()) { int next = itr.next(); assertFalse(c.contains(next)); assertFalse(d.contains(next)); } c = b.union(empty); d = empty.union(b); itr = b.intIterator(); while(itr.hasNext()) { int next = itr.next(); assertTrue(c.contains(next)); assertTrue(d.contains(next)); } itr = a.intIterator(); while(itr.hasNext()) { int next = itr.next(); assertFalse(c.contains(next)); assertFalse(d.contains(next)); } // just make sure the bitset is usable after building out an instance with an ample internal buffer for(int i = 0; i < max; i++) { c.add(i); assertTrue(c.contains(i)); d.add(i); assertTrue(d.contains(i)); } c.intersect(new NonBlockingSetInt()); new NonBlockingSetInt().intersect(c); } private NonBlockingSetInt _nbsi; protected void setUp () { _nbsi = new NonBlockingSetInt(); } protected void tearDown() { _nbsi = null; } // Test some basic stuff; add a few keys, remove a few keys public void testBasic() { assertTrue ( _nbsi.isEmpty() ); assertTrue ( _nbsi.add(1) ); checkSizes (1); assertTrue ( _nbsi.add(2) ); checkSizes (2); assertFalse( _nbsi.add(1) ); assertFalse( _nbsi.add(2) ); checkSizes (2); assertThat ( _nbsi.remove(1), is(true ) ); checkSizes (1); assertThat ( _nbsi.remove(1), is(false) ); assertTrue ( _nbsi.remove(2) ); checkSizes (0); assertFalse( _nbsi.remove(2) ); assertFalse( _nbsi.remove(3) ); assertTrue ( _nbsi.isEmpty() ); assertTrue ( _nbsi.add(63) ); checkSizes (1); assertTrue ( _nbsi.remove(63) ); assertFalse( _nbsi.remove(63) ); assertTrue ( _nbsi.isEmpty() ); assertTrue ( _nbsi.add(10000) ); checkSizes (1); assertTrue ( _nbsi.add(20000) ); checkSizes (2); assertFalse( _nbsi.add(10000) ); assertFalse( _nbsi.add(20000) ); checkSizes (2); assertThat ( _nbsi.remove(10000), is(true ) ); checkSizes (1); assertThat ( _nbsi.remove(10000), is(false) ); assertTrue ( _nbsi.remove(20000) ); checkSizes (0); assertFalse( _nbsi.remove(20000) ); } // Check all iterators for correct size counts private void checkSizes(int expectedSize) { assertEquals( "size()", _nbsi.size(), expectedSize ); Iterator it = _nbsi.iterator(); int result = 0; while (it.hasNext()) { result++; it.next(); } assertEquals( "iterator missed", expectedSize, result ); } public void testIteration() { assertTrue ( _nbsi.isEmpty() ); assertTrue ( _nbsi.add(1) ); assertTrue ( _nbsi.add(2) ); StringBuffer buf = new StringBuffer(); for( Iterator<Integer> i = _nbsi.iterator(); i.hasNext(); ) { Integer val = i.next(); buf.append(val); } assertThat("found all vals",buf.toString(),anyOf(is("12"),is("21"))); assertThat("toString works",_nbsi.toString(), anyOf(is("[1, 2]"),is("[2, 1]"))); } public void testIterationBig() { for( int i=0; i<100; i++ ) _nbsi.add(i); assertThat( _nbsi.size(), is(100) ); int sz =0; int sum = 0; for( Integer x : _nbsi ) { sz++; sum += x; assertTrue(x>=0 && x<=99); } assertThat("Found 100 ints",sz,is(100)); assertThat("Found all integers in list",sum,is(100*99/2)); assertThat( "can remove 3", _nbsi.remove(3), is(true) ); assertThat( "can remove 4", _nbsi.remove(4), is(true) ); sz =0; sum = 0; for( Integer x : _nbsi ) { sz++; sum += x; assertTrue(x>=0 && x<=99); } assertThat("Found 98 ints",sz,is(98)); assertThat("Found all integers in list",sum,is(100*99/2 - (3+4))); } public void testSerial() { assertTrue ( _nbsi.isEmpty() ); assertTrue ( _nbsi.add(1) ); assertTrue ( _nbsi.add(2) ); // Serialize it out try { FileOutputStream fos = new FileOutputStream("NBSI_test.txt"); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(_nbsi); out.close(); } catch(IOException ex) { ex.printStackTrace(); } // Read it back try { File f = new File("NBSI_test.txt"); FileInputStream fis = new FileInputStream(f); ObjectInputStream in = new ObjectInputStream(fis); NonBlockingSetInt nbsi = (NonBlockingSetInt)in.readObject(); in.close(); assertEquals(_nbsi.toString(),nbsi.toString()); if( !f.delete() ) throw new IOException("delete failed"); } catch(IOException ex) { ex.printStackTrace(); } catch(ClassNotFoundException ex) { ex.printStackTrace(); } } // Do some simple concurrent testing public void testConcurrentSimple() throws InterruptedException { final NonBlockingSetInt nbsi = new NonBlockingSetInt(); // In 2 threads, add & remove even & odd elements concurrently Thread t1 = new Thread() { public void run() { work_helper(nbsi,"T1",1); } }; t1.start(); work_helper(nbsi,"T0",1); t1.join(); // In the end, all members should be removed StringBuffer buf = new StringBuffer(); buf.append("Should be emptyset but has these elements: {"); boolean found = false; for( Integer x : nbsi ) { buf.append(" ").append(x); found = true; } if( found ) System.out.println(buf); assertThat( "concurrent size=0", nbsi.size(), is(0) ); for( Integer x : nbsi ) { assertTrue("No elements so never get here",false); } } void work_helper(NonBlockingSetInt nbsi, String thrd, int d) { final int ITERS = 100000; for( int j=0; j<10; j++ ) { long start = System.nanoTime(); for( int i=d; i<ITERS; i+=2 ) nbsi.add(i); for( int i=d; i<ITERS; i+=2 ) nbsi.remove(i); double delta_nanos = System.nanoTime()-start; double delta_secs = delta_nanos/1000000000.0; double ops = ITERS*2; //System.out.println("Thrd"+thrd+" "+(ops/delta_secs)+" ops/sec size="+nbsi.size()); } } public void testRetainAllNonBlocking() { NonBlockingSetInt nonBlockingSetInt = new NonBlockingSetInt(); nonBlockingSetInt.add(1); nonBlockingSetInt.add(2); nonBlockingSetInt.add(3); NonBlockingSetInt toRetain = new NonBlockingSetInt(); toRetain.add(1); toRetain.add(3); assertTrue(nonBlockingSetInt.retainAll(toRetain)); assertEquals(nonBlockingSetInt, toRetain); } }