/*
* 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
* or http://forgerock.org/license/CDDLv1.0.html.
* 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 2014-2015 ForgeRock AS
*/
package org.opends.server.replication.server.changelog.file;
import java.util.HashSet;
import java.util.Set;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
import org.opends.server.replication.common.ServerState;
import org.opends.server.replication.protocol.UpdateMsg;
import org.opends.server.replication.server.changelog.api.ChangelogException;
import org.opends.server.replication.server.changelog.api.ReplicationDomainDB;
import org.opends.server.replication.server.changelog.api.DBCursor.CursorOptions;
import org.opends.server.replication.server.changelog.file.ECLEnabledDomainPredicate;
import org.opends.server.replication.server.changelog.file.ECLMultiDomainDBCursor;
import org.opends.server.replication.server.changelog.file.MultiDomainDBCursor;
import org.opends.server.types.DN;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.opends.server.replication.server.changelog.api.DBCursor.KeyMatchingStrategy.*;
import static org.opends.server.replication.server.changelog.api.DBCursor.PositionStrategy.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
@SuppressWarnings("javadoc")
public class ECLMultiDomainDBCursorTest extends DirectoryServerTestCase
{
@Mock
private ReplicationDomainDB domainDB;
private CursorOptions options;
private MultiDomainDBCursor multiDomainCursor;
private ECLMultiDomainDBCursor eclCursor;
private final Set<DN> eclEnabledDomains = new HashSet<>();
private ECLEnabledDomainPredicate predicate = new ECLEnabledDomainPredicate()
{
@Override
public boolean isECLEnabledDomain(DN baseDN)
{
return eclEnabledDomains.contains(baseDN);
}
};
@BeforeMethod
public void setup() throws Exception
{
TestCaseUtils.startFakeServer();
MockitoAnnotations.initMocks(this);
options = new CursorOptions(GREATER_THAN_OR_EQUAL_TO_KEY, ON_MATCHING_KEY);
multiDomainCursor = new MultiDomainDBCursor(domainDB, options);
eclCursor = new ECLMultiDomainDBCursor(predicate, multiDomainCursor);
}
@AfterMethod
public void teardown() throws Exception
{
TestCaseUtils.shutdownFakeServer();
domainDB = null;
multiDomainCursor = null;
eclCursor.close();
eclCursor = null;
eclEnabledDomains.clear();
}
@Test
public void testEmptyCursor() throws Exception
{
assertEmpty();
}
@Test
public void testECLDisabledDomainWithCursor() throws Exception
{
final DN baseDN = DN.valueOf("dc=example,dc=com");
final UpdateMsg msg1 = new FakeUpdateMsg(1);
addDomainCursorToCursor(baseDN, new SequentialDBCursor(msg1));
assertEmpty();
}
@Test
public void testECLEnabledDomainWithCursor() throws Exception
{
final DN baseDN = DN.valueOf("dc=example,dc=com");
eclEnabledDomains.add(baseDN);
final UpdateMsg msg1 = new FakeUpdateMsg(1);
addDomainCursorToCursor(baseDN, new SequentialDBCursor(msg1));
assertSingleMessage(baseDN, msg1);
}
@Test(dependsOnMethods = { "testECLEnabledDomainWithCursor", "testECLDisabledDomainWithCursor" })
public void testECLEnabledAndDisabledDomainCursors() throws Exception
{
final DN baseDN1 = DN.valueOf("dc=example,dc=com");
final DN baseDN2 = DN.valueOf("cn=admin data");
eclEnabledDomains.add(baseDN1);
final UpdateMsg msgs[] = newUpdateMsgs(13);
// At least two updates in an enabled domain
addDomainCursorToCursor(baseDN1, new SequentialDBCursor(msgs[0], msgs[3]));
addDomainCursorToCursor(baseDN2, new SequentialDBCursor(msgs[1], msgs[2]));
assertMessagesInOrder(baseDN1, msgs[0], msgs[3]);
assertEmpty();
//Only one update in an enabled domain
addDomainCursorToCursor(baseDN1, new SequentialDBCursor(msgs[4]));
addDomainCursorToCursor(baseDN2, new SequentialDBCursor(msgs[5], msgs[6]));
assertMessagesInOrder(baseDN1, msgs[4], null);
assertEmpty();
// Two disabled domains
final DN baseDN3 = DN.valueOf("dc=example,dc=net");
addDomainCursorToCursor(baseDN1, new SequentialDBCursor(msgs[7], msgs[9]));
addDomainCursorToCursor(baseDN2, new SequentialDBCursor(msgs[8], msgs[10]));
addDomainCursorToCursor(baseDN3, new SequentialDBCursor(msgs[11], msgs[12]));
assertMessagesInOrder(baseDN1, msgs[7], msgs[9]);
assertEmpty();
// Test disable/enable domain tracking
eclEnabledDomains.add(baseDN3);
assertThat(eclCursor.shouldReInitialize()).isTrue();
assertThat(eclCursor.shouldReInitialize()).isFalse();
}
private void assertEmpty() throws Exception
{
assertMessagesInOrder(null, null, null);
}
private void assertSingleMessage(DN baseDN, UpdateMsg msg1) throws Exception
{
assertMessagesInOrder(baseDN, msg1, null);
}
private UpdateMsg[] newUpdateMsgs(int num)
{
UpdateMsg[] results = new UpdateMsg[num];
for (int i = 0; i < num; i++)
{
results[i] = new FakeUpdateMsg(i + 1);
}
return results;
}
private void assertMessagesInOrder(DN baseDN, UpdateMsg msg1, UpdateMsg msg2) throws Exception
{
assertThat(eclCursor.getRecord()).isNull();
assertThat(eclCursor.getData()).isNull();
if (msg1 != null)
{
assertThat(eclCursor.next()).isTrue();
assertThat(eclCursor.getRecord()).isEqualTo(msg1);
assertThat(eclCursor.getData()).isEqualTo(baseDN);
}
if (msg2 != null)
{
assertThat(eclCursor.next()).isTrue();
assertThat(eclCursor.getRecord()).isEqualTo(msg2);
assertThat(eclCursor.getData()).isEqualTo(baseDN);
}
assertThat(eclCursor.next()).isFalse();
assertThat(eclCursor.getRecord()).isNull();
assertThat(eclCursor.getData()).isNull();
}
private void addDomainCursorToCursor(DN baseDN, SequentialDBCursor cursor) throws ChangelogException
{
final ServerState state = new ServerState();
when(domainDB.getCursorFrom(baseDN, state, options)).thenReturn(cursor);
multiDomainCursor.addDomain(baseDN, state);
}
}