Author: mduerig
Date: Mon Jul 20 15:33:59 2015
New Revision: 1691965

URL: http://svn.apache.org/r1691965
Log:
OAK-3123: NPE in RecordIdMap
* Properly guard against NPE
* Added test case for empty map

Modified:
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMap.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMapTest.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMap.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMap.java?rev=1691965&r1=1691964&r2=1691965&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMap.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMap.java
 Mon Jul 20 15:33:59 2015
@@ -29,8 +29,11 @@ import javax.annotation.Nonnull;
  * A memory optimised map of {@code short} key to {@link RecordId} values.
  */
 public class RecordIdMap {
-    private short[] keys;
-    private RecordId[] values;
+    private static final short[] NO_KEYS = new short[0];
+    private static final RecordId[] NO_VALUES = new RecordId[0];
+
+    private short[] keys = NO_KEYS;
+    private RecordId[] values = NO_VALUES;
 
     /**
      * Associates {@code key} with {@code value} if not already present
@@ -39,7 +42,7 @@ public class RecordIdMap {
      * @return  {@code true} if added, {@code false} if already present
      */
     public boolean put(short key, @Nonnull RecordId value) {
-        if (keys == null) {
+        if (keys.length == 0) {
             keys = new short[1];
             values = new RecordId[1];
             keys[0] = key;
@@ -90,7 +93,7 @@ public class RecordIdMap {
      * @return  {@code true} iff {@code key} is present.
      */
     public boolean containsKey(short key) {
-        return keys != null && binarySearch(keys, key) >= 0;
+        return binarySearch(keys, key) >= 0;
     }
 
     /**
@@ -105,6 +108,7 @@ public class RecordIdMap {
      * the natural ordering of shorts.
      * @param index
      * @return the key at {@code index}
+     * @throws ArrayIndexOutOfBoundsException if not {@code 0 <= index < 
size()}
      */
     public short getKey(int index) {
         return keys[index];
@@ -115,6 +119,7 @@ public class RecordIdMap {
      * the natural ordering of shorts.
      * @param index
      * @return the value at {@code index}
+     * @throws ArrayIndexOutOfBoundsException if not {@code 0 <= index < 
size()}
      */
     @Nonnull
     public RecordId getRecordId(int index) {

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMapTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMapTest.java?rev=1691965&r1=1691964&r2=1691965&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMapTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordIdMapTest.java
 Mon Jul 20 15:33:59 2015
@@ -25,7 +25,10 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.segment.Segment.encode;
 import static 
org.apache.jackrabbit.oak.plugins.segment.TestUtils.newValidOffset;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.Map;
 import java.util.Map.Entry;
@@ -37,6 +40,22 @@ import org.junit.Test;
 public class RecordIdMapTest {
 
     @Test
+    public void testEmpty() {
+        RecordIdMap map = new RecordIdMap();
+        assertFalse(map.containsKey((short) 0));
+        assertNull(map.get((short) 0));
+        assertEquals(0, map.size());
+        try {
+            map.getKey(0);
+            fail("Expected AIOBE");
+        } catch (ArrayIndexOutOfBoundsException ignored) {}
+        try {
+            map.getRecordId(0);
+            fail("Expected AIOBE");
+        } catch (ArrayIndexOutOfBoundsException ignored) {}
+    }
+
+    @Test
     public void testRecordIdMap() {
         int maxSegments = 1000;
         int maxEntriesPerSegment = 10;


Reply via email to