From d7ff20abfb73f67c24d70cd27d6c6f5124503aa0 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 23 Dec 2015 14:51:38 +0000
Subject: [PATCH] EntryContainer.java: Remove null checks on operation objects

---
 opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java                                   |   75 ++------------
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java               |   90 ++++-------------
 opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java             |    8 +
 opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java |   81 ++++++++++++---
 4 files changed, 102 insertions(+), 152 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index 6e13f96..bb3b81e 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -1529,11 +1529,8 @@
             dn2uri.addEntry(txn, entry);
             id2childrenCount.updateTotalCount(txn, 1);
             indexBuffer.flush(txn);
-            if (addOperation != null)
-            {
-              // One last check before committing
-              addOperation.checkIfCanceled(true);
-            }
+            // One last check before committing
+            addOperation.checkIfCanceled(true);
           }
           catch (StorageRuntimeException | DirectoryException | CanceledOperationException e)
           {
@@ -1648,8 +1645,7 @@
             }
 
             // Delete the subordinate entries in dn2id if requested.
-            final boolean isSubtreeDelete = deleteOperation != null
-                    && deleteOperation.getRequestControl(SubtreeDeleteControl.DECODER) != null;
+            final boolean isSubtreeDelete = deleteOperation.getRequestControl(SubtreeDeleteControl.DECODER) != null;
 
             /* draft-armijo-ldap-treedelete, 4.1 Tree Delete Semantics: The server MUST NOT chase referrals stored in
              * the tree. If information about referrals is stored in this section of the tree, this pointer will be
@@ -1685,7 +1681,7 @@
                 }
                 entriesToBeDeleted.add(cursor.getValue().longValue());
                 cursor.delete();
-                checkIfCanceled(false);
+                deleteOperation.checkIfCanceled(false);
               }
             }
             // The target entry will have the lowest entryID so it will remain the first element.
@@ -1723,12 +1719,12 @@
                   entryCache.removeEntry(entry.getName());
                 }
                 isBaseEntry = false;
-                checkIfCanceled(false);
+                deleteOperation.checkIfCanceled(false);
               }
             }
             id2childrenCount.updateTotalCount(txn, -entriesToBeDeleted.size());
             indexBuffer.flush(txn);
-            checkIfCanceled(true);
+            deleteOperation.checkIfCanceled(true);
             if (isSubtreeDelete)
             {
               deleteOperation.addAdditionalLogItem(unquotedKeyValue(getClass(), "deletedEntries",
@@ -1753,7 +1749,7 @@
 
         private void invokeSubordinateDeletePlugins(final Entry entry) throws DirectoryException
         {
-          if (deleteOperation != null && !deleteOperation.isSynchronizationOperation())
+          if (!deleteOperation.isSynchronizationOperation())
           {
             SubordinateDelete pluginResult =
                     getPluginConfigManager().invokeSubordinateDeletePlugins(deleteOperation, entry);
@@ -1764,14 +1760,6 @@
             }
           }
         }
-
-        private void checkIfCanceled(boolean signalTooLate) throws CanceledOperationException
-        {
-          if (deleteOperation != null)
-          {
-            deleteOperation.checkIfCanceled(signalTooLate);
-          }
-        }
       });
     }
     catch (Exception e)
@@ -1938,39 +1926,14 @@
             // Ensure same ordering as deleteEntry: id2entry, dn2uri, then indexes.
             id2entry.put(txn, entryID, encodedNewEntry);
 
-            // Update the referral tree.
-            if (modifyOperation != null)
-            {
-              // In this case we know from the operation what the modifications were.
-              List<Modification> mods = modifyOperation.getModifications();
-              dn2uri.modifyEntry(txn, oldEntry, newEntry, mods);
-            }
-            else
-            {
-              dn2uri.replaceEntry(txn, oldEntry, newEntry);
-            }
-
-            // Update the indexes.
-            if (modifyOperation != null)
-            {
-              // In this case we know from the operation what the modifications were.
-              List<Modification> mods = modifyOperation.getModifications();
-              indexModifications(indexBuffer, oldEntry, newEntry, entryID, mods);
-            }
-            else
-            {
-              // The most optimal would be to figure out what the modifications were.
-              removeEntryFromIndexes(indexBuffer, oldEntry, entryID);
-              insertEntryIntoIndexes(indexBuffer, newEntry, entryID);
-            }
+            // Update the referral tree and indexes
+            dn2uri.modifyEntry(txn, oldEntry, newEntry, modifyOperation.getModifications());
+            indexModifications(indexBuffer, oldEntry, newEntry, entryID, modifyOperation.getModifications());
 
             indexBuffer.flush(txn);
 
-            if(modifyOperation != null)
-            {
-              // One last check before committing
-              modifyOperation.checkIfCanceled(true);
-            }
+            // One last check before committing
+            modifyOperation.checkIfCanceled(true);
 
             // Update the entry cache.
             EntryCache<?> entryCache = DirectoryServer.getEntryCache();
@@ -2105,12 +2068,12 @@
               {
                 renameSingleEntry(txn, renamedEntryID, cursor, indexBuffer, newTargetDN, renumberEntryIDs, isBaseEntry);
                 isBaseEntry = false;
-                checkIfCanceled(false);
+                modifyDNOperation.checkIfCanceled(false);
               }
 
             }
             indexBuffer.flush(txn);
-            checkIfCanceled(true);
+            modifyDNOperation.checkIfCanceled(true);
           }
           catch (StorageRuntimeException | DirectoryException | CanceledOperationException e)
           {
@@ -2155,7 +2118,7 @@
               dn2uri.checkTargetForReferral(oldEntry, null);
             }
             newEntry = newTargetEntry;
-            modifications = modifyDNOperation != null ? modifyDNOperation.getModifications() : null;
+            modifications = modifyDNOperation.getModifications();
           }
           else
           {
@@ -2198,14 +2161,6 @@
           }
         }
 
-        private void checkIfCanceled(boolean signalTooLate) throws CanceledOperationException
-        {
-          if (modifyDNOperation != null)
-          {
-            modifyDNOperation.checkIfCanceled(signalTooLate);
-          }
-        }
-
         private List<Modification> invokeSubordinateModifyDNPlugins(
                 final Entry oldEntry, final Entry newEntry) throws DirectoryException
         {
@@ -2218,7 +2173,7 @@
           //          provide an unmodifiable list for the modifications element.
           // FIXME -- This will need to be updated appropriately if we decided that
           //          these plugins should be invoked for synchronization operations.
-          if (modifyDNOperation != null && !modifyDNOperation.isSynchronizationOperation())
+          if (!modifyDNOperation.isSynchronizationOperation())
           {
             SubordinateModifyDN pluginResult = getPluginConfigManager().invokeSubordinateModifyDNPlugins(
                     modifyDNOperation, oldEntry, newEntry, modifications);
@@ -2397,17 +2352,14 @@
    */
   private static boolean isManageDsaITOperation(Operation operation)
   {
-    if(operation != null)
+    List<Control> controls = operation.getRequestControls();
+    if (controls != null)
     {
-      List<Control> controls = operation.getRequestControls();
-      if (controls != null)
+      for (Control control : controls)
       {
-        for (Control control : controls)
+        if (ServerConstants.OID_MANAGE_DSAIT_CONTROL.equals(control.getOID()))
         {
-          if (ServerConstants.OID_MANAGE_DSAIT_CONTROL.equals(control.getOID()))
-          {
-            return true;
-          }
+          return true;
         }
       }
     }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java b/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
index 17dcce4..8dad89a 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/TestCaseUtils.java
@@ -80,6 +80,7 @@
 
 import com.forgerock.opendj.util.OperatingSystem;
 
+import static org.mockito.Mockito.*;
 import static org.opends.server.loggers.TextAccessLogPublisher.*;
 import static org.opends.server.loggers.TextErrorLogPublisher.*;
 import static org.opends.server.loggers.TextHTTPAccessLogPublisher.*;
@@ -88,9 +89,7 @@
 import static org.opends.server.util.StaticUtils.*;
 import static org.testng.Assert.*;
 
-/**
- * This class defines some utility functions which can be used by test cases.
- */
+/** This class defines some utility functions which can be used by test cases. */
 @SuppressWarnings("javadoc")
 public final class TestCaseUtils {
   /** The name of the system property that specifies the server build root. */
@@ -345,7 +344,6 @@
         copyDirectory(new File(installedRoot), testInstallRoot);
 
         // Get the instance location
-
       }
       else
       {
@@ -615,10 +613,7 @@
     waitForOpsToComplete();
   }
 
-  /**
-   * This can be made public if quiesceServer becomes too heavy-weight in
-   * some circumstance.
-   */
+  /** This can be made public if quiesceServer becomes too heavy-weight in some circumstance. */
   private static void waitForOpsToComplete()
   {
     try {
@@ -630,7 +625,6 @@
     }
   }
 
-
   /**
    * Binds to the given socket port on the local host.
    * @return the bounded Server socket.
@@ -727,8 +721,6 @@
     DirectoryServer.setSchema(schemaBeforeStartingFakeServer);
   }
 
-
-
   /**
    * Shut down the server. This should only be called at the end of the test
    * suite and not by any unit tests.
@@ -815,9 +807,7 @@
     }
   }
 
-  /**
-   * Clears a memory-based backend.
-   */
+  /** Clears a memory-based backend. */
   public static void clearMemoryBackend(String backendID) throws Exception
   {
     MemoryBackend memoryBackend = (MemoryBackend) DirectoryServer.getBackend(backendID);
@@ -852,7 +842,7 @@
     if (clearBackend(b) && baseDN != null)
     {
       Entry e = createEntry(DN.valueOf(baseDN));
-      DirectoryServer.getBackend(backendId).addEntry(e, null);
+      DirectoryServer.getBackend(backendId).addEntry(e, mock(AddOperation.class));
     }
   }
 
@@ -860,7 +850,7 @@
   {
     if (b instanceof BackendImpl)
     {
-      final BackendImpl backend = (BackendImpl) b;
+      final BackendImpl<?> backend = (BackendImpl<?>) b;
       final RootContainer rootContainer = backend.getRootContainer();
       if (rootContainer != null)
       {
@@ -987,7 +977,6 @@
     }
   }
 
-
   /**
    * Get the LDAP port the test environment Directory Server instance is
    * running on.
@@ -1069,14 +1058,12 @@
     // No implementation.
   }
 
-
   ////////////////////////////////////////////////////////////////////////////
   ////////////////////////////////////////////////////////////////////////////
   // Various methods for converting LDIF Strings to Entries
   ////////////////////////////////////////////////////////////////////////////
   ////////////////////////////////////////////////////////////////////////////
 
-
   /**
    * Returns a modifiable List of entries parsed from the provided LDIF.
    * It's best to call this after the server has been initialized so
@@ -1202,8 +1189,6 @@
      return entriesFromLdifString(makeLdif(lines));
   }
 
-
-
   /**
    * Adds the provided entry to the Directory Server using an internal
    * operation.
@@ -1218,8 +1203,6 @@
     assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
   }
 
-
-
   /**
    * Deletes the provided entry from the Directory Server using an
    * internal operation.
@@ -1247,12 +1230,10 @@
     assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
   }
 
-
-
   public static boolean canBind(String dn, String pw) throws Exception
   {
     // Check that the user can bind.
-    try (Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort());)
+    try (Socket s = new Socket("127.0.0.1", TestCaseUtils.getServerLdapPort()))
     {
       TestCaseUtils.configureSocket(s);
       ASN1Reader r = ASN1.getReader(s.getInputStream());
@@ -1275,8 +1256,6 @@
     }
   }
 
-
-
   /**
    * Configures a socket for use in unit tests. This should only be used if the
    * socket is not expected to timeout.
@@ -1291,8 +1270,6 @@
     s.setSoTimeout(60 * 1000);
   }
 
-
-
   /**
    * Adds the provided entry to the Directory Server using an internal
    * operation.
@@ -1312,8 +1289,6 @@
     return e;
   }
 
-
-
   /**
    * Adds the provided entry to the Directory Server using an internal
    * operation.
@@ -1331,8 +1306,6 @@
     return addOperation.getResultCode();
   }
 
-
-
   /**
    * Adds the provided set of entries to the Directory Server using internal
    * operations.
@@ -1349,8 +1322,6 @@
     }
   }
 
-
-
   /**
    * Adds the provided set of entries to the Directory Server using internal
    * operations.
@@ -1369,8 +1340,6 @@
     }
   }
 
-
-
   /**
    * Applies a set of modifications to the server as described in the provided
    * set of lines (using LDIF change form).  The changes will be applied over
@@ -1455,9 +1424,7 @@
     }
   }
 
-  /**
-   * Return a Map constructed via alternating key and value pairs.
-   */
+  /** Return a Map constructed via alternating key and value pairs. */
   public static Map<String, String> makeMap(String... keyValuePairs)
   {
     Map<String, String> map = new LinkedHashMap<>();
@@ -1482,12 +1449,10 @@
    *  must write something to System.out. */
   public static final PrintStream originalSystemOut = System.out;
 
-  /** System.err is redirected to here so that we can only print it out
-   *  if a test fails. */
+  /** System.err is redirected to here so that we can only print it out if a test fails. */
   private static final ByteArrayOutputStream redirectedSystemErr = new ByteArrayOutputStream();
 
-  /** System.out is redirected to here so that we can only print it out
-   *  if a test fails. */
+  /** System.out is redirected to here so that we can only print it out if a test fails. */
   private static final ByteArrayOutputStream redirectedSystemOut = new ByteArrayOutputStream();
 
   public static synchronized void suppressOutput() {
@@ -1552,9 +1517,7 @@
     redirectedSystemErr.reset();
   }
 
-  /**
-   * Clear everything written to the Access, Error, or Debug loggers.
-   */
+  /** Clear everything written to the Access, Error, or Debug loggers. */
   public static synchronized void clearLoggersContents() {
     ACCESS_TEXT_WRITER.clear();
     ERROR_TEXT_WRITER.clear();
@@ -1642,7 +1605,6 @@
     return lines;
   }
 
-
   /** Read the contents of a file and return it as a String. */
   private static byte[] readFileBytes(File file) throws IOException {
     FileInputStream fis = new FileInputStream(file);
@@ -1675,7 +1637,6 @@
     return bytes;
   }
 
-
   /** Store the contents of a String in a file. */
   public static void writeFile(File file, String contents) throws IOException {
     writeFile(file.getAbsolutePath(), contents);
@@ -1736,8 +1697,6 @@
     assertEquals(DSConfig.main(fullArgs, System.out, System.err), 0);
   }
 
-
-
   /**
    * Gets the root configuration associated with the active server
    * instance. This root configuration can then be used to access and
@@ -1766,8 +1725,6 @@
     return context.getRootConfiguration();
   }
 
-
-
   /**
    * Return a String representation of all of the current threads.
    * @return a dump of all Threads on the server
@@ -1776,7 +1733,6 @@
   {
     Map<Thread,StackTraceElement[]> threadStacks = Thread.getAllStackTraces();
 
-
     // Re-arrange all of the elements by thread ID so that there is some logical order.
     Map<Long, Map.Entry<Thread, StackTraceElement[]>> orderedStacks = new TreeMap<>();
     for (Map.Entry<Thread,StackTraceElement[]> e : threadStacks.entrySet())
@@ -1900,18 +1856,15 @@
   /** FIXME Replace with {@link Assert#assertNotEquals(Object, Object, String)} once we upgrade to testng >= 6.1. */
   public static void assertNotEquals(Object actual1, Object actual2, String message)
   {
-    boolean fail = false;
     try
     {
       Assert.assertEquals(actual1, actual2);
-      fail = true;
+      Assert.fail(message);
     }
     catch (AssertionError e)
     {
-    }
-    if (fail)
-    {
-      Assert.fail(message);
+      // this is good: they are not equals
+      return;
     }
   }
 }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
index cabff17..efe076e 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
@@ -26,7 +26,7 @@
 package org.opends.server.backends.pluggable;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 import static org.opends.server.ConfigurationMock.legacyMockCfg;
 import static org.opends.server.TestCaseUtils.makeEntry;
 import static org.opends.server.protocols.internal.InternalClientConnection.getRootConnection;
@@ -55,6 +55,7 @@
 import org.opends.server.controls.ServerSideSortResponseControl;
 import org.opends.server.controls.VLVRequestControl;
 import org.opends.server.controls.VLVResponseControl;
+import org.opends.server.core.AddOperation;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
@@ -154,10 +155,11 @@
     backend.configureBackend(backendCfg, DirectoryServer.getInstance().getServerContext());
     backend.openBackend();
 
-    backend.addEntry(makeEntry("dn: " + BACKEND_BASE_DN, "objectclass: top", "objectclass: domain"), null);
+    AddOperation op = mock(AddOperation.class);
+    backend.addEntry(makeEntry("dn: " + BACKEND_BASE_DN, "objectclass: top", "objectclass: domain"), op);
     for (final User user : USERS)
     {
-      backend.addEntry(user.toEntry(), null);
+      backend.addEntry(user.toEntry(), op);
     }
   }
 
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
index 3fe8ba3..aa5c52f 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
@@ -26,9 +26,8 @@
 package org.opends.server.backends.pluggable;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.forgerock.opendj.ldap.ModificationType.ADD;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.forgerock.opendj.ldap.ModificationType.*;
+import static org.mockito.Mockito.*;
 import static org.opends.server.protocols.internal.InternalClientConnection.getRootConnection;
 import static org.opends.server.protocols.internal.Requests.newSearchRequest;
 import static org.opends.server.types.Attributes.create;
@@ -38,6 +37,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -51,6 +51,8 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.forgerock.util.Reject;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
 import org.opends.server.DirectoryServerTestCase;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType;
@@ -61,8 +63,8 @@
 import org.opends.server.api.Backend.BackendOperation;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.backends.RebuildConfig;
-import org.opends.server.backends.VerifyConfig;
 import org.opends.server.backends.RebuildConfig.RebuildMode;
+import org.opends.server.backends.VerifyConfig;
 import org.opends.server.backends.pluggable.spi.AccessMode;
 import org.opends.server.backends.pluggable.spi.ReadOnlyStorageException;
 import org.opends.server.backends.pluggable.spi.ReadOperation;
@@ -71,7 +73,12 @@
 import org.opends.server.backends.pluggable.spi.TreeName;
 import org.opends.server.backends.pluggable.spi.WriteOperation;
 import org.opends.server.backends.pluggable.spi.WriteableTransaction;
+import org.opends.server.core.AddOperation;
+import org.opends.server.core.DeleteOperation;
 import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.SearchOperation;
 import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
@@ -85,6 +92,7 @@
 import org.opends.server.types.LDIFImportConfig;
 import org.opends.server.types.Modification;
 import org.opends.server.types.RestoreConfig;
+import org.opends.server.types.SearchFilter;
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
 import org.testng.Reporter;
@@ -555,9 +563,10 @@
 
   private void addEntriesToBackend(List<Entry> entries) throws Exception
   {
+    AddOperation op = mock(AddOperation.class);
     for (Entry newEntry : entries)
     {
-      backend.addEntry(newEntry, null);
+      backend.addEntry(newEntry, op);
     }
   }
 
@@ -599,7 +608,8 @@
     backend.getRootContainer().checkForEnoughResources(null);
   }
 
