LDAP-234: Rollback intermittently causes data loss
Finalized incremental attributes retrieval support. Integrated incremental attributes retrieval support in compansating transaction classes. Integration tests for Active Directory (not enabled on CI machine).
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ldap.core.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.ldap.core.support.DefaultIncrementalAttributesMapper;
|
||||
import org.springframework.ldap.core.support.RangeOption;
|
||||
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
|
||||
/**
|
||||
* IncrementalAttributesMapper Tester.
|
||||
*
|
||||
* @author Marius Scurtescu
|
||||
* @author Mattias Hellborg Arthursson
|
||||
*/
|
||||
public class DefaultIncrementalAttributesMapperTest extends TestCase {
|
||||
private DefaultIncrementalAttributesMapper tested;
|
||||
|
||||
public DefaultIncrementalAttributesMapperTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
tested = new DefaultIncrementalAttributesMapper("member");
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
tested = null;
|
||||
}
|
||||
|
||||
public void testGetAttributesArray() throws Exception {
|
||||
String[] attributes = tested.getAttributesForLookup();
|
||||
|
||||
assertEquals(1, attributes.length);
|
||||
assertEquals("member", attributes[0]);
|
||||
|
||||
tested = new DefaultIncrementalAttributesMapper(10, "member");
|
||||
|
||||
attributes = tested.getAttributesForLookup();
|
||||
|
||||
assertEquals(1, attributes.length);
|
||||
assertEquals("member;Range=0-10", attributes[0]);
|
||||
}
|
||||
|
||||
public void testGetAttributesArrayWithTwoAttributes() {
|
||||
tested = new DefaultIncrementalAttributesMapper(20, new String[]{"member", "cn"});
|
||||
String[] attributes = tested.getAttributesForLookup();
|
||||
|
||||
assertEquals(2, attributes.length);
|
||||
|
||||
assertEquals("member;Range=0-20", attributes[0]);
|
||||
assertEquals("cn;Range=0-20", attributes[1]);
|
||||
}
|
||||
|
||||
public void testLoopEmpty() throws Exception {
|
||||
assertTrue(tested.hasMore());
|
||||
|
||||
Attributes attributes = new BasicAttributes();
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertNull(tested.getValues("member"));
|
||||
}
|
||||
|
||||
public void testLoop() throws Exception {
|
||||
Attributes attributes = createAttributes("member", new RangeOption(0, 10));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(tested.hasMore());
|
||||
assertEquals(11, tested.getValues("member").size());
|
||||
|
||||
attributes = createAttributes("member", new RangeOption(11), 5);
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertEquals(16, tested.getValues("member").size());
|
||||
}
|
||||
|
||||
public void test1LoopWithPageSizeExact() throws Exception {
|
||||
tested = new DefaultIncrementalAttributesMapper(10, "member");
|
||||
|
||||
Attributes attributes = createAttributes("member", new RangeOption(0, 10));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertEquals(11, tested.getValues("member").size());
|
||||
}
|
||||
|
||||
public void test2LoopsWithPageSizeExact() throws Exception {
|
||||
tested = new DefaultIncrementalAttributesMapper(20, "member");
|
||||
|
||||
Attributes attributes = createAttributes("member", new RangeOption(0, 10));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(tested.hasMore());
|
||||
assertEquals(11, tested.getValues("member").size());
|
||||
|
||||
attributes = createAttributes("member", new RangeOption(11, 30));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertEquals(31, tested.getValues("member").size());
|
||||
}
|
||||
|
||||
public void test2LoopsWithPageSize() throws Exception {
|
||||
tested = new DefaultIncrementalAttributesMapper(20, "member");
|
||||
|
||||
Attributes attributes = createAttributes("member", new RangeOption(0, 10));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(tested.hasMore());
|
||||
assertEquals(11, tested.getValues("member").size());
|
||||
|
||||
attributes = createAttributes("member", new RangeOption(11), 5);
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertEquals(16, tested.getValues("member").size());
|
||||
}
|
||||
|
||||
public void testLoopWithTwoRangedAttributesLoopOnOneAttribute() throws Exception {
|
||||
tested = new DefaultIncrementalAttributesMapper(10, new String[]{"member", "cn"});
|
||||
|
||||
Attributes attributes = createAttributes("member", new RangeOption(0, 5));
|
||||
attributes.put(createRangeAttribute("cn", new RangeOption(0, 10), 10));
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(tested.hasMore());
|
||||
assertEquals(6, tested.getValues("member").size());
|
||||
assertEquals(10, tested.getValues("cn").size());
|
||||
|
||||
assertEquals(1, tested.getAttributesForLookup().length);
|
||||
|
||||
attributes = createAttributes("member", new RangeOption(6), 5);
|
||||
|
||||
tested.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(tested.hasMore());
|
||||
assertEquals(11, tested.getValues("member").size());
|
||||
}
|
||||
private Attributes createAttributes(String attributeName, RangeOption range) {
|
||||
return createAttributes(attributeName, range, range.getTerminal() - range.getInitial() + 1);
|
||||
}
|
||||
|
||||
private Attributes createAttributes(String attributeName, RangeOption range, int valueCnt) {
|
||||
Attributes attributes = new BasicAttributes();
|
||||
|
||||
Attribute attribute = createRangeAttribute(attributeName, range, valueCnt);
|
||||
attributes.put(attribute);
|
||||
|
||||
return attributes;
|
||||
|
||||
}
|
||||
|
||||
private Attribute createRangeAttribute(String attributeName, RangeOption range, int valueCnt) {
|
||||
Attribute attribute = new BasicAttribute(attributeName + ";" + range.toString());
|
||||
for (int i = 0; i < valueCnt; i++) {
|
||||
attribute.add("value" + (range.getInitial() + i - 1));
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ldap.support.ad;
|
||||
package org.springframework.ldap.core.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.ldap.core.support.RangeOption;
|
||||
|
||||
/**
|
||||
* IncrementalAttributeMapper Tester.
|
||||
* IncrementalAttributesMapper Tester.
|
||||
*
|
||||
* @author Marius Scurtescu
|
||||
*/
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ldap.support.ad;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
|
||||
/**
|
||||
* IncrementalAttributeMapper Tester.
|
||||
*
|
||||
* @author Marius Scurtescu
|
||||
*/
|
||||
public class IncrementalAttributeMapperTest extends TestCase {
|
||||
private IncrementalAttributeMapper incrementalAttributeMapper;
|
||||
private ListAttributeValueProcessor valueProcessor;
|
||||
|
||||
public IncrementalAttributeMapperTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
valueProcessor = new ListAttributeValueProcessor();
|
||||
incrementalAttributeMapper = new IncrementalAttributeMapper("member", valueProcessor);
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
incrementalAttributeMapper = null;
|
||||
valueProcessor = null;
|
||||
}
|
||||
|
||||
public void testGetAttributesArray() throws Exception {
|
||||
String[] attributes = incrementalAttributeMapper.getAttributesArray();
|
||||
|
||||
assertEquals(1, attributes.length);
|
||||
assertEquals("member", attributes[0]);
|
||||
|
||||
incrementalAttributeMapper = new IncrementalAttributeMapper("member", valueProcessor, 10);
|
||||
|
||||
attributes = incrementalAttributeMapper.getAttributesArray();
|
||||
|
||||
assertEquals(1, attributes.length);
|
||||
assertEquals("member;Range=0-10", attributes[0]);
|
||||
}
|
||||
|
||||
public void testLoopEmpty() throws Exception {
|
||||
assertTrue(incrementalAttributeMapper.hasMore());
|
||||
|
||||
Attributes attributes = new BasicAttributes();
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(0, valueProcessor.getValues().size());
|
||||
}
|
||||
|
||||
public void testLoop() throws Exception {
|
||||
Attributes attributes = createAttributes(new RangeOption(0, 10), true);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(11, valueProcessor.getValues().size());
|
||||
|
||||
attributes = createAttributes(new RangeOption(11), 5, false);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(16, valueProcessor.getValues().size());
|
||||
}
|
||||
|
||||
public void test1LoopWithPageSizeExact() throws Exception {
|
||||
incrementalAttributeMapper = new IncrementalAttributeMapper("member", valueProcessor, 10);
|
||||
|
||||
Attributes attributes = createAttributes(new RangeOption(0, 10), true);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(11, valueProcessor.getValues().size());
|
||||
}
|
||||
|
||||
public void test2LoopsWithPageSizeExact() throws Exception {
|
||||
incrementalAttributeMapper = new IncrementalAttributeMapper("member", valueProcessor, 20);
|
||||
|
||||
Attributes attributes = createAttributes(new RangeOption(0, 10), true);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(11, valueProcessor.getValues().size());
|
||||
|
||||
attributes = createAttributes(new RangeOption(11, 30), false);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(31, valueProcessor.getValues().size());
|
||||
}
|
||||
|
||||
public void test2LoopsWithPageSize() throws Exception {
|
||||
incrementalAttributeMapper = new IncrementalAttributeMapper("member", valueProcessor, 20);
|
||||
|
||||
Attributes attributes = createAttributes(new RangeOption(0, 10), true);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertTrue(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(11, valueProcessor.getValues().size());
|
||||
|
||||
attributes = createAttributes(new RangeOption(11), 5, false);
|
||||
|
||||
incrementalAttributeMapper.mapFromAttributes(attributes);
|
||||
|
||||
assertFalse(incrementalAttributeMapper.hasMore());
|
||||
assertEquals(16, valueProcessor.getValues().size());
|
||||
}
|
||||
|
||||
private Attributes createAttributes(RangeOption range, boolean emptyPlain) {
|
||||
return createAttributes(range, range.getTerminal() - range.getInitial() + 1, emptyPlain);
|
||||
}
|
||||
|
||||
private Attributes createAttributes(RangeOption range, int valueCnt, boolean emptyPlain) {
|
||||
Attributes attributes = new BasicAttributes();
|
||||
|
||||
if (emptyPlain) {
|
||||
attributes.put(new BasicAttribute("member"));
|
||||
}
|
||||
|
||||
Attribute attribute = new BasicAttribute("member;" + range.toString());
|
||||
for (int i = 0; i < valueCnt; i++) {
|
||||
attribute.add("value" + (range.getInitial() + i - 1));
|
||||
}
|
||||
attributes.put(attribute);
|
||||
|
||||
return attributes;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,13 @@
|
||||
*/
|
||||
package org.springframework.ldap.transaction.compensating;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.core.IncrementalAttributesMapper;
|
||||
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.directory.Attributes;
|
||||
@@ -23,16 +30,6 @@ import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.ModificationItem;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.easymock.MockControl;
|
||||
import org.springframework.ldap.core.AttributesMapper;
|
||||
import org.springframework.ldap.core.DistinguishedName;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationExecutor;
|
||||
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationRecorder;
|
||||
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
|
||||
|
||||
public class ModifyAttributesOperationRecorderTest extends TestCase {
|
||||
private MockControl ldapOperationsControl;
|
||||
|
||||
@@ -40,7 +37,7 @@ public class ModifyAttributesOperationRecorderTest extends TestCase {
|
||||
|
||||
private MockControl attributesMapperControl;
|
||||
|
||||
private AttributesMapper attributesMapperMock;
|
||||
private IncrementalAttributesMapper attributesMapperMock;
|
||||
|
||||
private ModifyAttributesOperationRecorder tested;
|
||||
|
||||
@@ -49,8 +46,8 @@ public class ModifyAttributesOperationRecorderTest extends TestCase {
|
||||
ldapOperationsMock = (LdapOperations) ldapOperationsControl.getMock();
|
||||
|
||||
attributesMapperControl = MockControl
|
||||
.createControl(AttributesMapper.class);
|
||||
attributesMapperMock = (AttributesMapper) attributesMapperControl
|
||||
.createControl(IncrementalAttributesMapper.class);
|
||||
attributesMapperMock = (IncrementalAttributesMapper) attributesMapperControl
|
||||
.getMock();
|
||||
|
||||
tested = new ModifyAttributesOperationRecorder(ldapOperationsMock);
|
||||
@@ -79,14 +76,14 @@ public class ModifyAttributesOperationRecorderTest extends TestCase {
|
||||
public void testRecordOperation() {
|
||||
final ModificationItem incomingItem = new ModificationItem(
|
||||
DirContext.ADD_ATTRIBUTE, new BasicAttribute("attribute1"));
|
||||
ModificationItem[] incomingMods = new ModificationItem[] { incomingItem };
|
||||
ModificationItem[] incomingMods = new ModificationItem[]{incomingItem};
|
||||
final ModificationItem compensatingItem = new ModificationItem(
|
||||
DirContext.ADD_ATTRIBUTE, new BasicAttribute("attribute2"));
|
||||
|
||||
final Attributes expectedAttributes = new BasicAttributes();
|
||||
|
||||
tested = new ModifyAttributesOperationRecorder(ldapOperationsMock) {
|
||||
AttributesMapper getAttributesMapper() {
|
||||
IncrementalAttributesMapper getAttributesMapper(String[] attributeNames) {
|
||||
return attributesMapperMock;
|
||||
}
|
||||
|
||||
@@ -101,14 +98,24 @@ public class ModifyAttributesOperationRecorderTest extends TestCase {
|
||||
|
||||
DistinguishedName expectedName = new DistinguishedName("cn=john doe");
|
||||
ldapOperationsControl.setDefaultMatcher(MockControl.ARRAY_MATCHER);
|
||||
ldapOperationsControl.expectAndReturn(ldapOperationsMock.lookup(
|
||||
expectedName, new String[] { "attribute1" },
|
||||
attributesMapperMock), expectedAttributes);
|
||||
|
||||
attributesMapperControl.expectAndReturn(
|
||||
attributesMapperMock.hasMore(), true);
|
||||
attributesMapperControl.expectAndReturn(
|
||||
attributesMapperMock.getAttributesForLookup(),
|
||||
new String[]{"attribute1"});
|
||||
ldapOperationsControl.expectAndReturn(
|
||||
ldapOperationsMock.lookup(expectedName, new String[]{"attribute1"}, attributesMapperMock),
|
||||
expectedAttributes);
|
||||
attributesMapperControl.expectAndReturn(attributesMapperMock.hasMore(), false);
|
||||
attributesMapperControl.expectAndReturn(
|
||||
attributesMapperMock.getCollectedAttributes(),
|
||||
expectedAttributes);
|
||||
|
||||
replay();
|
||||
// Perform test
|
||||
CompensatingTransactionOperationExecutor operation = tested
|
||||
.recordOperation(new Object[] { expectedName, incomingMods });
|
||||
.recordOperation(new Object[]{expectedName, incomingMods});
|
||||
verify();
|
||||
|
||||
// Verify outcome
|
||||
|
||||
Reference in New Issue
Block a user