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

neil_a_wilson
29.27.2006 b218bc6741a7bbddc77cb1bdc210581bb96ad74b
Make several test case updates:

- Add additional test cases for abandon operations.

- Add a set of test cases for bind operations.

- Add a new short circuit plugin that can be used to force plugin to cause
operation processing to end prematurely and with a specified result.
2 files added
3 files modified
2869 ■■■■■ changed files
opends/tests/unit-tests-testng/resource/config-changes.ldif 26 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java 322 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java 1855 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/OperationTestCase.java 15 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/ShortCircuitPlugin.java 651 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/resource/config-changes.ldif
@@ -221,6 +221,32 @@
ds-cfg-plugin-type: startup
ds-cfg-plugin-type: shutdown
dn: cn=Short Circuit Plugin,cn=Plugins,cn=config
changetype: add
objectClass: top
objectClass: ds-cfg-plugin
cn: Short Circuit Plugin
ds-cfg-plugin-class: org.opends.server.plugins.ShortCircuitPlugin
ds-cfg-plugin-enabled: true
ds-cfg-plugin-type: preParseAbandon
ds-cfg-plugin-type: preParseAdd
ds-cfg-plugin-type: preParseBind
ds-cfg-plugin-type: preParseCompare
ds-cfg-plugin-type: preParseDelete
ds-cfg-plugin-type: preParseExtended
ds-cfg-plugin-type: preParseModify
ds-cfg-plugin-type: preParseModifyDN
ds-cfg-plugin-type: preParseSearch
ds-cfg-plugin-type: preParseUnbind
ds-cfg-plugin-type: preOperationAdd
ds-cfg-plugin-type: preOperationBind
ds-cfg-plugin-type: preOperationCompare
ds-cfg-plugin-type: preOperationDelete
ds-cfg-plugin-type: preOperationExtended
ds-cfg-plugin-type: preOperationModify
ds-cfg-plugin-type: preOperationModifyDN
ds-cfg-plugin-type: preOperationSearch
dn: cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config
changetype: add
objectClass: top
opends/tests/unit-tests-testng/src/server/org/opends/server/core/AbandonOperationTestCase.java
@@ -30,9 +30,9 @@
import java.net.Socket;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
@@ -56,21 +56,28 @@
import org.opends.server.protocols.ldap.DeleteResponseProtocolOp;
import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPModification;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.protocols.ldap.ModifyRequestProtocolOp;
import org.opends.server.protocols.ldap.ModifyResponseProtocolOp;
import org.opends.server.protocols.ldap.ModifyDNRequestProtocolOp;
import org.opends.server.protocols.ldap.ModifyDNResponseProtocolOp;
import org.opends.server.protocols.ldap.SearchRequestProtocolOp;
import org.opends.server.protocols.ldap.SearchResultDoneProtocolOp;
import org.opends.server.protocols.ldap.LDAPAttribute;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.Control;
import org.opends.server.types.DereferencePolicy;
import org.opends.server.types.Entry;
import org.opends.server.types.ModificationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchScope;
import static org.testng.Assert.*;
import static org.opends.server.util.ServerConstants.*;
/**
@@ -80,31 +87,9 @@
       extends OperationTestCase
{
  /**
   * Ensures that the Directory Server is running.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @BeforeClass()
  public void startServer()
         throws Exception
  {
    TestCaseUtils.startServer();
  }
  /**
   * Creates a set of valid operation instances of this type that may be used
   * for testing the general methods defined in the Operation superclass.  Only
   * the constructors for the operation need to be used -- it does not require
   * any further initialization (no tests will be performed that require any
   * further processing).
   *
   * @return  A set of operation instances of this type that may be used for
   *          testing the general methods defined in the Operation superclass.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Override()
  public Operation[] createTestOperations()
         throws Exception
  {
@@ -436,7 +421,7 @@
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(groups = { "slow" })
  @Test()
  public void testAbandonDelete()
         throws Exception
  {
@@ -505,5 +490,284 @@
    assertTrue(InvocationCounterPlugin.getPostConnectCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
  }
  /**
   * Tests the ability to abandon an extended operation.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testAbandonExtended()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InvocationCounterPlugin.resetAllCounters();
    // Establish a connection to the server and bind as a root user.
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    r.setIOTimeout(6000);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest);
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), LDAPResultCode.SUCCESS);
    // Create a "Who Am I?" extended oepration and send it to the server.  Make
    // sure to include the delay request control so it won't complete before we
    // can send the abandon request.
    ExtendedRequestProtocolOp whoAmIRequest =
         new ExtendedRequestProtocolOp(OID_WHO_AM_I_REQUEST, null);
    message = new LDAPMessage(2, whoAmIRequest,
                       DelayPreOpPlugin.createDelayLDAPControlList(5000));
    w.writeElement(message.encode());
    // Send the abandon request to the server and wait a few seconds to ensure
    // it has completed before closing the connection.
    AbandonRequestProtocolOp abandonRequest = new AbandonRequestProtocolOp(2);
    w.writeElement(new LDAPMessage(3, abandonRequest).encode());
    // Normally, abandoned operations don't receive a response.  However, the
    // testing configuration has been updated to ensure that if an operation
    // does get abandoned, the server will return a response for it with a
    // result code of "cancelled".
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    ExtendedResponseProtocolOp extendedResponse =
         message.getExtendedResponseProtocolOp();
    assertEquals(extendedResponse.getResultCode(), LDAPResultCode.CANCELED);
    s.close();
    assertTrue(InvocationCounterPlugin.getPostConnectCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
  }
  /**
   * Tests the ability to abandon a modify operation.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testAbandonModify()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InvocationCounterPlugin.resetAllCounters();
    // Establish a connection to the server and bind as a root user.
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    r.setIOTimeout(6000);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest);
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), LDAPResultCode.SUCCESS);
    // Create a modify request and send it to the server.  Make sure to include
    // the delay request control so it won't complete before we can send the
    // abandon request.
    ArrayList<ASN1OctetString> values = new ArrayList<ASN1OctetString>(1);
    values.add(new ASN1OctetString("foo"));
    ArrayList<LDAPModification> mods = new ArrayList<LDAPModification>(1);
    mods.add(new LDAPModification(ModificationType.REPLACE,
                                  new LDAPAttribute("description", values)));
    ModifyRequestProtocolOp modifyRequest =
         new ModifyRequestProtocolOp(new ASN1OctetString("o=test"), mods);
    message = new LDAPMessage(2, modifyRequest,
                       DelayPreOpPlugin.createDelayLDAPControlList(5000));
    w.writeElement(message.encode());
    // Send the abandon request to the server and wait a few seconds to ensure
    // it has completed before closing the connection.
    AbandonRequestProtocolOp abandonRequest = new AbandonRequestProtocolOp(2);
    w.writeElement(new LDAPMessage(3, abandonRequest).encode());
    // Normally, abandoned operations don't receive a response.  However, the
    // testing configuration has been updated to ensure that if an operation
    // does get abandoned, the server will return a response for it with a
    // result code of "cancelled".
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    ModifyResponseProtocolOp modifyResponse =
         message.getModifyResponseProtocolOp();
    assertEquals(modifyResponse.getResultCode(), LDAPResultCode.CANCELED);
    s.close();
    assertTrue(InvocationCounterPlugin.getPostConnectCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
  }
  /**
   * Tests the ability to abandon a modify DN operation.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testAbandonModifyDN()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InvocationCounterPlugin.resetAllCounters();
    // Add an entry to the server that we can rename.
    Entry e = TestCaseUtils.makeEntry(
         "dn: cn=test,o=test",
         "objectClass: top",
         "objectClass: device",
         "cn: test");
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    AddOperation addOperation =
         conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
                         e.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    // Establish a connection to the server and bind as a root user.
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    r.setIOTimeout(6000);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest);
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), LDAPResultCode.SUCCESS);
    // Create a modify DN request and send it to the server.  Make sure to
    // include the delay request control so it won't complete before we can send
    // the abandon request.
    ModifyDNRequestProtocolOp modifyDNRequest =
         new ModifyDNRequestProtocolOp(new ASN1OctetString("cn=test,o=test"),
                                       new ASN1OctetString("cn=test2"), true);
    message = new LDAPMessage(2, modifyDNRequest,
                       DelayPreOpPlugin.createDelayLDAPControlList(5000));
    w.writeElement(message.encode());
    // Send the abandon request to the server and wait a few seconds to ensure
    // it has completed before closing the connection.
    AbandonRequestProtocolOp abandonRequest = new AbandonRequestProtocolOp(2);
    w.writeElement(new LDAPMessage(3, abandonRequest).encode());
    // Normally, abandoned operations don't receive a response.  However, the
    // testing configuration has been updated to ensure that if an operation
    // does get abandoned, the server will return a response for it with a
    // result code of "cancelled".
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    ModifyDNResponseProtocolOp modifyDNResponse =
         message.getModifyDNResponseProtocolOp();
    assertEquals(modifyDNResponse.getResultCode(), LDAPResultCode.CANCELED);
    s.close();
    assertTrue(InvocationCounterPlugin.getPostConnectCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
  }
  /**
   * Tests the ability to abandon a search operation.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testAbandonSearch()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InvocationCounterPlugin.resetAllCounters();
    // Establish a connection to the server and bind as a root user.
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    r.setIOTimeout(6000);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest);
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), LDAPResultCode.SUCCESS);
    // Create a search request and send it to the server.  Make sure to include
    // the delay request control so it won't complete before we can send the
    // abandon request.
    SearchRequestProtocolOp searchRequest =
         new SearchRequestProtocolOp(new ASN1OctetString("o=test"),
                                     SearchScope.BASE_OBJECT,
                                     DereferencePolicy.NEVER_DEREF_ALIASES, 0,
                                     0, false,
                                     LDAPFilter.decode("(match=false)"),
                                     new LinkedHashSet<String>());
    message = new LDAPMessage(2, searchRequest,
                       DelayPreOpPlugin.createDelayLDAPControlList(5000));
    w.writeElement(message.encode());
    // Send the abandon request to the server and wait a few seconds to ensure
    // it has completed before closing the connection.
    AbandonRequestProtocolOp abandonRequest = new AbandonRequestProtocolOp(2);
    w.writeElement(new LDAPMessage(3, abandonRequest).encode());
    // Normally, abandoned operations don't receive a response.  However, the
    // testing configuration has been updated to ensure that if an operation
    // does get abandoned, the server will return a response for it with a
    // result code of "cancelled".
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    SearchResultDoneProtocolOp searchDone =
         message.getSearchResultDoneProtocolOp();
    assertEquals(searchDone.getResultCode(), LDAPResultCode.CANCELED);
    s.close();
    assertTrue(InvocationCounterPlugin.getPostConnectCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/core/BindOperationTestCase.java
New file
@@ -0,0 +1,1855 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import java.net.Socket;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.AddOperation;
import org.opends.server.core.BindOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.plugins.DisconnectClientPlugin;
import org.opends.server.plugins.InvocationCounterPlugin;
import org.opends.server.plugins.ShortCircuitPlugin;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.Attribute;
import org.opends.server.types.AuthenticationInfo;
import org.opends.server.types.AuthenticationType;
import org.opends.server.types.ByteString;
import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.ModificationType;
import org.opends.server.types.ResultCode;
import static org.testng.Assert.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
/**
 * A set of test cases for bind operations
 */
