mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Ludovic Poitou
12.52.2011 06757db3aca209339126dd2fc0f5ecb859e649d1
Fix to OPENDJ-274, resolve remaining nightly unit test failure with modifications of single valued attributes.
Tidy up some of the unit-tests around that area, adding more controls, making sure tests stop services on failure and reducing time to run.
4 files modified
569 ■■■■ changed files
opends/src/server/org/opends/server/replication/plugin/AttrHistoricalSingle.java 3 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java 511 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java 39 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java 16 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/replication/plugin/AttrHistoricalSingle.java
@@ -251,8 +251,7 @@
      break;
    case REPLACE:
      if ((changeNumber.older(deleteTime))
          && ((addTime == null) || (changeNumber.older(addTime))))
      if (changeNumber.older(deleteTime))
      {
        conflict = true;
        modsIterator.remove();
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.replication;
@@ -316,63 +317,69 @@
      openReplicationSession(baseDn, 2, 100, replServerPort, 1000, true);
    /*
     * Create a Change number generator to generate new changenumbers
     * when we need to send operation messages to the replicationServer.
     */
    ChangeNumberGenerator gen = new ChangeNumberGenerator(2, 0);
    try
    {
      /*
       * Create a Change number generator to generate new changenumbers
       * when we need to send operation messages to the replicationServer.
       */
      ChangeNumberGenerator gen = new ChangeNumberGenerator(2, 0);
    // Disable the directory server receive status.
    setReceiveStatus(synchroServerEntry.getDN().toString(), false);
      // Disable the directory server receive status.
      setReceiveStatus(synchroServerEntry.getDN().toString(), false);
    // Create and publish an update message to add an entry.
    AddMsg addMsg = new AddMsg(gen.newChangeNumber(),
        personWithUUIDEntry.getDN().toString(),
        user1entryUUID,
        baseUUID,
        personWithUUIDEntry.getObjectClassAttribute(),
        personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
    broker.publish(addMsg);
      // Create and publish an update message to add an entry.
      AddMsg addMsg = new AddMsg(gen.newChangeNumber(),
          personWithUUIDEntry.getDN().toString(),
          user1entryUUID,
          baseUUID,
          personWithUUIDEntry.getObjectClassAttribute(),
          personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
      broker.publish(addMsg);
    Entry resultEntry;
      Entry resultEntry;
    // Check that the entry has not been created in the directory server.
    resultEntry = getEntry(personWithUUIDEntry.getDN(), 1000, true);
    assertNull(resultEntry,
        "The replication message was replayed while the server " +
             "receive status was disabled");
      // Check that the entry has not been created in the directory server.
      resultEntry = getEntry(personWithUUIDEntry.getDN(), 1000, true);
      assertNull(resultEntry,
          "The replication message was replayed while the server "
          + "receive status was disabled");
    // Enable the directory server receive status.
    setReceiveStatus(synchroServerEntry.getDN().toString(), true);
      // Enable the directory server receive status.
      setReceiveStatus(synchroServerEntry.getDN().toString(), true);
    // Create and publish another update message to add an entry.
    addMsg = new AddMsg(gen.newChangeNumber(),
        personWithUUIDEntry.getDN().toString(),
        user1entryUUID,
        baseUUID,
        personWithUUIDEntry.getObjectClassAttribute(),
        personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
    broker.publish(addMsg);
      // Create and publish another update message to add an entry.
      addMsg = new AddMsg(gen.newChangeNumber(),
          personWithUUIDEntry.getDN().toString(),
          user1entryUUID,
          baseUUID,
          personWithUUIDEntry.getObjectClassAttribute(),
          personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
      broker.publish(addMsg);
    // Check that the entry has been created in the directory server.
    resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, true);
    assertNotNull(resultEntry,
        "The replication message was not replayed after the server " +
             "receive status was enabled");
      // Check that the entry has been created in the directory server.
      resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, true);
      assertNotNull(resultEntry,
          "The replication message was not replayed after the server "
          + "receive status was enabled");
    // Delete the entries to clean the database.
    DeleteMsg delMsg =
      new DeleteMsg(personWithUUIDEntry.getDN().toString(),
      // Delete the entries to clean the database.
      DeleteMsg delMsg =
          new DeleteMsg(personWithUUIDEntry.getDN().toString(),
          gen.newChangeNumber(), user1entryUUID);
    broker.publish(delMsg);
    resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, false);
      broker.publish(delMsg);
      resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, false);
    // Check that the delete operation has been applied.
    assertNull(resultEntry,
        "The DELETE replication message was not replayed");
    broker.stop();
      // Check that the delete operation has been applied.
      assertNull(resultEntry,
          "The DELETE replication message was not replayed");
    }
    finally
    {
      broker.stop();
    }
  }
  /**
@@ -397,77 +404,82 @@
    ReplicationBroker broker =
      openReplicationSession(baseDn, 2, 100, replServerPort, 1000, true);
    /*
     * Create a Change number generator to generate new changenumbers
     * when we need to send operation messages to the replicationServer.
     */
    ChangeNumberGenerator gen = new ChangeNumberGenerator( 2, 0);
    // Create and publish an update message to add an entry.
    AddMsg addMsg = new AddMsg(gen.newChangeNumber(),
        personWithUUIDEntry.getDN().toString(),
        user1entryUUID,
        baseUUID,
        personWithUUIDEntry.getObjectClassAttribute(),
        personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
    broker.publish(addMsg);
    Entry resultEntry;
    // Check that the entry has been created in the directory server.
    resultEntry = getEntry(personWithUUIDEntry.getDN(), 30000, true);
    assertNotNull(resultEntry,
        "The ADD replication message was not replayed");
    // Send a first modify operation message.
    List<Modification> mods = generatemods("telephonenumber", "01 02 45");
    ModifyMsg modMsg = new ModifyMsg(gen.newChangeNumber(),
        personWithUUIDEntry.getDN(), mods,
        user1entryUUID);
    broker.publish(modMsg);
    // Check that the modify has been replayed.
    boolean found = checkEntryHasAttribute(personWithUUIDEntry.getDN(),
                           "telephonenumber", "01 02 45", 10000, true);
    if (!found)
    try
    {
      fail("The first modification was not replayed.");
    }
      /*
       * Create a Change number generator to generate new changenumbers
       * when we need to send operation messages to the replicationServer.
       */
      ChangeNumberGenerator gen = new ChangeNumberGenerator(2, 0);
    // Simulate loss of heartbeats.
    HeartbeatThread.setHeartbeatsDisabled(true);
    Thread.sleep(3000);
    HeartbeatThread.setHeartbeatsDisabled(false);
    // Send a second modify operation message.
    mods = generatemods("description", "Description was changed");
    modMsg = new ModifyMsg(gen.newChangeNumber(),
        personWithUUIDEntry.getDN(), mods,
        user1entryUUID);
    broker.publish(modMsg);
      // Create and publish an update message to add an entry.
      AddMsg addMsg = new AddMsg(gen.newChangeNumber(),
          personWithUUIDEntry.getDN().toString(),
          user1entryUUID,
          baseUUID,
          personWithUUIDEntry.getObjectClassAttribute(),
          personWithUUIDEntry.getAttributes(), new ArrayList<Attribute>());
      broker.publish(addMsg);
    // Check that the modify has been replayed.
    found = checkEntryHasAttribute(personWithUUIDEntry.getDN(),
                                   "description", "Description was changed",
                                   10000, true);
    if (!found)
    {
      fail("The second modification was not replayed.");
    }
      Entry resultEntry;
    // Delete the entries to clean the database.
    DeleteMsg delMsg =
      new DeleteMsg(personWithUUIDEntry.getDN().toString(),
      // Check that the entry has been created in the directory server.
      resultEntry = getEntry(personWithUUIDEntry.getDN(), 30000, true);
      assertNotNull(resultEntry,
          "The ADD replication message was not replayed");
      // Send a first modify operation message.
      List<Modification> mods = generatemods("telephonenumber", "01 02 45");
      ModifyMsg modMsg = new ModifyMsg(gen.newChangeNumber(),
          personWithUUIDEntry.getDN(), mods,
          user1entryUUID);
      broker.publish(modMsg);
      // Check that the modify has been replayed.
      boolean found = checkEntryHasAttribute(personWithUUIDEntry.getDN(),
          "telephonenumber", "01 02 45", 10000, true);
      if (!found)
      {
        fail("The first modification was not replayed.");
      }
      // Simulate loss of heartbeats.
      HeartbeatThread.setHeartbeatsDisabled(true);
      Thread.sleep(3000);
      HeartbeatThread.setHeartbeatsDisabled(false);
      // Send a second modify operation message.
      mods = generatemods("description", "Description was changed");
      modMsg = new ModifyMsg(gen.newChangeNumber(),
          personWithUUIDEntry.getDN(), mods,
          user1entryUUID);
      broker.publish(modMsg);
      // Check that the modify has been replayed.
      found = checkEntryHasAttribute(personWithUUIDEntry.getDN(),
          "description", "Description was changed",
          10000, true);
      if (!found)
      {
        fail("The second modification was not replayed.");
      }
      // Delete the entries to clean the database.
      DeleteMsg delMsg =
          new DeleteMsg(personWithUUIDEntry.getDN().toString(),
          gen.newChangeNumber(), user1entryUUID);
    broker.publish(delMsg);
    resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, false);
      broker.publish(delMsg);
      resultEntry = getEntry(personWithUUIDEntry.getDN(), 10000, false);
    // Check that the delete operation has been applied.
    assertNull(resultEntry,
        "The DELETE replication message was not replayed");
    broker.stop();
      // Check that the delete operation has been applied.
      assertNull(resultEntry,
          "The DELETE replication message was not replayed");
    }
    finally
    {
      broker.stop();
    }
  }
  /**
@@ -500,109 +512,113 @@
     * This must use a different serverId to that of the directory server.
     */
    ReplicationBroker broker =
      openReplicationSession(baseDn, 2, 100, replServerPort, 1000, true);
        openReplicationSession(baseDn, 2, 100, replServerPort, 1000, true);
    // Add the first test entry.
    TestCaseUtils.addEntry(
         "dn: cn=test1," + baseDn.toString(),
         "displayname: Test1",
         "objectClass: top",
         "objectClass: person",
         "objectClass: organizationalPerson",
         "objectClass: inetOrgPerson",
         "cn: test1",
         "sn: test"
       );
    try
    {
      // Add the first test entry.
      TestCaseUtils.addEntry(
          "dn: cn=test1," + baseDn.toString(),
          "displayname: Test1",
          "objectClass: top",
          "objectClass: person",
          "objectClass: organizationalPerson",
          "objectClass: inetOrgPerson",
          "cn: test1",
          "sn: test");
    // Read the entry back to get its UUID.
    Entry entry = DirectoryServer.getEntry(dn1);
    List<Attribute> attrs = entry.getAttribute(entryuuidType);
    String entryuuid =
         attrs.get(0).iterator().next().getValue().toString();
      // Read the entry back to get its UUID.
      Entry entry = DirectoryServer.getEntry(dn1);
      List<Attribute> attrs = entry.getAttribute(entryuuidType);
      String entryuuid =
          attrs.get(0).iterator().next().getValue().toString();
    // A change on a first server.
    long changeTime = TimeThread.getTime();
    ChangeNumber t1 = new ChangeNumber(changeTime,  0,  3);
      // A change on a first server.
      long changeTime = TimeThread.getTime();
      ChangeNumber t1 = new ChangeNumber(changeTime, 0, 3);
    // A change on a second server.
    changeTime++;
    ChangeNumber t2 = new ChangeNumber(changeTime,  0,  4);
      // A change on a second server.
      changeTime++;
      ChangeNumber t2 = new ChangeNumber(changeTime, 0, 4);
    // Simulate the ordering t2:replace:B followed by t1:add:A that
    updateMonitorCount(baseDn, monitorAttr);
      // Simulate the ordering t2:replace:B followed by t1:add:A that
      updateMonitorCount(baseDn, monitorAttr);
    // Replay a replace of a value B at time t2 on a second server.
    Attribute attr = Attributes.create(attrType, "B");
    Modification mod = new Modification(ModificationType.REPLACE, attr);
    List<Modification> mods = new ArrayList<Modification>(1);
    mods.add(mod);
    ModifyMsg modMsg = new ModifyMsg(t2, dn1, mods, entryuuid);
    broker.publish(modMsg);
      // Replay a replace of a value B at time t2 on a second server.
      Attribute attr = Attributes.create(attrType, "B");
      Modification mod = new Modification(ModificationType.REPLACE, attr);
      List<Modification> mods = new ArrayList<Modification>(1);
      mods.add(mod);
      ModifyMsg modMsg = new ModifyMsg(t2, dn1, mods, entryuuid);
      broker.publish(modMsg);
    Thread.sleep(2000);
      Thread.sleep(2000);
    // Replay an add of a value A at time t1 on a first server.
    attr = Attributes.create(attrType, "A");
    mod = new Modification(ModificationType.ADD, attr);
    mods = new ArrayList<Modification>(1);
    mods.add(mod);
    modMsg = new ModifyMsg(t1, dn1, mods, entryuuid);
    broker.publish(modMsg);
      // Replay an add of a value A at time t1 on a first server.
      attr = Attributes.create(attrType, "A");
      mod = new Modification(ModificationType.ADD, attr);
      mods = new ArrayList<Modification>(1);
      mods.add(mod);
      modMsg = new ModifyMsg(t1, dn1, mods, entryuuid);
      broker.publish(modMsg);
    Thread.sleep(2000);
      Thread.sleep(2000);
    // Read the entry to see how the conflict was resolved.
    entry = DirectoryServer.getEntry(dn1);
    attrs = entry.getAttribute(attrType);
    String attrValue1 =
         attrs.get(0).iterator().next().getValue().toString();
      // Read the entry to see how the conflict was resolved.
      entry = DirectoryServer.getEntry(dn1);
      attrs = entry.getAttribute(attrType);
      String attrValue1 =
          attrs.get(0).iterator().next().getValue().toString();
    // the value should be the last (time t2) value added
    assertEquals(attrValue1, "B");
    assertEquals(getMonitorDelta(), 1);
      // the value should be the last (time t2) value added
      assertEquals(attrValue1, "B");
      assertEquals(getMonitorDelta(), 1);
    // Simulate the ordering t2:delete:displayname followed by
    // t1:replace:displayname
    // A change on a first server.
    changeTime++;
    t1 = new ChangeNumber(changeTime,  0,  3);
      // Simulate the ordering t2:delete:displayname followed by
      // t1:replace:displayname
      // A change on a first server.
      changeTime++;
      t1 = new ChangeNumber(changeTime, 0, 3);
    // A change on a second server.
    changeTime++;
    t2 = new ChangeNumber(changeTime,  0,  4);
      // A change on a second server.
      changeTime++;
      t2 = new ChangeNumber(changeTime, 0, 4);
    // Simulate the ordering t2:delete:displayname followed by t1:replace:A
    updateMonitorCount(baseDn, monitorAttr);
      // Simulate the ordering t2:delete:displayname followed by t1:replace:A
      updateMonitorCount(baseDn, monitorAttr);
    // Replay an delete of attribute displayname at time t2 on a second server.
    attr = Attributes.empty(attrType);
    mod = new Modification(ModificationType.DELETE, attr);
    mods = new ArrayList<Modification>(1);
    mods.add(mod);
    modMsg = new ModifyMsg(t2, dn1, mods, entryuuid);
    broker.publish(modMsg);
      // Replay an delete of attribute displayname at time t2 on a second server.
      attr = Attributes.empty(attrType);
      mod = new Modification(ModificationType.DELETE, attr);
      mods = new ArrayList<Modification>(1);
      mods.add(mod);
      modMsg = new ModifyMsg(t2, dn1, mods, entryuuid);
      broker.publish(modMsg);
    Thread.sleep(2000);
      Thread.sleep(2000);
    // Replay a replace of a value A at time t1 on a first server.
    attr = Attributes.create(attrType, "A");
    mod = new Modification(ModificationType.REPLACE, attr);
    mods = new ArrayList<Modification>(1);
    mods.add(mod);
    modMsg = new ModifyMsg(t1, dn1, mods, entryuuid);
    broker.publish(modMsg);
      // Replay a replace of a value A at time t1 on a first server.
      attr = Attributes.create(attrType, "A");
      mod = new Modification(ModificationType.REPLACE, attr);
      mods = new ArrayList<Modification>(1);
      mods.add(mod);
      modMsg = new ModifyMsg(t1, dn1, mods, entryuuid);
      broker.publish(modMsg);
    Thread.sleep(2000);
      Thread.sleep(2000);
    // Read the entry to see how the conflict was resolved.
    entry = DirectoryServer.getEntry(dn1);
    attrs = entry.getAttribute(attrType);
      // Read the entry to see how the conflict was resolved.
      entry = DirectoryServer.getEntry(dn1);
      attrs = entry.getAttribute(attrType);
    // there should not be a value (delete at time t1)
    assertNull(attrs);
    assertEquals(getMonitorDelta(), 1);
    broker.stop();
      // there should not be a value (delete at time t2)
      assertNull(attrs);
      assertEquals(getMonitorDelta(), 1);
    }
    finally
    {
      broker.stop();
    }
  }
