/* * 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 2013-2015 ForgeRock AS */ package org.opends.server.replication.server.changelog.file; import static org.forgerock.util.Pair.*; import static org.testng.Assert.*; import org.forgerock.util.Pair; import org.opends.server.DirectoryServerTestCase; import org.opends.server.replication.protocol.UpdateMsg; import org.opends.server.replication.server.changelog.api.ChangelogException; import org.opends.server.replication.server.changelog.api.DBCursor; import org.opends.server.replication.server.changelog.file.CompositeDBCursor; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @SuppressWarnings({ "javadoc", "unchecked" }) public class CompositeDBCursorTest extends DirectoryServerTestCase { private final class ConcreteCompositeDBCursor extends CompositeDBCursor<String> { @Override protected void incorporateNewCursors() throws ChangelogException { } } private UpdateMsg msg1; private UpdateMsg msg2; private UpdateMsg msg3; private UpdateMsg msg4; private UpdateMsg msg5; private UpdateMsg msg6; private String baseDN1 = "dc=forgerock,dc=com"; private String baseDN2 = "dc=example,dc=com"; @BeforeClass public void setupMsgs() { msg1 = new FakeUpdateMsg(1); msg2 = new FakeUpdateMsg(2); msg3 = new FakeUpdateMsg(3); msg4 = new FakeUpdateMsg(4); msg5 = new FakeUpdateMsg(5); msg6 = new FakeUpdateMsg(6); } @Test public void emptyCursor() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor(of(new SequentialDBCursor(), baseDN1)); assertInOrder(compCursor); } @Test public void oneElementCursor() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor(of(new SequentialDBCursor(msg1), baseDN1)); assertInOrder(compCursor, of(msg1, baseDN1)); } @Test public void twoElementsCursor() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor(of(new SequentialDBCursor(msg1, msg2), baseDN1)); assertInOrder(compCursor, of(msg1, baseDN1), of(msg2, baseDN1)); } @Test public void threeElementsCursor() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor(of(new SequentialDBCursor(msg1, msg2, msg3), baseDN1)); assertInOrder(compCursor, of(msg1, baseDN1), of(msg2, baseDN1), of(msg3, baseDN1)); } @Test public void twoEmptyCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(), baseDN1), of(new SequentialDBCursor(), baseDN2)); assertInOrder(compCursor); } @Test public void twoOneElementCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2), baseDN1), of(new SequentialDBCursor(msg1), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1)); } @Test public void twoTwoElementCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2, msg3), baseDN1), of(new SequentialDBCursor(msg1, msg4), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1), of(msg3, baseDN1), of(msg4, baseDN2)); } @Test public void twoThreeElementCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2, msg3, msg6), baseDN1), of(new SequentialDBCursor(msg1, msg4, msg5), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1), of(msg3, baseDN1), of(msg4, baseDN2), of(msg5, baseDN2), of(msg6, baseDN1)); } @Test public void recycleTwoElementsCursor() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg1, null, msg2), baseDN1)); assertNextRecord(compCursor, of(msg1, baseDN1)); assertFalse(compCursor.next()); assertNextRecord(compCursor, of(msg2, baseDN1)); } @Test public void recycleTwoElementsCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2, null, msg4), baseDN1), of(new SequentialDBCursor(null, msg1, msg3), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1), of(msg3, baseDN2), of(msg4, baseDN1)); } @Test public void recycleTwoElementsCursorsLongerExhaustion() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(null, null, msg1), baseDN1), of(new SequentialDBCursor(msg2, msg3, msg4), baseDN2)); assertInOrder(compCursor, of(msg2, baseDN2), of(msg1, baseDN1), of(msg3, baseDN2), of(msg4, baseDN2)); } @Test public void recycleThreeElementsCursors() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2, msg3, null, msg6), baseDN1), of(new SequentialDBCursor(null, msg1, null, msg4, msg5), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1), of(msg3, baseDN1), of(msg4, baseDN2), of(msg5, baseDN2), of(msg6, baseDN1)); } @Test public void recycleThreeElementsCursorsLongerExhaustion() throws Exception { final CompositeDBCursor<String> compCursor = newCompositeDBCursor( of(new SequentialDBCursor(msg2, msg3, null, msg6), baseDN1), of(new SequentialDBCursor(null, msg1, null, null, msg4, msg5), baseDN2)); assertInOrder(compCursor, of(msg1, baseDN2), of(msg2, baseDN1), of(msg3, baseDN1), of(msg4, baseDN2), of(msg5, baseDN2), of(msg6, baseDN1)); } private CompositeDBCursor<String> newCompositeDBCursor( Pair<? extends DBCursor<UpdateMsg>, String>... pairs) throws Exception { final CompositeDBCursor<String> cursor = new ConcreteCompositeDBCursor(); for (Pair<? extends DBCursor<UpdateMsg>, String> pair : pairs) { cursor.addCursor(pair.getFirst(), pair.getSecond()); } return cursor; } private void assertInOrder(final CompositeDBCursor<String> compCursor, Pair<UpdateMsg, String>... expecteds) throws ChangelogException { for (int i = 0; i < expecteds.length ; i++) { final Pair<UpdateMsg, String> expected = expecteds[i]; final String index = " at element i=" + i; assertTrue(compCursor.next(), index); assertSame(compCursor.getRecord(), expected.getFirst(), index); assertSame(compCursor.getData(), expected.getSecond(), index); } assertFalse(compCursor.next()); assertNull(compCursor.getRecord()); assertNull(compCursor.getData()); compCursor.close(); } private void assertNextRecord(final CompositeDBCursor<String> compCursor, Pair<UpdateMsg, String> expected) throws ChangelogException { assertTrue(compCursor.next()); assertSame(compCursor.getRecord(), expected.getFirst()); assertSame(compCursor.getData(), expected.getSecond()); } }