-  @Test(expectedExceptions = DirectoryException.class)
+  @Test(expectedExceptions = DirectoryException.class,
+      expectedExceptionsMessageRegExp="The entry .* cannot be added because its parent entry does not exist")
   public void testAddNoParent() throws Exception
   {
     Entry newEntry = TestCaseUtils.makeEntry("dn: " + badEntryDN, "objectclass: ou", "");
@@ -667,10 +677,43 @@
     Entry newEntry = oldEntry.duplicate(false);
 
     modifyAttribute = DirectoryServer.getAttributeTypeOrNull("jpegphoto");
-    newEntry.applyModifications(Arrays.asList(new Modification(ADD, create(modifyAttribute, modifyValue))));
+    List<Modification> mods = Arrays.asList(
+        // unindexed
+        new Modification(ADD, create(modifyAttribute, modifyValue)),
+        // indexed
+        new Modification(REPLACE, create("sn", "Smith")));
+    newEntry.applyModifications(mods);
 
-    backend.replaceEntry(oldEntry, newEntry, null);
+    ModifyOperation modifyOp = mock(ModifyOperation.class);
+    when(modifyOp.getModifications()).thenReturn(mods);
+    backend.replaceEntry(oldEntry, newEntry, modifyOp);
     assertTrue(backend.getEntry(oldEntry.getName()).hasValue(modifyAttribute, null, modifyValue));
+
+    final List<Entry> returnedEntries = new ArrayList<>();
+    backend.search(createSearchOperation(
+        newEntry.getName().parent(), SearchScope.WHOLE_SUBTREE, "(&(sn=Smith)(jpegphoto=foo))", returnedEntries));
+    assertThat(returnedEntries).hasSize(1);
+    assertThat(returnedEntries.get(0).getName()).isEqualTo(newEntry.getName());
+  }
+
+  private SearchOperation createSearchOperation(DN baseDN, SearchScope scope, String searchFilter,
+      final List<Entry> returnedEntries) throws DirectoryException
+  {
+    SearchOperation searchOp = mock(SearchOperation.class);
+    when(searchOp.getBaseDN()).thenReturn(baseDN);
+    when(searchOp.getScope()).thenReturn(scope);
+    when(searchOp.getFilter()).thenReturn(SearchFilter.createFilterFromString(searchFilter));
+    when(searchOp.getClientConnection()).thenReturn(new ClientConnectionStub());
+    doAnswer(new Answer<Object>()
+    {
+      @Override
+      public Object answer(InvocationOnMock invocation) throws Throwable
+      {
+        returnedEntries.add(invocation.getArgumentAt(0, Entry.class));
+        return null;
+      }
+    }).when(searchOp).returnEntry(any(Entry.class), any(List.class));
+    return searchOp;
   }
 
   @Test