@@ -636,6 +652,8 @@
    ReplicationBroker broker =
      openReplicationSession(baseDn, 2, 100, replServerPort, 1000, true);
    try
    {
    /*
     * Create a Change number generator to generate new changenumbers
     * when we need to send operations messages to the replicationServer.
@@ -1299,8 +1317,11 @@
        DN.decode("uid=new person,ou=baseDn2,"+baseDn),
        LDAPReplicationDomain.DS_SYNC_CONFLICT,
        "uid=newrdn,ou=baseDn2,ou=People," + TEST_ROOT_DN_STRING, 1000, true));
    broker.stop();
    }
    finally
    {
      broker.stop();
    }
  }
  /**
@@ -1731,63 +1752,69 @@
    ReplicationBroker broker =
      openReplicationSession(baseDn, serverId, 100, replServerPort, 1000, true);
    /*
     * Create a Change number generator to generate new changenumbers
     * when we need to send operation messages to the replicationServer.
     */
    long inTheFutur = System.currentTimeMillis() + (3600*1000);
    ChangeNumberGenerator gen = new ChangeNumberGenerator(serverId, inTheFutur);
    try
    {
      /*
       * Create a Change number generator to generate new changenumbers
       * when we need to send operation messages to the replicationServer.
       */
      long inTheFutur = System.currentTimeMillis() + (3600 * 1000);
      ChangeNumberGenerator gen = new ChangeNumberGenerator(serverId, inTheFutur);
    // Create and publish an update message to add an entry.
    AddMsg addMsg = new AddMsg(
        gen.newChangeNumber(),
        user3dn.toString(),
        user3UUID,
        baseUUID,
        user3Entry.getObjectClassAttribute(),
        user3Entry.getAttributes(),
        new ArrayList<Attribute>());
    broker.publish(addMsg);
      // Create and publish an update message to add an entry.
      AddMsg addMsg = new AddMsg(
          gen.newChangeNumber(),
          user3dn.toString(),
          user3UUID,
          baseUUID,
          user3Entry.getObjectClassAttribute(),
          user3Entry.getAttributes(),
          new ArrayList<Attribute>());
      broker.publish(addMsg);
    Entry resultEntry;
      Entry resultEntry;
    // Check that the entry has not been created in the directory server.
    resultEntry = getEntry(user3Entry.getDN(), 1000, true);
    assertNotNull(resultEntry, "The entry has not been created");
      // Check that the entry has not been created in the directory server.
      resultEntry = getEntry(user3Entry.getDN(), 1000, true);
      assertNotNull(resultEntry, "The entry has not been created");
    // Modify the entry
    List<Modification> mods = generatemods("telephonenumber", "01 02 45");
    ModifyOperationBasis modOp = new ModifyOperationBasis(
        connection,
        InternalClientConnection.nextOperationID(),
        InternalClientConnection.nextMessageID(),
        null,
        user3Entry.getDN(),
        mods);
    modOp.setInternalOperation(true);
    modOp.run();
      // Modify the entry
      List<Modification> mods = generatemods("telephonenumber", "01 02 45");
      ModifyOperationBasis modOp = new ModifyOperationBasis(
          connection,
          InternalClientConnection.nextOperationID(),
          InternalClientConnection.nextMessageID(),
          null,
          user3Entry.getDN(),
          mods);
      modOp.setInternalOperation(true);
      modOp.run();
    // See if the client has received the msg
    ReplicationMsg msg = broker.receive();
    assertTrue(msg instanceof ModifyMsg,
      "The received replication message is not a MODIFY msg");
    ModifyMsg modMsg = (ModifyMsg) msg;
    assertEquals(addMsg.getChangeNumber().getTimeSec(),
                 modMsg.getChangeNumber().getTimeSec(),
                "The MOD timestamp should have been adjusted to the ADD one");
      // See if the client has received the msg
      ReplicationMsg msg = broker.receive();
      assertTrue(msg instanceof ModifyMsg,
          "The received replication message is not a MODIFY msg");
      ModifyMsg modMsg = (ModifyMsg) msg;
      assertEquals(addMsg.getChangeNumber().getTimeSec(),
          modMsg.getChangeNumber().getTimeSec(),
          "The MOD timestamp should have been adjusted to the ADD one");
    // Delete the entries to clean the database.
    DeleteMsg delMsg =
      new DeleteMsg(
      // Delete the entries to clean the database.
      DeleteMsg delMsg =
          new DeleteMsg(
          user3Entry.getDN().toString(),
          gen.newChangeNumber(),
          user3UUID);
    broker.publish(delMsg);
      broker.publish(delMsg);
    // Check that the delete operation has been applied.
    resultEntry = getEntry(user3Entry.getDN(), 10000, false);
    assertNull(resultEntry,
        "The DELETE replication message was not replayed");
    broker.stop();
      // Check that the delete operation has been applied.
      resultEntry = getEntry(user3Entry.getDN(), 10000, false);
      assertNull(resultEntry,
          "The DELETE replication message was not replayed");
    }
    finally
    {
      broker.stop();
    }
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/HistoricalTest.java
@@ -23,6 +23,7 @@
 *
 *
 *      Copyright 2008-2010 Sun Microsystems, Inc.
 *      Portions Copyright 2011 ForgeRock AS
 */
package org.opends.server.replication.plugin;
@@ -346,8 +347,6 @@
    mod = new Modification(ModificationType.ADD, attr);
    publishModify(broker, t2, dn1, entryuuid, mod);
    Thread.sleep(2000);
    // Simulate the reverse ordering t2:add:B followed by t1:add:A that
    // would happen on the other server.
@@ -529,16 +528,16 @@
      assertEquals(count, assertCount);
    }
  /**
   * Test the task that purges the replication historical stored in the user
   * Test the task that purges the replication historical stored in the user
   * entry.
   * Steps :
   * - creates entry containing historical
   * - wait for the pruge delay
   * - lauch the purge task
   * - verify that all historical has been purged
   *
   *
   * TODO: another test should be written that configures the task no NOT have
   * the time to purge everything in 1 run .. and thus to relauch it to finish
   * the purge. And verify that the second run starts on the changeNumber where
@@ -554,36 +553,14 @@
    addEntriesWithHistorical(1, entryCnt);
    /*
    // every entry should have its hist
    try
    {
      // Search for matching entries in config backend
      InternalSearchOperation op = connection.processSearch(
          ByteString.valueOf(TEST_ROOT_DN_STRING),
          SearchScope.WHOLE_SUBTREE,
          LDAPFilter.decode("(ds-sync-hist=*)"));
      assertEquals(op.getResultCode(), ResultCode.SUCCESS,
          op.getErrorMessage().toString());
      // Check that no entries have been found
      LinkedList<SearchResultEntry> entries = op.getSearchEntries();
      assertTrue(entries != null);
      assertEquals(entries.size(), entryCnt);
    } catch (Exception e)
    {
      fail("assertNoConfigEntriesWithFilter: could not search config backend" + e.getMessage());
    }
    */
    // set the purge delay to 1 sec
    TestCaseUtils.dsconfig(
        "set-replication-domain-prop",
        "--provider-name","Multimaster Synchronization",
        "--domain-name",testName,
        "--set","conflicts-historical-purge-delay:1m");
        "--set","conflicts-historical-purge-delay:1s");
    Thread.sleep(60*1000);
    Thread.sleep(2*1000);
    // launch the purge
    Entry taskInit = TestCaseUtils.makeEntry(
@@ -594,7 +571,7 @@
        "objectclass: ds-task-purge-conflicts-historical",
        "ds-task-class-name: org.opends.server.tasks.PurgeConflictsHistoricalTask",
        "ds-task-purge-conflicts-historical-domain-dn: "+TEST_ROOT_DN_STRING,
    "ds-task-purge-conflicts-historical-maximum-duration: 1000"); // 1000 sec
    "ds-task-purge-conflicts-historical-maximum-duration: 120"); // 120 sec
    addTask(taskInit, ResultCode.SUCCESS, null);
