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

coulbeck
22.19.2006 143211dc9acc7ac6605844cc179315297537a796
1. Add test cases for task import from LDIF (tests are in the slow group).
2. Fix issue 702: Import of non-existent LDIF file leaves environment handle open.
3. In the test runner method TasksTestCase#testTask reduce the sleep from 1s to 10ms when polling for completed task.
4. Remove two unnecessary catch blocks in ImportTask.
2 files added
3 files modified
529 ■■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ImportJob.java 2 ●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java 22 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/LdifFileWriter.java 158 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java 50 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java 297 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ImportJob.java
@@ -348,7 +348,6 @@
      {
        ic.getEntryContainer().close();
      }
    }
    // Sync the environment to disk.
    msgID = MSGID_JEB_IMPORT_CLOSING_DATABASE;
@@ -356,6 +355,7 @@
    logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.NOTICE,
             message, msgID);
    env.close();
    }
    long finishTime = System.currentTimeMillis();
    long importTime = (finishTime - startTime);
opendj-sdk/opends/src/server/org/opends/server/tasks/ImportTask.java
@@ -252,15 +252,6 @@
                 message, msgID);
        return TaskState.STOPPED_BY_ERROR;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_LDIFIMPORT_CANNOT_PARSE_EXCLUDE_FILTER;
        String message = getMessage(msgID, filterString,
                                    stackTraceToSingleLineString(e));
        logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                 message, msgID);
        return TaskState.STOPPED_BY_ERROR;
      }
    }
    ArrayList<SearchFilter> includeFilters =
@@ -280,15 +271,6 @@
                 message, msgID);
        return TaskState.STOPPED_BY_ERROR;
      }
      catch (Exception e)
      {
        int    msgID   = MSGID_LDIFIMPORT_CANNOT_PARSE_INCLUDE_FILTER;
        String message = getMessage(msgID, filterString,
                                    stackTraceToSingleLineString(e));
        logError(ErrorLogCategory.BACKEND, ErrorLogSeverity.SEVERE_ERROR,
                 message, msgID);
        return TaskState.STOPPED_BY_ERROR;
      }
    }
