/**
   * A delete Record with a control.
   *
   * @throws Exception
   */
  @Test
  public void testWriteDeleteRequestContainingControl() throws Exception {
    final List<String> actual = new ArrayList<>();
    final LDIFChangeRecordWriter writer = new LDIFChangeRecordWriter(actual);
    final DN dn = DN.valueOf("uid=scarter,ou=People,dc=example,dc=com");

    // @formatter:off
    final DeleteRequest changeRequest =
        Requests.newDeleteRequest(dn)
            .addControl(
                PersistentSearchRequestControl.newControl(
                    true,
                    true,
                    true, // isCritical, changesOnly, returnECs
                    PersistentSearchChangeType.ADD,
                    PersistentSearchChangeType.DELETE,
                    PersistentSearchChangeType.MODIFY,
                    PersistentSearchChangeType.MODIFY_DN));
    // @formatter:on

    writer.writeComment("This record contains a control");
    writer.writeChangeRecord(changeRequest);
    writer.close();

    assertThat(actual.get(0)).isEqualTo("# This record contains a control");
    assertThat(actual.get(1)).isEqualTo("dn: uid=scarter,ou=People,dc=example,dc=com");
    assertThat(actual.get(2)).contains("control: 2.16.840.1.113730.3.4.3 true");
    assertThat(actual.get(3)).isEqualTo("changetype: delete");
    assertThat(actual.get(4)).isEqualTo("");
  }
  private void doTestRequestTimeout(boolean isPersistentSearch) throws Exception {
    InetSocketAddress address = TestCaseUtils.findFreeSocketAddress();

    /*
     * Use a mock server implementation which will ignore incoming requests
     * and leave the client waiting forever for a response.
     */
    @SuppressWarnings("unchecked")
    LDAPListener listener =
        new LDAPListener(
            address, Connections.newServerConnectionFactory(mock(RequestHandler.class)));

    /*
     * Use a very long time out in order to prevent the timeout thread from
     * triggering the timeout.
     */
    LDAPConnectionFactory factory =
        new LDAPConnectionFactory(
            address.getHostName(),
            address.getPort(),
            Options.defaultOptions()
                .set(TIMEOUT_IN_MILLISECONDS, TimeUnit.SECONDS.toMillis((long) 100)));
    GrizzlyLDAPConnection connection = (GrizzlyLDAPConnection) factory.getConnection();
    try {
      SearchRequest request =
          Requests.newSearchRequest("dc=test", SearchScope.BASE_OBJECT, "(objectClass=*)");
      if (isPersistentSearch) {
        request.addControl(PersistentSearchRequestControl.newControl(true, true, true));
      }
      SearchResultHandler searchHandler = mock(SearchResultHandler.class);
      @SuppressWarnings("unchecked")
      ExceptionHandler<LdapException> exceptionHandler = mock(ExceptionHandler.class);
      connection.searchAsync(request, searchHandler).thenOnException(exceptionHandler);

      // Pass in a time which is guaranteed to trigger expiration.
      connection.handleTimeout(System.currentTimeMillis() + 1000000);
      if (isPersistentSearch) {
        verifyZeroInteractions(searchHandler);
      } else {
        ArgumentCaptor<LdapException> arg = ArgumentCaptor.forClass(LdapException.class);
        verify(exceptionHandler).handleException(arg.capture());
        assertThat(arg.getValue()).isInstanceOf(TimeoutResultException.class);
        assertThat(arg.getValue().getResult().getResultCode())
            .isEqualTo(ResultCode.CLIENT_SIDE_TIMEOUT);
      }
    } finally {
      connection.close();
      listener.close();
      factory.close();
    }
  }