ソースを参照

tests

fix: IntCollectionUtils#equivalent
fix: IteratorUtils#first - throw instead NULL

new: LazyReference: new implementation of double check idiom without volatile :)
Ranides Atterwim 10 年 前
コミット
cb797c7a19

+ 0 - 6
assira/pom.xml

@@ -31,14 +31,8 @@
                                 <include>net/ranides/assira/annotations/javac/**</include>
                                 <include>net/ranides/assira/awt/ImageLoader*</include>
                                 <include>net/ranides/assira/awt/AWTInvoker*</include>
-                                <include>net/ranides/assira/collection/IntCollectionUtils*</include>
-                                <include>net/ranides/assira/collection/CollectionUtils*</include>
-                                <include>net/ranides/assira/collection/Swapper*</include>
-                                <include>net/ranides/assira/collection/HashFunction*</include>
                                 <include>net/ranides/assira/collection/arrays/ArrayUtils*</include>
                                 <include>net/ranides/assira/collection/arrays/NativeArrayUtils*</include>
-                                <include>net/ranides/assira/collection/lists/IntRange*</include>
-                                <include>net/ranides/assira/collection/utils/**</include>
                                 <include>net/ranides/assira/functional/**</include>
                                 <include>net/ranides/assira/generic/SerializationUtils*</include>
                                 <include>net/ranides/assira/generic/Wrapper*</include>

+ 1 - 1
assira/src/main/java/net/ranides/assira/collection/CollectionUtils.java

@@ -57,7 +57,7 @@ public final class CollectionUtils {
 			
 			@Override
 			public boolean contains(Object value) {
-				return values.contains(value) && predicate.test((T)value);
+				return predicate.test((T)value) && values.contains(value);
 			}
 		};
 	}

+ 1 - 1
assira/src/main/java/net/ranides/assira/collection/IntCollectionUtils.java

@@ -82,7 +82,7 @@ public final class IntCollectionUtils {
 			return a.containsAll(b);
 		}
 		if(b instanceof Set<?>) {
-			return b.containsAll(b);
+			return b.containsAll(a);
 		}
 		
         // najpierw spróbujmy tak sprawdzić - takie porównanie powinno być względnie tanie

+ 3 - 3
assira/src/main/java/net/ranides/assira/collection/iterators/IteratorUtils.java

@@ -26,10 +26,10 @@ public final class IteratorUtils {
     }
     
     public static <T> T first(Iterator<T> iterator) {
-		if(iterator==null) {
-			return null;
+		if(iterator.hasNext()) {
+			return iterator.next();
 		}
-        return iterator.hasNext() ? iterator.next() : null;
+        throw new NoSuchElementException();
     }
     
     public static <T> T first(Iterator<T> iterator, Predicate<T> predicate) {

+ 3 - 0
assira/src/main/java/net/ranides/assira/collection/lists/IntRange.java

@@ -53,6 +53,9 @@ public class IntRange extends AIntList implements RandomAccess {
 
     @Override
     public int getInt(int index) {
+		if(index <0 || index>=size()) {
+			throw new IndexOutOfBoundsException(index +" out of " + size());
+		}
         return begin + index;
     }
 

+ 53 - 5
assira/src/main/java/net/ranides/assira/generic/LazyReference.java

@@ -44,11 +44,24 @@ public final class LazyReference {
 
     /**
      * Initialization is synchronized using correctly implemented "double checked locking". 
+	 * Requires JDK 1.5+ because uses new "volatile semantics".
      * @param <T>
      * @param supplier
      * @return 
      */
