From ec144f32207385677a45c0eafda8038a1114ca32 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Wed, 12 Jul 2006 09:26:05 +0000
Subject: [PATCH] Add some unit tests for   - synchronization msg serialization/un-serialization (classes that inherit from SynchronizationMsg)  - modify conflicts resolution (Historical class)

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationMsgTest.java  |  278 +++++++++++++++++++++++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ModifyConflictTest.java      |  276 +++++++++++++++++++++++++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java |   37 +++
 opendj-sdk/opends/ext/testng/testng.xml                                                                             |    1 
 4 files changed, 592 insertions(+), 0 deletions(-)

diff --git a/opendj-sdk/opends/ext/testng/testng.xml b/opendj-sdk/opends/ext/testng/testng.xml
index 6b1c44b..6c21c90 100644
--- a/opendj-sdk/opends/ext/testng/testng.xml
+++ b/opendj-sdk/opends/ext/testng/testng.xml
@@ -4,6 +4,7 @@
         <package name="org.opends.server.protocols.asn1"/>
         <package name="org.opends.server.core"/>
         <package name="org.opends.server.backends.jeb"/>
+        <package name="org.opends.server.synchronization"/>
     </packages>
     
     <test name="precommit">
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ModifyConflictTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ModifyConflictTest.java
new file mode 100644
index 0000000..4d05a7a
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ModifyConflictTest.java
@@ -0,0 +1,276 @@
+/*
+ * 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.synchronization;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+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.ObjectClass;
+import static org.opends.server.synchronization.SynchMessages.SYNCHRONIZATION;
+
+/*
+ * Test the conflict resolution for modify operations
+ * This is still a work in progress.
+ * currently implemented tests
+ *  - check that an replace with a smaller csn is ignored 
+ * should test :
+ *  - conflict with multi-valued attributes
+ *  - conflict with single-valued attributes
+ *  - conflict with options
+ *  - conflict with binary attributes
+ *  - Replace, add, delete attribute, delete attribute value
+ *  - conflict on the objectclass attribute
+ */
+
+
+public class ModifyConflictTest extends SynchronizationTestCase
+{
+
+  /**
+   * Test that conflict between a modify-replace and modify-add
+   * for multi-valued attributes are handled correctly.
+   */
+  @Test()
+  public void replaceAndAdd()
+         throws Exception
+  { 
+    /*
+     * Objectclass and DN do not have any impact on the modifty conflict
+     * resolution for the description attribute.
+     * Always use the same values for all these tests.
+     */
+    DN dn = DN.decode("dc=com");    
+    Map<ObjectClass, String> objectClasses = new HashMap<ObjectClass, String>();
+    ObjectClass org = DirectoryServer.getObjectClass("organization");
+    objectClasses.put(org, "organization");
+    
+    /*
+     * start with a new entry with an empty description
+     */
+    Entry entry = new Entry(dn, objectClasses, null, null);
+    Historical hist = Historical.load(entry);
+    
+    /*
+     * simulate a modify-replace done at time t10
+     */
+    testModify(entry, hist, "description", ModificationType.REPLACE,
+               "init value", 10, true);
+    
+    /*
+     * Now simulate an add at an earlier date that the previous replace
+     * conflict resolution should remove it.
+     */ 
+    testModify(entry, hist, "description", ModificationType.ADD,
+               "older value", 1, false);
+  
+    /*
+     * Now simulate an add at an earlier date that the previous replace
+     * conflict resolution should remove it.
+     * (a second time to make sure...)
+     */   
+    testModify(entry, hist, "description", ModificationType.ADD,
+               "older value", 2, false);
+    
+    /*
+     * Now simulate an add at a later date that the previous replace.
+     * conflict resolution should keep it
+     */ 
+    testModify(entry, hist, "description", ModificationType.ADD,
+               "new value", 11, true);
+    
+  }
+  
+  /**
+   * Test that conflict between a modify-delete-attribute and modify-add
+   * for multi-valued attributes are handled correctly.
+   */
+  @Test()
+  public void deleteAndAdd()
+         throws Exception
+  { 
+    /*
+     * Objectclass and DN do not have any impact on the modifty conflict
+     * resolution for the description attribute.
+     * Always use the same values for all these tests.
+     */
+    DN dn = DN.decode("dc=com");    
+    Map<ObjectClass, String> objectClasses = new HashMap<ObjectClass, String>();
+    ObjectClass org = DirectoryServer.getObjectClass("organization");
+    objectClasses.put(org, "organization");
+    
+    /*
+     * start with a new entry with an empty description
+     */
+    Entry entry = new Entry(dn, objectClasses, null, null);
+    Historical hist = Historical.load(entry);
+    
+    /*
+     * simulate a delete of the whole description attribute done at time t10
+     */
+    testModify(entry, hist, "description", ModificationType.DELETE,
+               null, 10, true);
+    
+    /*
+     * Now simulate an add at an earlier date that the previous delete.
+     * The conflict resolution should detect that this add must be ignored.
+     */ 
+    testModify(entry, hist, "description",  ModificationType.ADD,
+               "older value", 1, false);
+  
+    /*
+     * Now simulate an add at an earlier date that the previous delete.
+     * The conflict resolution should detect that this add must be ignored.
+     * (a second time to make sure that historical information is kept...)
+     */   
+    testModify(entry, hist, "description", ModificationType.ADD,
+               "older value", 2, false);
+    
+    /*
+     * Now simulate an add at a later date that the previous delete.
+     * conflict resolution should keep it
+     */ 
+    testModify(entry, hist, "description", ModificationType.ADD,
+               "new value", 11, true);
+    
+  }
+  
+  /**
+  * Test that conflict between a modify-add and modify-add
+  * for multi-valued attributes are handled correctly.
+  */
+ @Test()
+ public void addAndAdd()
+        throws Exception
+ { 
+   /*
+    * Objectclass and DN do not have any impact on the modifty conflict
+    * resolution for the description attribute.
+    * Always use the same values for all these tests.
+    */
+   DN dn = DN.decode("dc=com");    
+   Map<ObjectClass, String> objectClasses = new HashMap<ObjectClass, String>();
+   ObjectClass org = DirectoryServer.getObjectClass("organization");
+   objectClasses.put(org, "organization");
+   
+   /*
+    * start with a new entry with an empty description
+    */
+   Entry entry = new Entry(dn, objectClasses, null, null);
+   Historical hist = Historical.load(entry);
+   
+   /*
+    * simulate a add of the description attribute done at time t10
+    */
+   testModify(entry, hist, "description", ModificationType.ADD,
+              "init value", 10, true);
+   
+   /*
+    * Now simulate an add at an earlier date that the previous add.
+    * The conflict resolution should detect that this add must be kept.
+    */ 
+   testModify(entry, hist, "description", ModificationType.ADD, 
+              "older value", 1, true);
+ 
+   /*
+    * Now simulate an add at an earlier date that the previous add.
+    * The conflict resolution should detect that this add must be kept.
+    * (a second time to make sure that historical information is kept...)
+    */   
+   testModify(entry, hist, "description", ModificationType.ADD,
+              "older value", 2, false);
+   
+   /*
+    * Now simulate an add at a later date that the previous add.
+    * conflict resolution should keep it
+    */ 
+   testModify(entry, hist, "description", ModificationType.ADD,
+              "new value", 11, true); 
+ }
+ 
+  /*
+   * helper function.
+   */
+  private static void testModify(Entry entry, 
+      Historical hist, String attrName, 
+      ModificationType modType, String value,
+      int date, boolean keepChangeResult)
+  {
+    InternalClientConnection connection = new InternalClientConnection();
+    ChangeNumber t = new ChangeNumber(date, (short) 0, (short) 0);
+    
+    /* create AttributeType description that will be usedfor this test */
+    AttributeType attrType =
+      DirectoryServer.getAttributeType(attrName, true);
+    
+    LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
+    if (value != null)
+      values.add(new AttributeValue(attrType, value));
+    Attribute attr = new Attribute(attrType, attrName, values);
+    List<Modification> mods = new ArrayList<Modification>();
+    Modification mod = new Modification(modType, attr);
+    mods.add(mod);
+    
+    ModifyOperation modOp = new ModifyOperation(connection, 1, 1, null,
+                                              entry.getDN(), mods);
+    
+    modOp.setAttachment(SYNCHRONIZATION, t);
+    
+    hist.replayOperation(modOp, entry);
+    
+    /*
+     * The last older change should have been detected as conflicting 
+     * and should be removed by the conflict resolution code. 
+     */
+    if (keepChangeResult)
+    {
+      assertTrue(mods.contains(mod));
+      assertEquals(1, mods.size());
+    }
+    else
+    {
+      assertFalse(mods.contains(mod));
+      assertEquals(0, mods.size());
+    }
+  }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationMsgTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationMsgTest.java
new file mode 100644
index 0000000..73c1be2
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationMsgTest.java
@@ -0,0 +1,278 @@
+/*
+ * 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.synchronization;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.ModifyDNOperation;
+import org.opends.server.core.ModifyOperation;
+import org.opends.server.core.Operation;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.synchronization.ModifyMsg;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.DN;
+import org.opends.server.types.Modification;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.RDN;
+import org.opends.server.util.TimeThread;
+
+import static org.opends.server.synchronization.SynchMessages.SYNCHRONIZATION;
+
+/**
+ * Test the contructors, encoders and decoders of the synchronization
+ * ModifyMsg, ModifyDnMsg, AddMsg and Delete Msg
+ */
+public class SynchronizationMsgTest extends SynchronizationTestCase
+{
+  /**
+   * Build some data for the ModifyMsg test below.
+   */
+  @DataProvider(name = "modifyEncodeDecode")
+  public Object[][] createData() {
+    ChangeNumber cn1 = new ChangeNumber(1, (short) 0, (short) 1);
+    ChangeNumber cn2 = new ChangeNumber(TimeThread.getTime(),
+                                       (short) 123, (short) 45);
+
+    AttributeType type = DirectoryServer.getAttributeType("description");
+
+    Attribute attr1 = new Attribute("description", "new value");
+    Modification mod1 = new Modification(ModificationType.REPLACE, attr1);
+    List<Modification> mods1 = new ArrayList<Modification>();
+    mods1.add(mod1);
+
+    Attribute attr2 =
+      new Attribute(DirectoryServer.getAttributeType("description", true));
+    Modification mod2 = new Modification(ModificationType.DELETE, attr2);
+    List<Modification> mods2 = new ArrayList<Modification>();
+    mods2.add(mod1);
+    mods2.add(mod2);
+
+    List<Modification> mods3 = new ArrayList<Modification>();
+    LinkedHashSet<AttributeValue> values3 =
+                      new LinkedHashSet<AttributeValue>();
+    values3.add(new AttributeValue(type, "string"));
+    values3.add(new AttributeValue(type, "value"));
+    values3.add(new AttributeValue(type, "again"));
+    Attribute attr3 = new Attribute(type, "description", values3);
+    Modification mod3 = new Modification(ModificationType.ADD, attr3);
+    mods3.add(mod3);
+
+    List<Modification> mods4 = new ArrayList<Modification>();
+    for (int i =0; i< 10; i++)
+    {
+      LinkedHashSet<AttributeValue> values =
+                      new LinkedHashSet<AttributeValue>();
+      values.add(new AttributeValue(type, "string" + String.valueOf(i)));
+      Attribute attr = new Attribute(type, "description", values);
+      Modification mod = new Modification(ModificationType.ADD, attr);
+      mods4.add(mod);
+    }
+
+    return new Object[][] {
+        { cn1, "dc=test", mods1},
+        { cn2, "dc=cn2", mods1},
+        { cn2, "dc=test with a much longer dn in case this would "
+               + "make a difference", mods1},
+        { cn2, "dc=test, cn=with a, o=more complex, ou=dn", mods1},
+        { cn2, "cn=use\\, backslash", mods1},
+        { cn2, "dc=test with several mod", mods2},
+        { cn2, "dc=test with several values", mods3},
+        { cn2, "dc=test with long mod", mods4},
+        };
+  }
+
+
+  /**
+   * Create a ModifyMsg from the data provided above.
+   * The call getBytes() to test the encoding of the Msg and
+   * create another ModifyMsg from the encoded byte array.
+   * Finally test that both Msg matches.
+   */
+  @Test(dataProvider = "modifyEncodeDecode")
+  public void modifyEncodeDecode(ChangeNumber changeNumber,
+                               String rawdn, List<Modification> mods)
+         throws Exception
+  {
+    DN dn = DN.decode(rawdn);
+    InternalClientConnection connection = new InternalClientConnection();
+    ModifyMsg msg = new ModifyMsg(changeNumber, dn, mods);
+    ModifyMsg generatedMsg = new ModifyMsg(msg.getBytes());
+
+    assertEquals(msg.changeNumber, generatedMsg.changeNumber);
+
+    Operation op = msg.createOperation(connection);
+    Operation generatedOperation = generatedMsg.createOperation(connection);
+
+    assertEquals(op.getClass(), ModifyOperation.class);
+    assertEquals(generatedOperation.getClass(), ModifyOperation.class);
+
+    ModifyOperation mod1 = (ModifyOperation) op;
+    ModifyOperation mod2 = (ModifyOperation) generatedOperation;
+
+    assertEquals(mod1.getRawEntryDN(), mod2.getRawEntryDN());
+
+    /*
+     * TODO : test that the generated mod equals the original mod.
+     */
+  }
+
+  /**
+   * Build some data for the DeleteMsg test below.
+   * @throws DirectoryException
+   */
+  @DataProvider(name = "deleteEncodeDecode")
+  public Object[][] createDelData() {
+    return new Object[][] {
+        {"dc=com"},
+        {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn"},
+        };
+  }
+
+  /**
+   * Create a Delete from the data provided above.
+   * The call getBytes() to test the encoding of the Msg and
+   * create another DeleteMsg from the encoded byte array.
+   * Finally test that both Msg matches.
+   */
+  @Test(dataProvider = "deleteEncodeDecode")
+  public void deleteEncodeDecode(String rawDN)
+         throws Exception
+  {
+    InternalClientConnection connection = new InternalClientConnection();
+    DeleteOperation op = new DeleteOperation(connection, 1, 1,null,
+                                             DN.decode(rawDN));
+    ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+      (short) 123, (short) 45);
+    op.setAttachment(SYNCHRONIZATION, cn);
+    DeleteMsg msg = new DeleteMsg(op);
+    DeleteMsg generatedMsg = new DeleteMsg(msg.getBytes());
+
+    assertEquals(msg.changeNumber, generatedMsg.changeNumber);
+
+    Operation generatedOperation = generatedMsg.createOperation(connection);
+
+    assertEquals(generatedOperation.getClass(), DeleteOperation.class);
+
+    DeleteOperation mod2 = (DeleteOperation) generatedOperation;
+
+    assertEquals(op.getRawEntryDN(), mod2.getRawEntryDN());
+  }
+
+  @DataProvider(name = "modifyDnEncodeDecode")
+  public Object[][] createModifyDnData() {
+    return new Object[][] {
+        {"dc=test,dc=com", "dc=new", false, "dc=change"},
+        {"dc=test,dc=com", "dc=new", true, "dc=change"},
+        // testNG does not like null argument so use "" for the newSuperior
+        // instead of null
+        {"dc=test,dc=com", "dc=new", false, ""},
+        {"dc=delete,dc=an,dc=entry,dc=with,dc=a,dc=long dn",
+                   "dc=new",true, ""},
+        };
+  }
+
+  @Test(dataProvider = "modifyDnEncodeDecode")
+  public void modifyDnEncodeDecode(String rawDN, String newRdn,
+                                   boolean deleteOldRdn, String newSuperior)
+         throws Exception
+  {
+    InternalClientConnection connection = new InternalClientConnection();
+    ModifyDNOperation op =
+      new ModifyDNOperation(connection, 1, 1, null,
+                  DN.decode(rawDN), RDN.decode(newRdn), deleteOldRdn,
+                  (newSuperior.length() != 0 ? DN.decode(newSuperior) : null));
+
+    ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+                                      (short) 123, (short) 45);
+    op.setAttachment(SYNCHRONIZATION, cn);
+    ModifyDNMsg msg = new ModifyDNMsg(op);
+    ModifyDNMsg generatedMsg = new ModifyDNMsg(msg.getBytes());
+    Operation generatedOperation = generatedMsg.createOperation(connection);
+    ModifyDNOperation mod2 = (ModifyDNOperation) generatedOperation;
+
+    assertEquals(msg.changeNumber, generatedMsg.changeNumber);
+    assertEquals(op.getRawEntryDN(), mod2.getRawEntryDN());
+    assertEquals(op.getRawNewRDN(), mod2.getRawNewRDN());
+    assertEquals(op.deleteOldRDN(), mod2.deleteOldRDN());
+    assertEquals(op.getRawNewSuperior(), mod2.getRawNewSuperior());
+  }
+
+  @DataProvider(name = "addEncodeDecode")
+  public Object[][] createAddData() {
+    return new Object[][] {
+        {"dc=test,dc=com"},
+        };
+  }
+  
+  @Test(dataProvider = "addEncodeDecode")
+  public void addEncodeDecode(String rawDN)
+         throws Exception
+  {
+    LinkedHashSet<AttributeValue> ocValues =
+      new LinkedHashSet<AttributeValue>();
+    ocValues.add(
+        new AttributeValue(DirectoryServer.getObjectClassAttributeType(),
+        "organization"));
+    Attribute objectClass =
+      new Attribute(DirectoryServer.getObjectClassAttributeType(),
+        "objectClass", ocValues);
+
+    AttributeType org = DirectoryServer.getAttributeType("o", true);
+    ArrayList<Attribute> userAttributes = new ArrayList<Attribute>(1);
+    LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
+    values.add(new AttributeValue(org, "com"));
+    Attribute attr = new Attribute(org, "o", values);
+    userAttributes.add(attr);
+
+    ArrayList<Attribute> operationalAttributes = new ArrayList<Attribute>(1);
+    org = DirectoryServer.getAttributeType("creatorsname", true);
+    values = new LinkedHashSet<AttributeValue>();
+    values.add(new AttributeValue(org, "dc=creator"));
+    attr = new Attribute(org, "creatorsname", values);
+    operationalAttributes.add(attr);
+
+    ChangeNumber cn = new ChangeNumber(TimeThread.getTime(),
+                                      (short) 123, (short) 45);
+
+    AddMsg msg = new AddMsg(cn, rawDN, objectClass, userAttributes,
+                            operationalAttributes);
+    AddMsg generatedMsg = new AddMsg(msg.getBytes());
+    assertEquals(msg.getBytes(), generatedMsg.getBytes());
+    // TODO : should test that generated attributes match original attributes.
+  }
+}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
new file mode 100644
index 0000000..75e1dc5
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
@@ -0,0 +1,37 @@
+/*
+ * 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.synchronization;
+
+import org.opends.server.DirectoryServerTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * An abstract class that all sycnhronization unit test should extend. 
+ */
+@Test(groups = { "precommit", "synchronization" })
+public abstract class SynchronizationTestCase extends DirectoryServerTestCase
+{}

--
Gitblit v1.10.0