@@ -680,14 +723,15 @@
     DN prevDN = DN.valueOf("ou=People," + testBaseDN);
     DN newDN = DN.valueOf("ou=users," + testBaseDN);
     Entry renameEntry = backend.getEntry(prevDN).duplicate(false);
+    ModifyDNOperation op = mock(ModifyDNOperation.class);
 
     renameEntry.setDN(newDN);
-    backend.renameEntry(prevDN, renameEntry, null);
+    backend.renameEntry(prevDN, renameEntry, op);
     Entry dbEntry = backend.getEntry(newDN);
     assertEquals(dbEntry.getName(), newDN, "Renamed entry is missing.");
 
     renameEntry.setDN(prevDN);
-    backend.renameEntry(newDN, renameEntry, null);
+    backend.renameEntry(newDN, renameEntry, op);
     dbEntry = backend.getEntry(prevDN);
     assertEquals(dbEntry.getName(), prevDN, "Original entry has not been renamed");
   }
@@ -699,18 +743,19 @@
     DN newDN = DN.valueOf("uid=USER.0,ou=People," + testBaseDN);
     Entry renameEntry = backend.getEntry(prevDN).duplicate(false);
 
+    ModifyDNOperation op = mock(ModifyDNOperation.class);
     renameEntry.setDN(newDN);