@@ -699,5 +676,5 @@
      assertEquals(LDAPModify.mainModify(args, false, null, System.err), 0);
    }
  }
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ModifyConflictTest.java
@@ -156,6 +156,10 @@
    testModify(entry, hist, DISPLAYNAME, ModificationType.ADD, "new value",
               11, false);
    List<Attribute> attrs = entry.getAttribute(DISPLAYNAME);
    Attribute attr = attrs.get(0);
    assertEquals(1, attr.size());
    attr.contains(AttributeValues.create(attr.getAttributeType(), "init value"));
  }
  /**
@@ -267,12 +271,22 @@
    testModify(entry, hist, DISPLAYNAME, ModificationType.REPLACE,
        "older value", 1, true);
    List<Attribute> attrs = entry.getAttribute(DISPLAYNAME);
    Attribute attr = attrs.get(0);
    assertEquals(1, attr.size());
    attr.contains(AttributeValues.create(attr.getAttributeType(), "older value"));
    /*
     * Now simulate a replace at a later date.
     * Conflict resolution should keept it.
     */
    testModify(entry, hist, DISPLAYNAME, ModificationType.REPLACE,
        "older value", 3, true);
        "newer value", 3, true);
    attrs = entry.getAttribute(DISPLAYNAME);
    attr = attrs.get(0);
    assertEquals(1, attr.size());
    attr.contains(AttributeValues.create(attr.getAttributeType(), "newer value"));
  }