opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ModifyConflictTest.java
@@ -31,18 +31,17 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.UUID; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static org.testng.Assert.*; import static org.opends.server.synchronization.OperationContext.*; import org.opends.server.SchemaFixture; import org.opends.server.core.AddOperation; import org.opends.server.core.DirectoryServer; import org.opends.server.core.ModifyOperation; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; @@ -54,45 +53,73 @@ import org.opends.server.types.ObjectClass; /* * 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 * Test the conflict resolution for modify operations As a consequence, * this will also test the Historical.java Class 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 public class ModifyConflictTest extends SynchronizationTestCase { /** * Test that conflict between a modify-replace and modify-add * for multi-valued attributes are handled correctly. * Test that conflict between a modify-replace and modify-add for * multi-valued attributes@DataProvider(name = "ackMsg") are handled * correctly. */ @Test() public void replaceAndAdd() throws Exception 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); // Construct a new random UUID. and add it into the entry UUID uuid = UUID.randomUUID(); // Create the att values list of uuid LinkedHashSet<AttributeValue> valuesUuid = new LinkedHashSet<AttributeValue>( 1); valuesUuid.add(new AttributeValue(Historical.entryuuidAttrType, new ASN1OctetString(uuid.toString()))); ArrayList<Attribute> uuidList = new ArrayList<Attribute>(1); Attribute uuidAttr = new Attribute(Historical.entryuuidAttrType, "entryUUID", valuesUuid); uuidList.add(uuidAttr); /* * Add the uuid in the entry */ Map<AttributeType, List<Attribute>> operationalAttributes = entry .getOperationalAttributes(); operationalAttributes.put(Historical.entryuuidAttrType, uuidList); // Create the att values list of historicalAttr String stringVal = "ds-sync-hist:00000108b3a6cbb800000001:repl:00000108b3a6cbb800000002"; AttributeValue val = new AttributeValue(Historical.historicalAttrType, stringVal); LinkedHashSet<AttributeValue> valuesHist = new LinkedHashSet<AttributeValue>(1); valuesHist.add(val); ArrayList<Attribute> histList = new ArrayList<Attribute>(1); Attribute histAttr = new Attribute(Historical.historicalAttrType, "ds-sync-hist", valuesHist); histList.add(histAttr); //Add the historical att in the entry operationalAttributes.put(Historical.historicalAttrType,histList) ; // load historical from the entry Historical hist = Historical.load(entry); /* @@ -110,33 +137,122 @@ /* * Now simulate an add at an earlier date that the previous replace * conflict resolution should remove it. * (a second time to make sure...) * conflict resolution should remove it. (a second time to make * sure...) */ testModify(entry, hist, "description", ModificationType.ADD, "older value", 2, false); "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); testModify(entry, hist, "description", ModificationType.ADD, "new value", 11, true); } /* * helper function. */ private void testHistoricalAndFake( Historical hist, Entry entry) { // Get the historical uuid associated to the entry // (the one that needs to be tested) String uuid = hist.getEntryUuid(entry); // Get the Entry uuid in String format List<Attribute> uuidAttrs = entry .getOperationalAttribute(Historical.entryuuidAttrType); uuidAttrs.get(0).getValues().iterator().next().toString(); if (uuidAttrs != null) { if (uuidAttrs.size() > 0) { Attribute att = uuidAttrs.get(0); String retrievedUuid = (att.getValues().iterator().next()).toString(); assertTrue(retrievedUuid.equals(uuid)); } } try { Historical dup = hist.duplicate(); // TODO Check values } catch (RuntimeException e) { assertTrue(false) ; } // Test FakeOperation try { Iterable<FakeOperation> fks = Historical.generateFakeOperations(entry); if (fks.iterator().hasNext()) { FakeOperation fk = fks.iterator().next(); assertTrue(new FakeOperationComparator().compare(fk, fk) == 0); assertTrue(new FakeOperationComparator().compare(null , fk) < 0); SynchronizationMessage generatedMsg = fk.generateMessage() ; if (generatedMsg instanceof UpdateMessage) { UpdateMessage new_name = (UpdateMessage) generatedMsg; assertEquals(new_name.getUniqueId(),uuid); } } } catch (RuntimeException e) { assertTrue(false) ; } } /* * helper function. */ private void testHistorical( Historical hist, AddOperation addOp) { // Get the historical uuid associated to the entry // (the one that needs to be tested) String uuid = hist.getEntryUuid(addOp); // Get the op uuid in String format List<Attribute> uuidAttrs = addOp.getOperationalAttributes().get( Historical.entryuuidAttrType); uuidAttrs.get(0).getValues().iterator().next().toString(); if (uuidAttrs != null) { if (uuidAttrs.size() > 0) { Attribute att = uuidAttrs.get(0); String retrievedUuid = (att.getValues().iterator().next()).toString(); assertTrue(retrievedUuid.equals(uuid)); } } } /** * Test that conflict between a modify-delete-attribute and modify-add * for multi-valued attributes are handled correctly. */ @Test() public void deleteAndAdd() throws Exception 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. * 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>(); @@ -147,25 +263,66 @@ * start with a new entry with an empty description */ Entry entry = new Entry(dn, objectClasses, null, null); // Construct a new random UUID. and add it into the entry UUID uuid = UUID.randomUUID(); // Create the att values list LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>( 1); values.add(new AttributeValue(Historical.entryuuidAttrType, new ASN1OctetString(uuid.toString()))); ArrayList<Attribute> uuidList = new ArrayList<Attribute>(1); Attribute uuidAttr = new Attribute(Historical.entryuuidAttrType, "entryUUID", values); uuidList.add(uuidAttr); /* * Add the uuid in the entry */ Map<AttributeType, List<Attribute>> operationalAttributes = entry .getOperationalAttributes(); operationalAttributes.put(Historical.entryuuidAttrType, uuidList); // Create the att values list of historicalAttr String stringVal = "ds-sync-hist:00000108b3a6cbb800000001:del:00000108b3a6cbb800000002"; AttributeValue val = new AttributeValue(Historical.historicalAttrType, stringVal); LinkedHashSet<AttributeValue> valuesHist = new LinkedHashSet<AttributeValue>(1); valuesHist.add(val); ArrayList<Attribute> histList = new ArrayList<Attribute>(1); Attribute histAttr = new Attribute(Historical.historicalAttrType, "ds-sync-hist", valuesHist); //Add the historical att in the entry entry.putAttribute(Historical.historicalAttrType,histList) ; // load historical from the entry Historical hist = Historical.load(entry); /* * simulate a delete of the whole description attribute done at time t10 * simulate a delete of the whole description attribute done at time * t10 */ testModify(entry, hist, "description", ModificationType.DELETE, null, 10, true); 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. * 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...) * 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); @@ -174,23 +331,22 @@ * 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); 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 that conflict between a modify-add and modify-add for * multi-valued attributes are handled correctly. */ @Test() public void addAndAdd() throws Exception 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. * 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>(); @@ -201,6 +357,46 @@ * start with a new entry with an empty description */ Entry entry = new Entry(dn, objectClasses, null, null); // Construct a new random UUID. and add it into the entry UUID uuid = UUID.randomUUID(); // Create the att values list LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>( 1); values.add(new AttributeValue(Historical.entryuuidAttrType, new ASN1OctetString(uuid.toString()))); ArrayList<Attribute> uuidList = new ArrayList<Attribute>(1); Attribute uuidAttr = new Attribute(Historical.entryuuidAttrType, "entryUUID", values); uuidList.add(uuidAttr); /* * Add the uuid in the entry */ Map<AttributeType, List<Attribute>> operationalAttributes = entry .getOperationalAttributes(); operationalAttributes.put(Historical.entryuuidAttrType, uuidList); // Create the att values list of historicalAttr String stringVal = "ds-sync-hist:00000108b3a6cbb800000001:add:00000108b3a6cbb800000002"; AttributeValue val = new AttributeValue(Historical.historicalAttrType, stringVal); LinkedHashSet<AttributeValue> valuesHist = new LinkedHashSet<AttributeValue>(1); valuesHist.add(val); ArrayList<Attribute> histList = new ArrayList<Attribute>(1); Attribute histAttr = new Attribute(Historical.historicalAttrType, "ds-sync-hist", valuesHist); histList.add(histAttr); //Add the historycal att in the entry entry.putAttribute(Historical.historicalAttrType,histList) ; // load historical from the entry Historical hist = Historical.load(entry); /* @@ -208,34 +404,33 @@ */ 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. * 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...) * 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 * 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); testModify(entry, hist, "description", ModificationType.ADD, "new value", 11, true); } /* * helper function. */ private static void testModify(Entry entry, private void testModify(Entry entry, Historical hist, String attrName, ModificationType modType, String value, int date, boolean keepChangeResult) @@ -261,10 +456,20 @@ modOp.setAttachment(SYNCHROCONTEXT, ctx); hist.replayOperation(modOp, entry); if (modType.intValue() == ModificationType.ADD.intValue()) { AddOperation addOp = new AddOperation(connection, 1, 1, null, entry .getDN(), entry.getObjectClasses(), entry.getUserAttributes(), entry.getOperationalAttributes()); testHistorical(hist, addOp); } else { testHistoricalAndFake(hist, entry); } /* * The last older change should have been detected as conflicting * and should be removed by the conflict resolution code. * The last older change should have been detected as conflicting and * should be removed by the conflict resolution code. */ if (keepChangeResult) { @@ -277,27 +482,4 @@ assertEquals(0, mods.size()); } } /** * Set up the environment for performing the tests in this suite. * * @throws Exception * If the environment could not be set up. */ @BeforeClass public void setUp() throws Exception { // This test suite depends on having the schema available. SchemaFixture.FACTORY.setUp(); } /** * Tears down the environment for performing the tests in this suite. * * @throws Exception * If the environment could not be finalized. */ @AfterClass public void tearDown() throws Exception { SchemaFixture.FACTORY.tearDown(); } } opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ServerStateTest.java
New file @@ -0,0 +1,134 @@ /* * 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.Set; import java.util.Map; import java.util.zip.DataFormatException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; import org.opends.server.api.ClientConnection; import org.opends.server.core.AddOperation; 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.protocols.ldap.LDAPAttribute; 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.Control; import org.opends.server.types.DN; import org.opends.server.types.Modification; import org.opends.server.types.ModificationType; import org.opends.server.types.ObjectClass; import org.opends.server.types.RDN; import org.opends.server.util.TimeThread; import static org.opends.server.synchronization.OperationContext.*; /** * Test the ServerState */ public class ServerStateTest extends SynchronizationTestCase { /** * Create ChangeNumber Data */ @DataProvider(name = "changeNumberData") public Object[][] createChangeNumberData() { return new Object[][] { {new ChangeNumber(1, (short) 0, (short) 1)}, {new ChangeNumber(TimeThread.getTime(), (short) 123, (short) 45)} }; } /** * Create a new ServerState object */ @Test(dataProvider = "changeNumberData") public void serverStateTest(ChangeNumber cn) throws Exception { // Check constructor DN dn = DN.decode("cn=com"); ServerState serverState = new ServerState(dn) ; // Check Load // serverState.loadState() ; // TODO Check result // Check getServerStateDn() DN returned_DN = serverState.getServerStateDn(); // TODO Check the returned DN // Check update assertFalse(serverState.update(null)); assertTrue(serverState.update(cn)); assertFalse(serverState.update(cn)); ChangeNumber cn1, cn2, cn3; cn1 = new ChangeNumber(cn.getTime()+1,cn.getSeqnum(),cn.getServerId()); cn2 = new ChangeNumber(cn1.getTime(),cn1.getSeqnum()+1,cn1.getServerId()); cn3 = new ChangeNumber(cn2.getTime(),cn2.getSeqnum(),(short)(cn2.getServerId()+1)); assertTrue(serverState.update(cn1)) ; assertTrue(serverState.update(cn2)) ; assertTrue(serverState.update(cn3)) ; // Check toStringSet ChangeNumber[] cns = {cn2,cn3}; Set<String> stringSet = serverState.toStringSet(); assertEquals(cns.length, stringSet.size()); // TODO Check the value // Check getMaxChangeNumber assertEquals(cn2.compareTo(serverState.getMaxChangeNumber(cn2.getServerId())),0); assertEquals(cn3.compareTo(serverState.getMaxChangeNumber(cn3.getServerId())),0); // Check the toString String stringRep = serverState.toString() ; // TODO Check the value // Check getBytes byte[] b = serverState.getBytes(); ServerState generatedServerState = new ServerState(b,0,b.length -1) ; assertEquals(b, generatedServerState.getBytes()) ; } } opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SyncMessagesTest.java
New file @@ -0,0 +1,63 @@ /* * 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.lang.reflect.Field; import org.opends.server.messages.MessageHandler; import org.testng.annotations.Test; import static org.testng.Assert.*; /** * Test of ValueInfo */ public class SyncMessagesTest extends SynchronizationTestCase { /** * Create a ValueInfo and check the methods */ @Test() public void synchroMessagesTest() throws Exception { SynchMessages.registerMessages() ; Field fields[] = SynchMessages.class.getFields() ; SynchMessages synMsg = new SynchMessages() ; for (Field f : fields) { if (f.getClass().equals(Integer.class)) { // Get the id String msg = MessageHandler.getMessage(f.getInt(synMsg)); assertFalse(msg.startsWith("Unknown message for message ID")); } } } } opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationMsgTest.java
@@ -27,6 +27,7 @@ package org.opends.server.synchronization; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.zip.DataFormatException; @@ -35,6 +36,8 @@ import org.testng.annotations.Test; import static org.testng.Assert.*; import org.opends.server.api.ClientConnection; import org.opends.server.core.AddOperation; import org.opends.server.core.DeleteOperation; import org.opends.server.core.DirectoryException; import org.opends.server.core.DirectoryServer; @@ -49,6 +52,7 @@ import org.opends.server.types.DN; import org.opends.server.types.Modification; import org.opends.server.types.ModificationType; import org.opends.server.types.ObjectClass; import org.opends.server.types.RDN; import org.opends.server.util.TimeThread; @@ -132,7 +136,9 @@ DN dn = DN.decode(rawdn); InternalClientConnection connection = new InternalClientConnection(); ModifyMsg msg = new ModifyMsg(changeNumber, dn, mods, "fakeuniqueid"); ModifyMsg generatedMsg = new ModifyMsg(msg.getBytes()); ModifyMsg generatedMsg = (ModifyMsg) SynchronizationMessage .generateMsg(msg.getBytes()); assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber()); @@ -148,10 +154,57 @@ assertEquals(mod1.getRawEntryDN(), mod2.getRawEntryDN()); assertEquals( mod1.getAttachment(SYNCHROCONTEXT), mod2.getAttachment(SYNCHROCONTEXT)); /* * TODO : test that the generated mod equals the original mod. */ // Check pending change testPendingChange(changeNumber,op,msg); } /** * Create a Update Message 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 updateMsgTest(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, "fakeuniqueid");; // Check uuid assertEquals("fakeuniqueid", msg.getUniqueId()); // Check isAssured assertFalse(msg.isAssured()); msg.setAssured(); assertTrue(msg.isAssured()); // Check equals ModifyMsg generatedMsg = (ModifyMsg) SynchronizationMessage .generateMsg(msg.getBytes()); assertFalse(msg.equals(null)); assertFalse(msg.equals(new Object())); assertTrue(msg.equals(generatedMsg)); // Check hashCode assertEquals(msg.hashCode(), generatedMsg.hashCode()); // Check compareTo assertEquals(msg.compareTo(generatedMsg), 0); // Check Get / Set DN assertTrue(dn.equals(DN.decode(msg.getDn()))); String fakeDN = "cn=fake cn"; msg.setDn(fakeDN) ; assertEquals(msg.getDn(), fakeDN) ; } /** @@ -183,7 +236,10 @@ (short) 123, (short) 45); op.setAttachment(SYNCHROCONTEXT, new DeleteContext(cn, "uniqueid")); DeleteMsg msg = new DeleteMsg(op); DeleteMsg generatedMsg = new DeleteMsg(msg.getBytes()); DeleteMsg generatedMsg = (DeleteMsg) SynchronizationMessage .generateMsg(msg.getBytes()); assertEquals(msg.toString(), generatedMsg.toString()); assertEquals(msg.getChangeNumber(), generatedMsg.getChangeNumber()); @@ -194,6 +250,10 @@ DeleteOperation mod2 = (DeleteOperation) generatedOperation; assertEquals(op.getRawEntryDN(), mod2.getRawEntryDN()); // Create an update message from this op DeleteMsg updateMsg = (DeleteMsg) UpdateMessage.generateMsg(op, true); assertEquals(msg.getChangeNumber(), updateMsg.getChangeNumber()); } @DataProvider(name = "modifyDnEncodeDecode") @@ -225,7 +285,8 @@ op.setAttachment(SYNCHROCONTEXT, new ModifyDnContext(cn, "uniqueid", "newparentId")); ModifyDNMsg msg = new ModifyDNMsg(op); ModifyDNMsg generatedMsg = new ModifyDNMsg(msg.getBytes()); ModifyDNMsg generatedMsg = (ModifyDNMsg) SynchronizationMessage .generateMsg(msg.getBytes()); Operation generatedOperation = generatedMsg.createOperation(connection); ModifyDNOperation mod2 = (ModifyDNOperation) generatedOperation; @@ -234,6 +295,10 @@ assertEquals(op.getRawNewRDN(), mod2.getRawNewRDN()); assertEquals(op.deleteOldRDN(), mod2.deleteOldRDN()); assertEquals(op.getRawNewSuperior(), mod2.getRawNewSuperior()); // Create an update message from this op ModifyDNMsg updateMsg = (ModifyDNMsg) UpdateMessage.generateMsg(op, true); assertEquals(msg.getChangeNumber(), updateMsg.getChangeNumber()); } @DataProvider(name = "addEncodeDecode") @@ -255,6 +320,10 @@ Attribute objectClass = new Attribute(DirectoryServer.getObjectClassAttributeType(), "objectClass", ocValues); HashMap<ObjectClass,String> objectClassList= new HashMap<ObjectClass,String>(); objectClassList.put(DirectoryServer.getObjectClass("organization"), "organization"); AttributeType org = DirectoryServer.getAttributeType("o", true); ArrayList<Attribute> userAttributes = new ArrayList<Attribute>(1); @@ -262,6 +331,10 @@ values.add(new AttributeValue(org, "com")); Attribute attr = new Attribute(org, "o", values); userAttributes.add(attr); HashMap<AttributeType,List<Attribute>> userAttList= new HashMap<AttributeType,List<Attribute>>(); userAttList.put(org,userAttributes); ArrayList<Attribute> operationalAttributes = new ArrayList<Attribute>(1); org = DirectoryServer.getAttributeType("creatorsname", true); @@ -269,6 +342,9 @@ values.add(new AttributeValue(org, "dc=creator")); attr = new Attribute(org, "creatorsname", values); operationalAttributes.add(attr); HashMap<AttributeType,List<Attribute>> opList= new HashMap<AttributeType,List<Attribute>>(); opList.put(org,operationalAttributes); ChangeNumber cn = new ChangeNumber(TimeThread.getTime(), (short) 123, (short) 45); @@ -276,9 +352,42 @@ AddMsg msg = new AddMsg(cn, rawDN, "thisIsaUniqueID", "parentUniqueId", objectClass, userAttributes, operationalAttributes); AddMsg generatedMsg = new AddMsg(msg.getBytes()); AddMsg generatedMsg = (AddMsg) SynchronizationMessage.generateMsg(msg .getBytes()); assertEquals(msg.getBytes(), generatedMsg.getBytes()); assertEquals(msg.toString(), generatedMsg.toString()); // TODO : should test that generated attributes match original attributes. // Create an new Add Operation from the current addMsg InternalClientConnection connection = new InternalClientConnection(); AddOperation addOp = msg.createOperation(connection, rawDN) ; // TODO : should test that generated attributes match original attributes. // List<LDAPAttribute> rawAtt = addOp.getRawAttributes(); assertEquals(msg.getBytes(), generatedMsg.getBytes()); assertEquals(msg.toString(), generatedMsg.toString()); //Create an Add operation and generate and Add msg from it DN dn = DN.decode(rawDN); addOp = new AddOperation((ClientConnection) connection, (long) 1, 1, null, dn, objectClassList, userAttList, opList); OperationContext opCtx = new AddContext(cn, "thisIsaUniqueID", "parentUniqueId"); addOp.setAttachment(SYNCHROCONTEXT, opCtx); generatedMsg = new AddMsg(addOp); assertEquals(msg.getBytes(), generatedMsg.getBytes()); assertEquals(msg.toString(), generatedMsg.toString()); // TODO : should test that generated attributes match original attributes. // Create an update message from this op AddMsg updateMsg = (AddMsg) UpdateMessage.generateMsg(addOp, true); assertEquals(msg.getChangeNumber(), updateMsg.getChangeNumber()); } /** @@ -328,6 +437,37 @@ } // Check that retrieved CN is OK msg2 = new AckMessage(msg1.getBytes()); msg2 = (AckMessage) SynchronizationMessage.generateMsg(msg1.getBytes()); } /** * Test PendingChange */ private void testPendingChange(ChangeNumber cn, Operation op, SynchronizationMessage msg) { if (! (msg instanceof UpdateMessage)) { return ; } UpdateMessage updateMsg = (UpdateMessage) msg; PendingChange pendingChange = new PendingChange(cn,null,null); pendingChange.setCommitted(false); assertFalse(pendingChange.isCommitted()) ; pendingChange.setCommitted(true); assertTrue(pendingChange.isCommitted()) ; assertTrue(cn.compareTo(pendingChange.getChangeNumber()) == 0); assertEquals(pendingChange.getMsg(), null) ; pendingChange.setMsg(updateMsg); assertEquals(updateMsg.getBytes(), pendingChange.getMsg().getBytes()); assertEquals(pendingChange.getOp(), null) ; pendingChange.setOp(op); assertEquals(op.getClass(), op.getClass()); } } opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
@@ -27,11 +27,44 @@ package org.opends.server.synchronization; import org.opends.server.DirectoryServerTestCase; import org.opends.server.SchemaFixture; import org.testng.annotations.Test; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; /** * An abstract class that all synchronization unit test should extend. */ @Test(groups = { "precommit", "synchronization" }) public abstract class SynchronizationTestCase extends DirectoryServerTestCase {} { /** * Tears down the environment for performing the tests in this suite. * * @throws Exception * If the environment could not be finalized. */ @AfterClass public void tearDown() throws Exception { SchemaFixture.FACTORY.tearDown(); } /** * Set up the environment for performing the tests in this suite. * * @throws Exception * If the environment could not be set up. */ @BeforeClass public void setUp() throws Exception { // This test suite depends on having the schema available. SchemaFixture.FACTORY.setUp(); } }