InitOnLineTest.java revision 9aa1482c49865483f798f91ef7d16f03cc3ec811
/*
* 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 legal-notices/CDDLv1_0.txt
* 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 legal-notices/CDDLv1_0.txt.
* 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
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 ForgeRock AS
*/
/**
* Tests contained here:
*
* Initialize Test Cases <=> Pull entries
* ---------------------
* InitializeImport : Tests the import in the target DS.
* Creates a task on current DS and makes a broker simulates DS2 sending entries.
* InitializeExport : Tests the export from the source DS
* A broker simulates DS2 pulling entries from current DS.
*
* Initialize Target Test Cases <=> Push entries
* ----------------------------
* InitializeTargetExport : Tests the export from the source DS
* Creates a task on current DS and makes broker simulates DS2 receiving entries
* InitializeTargetImport : Test the import in the target DS
* A broker simulates DS2 receiving entries from current DS.
*
* InitializeTargetConfigErrors : Tests configuration errors of the
* InitializeTarget task
*/
@SuppressWarnings("javadoc")
public class InitOnLineTest extends ReplicationTestCase
{
/** The tracer object for the debug logger. */
private static final int WINDOW_SIZE = 10;
private Entry taskInitFromS2;
private Entry taskInitTargetS2;
private Entry taskInitTargetAll;
private String[] updatedEntries;
private static final int server1ID = 1;
private static final int server2ID = 2;
private static final int server3ID = 3;
private static final int replServer1ID = 8;
private static final int replServer2ID = 9;
private static final int replServer3ID = 10;
private static int[] replServerPort = new int[20];
private ReplicationBroker server2;
private ReplicationBroker server3;
private ReplicationServer replServer1;
private ReplicationServer replServer2;
private ReplicationServer replServer3;
private LDAPReplicationDomain replDomain;
private int initWindow = 100;
{
}
/**
* Set up the environment for performing the tests in this Class.
*/
{
super.setUp();
// This test suite depends on having the schema available.
// This test uses import tasks which do not work with memory backend
// (like the test backend we use in every tests): backend is disabled then
// re-enabled and this clears the backend reference and thus the underlying
// data. So for this particular test, we use a classical backend.
// For most tests, a limited number of entries is enough
// Create an internal connection in order to provide operations
// to DS to populate the db -
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + EXAMPLE_DN,
"ds-task-initialize-replica-server-id: " + server2ID);
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTargetTask",
"ds-task-initialize-domain-dn: " + EXAMPLE_DN,
"ds-task-initialize-replica-server-id: " + server2ID);
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTargetTask",
"ds-task-initialize-domain-dn: " + EXAMPLE_DN,
"ds-task-initialize-replica-server-id: all");
}
/** Tests that entries have been written in the db. */
private void testEntriesInDb() throws Exception
{
log("TestEntriesInDb");
short found = 0;
{
if (resultEntry == null)
{
}
else
{
found++;
}
}
" Entries present in DB :" + found +
}
/**
* Wait a task to be completed and check the expected state and expected
* stats.
* @param taskEntry The task to process.
* @param expectedState The expected state for this task.
* @param expectedLeft The expected number of entries still to be processed.
* @param expectedDone The expected number of entries to be processed.
*/
{
{
// Check that the task state is as expected.
"The task completed in an unexpected state");
// Check that the task contains some log messages.
{
fail("No log messages were written to the task entry on a failed task");
}
// Check that the task state is as expected.
expectedLeft, "The number of entries to process is not correct.");
// Check that the task state is as expected.
expectedDone, "The number of entries processed is not correct.");
}
}
{
// FIXME - Factorize with TasksTestCase
// Wait until the task completes.
int timeout = 2000;
do
{
if (completionTime != null)
{
return resultEntry;
}
{
}
}
while (true);
}
{
}
/**
* Add to the current DB the entries necessary to the test.
*/
private void addTestEntriesToDB() throws Exception
{
{
}
+ " successfully added to DB");
}
{
{
}
}
/**
* Creates entries necessary to the test.
*/
{
// It is relevant to test ReplLDIFInputStream
// and ReplLDIFOutputStream with big entries
char bigAttributeValue[] = new char[30240];
{
}
+ "objectClass: top\n"
+ "objectClass: domain\n"
+ "dc: example\n"
+ "entryUUID: 21111111-1111-1111-1111-111111111111\n"
+ "\n";
+ "objectClass: top\n"
+ "objectClass: organizationalUnit\n"
+ "ou: People\n"
+ "entryUUID: 21111111-1111-1111-1111-111111111112\n"
+ "\n";
for (int i=0; i<entriesCnt; i++)
{
+ "objectclass: top\n"
+ "objectclass: person\n"
+ "objectclass: organizationalPerson\n"
+ "objectclass: inetOrgPerson\n"
+ "entryUUID: 21111111-1111-1111-1111-"+useri+
+ "\n";
}
return entries;
}
/**
* Broker will send the entries to a server.
* @param broker The broker that will send the entries.
* @param senderID The serverID of this broker.
* @param destinationServerID The target server.
* @param requestorID The initiator server.
*/
{
int cnt = 0;
{
}
}
{
// Expect the broker to receive the entries
int entriesReceived = 0;
while (true)
{
{
break;
}
if (msg instanceof InitializeTargetMsg)
{
entriesReceived = 0;
}
{
}
{
break;
}
{
break;
}
else
{
}
}
sleep(500);
}
/**
* Count the number of entries in the provided byte[].
* This is based on the hypothesis that the entries are separated
* by a "\n\n" String.
*
* @param entryBytes
* @return The number of entries in the provided byte[].
*/
private int countEntryLimits(byte[] entryBytes)
{
int entryCount = 0;
int count = 0;
{
{
entryCount++;
count++;
}
count++;
}
return entryCount;
}
/**
* Creates a new replicationServer.
* @param replServerId The serverID of the replicationServer to create.
* @return The new replicationServer.
*/
{
if (replServerId != replServer1ID)
{
}
if (replServerId != replServer2ID)
{
}
if (replServerId != replServer3ID)
{
}
return replicationServer;
}
{
// suffix synchronized
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider\n"
+ "objectClass: ds-cfg-replication-domain\n"
+ "ds-cfg-replication-server: localhost:"
+ "ds-cfg-receive-status: true\n"
+ "ds-cfg-window-size: " + WINDOW_SIZE;
assertFalse(replDomain.ieRunning(), "ReplicationDomain: Import/Export is not expected to be running");
}
{
{
}
return replServerPort[replServerId];
}
/**
* Tests the import side of the Initialize task
* Test steps :
* - create a task 'InitFromS2' in S1
* - make S2 export its entries
* - test that S1 has successfully imported the entries and completed the task.
*
* TODO: Error case: make S2 crash/disconnect in the middle of the export
* and test that, on S1 side, the task ends with an error.
* State of the backend on S1 partially initialized: ?
*/
public void initializeImport() throws Exception
{
try
{
// Connect DS to the replicationServer
{
}
// In S1 launch the total update
// S2 should receive init msg
// S2 publishes entries to S1
initMsg.getSenderID());
// Wait for task (import) completion in S1
// Test import result in S1
} finally
{
}
}
/**
* Tests the export side of the Initialize task
* Test steps :
* - add entries in S1, make S2 publish InitRequest
* - test that S1 has successfully exported the entries (by receiving them
* on S2 side).
*/
public void initializeExport() throws Exception
{
try
{
// Connect DS to the replicationServer
{
}
// Signal RS we just entered the full update status
} finally
{
}
}
/**
* Tests the import side of the InitializeTarget task
* Test steps :
* - add entries in S1 and create a task 'InitTargetS2' in S1
* - wait task completed
* - test that S2 has successfully received the entries
*/
public void initializeTargetExport() throws Exception
{
try
{
// Creates config to synchronize suffix
// Add in S1 the entries to be exported
// S1 is the server we are running in, S2 is simulated by a broker
{
}
// Launch in S1 the task that will initialize S2
// Signal RS we just entered the full update status
// Tests that entries have been received by S2
} finally
{
}
}
/**
* Tests the import side of the InitializeTarget task
* Test steps :
* - addEntries in S1, create a task 'InitAll' in S1
* - wait task completed on S1
* - test that S2 and S3 have successfully imported the entries.
*
* TODO: Error case: make S1 crash in the middle of the export and test that
* the task ends with an error. State of the backend on both S2 and S3: ?
*
* TODO: Error case: make S2 crash in the middle of the import and test what??
*/
public void initializeTargetExportAll() throws Exception
{
try
{
// Creates config to synchronize suffix
// Add in S1 the entries to be exported
// S1 is the server we are running in, S2 and S3 are simulated by brokers
{
}
{
}
// Launch in S1 the task that will initialize S2
// Tests that entries have been received by S2
// Signal RS we just entered the full update status
} finally
{
}
}
/**
* Tests the import side of the InitializeTarget task.
*/
public void initializeTargetImport() throws Exception
{
try
{
// S1 is the server we are running in, S2 is simulated by a broker
{
}
// Creates config to synchronize suffix
// S2 publishes entries to S1
// wait until the replication domain has expected generationID
// this should indicate that the import occurred correctly.
final long EXPECTED_GENERATION_ID = 52955L;
long readGenerationId = -1L;
{
{
break;
}
}
testCase + " Import success waited longer than expected");
// Test that entries have been imported in S1
} finally
{
}
}
/**
* Tests the import side of the InitializeTarget task.
*/
public void initializeTargetConfigErrors() throws Exception
{
try
{
// Invalid domain base dn
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTargetTask",
"ds-task-initialize-domain-dn: foo",
"ds-task-initialize-remote-replica-server-id: " + server2ID);
// Domain base dn not related to any domain
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTargetTask",
"ds-task-initialize-domain-dn: dc=foo",
"ds-task-initialize-remote-replica-server-id: " + server2ID);
// Invalid scope
// createTask(taskInitTargetS2);
// Scope containing a serverID absent from the domain
// createTask(taskInitTargetS2);
} finally
{
}
}
/**
* Tests the import side of the InitializeTarget task.
*/
public void initializeConfigErrors() throws Exception
{
try
{
// Creates config to synchronize suffix
// Invalid domain base dn
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: dc=foo",
"ds-task-initialize-replica-server-id: " + server2ID);
// Domain base dn not related to any domain
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: dc=foo",
"ds-task-initialize-replica-server-id: " + server2ID);
// Invalid Source
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: -3");
// Scope containing a serverID absent from the domain
// createTask(taskInitTargetS2);
} finally
{
}
}
public void initializeTargetBroken() throws Exception
{
}
public void initializeBroken() throws Exception
{
}
/**
* TestReplServerInfos tests that in a topology with more than one replication
* server, in each replication server is stored the list of LDAP servers
* connected to each replication server of the topology, thanks to the
* ReplServerInfoMessage(s) exchanged by the replication servers.
*/
public void testReplServerInfos() throws Exception
{
try
{
// Connects lDAP1 to replServer1
// Connects lDAP2 to replServer2
// Connects lDAP3 to replServer2
// Check that the list of connected LDAP servers is correct in each replication servers
// Test updates
// TODO Test ReplicationServerDomain.getDestinationServers method.
} finally
{
}
}
{
}
public void initializeTargetExportMultiSS() throws Exception
{
try
{
// Creates config to synchronize suffix
// Add in S1 the entries to be exported
// S1 is the server we are running in, S2 is simulated by a broker
// connected to replServer2
{
}
// Launch in S1 the task that will initialize S2
// Signal RS we just entered the full update status
// Tests that entries have been received by S2
}
finally
{
}
}
{
do
{
}
while (!(msgrcv instanceof InitializeTargetMsg));
}
public void initializeExportMultiSS() throws Exception
{
try
{
// Connect DS to the replicationServer 1
// Put entries in DB
// Connect a broker acting as server 2 to Repl Server 2
{
}
// Connect a broker acting as server 3 to Repl Server 3
{
}
// S3 sends init request
// S3 should receive target, entries & done
// Signal RS we just entered the full update status
}
finally
{
}
}
public void initializeNoSource() throws Exception
{
try
{
// Creates config to synchronize suffix
// Test 1
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: " + 20);
// Test 2
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: " + server1ID);
if (replDomain != null)
{
assertFalse(replDomain.ieRunning(), "ReplicationDomain: Import/Export is not expected to be running");
}
} finally
{
}
}
public void initializeTargetNoTarget() throws Exception
{
try
{
// Creates config to synchronize suffix
// Put entries in DB
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTargetTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: " + 0);
if (replDomain != null)
{
assertFalse(replDomain.ieRunning(), "ReplicationDomain: Import/Export is not expected to be running");
}
} finally
{
}
}
public void initializeStopped() throws Exception
{
}
public void initializeTargetStopped() throws Exception
{
}
public void initializeCompressed() throws Exception
{
}
public void initializeTargetEncrypted() throws Exception
{
}
public void initializeSimultaneous() throws Exception
{
try
{
// Connect a broker acting as server 2 to replServer2
{
}
// Creates config to synchronize suffix
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: " + server2ID);
",cn=Scheduled Tasks,cn=Tasks",
"objectclass: top",
"objectclass: ds-task",
"objectclass: ds-task-initialize-from-remote-replica",
"ds-task-class-name: org.opends.server.tasks.InitializeTask",
"ds-task-initialize-domain-dn: " + baseDN,
"ds-task-initialize-replica-server-id: " + server2ID);
// Second task is expected to be rejected
// First task is still running
// External request is supposed to be rejected
// Now tests error in the middle of an import
// S2 sends init request
} finally
{
}
}
/**
* Disconnect broker and remove entries from the local DB
* @param testCase The name of the test case.
*/
{
if (replDomain != null)
{
// race condition could cause the main thread to reach
// this code before the task is fully completed.
// in those cases, loop for a while waiting for completion.
for (int i = 0; i< 10; i++)
{
if (!replDomain.ieRunning())
{
break;
}
sleep(500);
}
assertFalse(replDomain.ieRunning(), "ReplicationDomain: Import/Export is not expected to be running");
}
// Remove domain config
super.cleanConfigEntries();
replDomain = null;
// do not try to remove non-leaves
super.cleanRealEntries();
}
/**
* Clean up the environment.
*/
public void classCleanUp() throws Exception
{
callParanoiaCheck = false;
super.classCleanUp();
}
}