-    public static <T> Supplier<T> shared(Supplier<T> supplier) {
+    public static <T> Supplier<T> sharedVolatile(Supplier<T> supplier) {
+        return new SharedVolatile<>(supplier);
+    }
+	
+	/**
+     * Initialization is synchronized using correctly implemented "double checked locking".
+	 * It uses wrapper object with "final" attribute instead of "volatile". I don't
+	 * know anything about compatibility of that with JDK &lt; 1.5.
+     * @param <T>
+     * @param supplier
+     * @return 
+     */
+	public static <T> Supplier<T> shared(Supplier<T> supplier) {
         return new Shared<>(supplier);
     }
 
@@ -96,7 +109,7 @@ public final class LazyReference {
 
     }
     
-    private static class Shared<T> implements Supplier<T> {
+    private static class SharedVolatile<T> implements Supplier<T> {
         
         // works in JDK5 +
         // http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
@@ -105,7 +118,7 @@ public final class LazyReference {
 
         private volatile T ref = null;
 
-        public Shared(Supplier<T> supplier) {
+        public SharedVolatile(Supplier<T> supplier) {
             this.supplier = supplier;
         }
 
@@ -124,6 +137,41 @@ public final class LazyReference {
         }
 
     }
-
-
+	
+	private static final class SharedWrapper<T> {
+		
+		public final T value;
+
+		public SharedWrapper(T value) {
+			this.value = value;
+		}
+		
+	}
+	
+	private static final class Shared<T> implements Supplier<T>  {
+		
+		private final Supplier<T> supplier;
+		
+		private SharedWrapper<T> ref = null;
+
+		public Shared(Supplier<T> supplier) {
+			this.supplier = supplier;
+		}
+
+		@Override
+		public T get() {
+			SharedWrapper<T> temp = ref;
+			if (temp == null) {
+				synchronized(this) {
+					temp = ref;
+					if (temp == null) {
+						ref = temp = new SharedWrapper<T>(supplier.get());
+					}
+				}
+			}
+			return temp.value;
+		}
+		
+	}
+	
 }

+ 93 - 0
assira/src/test/java/net/ranides/assira/collection/CollectionUtilsTest.java

@@ -0,0 +1,93 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import net.ranides.assira.collection.sets.HashSet;
+import static net.ranides.assira.junit.NewAssert.assertThrows;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class CollectionUtilsTest {
+
+	@Test
+    public void testFirst() {
+		List<String> list8= Arrays.asList("a", "b", "cc", "d", "ee", "f", "gg", "h");
+		List<String> list1 = Arrays.asList("a");
+		List<String> list0 = Arrays.asList();
+		
+        assertEquals("a", CollectionUtils.first(list8));
+        assertEquals("a", CollectionUtils.first(list1));
+		
+        assertThrows(NoSuchElementException.class, ()-> {
+			CollectionUtils.first(list0);
+		});
+		assertThrows(NoSuchElementException.class, ()-> {
+			CollectionUtils.first(list8, v -> false);
+		});
+		
+		assertEquals("a", CollectionUtils.first(list8, v -> true));
+		assertEquals("cc", CollectionUtils.first(list8, v -> v.length()>1));
+    }
+	
+	@Test
+    public void testLast() {
+		List<String> list8= Arrays.asList("a", "b", "cc", "d", "ee", "f", "gg", "h");
+		List<String> list1 = Arrays.asList("a");
+		List<String> list0 = Arrays.asList();
+		
+        assertEquals("h", CollectionUtils.last(list8));
+        assertEquals("a", CollectionUtils.last(list1));
+		
+        assertThrows(NoSuchElementException.class, ()-> {
+			CollectionUtils.last(list0);
+		});
+		assertThrows(NoSuchElementException.class, ()-> {
+			CollectionUtils.last(list8, v -> false);
+		});
+		
+		assertEquals("h", CollectionUtils.last(list8, v -> true));
+		assertEquals("gg", CollectionUtils.last(list8, v -> v.length()>1));
+    }
+	
+	@Test
+	public void testFilter() {
+		Collection<Integer> c = CollectionUtils.filter(Arrays.asList(1,2,3,4,5,6), v -> 0==v%2);
+		assertTrue("not expected: "+c, CollectionUtils.equivalent(Arrays.asList(2,4,6), c));
+		assertTrue(c.contains(2));
+		assertFalse(c.contains(8));
+		assertFalse(c.contains(3));
+	}
+	
+	@Test
+	public void testEquivalent() {
+		List<Integer> a = Arrays.asList(1,2,3,4,5);
+		List<Integer> b = Arrays.asList(1,5,4,3,2);
+		List<Integer> c = Arrays.asList(1,5,4,3,8);
+		List<Integer> d = Arrays.asList(1,5,4,3);
+		
+		Set<Integer> e = new HashSet<Integer>(a);
+		
+		assertTrue( CollectionUtils.equivalent(a,b) );
+		assertFalse( CollectionUtils.equivalent(a,c) );
+		assertFalse( CollectionUtils.equivalent(a,d) );
+		
+		assertTrue( CollectionUtils.equivalent(a,e) );
+		assertTrue( CollectionUtils.equivalent(e,a) );
+		assertFalse( CollectionUtils.equivalent(c,e) );
+		assertFalse( CollectionUtils.equivalent(e,c) );
+	}
+	
+}

+ 91 - 0
assira/src/test/java/net/ranides/assira/collection/IntCollectionUtilsTest.java

@@ -0,0 +1,91 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection;
+
+import java.util.NoSuchElementException;
+import net.ranides.assira.collection.lists.IntList;
+import net.ranides.assira.collection.sets.IntHashSet;
+import net.ranides.assira.collection.sets.IntSet;
+import static net.ranides.assira.junit.NewAssert.assertThrows;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class IntCollectionUtilsTest {
+	
+	@Test
+    public void testFirst() {
+		IntList list8 = IntList.asList(1, 2, 13, 4, 15, 6, 17, 8);
+		IntList list1 = IntList.asList(1);
+		IntList list0 = IntList.asList();
+		
+        assertEquals(1, IntCollectionUtils.first(list8));
+        assertEquals(1, IntCollectionUtils.first(list1));
+		
+        assertThrows(NoSuchElementException.class, ()-> {
+			IntCollectionUtils.first(list0);
+		});
+		assertThrows(NoSuchElementException.class, ()-> {
+			IntCollectionUtils.first(list8, v -> false);
+		});
+		
+		assertEquals(1, IntCollectionUtils.first(list8, v -> true));
+		assertEquals(13, IntCollectionUtils.first(list8, v -> v>10));
+    }
+	
+	@Test
+    public void testLast() {
+		IntList list8 = IntList.asList(1, 2, 13, 4, 15, 6, 17, 8);
+		IntList list1 = IntList.asList(1);
+		IntList list0 = IntList.asList();
+		
+        assertEquals(8, IntCollectionUtils.last(list8));
+        assertEquals(1, IntCollectionUtils.last(list1));
+		
+        assertThrows(NoSuchElementException.class, ()-> {
+			IntCollectionUtils.last(list0);
+		});
+		assertThrows(NoSuchElementException.class, ()-> {
+			IntCollectionUtils.last(list8, v -> false);
+		});
+		
+		assertEquals(8, IntCollectionUtils.last(list8, v -> true));
+		assertEquals(17, IntCollectionUtils.last(list8, v -> v>10));
+    }
+	
+	@Test
+	public void testFilter() {
+		IntCollection c = IntCollectionUtils.filter(IntList.asList(1,2,3,4,5,6), v -> 0==v%2);
+		assertTrue("not expected: "+c, IntCollectionUtils.equivalent(IntList.asList(2,4,6), c));
+		assertTrue(c.contains(2));
+		assertFalse(c.contains(8));
+		assertFalse(c.contains(3));
+	}
+	
+	@Test
+	public void testEquivalent() {
+		IntList a = IntList.asList(1,2,3,4,5);
+		IntList b = IntList.asList(1,5,4,3,2);
+		IntList c = IntList.asList(1,5,4,3,8);
+		IntList d = IntList.asList(1,5,4,3);
+		
+		IntSet e = new IntHashSet(a);
+		
+		assertTrue( IntCollectionUtils.equivalent(a,b) );
+		assertFalse( IntCollectionUtils.equivalent(a,c) );
+		assertFalse( IntCollectionUtils.equivalent(a,d) );
+		
+		assertTrue( IntCollectionUtils.equivalent(a,e) );
+		assertTrue( IntCollectionUtils.equivalent(e,a) );
+		assertFalse( IntCollectionUtils.equivalent(c,e) );
+		assertFalse( IntCollectionUtils.equivalent(e,c) );
+	}
+	
+}

+ 35 - 0
assira/src/test/java/net/ranides/assira/collection/SwapperTest.java

@@ -0,0 +1,35 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection;
+
+import java.util.Arrays;
+import java.util.List;
+import net.ranides.assira.collection.lists.IntList;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class SwapperTest {
+	
+	public SwapperTest() {
+	}
+
+	@Test
+	public void testSwapper() {
+		IntList list1 = IntList.asList(1,2,3,4);
+		Swapper.swapper(list1).swap(0, 2);
+		assertEquals(IntList.asList(3,2,1,4), list1);
+		
+		List<String> list2 = Arrays.asList("1","2","3","4");
+		Swapper.swapper(list2).swap(0, 2);
+		assertEquals(Arrays.asList("3","2","1","4"), list2);
+	}
+	
+}

+ 3 - 2
assira/src/test/java/net/ranides/assira/collection/iterators/IntIteratorUtilsTest.java

@@ -32,8 +32,9 @@ public class IntIteratorUtilsTest {
 		assertEquals(1, IntIteratorUtils.first(IntList.asList(1,2).iterator()));
 		assertEquals(1, IntIteratorUtils.first(IntList.asList(1).iterator()));
 		
-		assertNull(IteratorUtils.first(Arrays.asList().iterator()));
-		assertNull(IteratorUtils.first(null));
+		assertThrows(NoSuchElementException.class, () -> {
+			IteratorUtils.first(Arrays.asList().iterator());
+		});
 	}
 	
 	@Test

+ 3 - 2
assira/src/test/java/net/ranides/assira/collection/iterators/IteratorUtilsTest.java

@@ -29,8 +29,9 @@ public class IteratorUtilsTest {
 		assertEquals((Integer)1, IteratorUtils.first(Arrays.asList(1,2).iterator()));
 		assertEquals((Integer)1, IteratorUtils.first(Arrays.asList(1).iterator()));
 		
-		assertNull(IteratorUtils.first(Arrays.asList().iterator()));
-		assertNull(IteratorUtils.first(null));
+		assertThrows(NoSuchElementException.class, () -> {
+			IteratorUtils.first(Arrays.asList().iterator());
+		});
 	}
 	
 	@Test

+ 18 - 0
assira/src/test/java/net/ranides/assira/collection/lists/IntRangeTest.java

@@ -1,5 +1,6 @@
 package net.ranides.assira.collection.lists;
 
+import java.util.Arrays;
 import net.ranides.assira.collection.iterators.IntListIterator;
 import net.ranides.assira.collection.suite.IteratorTester;
 import net.ranides.assira.junit.NewAssert;
@@ -19,6 +20,23 @@ public class IntRangeTest {
 		assertTrue(true);
 	}
 	
+	@Test
+	public void testGet() {
+		IntRange range = new IntRange(4, 10);
+		assertEquals(6, range.size());
+		
+		assertEquals(4, range.getInt(0));
+		assertEquals(5, range.getInt(1));
+		assertEquals(6, range.getInt(2));
+		assertEquals(9, range.getInt(5));
+		
+		NewAssert.assertThrows(IndexOutOfBoundsException.class, ()->{
+			range.getInt(6);
+		});
+		
+		NewAssert.assertSymEquals(Arrays.asList(4,5,6,7,8,9), range);
+	}
+	
 	@Test
 	public void testConstness() {
 		IntRange range = new IntRange(4, 10);

+ 23 - 2
assira/src/test/java/net/ranides/assira/generic/LazyReferenceTest.java

@@ -12,9 +12,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
-import junit.framework.Assert;
 import static net.ranides.assira.junit.NewAssert.*;
-import org.junit.Ignore;
 import org.junit.Test;
 
 /**
@@ -63,6 +61,29 @@ public class LazyReferenceTest {
 		}
 	}
 	
+	@Test
+	public void testSharedVolatile() throws InterruptedException, Throwable {
+		List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());
+		
+		AtomicInteger ai = new AtomicInteger(5);
+		Supplier<Integer> ref = LazyReference.sharedVolatile(() -> ai.getAndIncrement());
+		
+		for(int t=0; t<20; t++) {
+			thread(50, errors::add, ()->{
+				for(int i=0; i<10; i++) {
+					sleep(50);
+					Integer v = ref.get();
+					assertEquals(5, v.intValue());
+				}
+			});
+		}
+		sleep(1000);
+
+		if(!errors.isEmpty()) {
+			throw errors.get(0);
+		}
+	}
+	
 	@Test
 	public void testShared() throws InterruptedException, Throwable {
 		List<Throwable> errors = Collections.synchronizedList(new ArrayList<>());