From 427fa0913cb9a738f055904f6df776df7ff805b5 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 02 Dec 2015 15:57:04 +0000
Subject: [PATCH] Fixed NPE when searching an inexistent DN with scope SINGLE_LEVEL or SUBORDINATES + added tests

---
 opendj-server-legacy/src/test/java/org/opends/server/core/SearchOperationTestCase.java |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DN2ID.java     |    8 ++--
 2 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DN2ID.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DN2ID.java
index 84626de..734c14b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DN2ID.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DN2ID.java
@@ -285,14 +285,14 @@
       SequentialCursorDecorator<Cursor<ByteString, ByteString>, ByteString, ByteString>
   {
     private final ByteStringBuilder builder;
-    private final ByteString limit;
+    private final ByteSequence limit;
     private boolean cursorOnParent;
 
     ChildrenCursor(Cursor<ByteString, ByteString> delegate)
     {
       super(delegate);
       builder = new ByteStringBuilder(128);
-      limit = delegate.isDefined() ? afterKey(delegate.getKey()).toByteString() : null;
+      limit = delegate.isDefined() ? afterKey(delegate.getKey()) : ByteString.empty();
       cursorOnParent = true;
     }
 
@@ -323,12 +323,12 @@
   private static final class SubtreeCursor extends
       SequentialCursorDecorator<Cursor<ByteString, ByteString>, ByteString, ByteString>
   {
-    private final ByteString limit;
+    private final ByteSequence limit;
 
     SubtreeCursor(Cursor<ByteString, ByteString> delegate)
     {
       super(delegate);
-      limit = delegate.isDefined() ? afterKey(delegate.getKey()).toByteString() : null;
+      limit = delegate.isDefined() ? afterKey(delegate.getKey()) : ByteString.empty();
     }
 
     @Override
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/core/SearchOperationTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/core/SearchOperationTestCase.java
index 57dd0f9..155edd5 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/core/SearchOperationTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/core/SearchOperationTestCase.java
@@ -303,6 +303,106 @@
   }
 
   @Test
+  public void testSearchNonExistingDN_baseObject() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request =
+        Requests.newSearchRequest("uid=doesNotExist," + BASE, SearchScope.BASE_OBJECT, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.NO_SUCH_OBJECT);
+  }
+
+  @Test
+  public void testSearchExistingDN_baseObject() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request = Requests.newSearchRequest(BASE, SearchScope.BASE_OBJECT, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.SUCCESS);
+    assertThat(getEntryNames(searchOp)).containsExactly(BASE);
+  }
+
+  @Test
+  public void testSearchNonExistingDN_singleLevel() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request =
+        Requests.newSearchRequest("uid=doesNotExist," + BASE, SearchScope.SINGLE_LEVEL, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.NO_SUCH_OBJECT);
+  }
+
+  @Test
+  public void testSearchExistingDN_singleLevel() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request = Requests.newSearchRequest(BASE, SearchScope.SINGLE_LEVEL, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.SUCCESS);
+    assertThat(getEntryNames(searchOp)).containsExactly(
+        "uid=rogasawara," + BASE,
+        "ou=level1," + BASE);
+  }
+
+  @Test
+  public void testSearchNonExisting_subordinates() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request =
+        Requests.newSearchRequest("uid=doesNotExist," + BASE, SearchScope.SUBORDINATES, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.NO_SUCH_OBJECT);
+  }
+
+  @Test
+  public void testSearchExistingDN_subordinates() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request = Requests.newSearchRequest(BASE, SearchScope.SUBORDINATES, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.SUCCESS);
+    assertThat(getEntryNames(searchOp)).containsExactly(
+        "uid=rogasawara," + BASE,
+        "ou=level1," + BASE,
+        "ou=level2,ou=level1," + BASE);
+  }
+
+  @Test
+  public void testSearchNonExisting_wholeSubtree() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request =
+        Requests.newSearchRequest("uid=doesNotExist," + BASE, SearchScope.WHOLE_SUBTREE, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.NO_SUCH_OBJECT);
+  }
+
+  @Test
+  public void testSearchExistingDN_wholeSubtree() throws Exception
+  {
+    InvocationCounterPlugin.resetAllCounters();
+    SearchRequest request = Requests.newSearchRequest(BASE, SearchScope.WHOLE_SUBTREE, "(objectclass=*)");
+    InternalSearchOperation searchOp = getRootConnection().processSearch(request);
+    assertThat(searchOp.getResultCode()).isEqualTo(ResultCode.SUCCESS);
+    assertThat(getEntryNames(searchOp)).containsExactly(
+        BASE,
+        "uid=rogasawara," + BASE,
+        "ou=level1," + BASE,
+        "ou=level2,ou=level1," + BASE);
+  }
+
+  private List<String> getEntryNames(InternalSearchOperation searchOp)
+  {
+    List<SearchResultEntry> entries = searchOp.getSearchEntries();
+    List<String> results = new ArrayList<>(entries.size());
+    for (SearchResultEntry entry : entries)
+    {
+      results.add(entry.getName().toString());
+    }
+    return results;
+  }
+
+  @Test
   public void testSearchInternalUnspecifiedAttributes() throws Exception
   {
     InternalSearchOperation searchOperation = newInternalSearchOperation("(objectclass=inetorgperson)");

--
Gitblit v1.10.0