-    backend.renameEntry(prevDN, renameEntry, null);
+    backend.renameEntry(prevDN, renameEntry, op);
     Entry dbEntry = backend.getEntry(newDN);
     assertEquals(dbEntry.getName().rdn().toString(), "uid=USER.0");
 
     renameEntry.setDN(prevDN);
-    backend.renameEntry(newDN, renameEntry, null);
+    backend.renameEntry(newDN, renameEntry, op);
     dbEntry = backend.getEntry(prevDN);
     assertEquals(dbEntry.getName().rdn().toString(), "uid=user.0");
   }
 
-  @Test
+  @Test(expectedExceptions = DirectoryException.class)
   public void testDeleteEntry() throws Exception
   {
     Entry deletedEntry = backend.getEntry(dnToDel).duplicate(false);
@@ -720,19 +765,17 @@
       deleteEntry(dnToDel);
       fail("Should have generated a DirectoryException");
     }
-    catch (DirectoryException de)
-    {
-      // Expected exception, do nothing, test succeeds.
-    }
     finally
     {
-      backend.addEntry(deletedEntry, null);
+      AddOperation op = mock(AddOperation.class);
+      backend.addEntry(deletedEntry, op);
     }
   }
 
   private void deleteEntry(DN dn) throws Exception
   {
-    backend.deleteEntry(dn, null);
+    DeleteOperation op = mock(DeleteOperation.class);
+    backend.deleteEntry(dn, op);
     assertNull(backend.getEntry(workEntries.get(1).getName()));
   }
 

--
Gitblit v1.10.0