@@ -354,7 +336,7 @@
    for (String s : excludeBranchStrings)
    {
      DN excludeBranch = null;
      DN excludeBranch;
      try
      {
        excludeBranch = DN.decode(s);
@@ -393,7 +375,7 @@
      includeBranches = new ArrayList<DN>(includeBranchStrings.size());
      for (String s : includeBranchStrings)
      {
        DN includeBranch = null;
        DN includeBranch;
        try
        {
          includeBranch = DN.decode(s);
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/LdifFileWriter.java
New file
@@ -0,0 +1,158 @@
/*
 * 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.tasks;
import org.opends.server.tools.makeldif.EntryWriter;
import org.opends.server.tools.makeldif.MakeLDIFException;
import org.opends.server.tools.makeldif.TemplateFile;
import org.opends.server.types.Entry;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.ExistingFileBehavior;
import org.opends.server.util.LDIFWriter;
import org.opends.server.util.LDIFException;
import org.opends.server.core.InitializationException;
import java.io.IOException;
import java.util.Random;
import java.util.ArrayList;
/**
 * This class makes test LDIF files using the makeldif package.
 */
public class LdifFileWriter implements EntryWriter
{
  /**
   * The LDIF writer used to write the entries to the file.
   */
  private LDIFWriter ldifWriter;
  /**
   * Construct an LdifFileWriter from an LDIF Writer.
   * @param ldifWriter The LDIF writer that should be used to write the entries.
   */
  private LdifFileWriter(LDIFWriter ldifWriter)
  {
    this.ldifWriter = ldifWriter;
  }
  /**
   * Make an LDIF file containing test data.  It uses a fixed value for the
   * random seed.
   * @param ldifPath The path to the LDIF file to be written.
   * @param resourcePath The path to the makeldif resource directory.
   * @param templatePath The path to the makeldif template file.
   * @throws IOException If there is an exception parsing the template or
   * generating the LDIF.
   * @throws InitializationException If there is an exception parsing the
   * template.
   * @throws MakeLDIFException If there is an exception parsing the template or
   * generating the LDIF.
   */
  public static void makeLdif(String ldifPath,
                              String resourcePath,
                              String templatePath)
       throws IOException, InitializationException, MakeLDIFException
  {
    TemplateFile template = new TemplateFile(resourcePath, new Random(1));
    ArrayList<String> warnings = new ArrayList<String>();
    template.parse(templatePath, warnings);
    makeLdif(ldifPath, template);
  }
  /**
   * Make an LDIF file containing test data.  It uses a fixed value for the
   * random seed.
   * @param ldifPath The path to the LDIF file to be written.
   * @param resourcePath The path to the makeldif resource directory.
   * @param templateLines The lines making up the template.
   * @throws IOException If there is an exception parsing the template or
   * generating the LDIF.
   * @throws InitializationException If there is an exception parsing the
   * template.
   * @throws MakeLDIFException If there is an exception parsing the template or
   * generating the LDIF.
   */
  public static void makeLdif(String ldifPath,
                              String resourcePath,
                              String[] templateLines)
       throws IOException, InitializationException, MakeLDIFException
  {
    TemplateFile template = new TemplateFile(resourcePath, new Random(1));
    ArrayList<String> warnings = new ArrayList<String>();
    template.parse(templateLines, warnings);
    makeLdif(ldifPath, template);
  }
  /**
   * Make an LDIF file containing test data.
   * @param ldifPath The path to the LDIF file to be written.
   * @param template The makeldif template.
   * @throws IOException If there is an exception parsing the template or
   * generating the LDIF.
   * @throws MakeLDIFException If there is an exception parsing the template or
   * generating the LDIF.
   */
  public static void makeLdif(String ldifPath, TemplateFile template)
       throws IOException, MakeLDIFException
  {
    LDIFExportConfig exportConfig =
         new LDIFExportConfig(ldifPath, ExistingFileBehavior.OVERWRITE);
    LDIFWriter ldifWriter = new LDIFWriter(exportConfig);
    template.generateLDIF(new LdifFileWriter(ldifWriter));
  }
  /**
   * {@inheritDoc}
   */
  public boolean writeEntry(Entry entry)
       throws IOException, MakeLDIFException
  {
    try
    {
      return ldifWriter.writeEntry(entry);
    } catch (LDIFException e)
    {
      e.printStackTrace();
      return false;
    }
  }
  /**
   * {@inheritDoc}
   */
  public void closeEntryWriter()
  {
    try
    {
      ldifWriter.close();
    } catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TasksTestCase.java
@@ -30,7 +30,7 @@
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.schema.DirectoryStringSyntax;
import static org.opends.server.config.ConfigConstants.
@@ -54,6 +54,8 @@
  /**
   * Add a task definition and check that it completes with the expected state.
   * The task is expected to complete quickly and the timeout is set
   * accordingly.
   * @param taskEntry The task entry.
   * @param expectedState The expected completion state of the task.
   * @throws Exception If the test fails.
@@ -61,6 +63,19 @@
  protected void testTask(Entry taskEntry, TaskState expectedState)
       throws Exception
  {
    testTask(taskEntry, expectedState, 10);
  }
  /**
   * Add a task definition and check that it completes with the expected state.
   * @param taskEntry The task entry.
   * @param expectedState The expected completion state of the task.
   * @param timeout The number of seconds to wait for the task to complete.
   * @throws Exception If the test fails.
   */
  protected void testTask(Entry taskEntry, TaskState expectedState, int timeout)
       throws Exception
  {
    InternalClientConnection connection =
         InternalClientConnection.getRootConnection();
@@ -78,27 +93,42 @@
         ATTR_TASK_COMPLETION_TIME.toLowerCase());
    SearchFilter filter =
         SearchFilter.createFilterFromString("(objectclass=*)");
    Entry resultEntry;
    String completionTime;
    int countdown = 10; // Do not wait forever.
    Entry resultEntry = null;
    String completionTime = null;
    long startMillisecs = System.currentTimeMillis();
    do
    {
      countdown--;
      Thread.sleep(1000);
      InternalSearchOperation searchOperation =
           connection.processSearch(taskEntry.getDN(),
                                    SearchScope.BASE_OBJECT,
                                    filter);
      try
      {
      resultEntry = searchOperation.getSearchEntries().getFirst();
      } catch (Exception e)
      {
        // FIXME How is this possible?
//        fail("Task entry was not returned from the search.");
        continue;
      }
      completionTime =
           resultEntry.getAttributeValue(completionTimeType,
                                         DirectoryStringSyntax.DECODER);
    } while (completionTime == null && countdown > 0);
      if (completionTime == null)
      {
        if (System.currentTimeMillis() - startMillisecs > 1000*timeout)
        {
          break;
        }
        Thread.sleep(10);
      }
    } while (completionTime == null);
    assertNotNull(completionTime,
                  "The task did not complete");
    if (completionTime == null)
    {
      fail("The task had not completed after " + timeout + " seconds.");
    }
    // Check that the task state is as expected.
    AttributeType taskStateType =
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/TestImportAndExport.java
New file
@@ -0,0 +1,297 @@
/*
 * 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.tasks;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import org.testng.annotations.DataProvider;
import org.opends.server.core.DirectoryServer;
import org.opends.server.TestCaseUtils;
import org.opends.server.types.Entry;
import org.opends.server.backends.task.TaskState;
import java.io.File;
import java.util.UUID;
/**
 * Tests invocation of the backup and restore tasks, but does not aim to
 * thoroughly test the underlying backend implementations.
 */
public class TestImportAndExport extends TasksTestCase
{
  /**
   * A makeldif template used to create some test entries.
   */
  private static String[] template = new String[] {
       "define suffix=dc=example,dc=com",
       "define maildomain=example.com",
       "define numusers=101",
       "",
       "branch: [suffix]",
       "",
       "branch: ou=People,[suffix]",
       "subordinateTemplate: person:[numusers]",
       "",
       "template: person",
       "rdnAttr: uid",
       "objectClass: top",
       "objectClass: person",
       "objectClass: organizationalPerson",
       "objectClass: inetOrgPerson",
       "givenName: <first>",
       "sn: <last>",
       "cn: {givenName} {sn}",
       "initials: {givenName:1}<random:chars:" +
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ:1>{sn:1}",
       "employeeNumber: <sequential:0>",
       "uid: user.{employeeNumber}",
       "mail: {uid}@[maildomain]",
       "userPassword: password",
       "telephoneNumber: <random:telephone>",
       "homePhone: <random:telephone>",
       "pager: <random:telephone>",
       "mobile: <random:telephone>",
       "street: <random:numeric:5> <file:streets> Street",
       "l: <file:cities>",
       "st: <file:states>",
       "postalCode: <random:numeric:5>",
       "postalAddress: {cn}${street}${l}, {st}  {postalCode}",
       "description: This is the description for {cn}.",
       ""};
  /**
   * A temporary LDIF file containing some test entries.
   */
  private File ldifFile;
  /**
   * A temporary file to contain rejected entries.
   */
  private File rejectFile;
  @BeforeClass
  public void setUp() throws Exception
  {
    // The server must be running for these tests.
    TestCaseUtils.startServer();
    // Create a temporary test LDIF file.
    ldifFile = File.createTempFile("import-test", ".ldif");
    String resourcePath = DirectoryServer.getServerRoot() + File.separator +
         "config" + File.separator + "MakeLDIF";
    LdifFileWriter.makeLdif(ldifFile.getPath(), resourcePath, template);
    // Create a temporary rejects file.
    rejectFile = File.createTempFile("import-test-rejects", ".ldif");
  }
  @AfterClass
  public void tearDown()
  {
    ldifFile.delete();
    rejectFile.delete();
  }
  /**
   * Import and export tasks test data provider.
   *
   * @return The array of tasks test data.  The first column is a task entry
   *  and the second column is the expected completed task state.
   */
  @DataProvider(name = "importexport")
  public Object[][] createData() throws Exception
  {
    return new Object[][] {
         // A fairly simple valid import task.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-reject-file: " + rejectFile.getPath(),
                   "ds-task-import-overwrite-rejects: TRUE",
                   "ds-task-import-exclude-attribute: description",
                   "ds-task-import-exclude-filter: (st=CA)",
                   "ds-task-import-exclude-branch: o=exclude,dc=example,dc=com"
              ),
              TaskState.COMPLETED_SUCCESSFULLY
         },
         // A complex valid import task.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-is-compressed: FALSE",
                   "ds-task-import-is-encrypted: FALSE",
                   "ds-task-import-reject-file: " + rejectFile.getPath(),
                   "ds-task-import-overwrite-rejects: FALSE",
                   "ds-task-import-append: TRUE",
                   "ds-task-import-replace-existing: TRUE",
                   "ds-task-import-skip-schema-validation: TRUE",
                   "ds-task-import-include-branch: dc=example,dc=com",
                   "ds-task-import-exclude-branch: o=exclude,dc=example,dc=com",
                   "ds-task-import-include-attribute: cn",
                   "ds-task-import-include-attribute: sn",
                   "ds-task-import-include-attribute: uid",
                   "ds-task-import-include-filter: (objectclass=*)"
              ),
              TaskState.COMPLETED_SUCCESSFULLY
         },
         // LDIF file does not exist.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: doesnotexist",
                   "ds-task-import-backend-id: userRoot"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Invalid exclude filter.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-exclude-filter: ()"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Invalid include filter.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-include-filter: ()"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Backend id does not exist.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-backend-id: doesnotexist"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Backend does not support import.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-backend-id: monitor"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Backend does not handle include branch.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-include-branch: dc=opends,dc=org"
              ),
              TaskState.STOPPED_BY_ERROR
         },
         // Rejects file is a directory.
         {
              TestCaseUtils.makeEntry(
                   "dn: ds-task-id=" + UUID.randomUUID() +
                        ",cn=Scheduled Tasks,cn=Tasks",
                   "objectclass: top",
                   "objectclass: ds-task",
                   "objectclass: ds-task-import",
                   "ds-task-class-name: org.opends.server.tasks.ImportTask",
                   "ds-task-import-backend-id: userRoot",
                   "ds-task-import-ldif-file: " + ldifFile.getPath(),
                   "ds-task-import-reject-file: " + ldifFile.getParent(),
                   "ds-task-import-overwrite-rejects: TRUE"
              ),
              TaskState.STOPPED_BY_ERROR
         },
    };
  }
  /**
   * Test that various import and export task definitions complete with the
   * expected state.
   * @param taskEntry The task entry.
   * @param expectedState The expected completion state of the task.
   */
  @Test(dataProvider = "importexport", groups = "slow")
  public void testImportExport(Entry taskEntry, TaskState expectedState)
       throws Exception
  {
    testTask(taskEntry, expectedState);
  }
}