Bladeren bron

test (36)

fix: AVLTreeMap - bug with inner class
Ranides Atterwim 10 jaren geleden
bovenliggende
commit
90a1467af5

+ 22 - 0
assira/src/main/java/net/ranides/assira/collection/HashIntComparator.java

@@ -0,0 +1,22 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/???
+ */
+package net.ranides.assira.collection;
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public interface HashIntComparator extends HashComparator<Integer>, IntComparator, Serializable {
+
+    @Override
+    default boolean equals(Integer value1, Integer value2) {
+        return 0 == compare(value1, value2);
+    }
+    
+}

+ 5 - 1
assira/src/main/java/net/ranides/assira/collection/maps/IntSortedMap.java

@@ -396,9 +396,13 @@ public abstract class IntSortedMap<V> extends IntMap<V> implements SortedMap<Int
     }
     
     protected class EntrySet extends ASortedSet<IntEntry<V>> {
+        
+        protected EntrySet(IntSortedMap<V> that) {
+			super((entry1, entry2) -> that.compare(entry1.getIntKey(), entry2.getIntKey()));
+		}
 
 		public EntrySet() {
-			super((entry1, entry2) -> IntSortedMap.this.compare(entry1.getIntKey(), entry2.getIntKey()));
+			this(IntSortedMap.this);
 		}
 
         @Override

+ 2 - 20
assira/src/test/java/net/ranides/assira/collection/maps/AVLTreeMapTest.java

@@ -8,13 +8,10 @@ package net.ranides.assira.collection.maps;
 
 import java.util.Map;
 import java.util.SortedMap;
-import net.ranides.assira.collection.lookups.AVLTreeLookup;
-import net.ranides.assira.collection.lookups.Lookup;
 import static net.ranides.assira.collection.mockup.TPointUtils.*;
 import net.ranides.assira.collection.mockup.TPoint;
 import net.ranides.assira.collection.suite.CollectionSuite;
-
-import static net.ranides.assira.junit.QAssert.assertThrows;
+import net.ranides.assira.junit.QAssert;
 import org.junit.Test;
 import static org.junit.Assert.*;
 
@@ -51,24 +48,9 @@ public class AVLTreeMapTest {
         assertEquals(120, new AVLTreeMap<>($ukeys(60), $objects(180), TPoint.SUM).size());
         assertEquals(180, new AVLTreeMap<>($ukeys(60), $objects(180) ).size());
         
-        assertThrows(IllegalArgumentException.class, () -> 
+        QAssert.assertThrows(IllegalArgumentException.class, () -> 
             new AVLTreeMap<>($ukeys(60), $objects(10), TPoint.SUM)
         );
     }
-    
-//    @Test
-//    public void testConstruct() {
-//        assertNotNull( new AVLTreeMap<>() );
-//        assertNotNull( new AVLTreeMap<>(TPoint.SUM) );
-//    }
-//    
-//    @Test
-//    public void testConstructCopy() {
-//        assertEquals(120, new AVLTreeMap<>($ukeys(60), $objects(180), TPoint.SUM).size());
-//        
-//        QAssert.assertThrows(IllegalArgumentException.class, () -> 
-//            new RBTreeLookup<>($ukeys(60), $values(10), TPoint.SUM)
-//        );
-//    }
    
 }

+ 58 - 0
assira/src/test/java/net/ranides/assira/collection/maps/IntAVLTreeMapTest.java

@@ -0,0 +1,58 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/???
+ */
+package net.ranides.assira.collection.maps;
+
+import java.util.Map;
+import java.util.SortedMap;
+import net.ranides.assira.collection.mockup.IntValue;
+import static net.ranides.assira.collection.mockup.IntValueUtils.*;
+import net.ranides.assira.junit.QAssert;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class IntAVLTreeMapTest {
+    
+//    @Test
+//    public void testSuite() {
+//        assertTrue(CollectionSuite.SUITE.run(() -> new AVLTreeMap<>(IntValue.SUM)));
+//    }
+
+    @Test
+    public void testConstruct() {
+        assertNotNull( new IntAVLTreeMap<>() );
+        assertNotNull( new IntAVLTreeMap<>(IntValue.MOD) );
+    }
+    
+    @Test
+    public void testConstructCopy() {
+        int N_KEY = 60;
+        int N_EXP = 2 * N_KEY;
+        int N_VAL = 3 * N_KEY;
+        
+        Map<Integer, String> imap = $map($ukeys(N_KEY));
+        IntAVLTreeMap<String> smap1 = new IntAVLTreeMap<>($ukeys(N_KEY), $values(N_VAL), IntValue.STD);
+        IntAVLTreeMap<String> smap2 = new IntAVLTreeMap<>($ukeys(N_KEY), $values(N_VAL), IntValue.MOD);
+        
+        assertEquals(N_VAL, new IntAVLTreeMap<>(imap).size());
+        assertEquals(N_VAL, new IntAVLTreeMap<>((SortedMap<Integer,String>)imap).size());
+        
+        assertEquals(N_VAL, new IntAVLTreeMap<>(smap1).size());
+        assertEquals(N_EXP, new IntAVLTreeMap<>(smap2).size());
+        
+        assertEquals(N_EXP, new IntAVLTreeMap<>($ukeys(N_KEY), $values(N_VAL), IntValue.MOD).size());
+        assertEquals(N_VAL, new IntAVLTreeMap<>($ukeys(N_KEY), $values(N_VAL) ).size());
+        
+        QAssert.assertThrows(IllegalArgumentException.class, () -> 
+            new IntAVLTreeMap<>($ukeys(60), $values(10), IntValue.MOD)
+        );
+    }
+    
+}

+ 49 - 0
assira/src/test/java/net/ranides/assira/collection/mockup/IntValue.java

@@ -0,0 +1,49 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.collection.mockup;
+
+import net.ranides.assira.collection.HashIntComparator;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class IntValue {
+    
+    public static final HashIntComparator MOD = new HashIntComparator() {
+        
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public int compare(int a, int b) {
+            return (a%10_000) - (b%10_000);
+        }
+
+        @Override
+        public int hashCode(Integer object) {
+            return (object % 1_000);
+        }
+        
+    };
+    
+    public static final HashIntComparator STD = new HashIntComparator() {
+        
+        private static final long serialVersionUID = 1L;
+        
+        @Override
+        public int compare(int a, int b) {
+            return (a & 0xFFFF) - (b & 0xFFFF);
+        }
+        
+        @Override
+        public int hashCode(Integer object) {
+            return (object % 0xFFF);
+        }
+        
+    };
+
+}

+ 275 - 0
assira/src/test/java/net/ranides/assira/collection/mockup/IntValueUtils.java

@@ -0,0 +1,275 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/???
+ */
+package net.ranides.assira.collection.mockup;
+
+import java.util.AbstractMap;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.TreeMap;
+import net.ranides.assira.collection.HashComparator;
+import net.ranides.assira.collection.lookups.Lookup;
+import static net.ranides.assira.collection.mockup.ValueEnum.*;
+import net.ranides.assira.generic.CompareUtils;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class IntValueUtils {
+    
+    private IntValueUtils() {
+        // utility class
+    }
+    
+    public static final ValueGenerator<Integer, ValueEnum> KEYS = new ValueGenerator<Integer, ValueEnum>(TPoint.class) {
+        
+        @Override
+        public HashComparator<Integer> comparator() {
+            return IntValue.MOD;
+        }
+        
+        @Override
+        public Integer object(ValueEnum key) {
+            return $key(key);
+        }
+        
+        @Override
+        public Integer object(int key) {
+            return key;
+        }
+    };
+    
+    public static final ValueGenerator<Entry<Integer, String>, ValueEnum> ENTRIES = new ValueGenerator<Entry<Integer, String>, ValueEnum>(Entry.class) {
+
+        @Override
+        public HashComparator<Entry<Integer, String>> comparator() {
+            return ENTRY_SUM;
+        }
+
+        @Override
+        public Entry<Integer, String> object(ValueEnum key) {
+            return $entry(key);
+        }
+
+        @Override
+        public Entry<Integer, String> object(int key) {
+            return $entry(KEYS.object(key), "s"+key);
+        }
+        
+    };
+    
+    private static final HashComparator<Entry<Integer,String>> ENTRY_SUM = new HashComparator<Entry<Integer, String>>() {
+        @Override
+        public int hashCode(Entry<Integer, String> entry) {
+            return IntValue.MOD.hashCode(entry.getKey());
+        }
+
+        @Override
+        public int compare(Entry<Integer, String> entry1, Entry<Integer, String> entry2) {
+            int d = IntValue.MOD.compare(entry1.getKey(), entry2.getKey());
+            return d != 0 ? d : CompareUtils.cmp(entry1.getValue(), entry2.getValue());
+        }
+    };
+
+    private static final EnumMap<ValueEnum, Integer> M_KEYS = new EnumMap<>(ValueEnum.class);
+    
+    static {
+        M_KEYS.put(ValueEnum.A1,    20500);  // 17
+        M_KEYS.put(ValueEnum.A1_EQ, 30500);  // 17
+        M_KEYS.put(ValueEnum.A1_NE, 21500);  // 9
+        M_KEYS.put(ValueEnum.B1,    20501);  // 24
+        M_KEYS.put(ValueEnum.C1,    20502);  // 26
+        M_KEYS.put(ValueEnum.D1,    20510);  // 63
+        M_KEYS.put(ValueEnum.D2,    20511);  // 64
+        M_KEYS.put(ValueEnum.D3,    20512);  // 65
+        M_KEYS.put(ValueEnum.D4,    20513);  // 66
+        M_KEYS.put(ValueEnum.E1,    20520);  // 81
+        M_KEYS.put(ValueEnum.E1_EQ, 30520);  // 81
+        M_KEYS.put(ValueEnum.E1_NE, 31520);  // 92
+        
+        M_KEYS.put(ValueEnum.SUB_MIN, 0);        // 6
+        M_KEYS.put(ValueEnum.SUB_MAX, 32000);     // 99
+    }
+    
+    private static final EnumMap<ValueEnum, String> M_VALS = new EnumMap<>(ValueEnum.class);
+    
+    static {
+        M_VALS.put(ValueEnum.A1,      "v17");
+        M_VALS.put(ValueEnum.A1_EQ,   "v19");
+        M_VALS.put(ValueEnum.A1_NE,   "v20");
+        M_VALS.put(ValueEnum.B1,      "v21");
+        M_VALS.put(ValueEnum.C1,      "v22");
+        M_VALS.put(ValueEnum.D1,      "v31");
+        M_VALS.put(ValueEnum.D2,      "v32");
+        M_VALS.put(ValueEnum.D3,      "v33");
+        M_VALS.put(ValueEnum.D4,      "v34");
+        M_VALS.put(ValueEnum.E1,      "v81");
+        M_VALS.put(ValueEnum.E1_EQ,   "v81");
+        M_VALS.put(ValueEnum.E1_NE,   "v81");
+        M_VALS.put(ValueEnum.SUB_MIN, "v91");
+        M_VALS.put(ValueEnum.SUB_MAX, "v92");
+    }
+    
+    public static void $put(Map<Integer, String> target, ValueEnum... items) {
+        for(ValueEnum item : items) {
+            target.put($key(item), $value(item));
+        }
+    }
+    
+    public static void $put(Map<Integer, String> target, Integer... items) {
+        for (Integer point : items) {
+            target.put(point, $value(B1));
+        }
+    }
+    
+    public static Entry<Integer, String> $find(Map<Integer, String> target, ValueEnum key) {
+        for(Entry<Integer, String> entry : target.entrySet()) {
+            if($equals(entry.getKey(), key)) {
+                return entry;
+            }
+        }
+        fail("Entry not found: " + key);
+        return null;
+    }
+    
+	public static int[] $shuffle(int[] array) {
+		$shuffle(array, null);
+        return array;
+	}
+    
+    public static void $shuffle(int[] array, String[] values) {
+		int n = array.length;
+		Random random = new Random(777);
+		for(int i=0; i<n; i++) {
+			int a = random.nextInt(n);
+			int b = random.nextInt(n);
+			Integer point = array[a];
+			array[a] = array[b];
+			array[b] = point;
+            if(null != values) {
+                String value = values[a];
+                values[a] = values[b];
+                values[b] = value;
+            }
+		}
+	}
+
+    public static Integer $key(ValueEnum type) {
+        return M_KEYS.get(type);
+    }
+    
+    public static int[] $keys(ValueEnum... values) {
+        int[] array = new int[values.length];
+        for(int i=0; i<values.length; i++) {
+            array[i] = $key(values[i]);
+        }
+        return array;
+    }
+
+    public static int[] $keys(int count) {
+        int[] array = new int[count];
+        for (int i = 0; i < count; i++) {
+            array[i] = i;
+        }
+        return array;
+    }
+
+    /**
+     * Zwraca listę 3*count elementów, w której punkty są częściowo równe:
+     * A B1 C, A B1 C, A B1 C, ...
+     * gdzie
+     *    A - punkt oryginalny
+     *    B1 - punkty równy
+     *    C - punkt różny ale ten sam hashcode
+     * @param count
+     * @return
+     */
+    public static int[] $ukeys(int count) {
+        int n = 3 * count;
+        int[] array = new int[n];
+        for (int i = 0; i < n; i += 3) {
+            array[i + 0] = i;
+            array[i + 1] = i+10000;
+            array[i + 2] = i+11000;
+        }
+        return array;
+    }
+
+    public static String $value(ValueEnum type) {
+        return M_VALS.get(type);
+    }
+
+    public static String[] $values(int count) {
+        String[] array = new String[count];
+        for (int i = 0; i < count; i++) {
+            array[i] = "s"+(i++);
+        }
+        return array;
+    }
+    
+    public static String[] $values(ValueEnum... values) {
+        String[] array = new String[values.length];
+        for(int i=0; i<values.length; i++) {
+            array[i] = $value(values[i]);
+        }
+        return array;
+    }
+
+    public static Map<Integer, String> $map(int[] keys) {
+        Map<Integer, String> target = new TreeMap<>(IntValue.STD);
+        String[] values = $values(keys.length);
+        for (int i = 0; i < keys.length; i++) {
+            target.put(keys[i], values[i]);
+        }
+        return target;
+    }
+
+    public static Map<Integer, String> $map(int[] points, String[] values) {
+        Map<Integer, String> target = new TreeMap<>(IntValue.STD);
+        for (int i = 0; i < points.length; i++) {
+            target.put(points[i], values[i]);
+        }
+        return target;
+    }
+
+    public static boolean $equals(Integer point1, Integer point2) {
+        return IntValue.MOD.equals(point1, point2);
+    }
+    
+    public static boolean $equals(Integer point1, ValueEnum point2) {
+        return IntValue.MOD.equals(point1, $key(point2));
+    }
+
+    public static int $hashcode(Integer point) {
+        return IntValue.MOD.hashCode(point);
+    }
+    
+    public static int $hashcode(ValueEnum point) {
+        return IntValue.MOD.hashCode($key(point));
+    }
+    
+    public static Entry<Integer, String> $entry(Integer key, String value){
+        return new AbstractMap.SimpleEntry<>(key, value);
+    }
+    
+    public static Entry<Integer, String> $entry(ValueEnum point){
+        return $entry($key(point), $value(point));
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static Entry<Integer, String>[] $entries(ValueEnum... values) {
+        Entry<Integer, String>[] array = new Entry[values.length];
+        for(int i=0; i<values.length; i++) {
+            array[i] = $entry(values[i]);
+        }
+        return array;
+    }
+    
+}

+ 4 - 4
assira/src/test/java/net/ranides/assira/collection/mockup/TPoint.java

@@ -18,9 +18,9 @@ public class TPoint implements Serializable {
     
     private static final long serialVersionUID = 1L;
 
-    private final int x;
-    private final int y;
-    private final int z;
+    public final int x;
+    public final int y;
+    public final int z;
 
     public TPoint(int x, int y, int z) {
         this.x = x;
@@ -96,7 +96,7 @@ public class TPoint implements Serializable {
     };
     
     private static int zz(int z) {
-        return z & 0xFFFF;
+        return z & 0x3FF;
     }
 
 }

+ 21 - 16
assira/src/test/java/net/ranides/assira/collection/mockup/TPointUtils.java

@@ -28,6 +28,16 @@ public final class TPointUtils {
         // utility class
     }
     
+    // zarezerwowane:
+    //      punkty hashcode < 100
+    //      punkty suma < 100
+    //      wartości mniejsze < 100
+    
+    private static final int MIN_X = 250;
+    private static final int MIN_Y = 100;
+    private static final int MIN_Z = 100;
+    private static final int MIN_V = 200;
+    
     public static final ValueGenerator<TPoint, ValueEnum> KEYS = new ValueGenerator<TPoint, ValueEnum>(TPoint.class) {
         
         @Override
@@ -42,7 +52,7 @@ public final class TPointUtils {
         
         @Override
         public TPoint object(int key) {
-            return new TPoint(250+key, 100+key, 100+key);
+            return new TPoint(MIN_X+key, MIN_Y+key, MIN_Z+key);
         }
     };
     
@@ -60,7 +70,7 @@ public final class TPointUtils {
 
         @Override
         public Entry<TPoint, Integer> object(int key) {
-            return $entry(KEYS.object(key), 100+key);
+            return $entry(KEYS.object(key), MIN_V+key);
         }
         
     };
@@ -78,11 +88,6 @@ public final class TPointUtils {
         }
     };
 
-    // zarezerwowane:
-    //      punkty hashcode < 100
-    //      punkty suma < 100
-    //      wartości mniejsze < 100
-
     private static final EnumMap<ValueEnum, TPoint> M_KEYS = new EnumMap<>(ValueEnum.class);
     
     static {
@@ -96,7 +101,7 @@ public final class TPointUtils {
         M_KEYS.put(ValueEnum.D3,    new TPoint(20, 40, 5));              // 65
         M_KEYS.put(ValueEnum.D4,    new TPoint(20, 40, 6));              // 66
         M_KEYS.put(ValueEnum.E1,    new TPoint(33, 42, 6));              // 81
-        M_KEYS.put(ValueEnum.E1_EQ, new TPoint(33, 42, 6+0x10000));      // 81
+        M_KEYS.put(ValueEnum.E1_EQ, new TPoint(33, 42, 6+0x400));        // 81
         M_KEYS.put(ValueEnum.E1_NE, new TPoint(33, 42, 17));             // 92
         
         M_KEYS.put(ValueEnum.SUB_MIN, new TPoint(3, 2, 1));              // 6
@@ -196,9 +201,9 @@ public final class TPointUtils {
     }
 
     public static TPoint[] $keys(int count) {
-        int x = 250;
-        int y = 100;
-        int z = 100;
+        int x = MIN_X;
+        int y = MIN_Y;
+        int z = MIN_Z;
         TPoint[] array = new TPoint[count];
         for (int i = 0; i < count; i++) {
             array[i] = new TPoint(x++, y++, z++);
@@ -217,9 +222,9 @@ public final class TPointUtils {
      * @return
      */
     public static TPoint[] $ukeys(int count) {
-        int x = 250;
-        int y = 100;
-        int z = 100;
+        int x = MIN_X;
+        int y = MIN_Y;
+        int z = MIN_Z;
         int n = 3 * count;
         TPoint[] array = new TPoint[n];
         for (int i = 0; i < n; i += 3) {
@@ -239,7 +244,7 @@ public final class TPointUtils {
 
     public static int[] $values(int count) {
         int[] array = new int[count];
-        int value = 200;
+        int value = MIN_V;
         for (int i = 0; i < count; i++) {
             array[i] = (value++);
         }
@@ -260,7 +265,7 @@ public final class TPointUtils {
 
     public static Integer[] $objects(int count) {
         Integer[] array = new Integer[count];
-        int value = 200;
+        int value = MIN_V;
         for (int i = 0; i < count; i++) {
             array[i] = (value++);
         }