public class BindOperationTestCase
       extends OperationTestCase
{
  /**
   * Retrieves a set of bind operation objects using simple authentication.
   *
   * @return  A set of bind operation objects using simple authentication.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @DataProvider(name = "simpleBinds")
  public Object[][] getSimpleBindOperations()
         throws Exception
  {
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    ArrayList<Control> noControls = new ArrayList<Control>(0);
    ASN1OctetString nullOS = null;
    DN nullDN = null;
    BindOperation[] simpleBinds = new BindOperation[]
    {
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new ASN1OctetString(), new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new ASN1OctetString(),
                        new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullOS, new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullOS, new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new ASN1OctetString(), nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new ASN1OctetString(), nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullOS, nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullOS, nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new ASN1OctetString("cn=Directory Manager"),
                        new ASN1OctetString("password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new DN(), new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new DN(), new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullDN, new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullDN, new ASN1OctetString()),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new DN(), nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new DN(), nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullDN, nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullDN, nullOS),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, DN.decode("cn=Directory Manager"),
                        new ASN1OctetString("password"))
    };
    Object[][] array = new Object[simpleBinds.length][1];
    for (int i=0; i < simpleBinds.length; i++)
    {
      array[i][0] = simpleBinds[i];
    }
    return array;
  }
  /**
   * Retrieves a set of bind operation objects using SASL authentication.
   *
   * @return  A set of bind operation objects using SASL authentication.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @DataProvider(name = "saslBinds")
  public Object[][] getSASLBindOperations()
         throws Exception
  {
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();
    ArrayList<Control> noControls = new ArrayList<Control>(0);
    ASN1OctetString nullOS = null;
    DN nullDN = null;
    BindOperation[] saslBinds = new BindOperation[]
    {
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new ASN1OctetString(), "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new ASN1OctetString(), "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullOS, "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullOS, "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new ASN1OctetString(), "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new ASN1OctetString(), "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullOS, "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullOS, "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new DN(), "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new DN(), "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullDN, "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullDN, "EXTERNAL", null),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, new DN(), "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, new DN(), "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        null, nullDN, "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password")),
      new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                        noControls, nullDN, "PLAIN",
                        new ASN1OctetString("\u0000u:test.user\u0000password"))
    };
    Object[][] array = new Object[saslBinds.length][1];
    for (int i=0; i < saslBinds.length; i++)
    {
      array[i][0] = saslBinds[i];
    }
    return array;
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public Operation[] createTestOperations()
         throws Exception
  {
    Object[][] simpleBinds = getSimpleBindOperations();
    Object[][] saslBinds   = getSASLBindOperations();
    Operation[] bindOps = new Operation[simpleBinds.length + saslBinds.length];
    int pos = 0;
    for (int i=0; i < simpleBinds.length; i++)
    {
      bindOps[pos++] = (BindOperation) simpleBinds[i][0];
    }
    for (int i=0; i < saslBinds.length; i++)
    {
      bindOps[pos++] = (BindOperation) saslBinds[i][0];
    }
    return bindOps;
  }
  /**
   * Tests the <CODE>getAuthenticationType</CODE> method for simple bind
   * operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetAuthenticationTypeSimple(BindOperation o)
  {
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
  }
  /**
   * Tests the <CODE>getAuthenticationType</CODE> method for SASL bind
   * operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetAuthenticationTypeSASL(BindOperation o)
  {
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
  }
  /**
   * Tests the <CODE>getRawBindDN</CODE> method for simple bind operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetRawBindDNSimple(BindOperation o)
  {
    assertNotNull(o.getRawBindDN());
  }
  /**
   * Tests the <CODE>getRawBindDN</CODE> method for SASL bind operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetRawBindDNSASL(BindOperation o)
  {
    assertNotNull(o.getRawBindDN());
  }
  /**
   * Tests the <CODE>setRawBindDN()</CODE> method for simple bind operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testSetRawBindDNSimple(BindOperation o)
  {
    ByteString originalRawBindDN = o.getRawBindDN();
    assertNotNull(originalRawBindDN);
    o.setRawBindDN(null);
    assertEquals(o.getRawBindDN(), new ASN1OctetString());
    o.setRawBindDN(new ASN1OctetString());
    assertEquals(o.getRawBindDN(), new ASN1OctetString());
    o.setRawBindDN(new ASN1OctetString("cn=Directory Manager"));
    assertEquals(o.getRawBindDN(), new ASN1OctetString("cn=Directory Manager"));
    o.setRawBindDN(originalRawBindDN);
    assertEquals(o.getRawBindDN(), originalRawBindDN);
  }
  /**
   * Tests the <CODE>setRawBindDN()</CODE> method for SASL bind operations.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testSetRawBindDNSASL(BindOperation o)
  {
    ByteString originalRawBindDN = o.getRawBindDN();
    assertNotNull(originalRawBindDN);
    o.setRawBindDN(null);
    assertEquals(o.getRawBindDN(), new ASN1OctetString());
    o.setRawBindDN(new ASN1OctetString());
    assertEquals(o.getRawBindDN(), new ASN1OctetString());
    o.setRawBindDN(new ASN1OctetString("cn=Directory Manager"));
    assertEquals(o.getRawBindDN(), new ASN1OctetString("cn=Directory Manager"));
    o.setRawBindDN(originalRawBindDN);
    assertEquals(o.getRawBindDN(), originalRawBindDN);
  }
  /**
   * Tests the <CODE>getBindDN</CODE> and <CODE>setBindDN</CODE> methods on bind
   * operations using simple authentication.
   *
   * @param  o  The bind operation to be tested.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetAndSetBindDNSimple(BindOperation o)
         throws Exception
  {
    DN originalDN = o.getBindDN();
    o.setBindDN(null);
    assertNull(o.getBindDN());
    o.setBindDN(new DN());
    assertNotNull(o.getBindDN());
    assertTrue(o.getBindDN().isNullDN());
    o.setBindDN(DN.decode("cn=Directory Manager"));
    assertNotNull(o.getBindDN());
    assertEquals(o.getBindDN(), DN.decode("cn=Directory Manager"));
    o.setBindDN(originalDN);
    assertEquals(o.getBindDN(), originalDN);
  }
  /**
   * Tests the <CODE>getSimplePassword</CODE> method for bind operations using
   * simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetSimplePasswordSimple(BindOperation o)
  {
    assertNotNull(o.getSimplePassword());
  }
  /**
   * Tests the <CODE>getSimplePassword</CODE> method for bind operations using
   * SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetSimplePasswordSASL(BindOperation o)
  {
    assertNull(o.getSimplePassword());
  }
  /**
   * Tests the <CODE>getSASLMechanism</CODE> method for bind operations using
   * simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetSASLMechanismSimple(BindOperation o)
  {
    assertNull(o.getSASLMechanism());
  }
  /**
   * Tests the <CODE>getSASLMechanism</CODE> method for bind operations using
   * SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetSASLMechanismSASL(BindOperation o)
  {
    assertNotNull(o.getSASLMechanism());
  }
  /**
   * Tests the <CODE>getSASLCredentials</CODE> method for bind operations using
   * simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetSASLCredentialsSimple(BindOperation o)
  {
    assertNull(o.getSASLCredentials());
  }
  /**
   * Tests the <CODE>getSASLCredentials</CODE> method for bind operations using
   * SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetSASLCredentialsSASL(BindOperation o)
  {
    // We don't know whether they should be null or not, so we'll just not
    // bother checking what it returns.
    o.getSASLCredentials();
  }
  /**
   * Tests the ability to change a simple bind operation to a SASL bind
   * operation and back again.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testChangeSimpleToSASLAndBack(BindOperation o)
  {
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNull(o.getSASLMechanism());
    assertNull(o.getSASLCredentials());
    ByteString originalPassword = o.getSimplePassword();
    assertNotNull(originalPassword);
    o.setSASLCredentials("EXTERNAL", null);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNotNull(o.getSASLMechanism());
    assertNull(o.getSASLCredentials());
    o.setSimplePassword(originalPassword);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNull(o.getSASLMechanism());
    assertNull(o.getSASLCredentials());
    o.setSASLCredentials("PLAIN",
         new ASN1OctetString("\u0000u:test.user\u0000password"));
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNotNull(o.getSASLMechanism());
    assertNotNull(o.getSASLCredentials());
    o.setSimplePassword(originalPassword);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNull(o.getSASLMechanism());
    assertNull(o.getSASLCredentials());
  }
  /**
   * Tests the ability to change a SASL bind operation to a simple bind
   * operation and back again.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testChangeSASLToSimpleAndBack(BindOperation o)
  {
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNull(o.getSimplePassword());
    String          originalMech  = o.getSASLMechanism();
    ASN1OctetString originalCreds = o.getSASLCredentials();
    assertNotNull(originalMech);
    o.setSimplePassword(null);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNotNull(o.getSimplePassword());
    o.setSASLCredentials(originalMech, originalCreds);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNull(o.getSimplePassword());
    o.setSimplePassword(new ASN1OctetString());
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNotNull(o.getSimplePassword());
    o.setSASLCredentials(originalMech, originalCreds);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNull(o.getSimplePassword());
    o.setSimplePassword(new ASN1OctetString("password"));
    assertEquals(o.getAuthenticationType(), AuthenticationType.SIMPLE);
    assertNotNull(o.getSimplePassword());
    o.setSASLCredentials(originalMech, originalCreds);
    assertEquals(o.getAuthenticationType(), AuthenticationType.SASL);
    assertNull(o.getSimplePassword());
  }
  /**
   * Tests the <CODE>getServerSASLCredentials</CODE> method for bind operations
   * using simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetServerSASLCredentialsSimple(BindOperation o)
  {
    assertNull(o.getServerSASLCredentials());
  }
  /**
   * Tests the <CODE>getServerSASLCredentials</CODE> method for bind operations
   * using SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetServerSASLCredentialsSASL(BindOperation o)
  {
    assertNull(o.getServerSASLCredentials());
  }
  /**
   * Tests the <CODE>getSASLAuthUserEntry</CODE> method for bind operations
   * using simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetSASLAuthUserEntrySimple(BindOperation o)
  {
    assertNull(o.getSASLAuthUserEntry());
  }
  /**
   * Tests the <CODE>getSASLAuthUserEntry</CODE> method for bind operations
   * using SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetSASLAuthUserEntrySASL(BindOperation o)
  {
    assertNull(o.getSASLAuthUserEntry());
  }
  /**
   * Tests the <CODE>getSASLAuthUserEntry</CODE> method for completed SASL bind
   * operations in which this value will be set.
   */
  public void testGetSASLAuthUserEntryNonNull()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
                       conn.processSASLBind(new DN(), "PLAIN", saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(bindOperation.getSASLAuthUserEntry());
  }
  /**
   * Tests the <CODE>getUserEntryDN</CODE> method for bind operations using
   * simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetUserEntryDNSimple(BindOperation o)
  {
    assertNull(o.getUserEntryDN());
  }
  /**
   * Tests the <CODE>getUserEntryDN</CODE> method for a completed bind operation
   * using simple authentication in which this value will be set.
   */
  @Test()
  public void testGetUserEntryDNSimpleNonNull()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(bindOperation.getUserEntryDN());
  }
  /**
   * Tests the <CODE>getUserEntryDN</CODE> method for bind operations using SASL
   * authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetUserEntryDNSASL(BindOperation o)
{
    assertNull(o.getUserEntryDN());
  }
  /**
   * Tests the <CODE>getUserEntryDN</CODE> method for a completed bind operation
   * using SASL authentication in which this value will be set.
   */
  @Test()
  public void testGetUserEntryDNSASLNonNull()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         conn.processSASLBind(new DN(), "PLAIN", saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(bindOperation.getUserEntryDN());
  }
  /**
   * Tests the <CODE>getProcessingStartTime</CODE>,
   * <CODE>getProcessingStopTime</CODE>, and <CODE>getProcessingTime()</CODE>
   * methods for a completed bind operation using simple authentication.
   */
  @Test()
  public void testGetProcessingStartAndStopTimesSimple()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertTrue(bindOperation.getProcessingStartTime() > 0);
    assertTrue(bindOperation.getProcessingStopTime() >=
               bindOperation.getProcessingStartTime());
    assertTrue(bindOperation.getProcessingTime() >= 0);
  }
  /**
   * Tests the <CODE>getProcessingStartTime</CODE>,
   * <CODE>getProcessingStopTime</CODE>, and <CODE>getProcessingTime()</CODE>
   * methods for a completed bind operation using SASL authentication.
   */
  @Test()
  public void testGetProcessingStartAndStopTimesSASL()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         conn.processSASLBind(new DN(), "PLAIN", saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertTrue(bindOperation.getProcessingStartTime() > 0);
    assertTrue(bindOperation.getProcessingStopTime() >=
               bindOperation.getProcessingStartTime());
    assertTrue(bindOperation.getProcessingTime() >= 0);
  }
  /**
   * Tests the <CODE>getOperationType</CODE> method for bind operations using
   * simple authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "simpleBinds")
  public void testGetOperationTypeSimple(BindOperation o)
  {
    assertEquals(o.getOperationType(), OperationType.BIND);
  }
  /**
   * Tests the <CODE>getOperationType</CODE> method for bind operations using
   * SASL authentication.
   *
   * @param  o  The bind operation to be tested.
   */
  @Test(dataProvider = "saslBinds")
  public void testGetOperationTypeSASL(BindOperation o)
  {
    assertEquals(o.getOperationType(), OperationType.BIND);
  }
  /**
   * Tests the <CODE>getResponseLogElements</CODE> method for a completed
   * successful bind operation using simple authentication.
   */
  @Test()
  public void testGetResponseLogElementsSimple()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(bindOperation.getResponseLogElements());
    assertTrue(bindOperation.getResponseLogElements().length > 0);
  }
  /**
   * Tests the <CODE>getResponseLogElements</CODE> method for a completed bind
   * operation using SASL authentication.
   */
  @Test()
  public void testGetResponseLogElementsSASL()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         conn.processSASLBind(new DN(), "PLAIN", saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(bindOperation.getResponseLogElements());
    assertTrue(bindOperation.getResponseLogElements().length > 0);
  }
  /**
   * Tests the <CODE>getResponseLogElements</CODE> method for a failed simple
   * bind attempt in which the target user didn't exist.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testGetResponseLogElementsSimpleNoSuchUser()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("uid=test,o=test"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
    assertNotNull(bindOperation.getResponseLogElements());
    assertTrue(bindOperation.getResponseLogElements().length > 0);
  }
  /**
   * Tests a simple bind operation to ensure that all plugin types are invoked
   * as expected.
   */
  @Test()
  public void testAllPluginsCalledSimple()
  {
    InvocationCounterPlugin.resetAllCounters();
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreOperationCount() > 0);
    assertTrue(InvocationCounterPlugin.getPostOperationCount() > 0);
    assertTrue(InvocationCounterPlugin.getPostResponseCount() > 0);
  }
  /**
   * Tests a SASL bind operation to ensure that all plugin types are invoked
   * as expected.
   */
  @Test()
  public void testAllPluginsCalledSASL()
  {
    InvocationCounterPlugin.resetAllCounters();
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         conn.processSASLBind(new DN(), "PLAIN", saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    assertTrue(InvocationCounterPlugin.getPreParseCount() > 0);
    assertTrue(InvocationCounterPlugin.getPreOperationCount() > 0);
    assertTrue(InvocationCounterPlugin.getPostOperationCount() > 0);
    assertTrue(InvocationCounterPlugin.getPostResponseCount() > 0);
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the client connection is lost in pre-parse plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreParseSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList("PreParse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the client connection is lost in pre-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreOperationSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PreOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the client connection is lost in post-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostOperationSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the client connection is lost in post-response plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostResponseSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostResponse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    while (element != null)
    {
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertTrue((message.getProtocolOpType() == OP_TYPE_BIND_RESPONSE) ||
                 (message.getProtocolOpType() == OP_TYPE_EXTENDED_RESPONSE));
      element = r.readElement();
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the client connection is lost in pre-parse plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreParseSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList("PreParse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the client connection is lost in pre-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreOperationSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PreOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the client connection is lost in post-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostOperationSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the client connection is lost in post-response plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostResponseSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostResponse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    while (element != null)
    {
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertTrue((message.getProtocolOpType() == OP_TYPE_BIND_RESPONSE) ||
                 (message.getProtocolOpType() == OP_TYPE_EXTENDED_RESPONSE));
      element = r.readElement();
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * client connection is lost in pre-parse plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreParseSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList("PreParse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * client connection is lost in pre-operation plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPreOperationSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PreOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * client connection is lost in post-operation plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostOperationSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostOperation"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    if (element != null)
    {
      // If we got an element back, then it must be a notice of disconnect
      // unsolicited notification.
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertEquals(message.getProtocolOpType(), OP_TYPE_EXTENDED_RESPONSE);
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * client connection is lost in post-response plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindDisconnectInPostResponseSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         DisconnectClientPlugin.createDisconnectLDAPControlList(
              "PostResponse"));
    w.writeElement(message.encode());
    ASN1Element element = r.readElement();
    while (element != null)
    {
      message = LDAPMessage.decode(element.decodeAsSequence());
      assertTrue((message.getProtocolOpType() == OP_TYPE_BIND_RESPONSE) ||
                 (message.getProtocolOpType() == OP_TYPE_EXTENDED_RESPONSE));
      element = r.readElement();
    }
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the operation gets short-circuited in pre-parse plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreParseSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80, "PreParse"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an anonymous simple bind operation to ensure that it's treated
   * properly if the operation gets short-circuited in pre-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreOperationSimpleAnonymous()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), 3,
                                   new ASN1OctetString());
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80,
                                                              "PreOperation"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the operation gets short-circuited in pre-parse plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreParseSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80, "PreParse"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests an authenticated simple bind operation to ensure that it's treated
   * properly if the operation gets short-circuited in pre-operation plugin
   * processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreOperationSimpleAuthenticated()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString("cn=Directory Manager"),
                                   3, new ASN1OctetString("password"));
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80,
                                                              "PreOperation"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * operation gets short-circuited in pre-parse plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreParseSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80, "PreParse"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests a SASL bind operation to ensure that it's treated properly if the
   * operation gets short-circuited in pre-operation plugin processing.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testBindShortCircuitInPreOperationSASL()
         throws Exception
  {
    Socket s = new Socket("127.0.0.1", (int) TestCaseUtils.getServerLdapPort());
    ASN1Reader r = new ASN1Reader(s);
    ASN1Writer w = new ASN1Writer(s);
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindRequestProtocolOp bindRequest =
         new BindRequestProtocolOp(new ASN1OctetString(), "PLAIN", saslCreds);
    LDAPMessage message = new LDAPMessage(1, bindRequest,
         ShortCircuitPlugin.createShortCircuitLDAPControlList(80,
                                                              "PreOperation"));
    w.writeElement(message.encode());
    message = LDAPMessage.decode(r.readElement().decodeAsSequence());
    BindResponseProtocolOp bindResponse = message.getBindResponseProtocolOp();
    assertEquals(bindResponse.getResultCode(), 80);
    try
    {
      s.close();
    } catch (Exception e) {}
  }
  /**
   * Tests performing a simple bind operation with an invalid user DN.
   */
  @Test()
  public void testSimpleBindInvalidDN()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("invaliddn"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
  /**
   * Tests performing a SASL bind operation with an invalid user DN.
   */
  @Test()
  public void testSASLBindInvalidDN()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         conn.processSASLBind(new ASN1OctetString("invaliddn"), "PLAIN",
                              saslCreds);
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
  /**
   * Tests performing a simple bind operation with an unsupported control that
   * is marked critical.
   */
  @Test()
  public void testSimpleBindUnsupportedCriticalControl()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ArrayList<Control> requestControls = new ArrayList<Control>(1);
    requestControls.add(new Control("1.2.3.4", true));
    BindOperation bindOperation =
         new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                           requestControls, new DN(), new ASN1OctetString());
    bindOperation.run();
    assertEquals(bindOperation.getResultCode(),
                 ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
  }
  /**
   * Tests performing a SASL bind operation with an unsupported control that is
   * marked critical.
   */
  @Test()
  public void testSASLBindUnsupportedCriticalControl()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ArrayList<Control> requestControls = new ArrayList<Control>(1);
    requestControls.add(new Control("1.2.3.4", true));
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                           requestControls, new DN(), "PLAIN", saslCreds);
    bindOperation.run();
    assertEquals(bindOperation.getResultCode(),
                 ResultCode.UNAVAILABLE_CRITICAL_EXTENSION);
  }
  /**
   * Tests performing a simple bind operation with an unsupported control that
   * is not marked critical.
   */
  @Test()
  public void testSimpleBindUnsupportedNonCriticalControl()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ArrayList<Control> requestControls = new ArrayList<Control>(1);
    requestControls.add(new Control("1.2.3.4", false));
    BindOperation bindOperation =
         new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                           requestControls, new DN(), new ASN1OctetString());
    bindOperation.run();
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Tests performing a SASL bind operation with an unsupported control that is
   * is not marked critical.
   */
  @Test()
  public void testSASLBindUnsupportedNonCriticalControl()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    ArrayList<Control> requestControls = new ArrayList<Control>(1);
    requestControls.add(new Control("1.2.3.4", false));
    ASN1OctetString saslCreds =
         new ASN1OctetString("\u0000dn:cn=Directory Manager\u0000password");
    BindOperation bindOperation =
         new BindOperation(conn, conn.nextOperationID(), conn.nextMessageID(),
                           requestControls, new DN(), "PLAIN", saslCreds);
    bindOperation.run();
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Tests performing a simple bind operation with the DN of a user that doesn't
   * exist.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSimpleBindNoSuchUser()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("uid=test,o=test"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
  /**
   * Tests performing a simple bind operation with the DN of a valid user but
   * without including a password in the request, with the server configured to
   * disallow that combination.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSimpleBindWithDNNoPasswordDisallowed()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString());
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
  /**
   * Tests performing a simple bind operation with the DN of a valid user but
   * without including a password in the request, with the server configured to
   * allow that combination.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSimpleBindWithDNNoPasswordAllowed()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    String attr = "ds-cfg-bind-with-dn-requires-password";
    ArrayList<Modification> mods = new ArrayList<Modification>();
    mods.add(new Modification(ModificationType.REPLACE,
                              new Attribute(attr, "false")));
    ModifyOperation modifyOperation =
         conn.processModify(DN.decode("cn=config"), mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString());
    assertEquals(bindOperation.getResultCode(), ResultCode.SUCCESS);
    mods.clear();
    mods.add(new Modification(ModificationType.REPLACE,
                              new Attribute(attr, "true")));
    modifyOperation =  conn.processModify(DN.decode("cn=config"), mods);
    assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
  }
  /**
   * Tests performing a simple bind operation as a user who doesn't have a
   * password.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSimpleBindNoUserPassword()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(true);
    Entry e = TestCaseUtils.makeEntry(
         "dn: uid=test,o=test",
         "objectClass: top",
         "objectClass: person",
         "objectClass: organizationalPerson",
         "objectClass: inetOrgPerson",
         "uid: test",
         "givenName: Test",
         "sn: User",
         "cn: Test User");
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    AddOperation addOperation =
         conn.processAdd(e.getDN(), e.getObjectClasses(), e.getUserAttributes(),
                         e.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("uid=test,o=test"),
                                new ASN1OctetString("password"));
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
  /**
   * Tests performing a simple bind operation with a valid DN but incorrect
   * password.
   */
  @Test()
  public void testSimpleBindWrongPassword()
  {
    InternalClientConnection conn =
         new InternalClientConnection(new AuthenticationInfo());
    BindOperation bindOperation =
         conn.processSimpleBind(new ASN1OctetString("cn=Directory Manager"),
                                new ASN1OctetString("wrongpassword"));
    assertEquals(bindOperation.getResultCode(), ResultCode.INVALID_CREDENTIALS);
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/core/OperationTestCase.java
@@ -28,6 +28,7 @@
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -45,6 +46,20 @@
       extends CoreTestCase
{
  /**
   * Ensures that the Directory Server is running.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  public void startServer()
         throws Exception
  {
    TestCaseUtils.startServer();
  }
  /**
   * Creates a set of valid operation instances of this type that may be used
   * for testing the general methods defined in the Operation superclass.  Only
   * the constructors for the operation need to be used -- it does not require
opends/tests/unit-tests-testng/src/server/org/opends/server/plugins/ShortCircuitPlugin.java
New file
@@ -0,0 +1,651 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.plugins;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.opends.server.api.plugin.DirectoryServerPlugin;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.api.plugin.PreOperationPluginResult;
import org.opends.server.api.plugin.PreParsePluginResult;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AbandonOperation;
import org.opends.server.core.AddOperation;
import org.opends.server.core.BindOperation;
import org.opends.server.core.CompareOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ExtendedOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.Operation;
import org.opends.server.core.SearchOperation;
import org.opends.server.core.UnbindOperation;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1Enumerated;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.ldap.LDAPControl;
import org.opends.server.types.Control;
import org.opends.server.types.ResultCode;
/**
 * This class defines a very simple plugin that causes request processing to end
 * immediately and send a specific result code to the client.  It will be
 * triggered by a control contained in the client request, and may be invoked
 * during either pre-parse or pre-operation processing.
 */
public class ShortCircuitPlugin
       extends DirectoryServerPlugin
{
  /**
   * The OID for the short circuit request control, which is used to flag
   * operations that should cause the operation processing to end immediately.
   */
  public static final String OID_SHORT_CIRCUIT_REQUEST =
       "1.3.6.1.4.1.26027.1.999.3";
  /**
   * Creates a new instance of this Directory Server plugin.  Every
   * plugin must implement a default constructor (it is the only one
   * that will be used to create plugins defined in the
   * configuration), and every plugin constructor must call
   * <CODE>super()</CODE> as its first element.
   */
  public ShortCircuitPlugin()
  {
    super();
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public void initializePlugin(DirectoryServer directoryServer,
                               Set<PluginType> pluginTypes,
                               ConfigEntry configEntry)
         throws ConfigException
  {
    // This plugin may only be used as a pre-parse or pre-operation plugin.
    for (PluginType t : pluginTypes)
    {
      switch (t)
      {
        case PRE_PARSE_ABANDON:
        case PRE_PARSE_ADD:
        case PRE_PARSE_BIND:
        case PRE_PARSE_COMPARE:
        case PRE_PARSE_DELETE:
        case PRE_PARSE_EXTENDED:
        case PRE_PARSE_MODIFY:
        case PRE_PARSE_MODIFY_DN:
        case PRE_PARSE_SEARCH:
        case PRE_PARSE_UNBIND:
        case PRE_OPERATION_ADD:
        case PRE_OPERATION_BIND:
        case PRE_OPERATION_COMPARE:
        case PRE_OPERATION_DELETE:
        case PRE_OPERATION_EXTENDED:
        case PRE_OPERATION_MODIFY:
        case PRE_OPERATION_MODIFY_DN:
        case PRE_OPERATION_SEARCH:
          // This is fine.
          break;
        default:
          throw new ConfigException(-1, "Invalid plugin type " + t +
                                    " for the short circuit plugin.");
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(AbandonOperation abandonOperation)
  {
    int resultCode = shortCircuitInternal(abandonOperation, "PreParse");
    if (resultCode >= 0)
    {
      abandonOperation.setResultCode(ResultCode.valueOf(resultCode));
      abandonOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(AddOperation addOperation)
  {
    int resultCode = shortCircuitInternal(addOperation, "PreParse");
    if (resultCode >= 0)
    {
      addOperation.setResultCode(ResultCode.valueOf(resultCode));
      addOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(BindOperation bindOperation)
  {
    int resultCode = shortCircuitInternal(bindOperation, "PreParse");
    if (resultCode >= 0)
    {
      bindOperation.setResultCode(ResultCode.valueOf(resultCode));
      bindOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(CompareOperation compareOperation)
  {
    int resultCode = shortCircuitInternal(compareOperation, "PreParse");
    if (resultCode >= 0)
    {
      compareOperation.setResultCode(ResultCode.valueOf(resultCode));
      compareOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(DeleteOperation deleteOperation)
  {
    int resultCode = shortCircuitInternal(deleteOperation, "PreParse");
    if (resultCode >= 0)
    {
      deleteOperation.setResultCode(ResultCode.valueOf(resultCode));
      deleteOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(ExtendedOperation extendedOperation)
  {
    int resultCode = shortCircuitInternal(extendedOperation, "PreParse");
    if (resultCode >= 0)
    {
      extendedOperation.setResultCode(ResultCode.valueOf(resultCode));
      extendedOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(ModifyOperation modifyOperation)
  {
    int resultCode = shortCircuitInternal(modifyOperation, "PreParse");
    if (resultCode >= 0)
    {
      modifyOperation.setResultCode(ResultCode.valueOf(resultCode));
      modifyOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(ModifyDNOperation modifyDNOperation)
  {
    int resultCode = shortCircuitInternal(modifyDNOperation, "PreParse");
    if (resultCode >= 0)
    {
      modifyDNOperation.setResultCode(ResultCode.valueOf(resultCode));
      modifyDNOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(SearchOperation searchOperation)
  {
    int resultCode = shortCircuitInternal(searchOperation, "PreParse");
    if (resultCode >= 0)
    {
      searchOperation.setResultCode(ResultCode.valueOf(resultCode));
      searchOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreParsePluginResult doPreParse(UnbindOperation unbindOperation)
  {
    int resultCode = shortCircuitInternal(unbindOperation, "PreParse");
    if (resultCode >= 0)
    {
      unbindOperation.setResultCode(ResultCode.valueOf(resultCode));
      unbindOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreParsePluginResult(false, false, true);
    }
    else
    {
      return new PreParsePluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(AddOperation addOperation)
  {
    int resultCode = shortCircuitInternal(addOperation, "PreOperation");
    if (resultCode >= 0)
    {
      addOperation.setResultCode(ResultCode.valueOf(resultCode));
      addOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(BindOperation bindOperation)
  {
    int resultCode = shortCircuitInternal(bindOperation, "PreOperation");
    if (resultCode >= 0)
    {
      bindOperation.setResultCode(ResultCode.valueOf(resultCode));
      bindOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(CompareOperation
                                                      compareOperation)
  {
    int resultCode = shortCircuitInternal(compareOperation, "PreOperation");
    if (resultCode >= 0)
    {
      compareOperation.setResultCode(ResultCode.valueOf(resultCode));
      compareOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(DeleteOperation
                                                      deleteOperation)
  {
    int resultCode = shortCircuitInternal(deleteOperation, "PreOperation");
    if (resultCode >= 0)
    {
      deleteOperation.setResultCode(ResultCode.valueOf(resultCode));
      deleteOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(ExtendedOperation
                                                      extendedOperation)
  {
    int resultCode = shortCircuitInternal(extendedOperation, "PreOperation");
    if (resultCode >= 0)
    {
      extendedOperation.setResultCode(ResultCode.valueOf(resultCode));
      extendedOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(ModifyOperation
                                                      modifyOperation)
  {
    int resultCode = shortCircuitInternal(modifyOperation, "PreOperation");
    if (resultCode >= 0)
    {
      modifyOperation.setResultCode(ResultCode.valueOf(resultCode));
      modifyOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(ModifyDNOperation
                                                      modifyDNOperation)
  {
    int resultCode = shortCircuitInternal(modifyDNOperation, "PreOperation");
    if (resultCode >= 0)
    {
      modifyDNOperation.setResultCode(ResultCode.valueOf(resultCode));
      modifyDNOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public PreOperationPluginResult doPreOperation(SearchOperation
                                                      searchOperation)
  {
    int resultCode = shortCircuitInternal(searchOperation, "PreOperation");
    if (resultCode >= 0)
    {
      searchOperation.setResultCode(ResultCode.valueOf(resultCode));
      searchOperation.appendErrorMessage("Short-circuit in pre-parse");
      return new PreOperationPluginResult(false, false, true);
    }
    else
    {
      return new PreOperationPluginResult();
    }
  }
  /**
   * Looks for a short-circuit request control in the operation and if one is
   * found with the correct section then generate the appropriate result.
   *
   * @param  operation  The operation to be processed.
   * @param  section    The section to match in the control value.
   *
   * @return  The result code that should be immediately sent to the client, or
   *          -1 if operation processing should continue as normal.
   */
  private int shortCircuitInternal(Operation operation, String section)
  {
    List<Control> requestControls = operation.getRequestControls();
    if (requestControls != null)
    {
      for (Control c : requestControls)
      {
        if (c.getOID().equals(OID_SHORT_CIRCUIT_REQUEST))
        {
          try
          {
            ASN1Sequence sequence =
                 ASN1Sequence.decodeAsSequence(c.getValue().value());
            ArrayList<ASN1Element> elements = sequence.elements();
            int resultCode = elements.get(0).decodeAsEnumerated().intValue();
            String controlSection =
                        elements.get(1).decodeAsOctetString().stringValue();
            if (section.equalsIgnoreCase(controlSection))
            {
              return resultCode;
            }
          }
          catch (Exception e)
          {
            System.err.println("***** ERROR:  Could not decode short circuit " +
                               "control value:  " + e);
            e.printStackTrace();
            return -1;
          }
        }
      }
    }
    // If we've gotten here, then we shouldn't short-circuit the operation
    // processing.
    return -1;
  }
  /**
   * Creates a short circuit request control with the specified result code and
   * section.
   *
   * @param  resultCode  The result code to return to the client.
   * @param  section     The section to use to determine when to short circuit.
   *
   * @return  The appropriate short circuit request control.
   */
  public static Control createShortCircuitControl(int resultCode,
                                                  String section)
  {
    ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
    elements.add(new ASN1Enumerated(resultCode));
    elements.add(new ASN1OctetString(section));
    ASN1OctetString controlValue =
         new ASN1OctetString(new ASN1Sequence(elements).encode());
    return new Control(OID_SHORT_CIRCUIT_REQUEST, false, controlValue);
  }
  /**
   * Retrieves a list containing a short circuit control with the specified
   * result code and section.
   *
   * @param  resultCode  The result code to return to the client.
   * @param  section     The section to use to determine when to short circuit.
   *
   * @return  A list containing the appropriate short circuit request control.
   */
  public static List<Control> createShortCircuitControlList(int resultCode,
                                                            String section)
  {
    ArrayList<Control> controlList = new ArrayList<Control>(1);
    controlList.add(createShortCircuitControl(resultCode, section));
    return controlList;
  }
  /**
   * Creates a short circuit LDAP request control with the specified result code
   * and section.
   *
   * @param  resultCode  The result code to return to the client.
   * @param  section     The section to use to determine when to short circuit.
   *
   * @return  The appropriate short circuit LDAP request control.
   */
  public static LDAPControl createShortCircuitLDAPControl(int resultCode,
                                                          String section)
  {
    return new LDAPControl(createShortCircuitControl(resultCode, section));
  }
  /**
   * Retrieves a list containing a short circuit LDAP control with the specified
   * result code and section.
   *
   * @param  resultCode  The result code to return to the client.
   * @param  section     The section to use to determine when to short circuit.
   *
   * @return  A list containing the appropriate short circuit LDAP request
   *          control.
   */
  public static ArrayList<LDAPControl> createShortCircuitLDAPControlList(
                                            int resultCode, String section)
  {
    ArrayList<LDAPControl> controlList = new ArrayList<LDAPControl>(1);
    controlList.add(createShortCircuitLDAPControl(resultCode, section));
    return controlList;
  }
}