/*
* 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
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
*/
package org.opends.server.types;
import java.util.ArrayList;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.fail;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.util.Platform;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
* This class defines a set of tests for the
* {@link org.opends.server.types.RDN} class.
*/
public final class TestRDN extends TypesTestCase {
// Domain component attribute type.
private AttributeType AT_DC;
// Common name attribute type.
private AttributeType AT_CN;
// Test attribute value.
private AttributeValue AV_DC_ORG;
// Test attribute value.
private AttributeValue AV_DC_OPENDS;
// Test attribute value.
private AttributeValue AV_CN;
/**
* 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, so
// we'll start the server.
TestCaseUtils.startServer();
AT_DC = DirectoryServer.getAttributeType("dc");
AT_CN = DirectoryServer.getAttributeType("cn");
AttributeType dummy = DirectoryServer.getDefaultAttributeType(
"x-test-integer-type", DirectoryServer
.getDefaultIntegerSyntax());
DirectoryServer.getSchema().registerAttributeType(dummy, true);
AV_DC_ORG = AttributeValues.create(AT_DC, "org");
AV_DC_OPENDS = AttributeValues.create(AT_DC, "opends");
AV_CN = AttributeValues.create(AT_DC, "hello world");
}
/**
* Test RDN construction with single AVA.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testConstructor() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertEquals(rdn.getNumValues(), 1);
assertEquals(rdn.getAttributeType(0), AT_DC);
assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
}
/**
* Test RDN construction with single AVA and a user-defined name.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testConstructorWithName() throws Exception {
RDN rdn = new RDN(AT_DC, "domainComponent", AV_DC_ORG);
assertEquals(rdn.getNumValues(), 1);
assertEquals(rdn.getAttributeType(0), AT_DC);
assertEquals(rdn.getAttributeName(0), "domainComponent");
assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
}
/**
* Test RDN construction with a multiple AVA elements.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testConstructorMultiAVA() throws Exception {
AttributeType[] attrTypes = { AT_DC, AT_CN };
String[] attrNames = { AT_DC.getNameOrOID(),
AT_CN.getNameOrOID() };
AttributeValue[] attrValues = { AV_DC_ORG, AV_CN };
RDN rdn = new RDN(attrTypes, attrNames, attrValues);
assertEquals(rdn.getNumValues(), 2);
assertEquals(rdn.getAttributeType(0), AT_DC);
assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
assertEquals(rdn.getAttributeType(1), AT_CN);
assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
assertEquals(rdn.getAttributeValue(1), AV_CN);
}
/**
* Test RDN construction with a multiple AVA elements.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testConstructorMultiAVAList() throws Exception {
ArrayList<AttributeType> typeList = new ArrayList<AttributeType>();
ArrayList<String> nameList = new ArrayList<String>();
ArrayList<AttributeValue> valueList = new ArrayList<AttributeValue>();
typeList.add(AT_DC);
nameList.add(AT_DC.getNameOrOID());
valueList.add(AV_DC_ORG);
typeList.add(AT_CN);
nameList.add(AT_CN.getNameOrOID());
valueList.add(AV_CN);
RDN rdn = new RDN(typeList, nameList, valueList);
assertEquals(rdn.getNumValues(), 2);
assertEquals(rdn.getAttributeType(0), AT_DC);
assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
assertEquals(rdn.getAttributeType(1), AT_CN);
assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
assertEquals(rdn.getAttributeValue(1), AV_CN);
}
/**
* RDN test data provider.
*
* @return The array of test RDN strings.
*/
@DataProvider(name = "testRDNs")
public Object[][] createData() {
return new Object[][] {
{ "dc=hello world", "dc=hello world", "dc=hello world" },
{ "dc =hello world", "dc=hello world", "dc=hello world" },
{ "dc =hello world", "dc=hello world", "dc=hello world" },
{ "dc= hello world", "dc=hello world", "dc=hello world" },
{ "dc= hello world", "dc=hello world", "dc=hello world" },
{ "undefined=hello", "undefined=hello", "undefined=hello" },
{ "DC=HELLO WORLD", "dc=hello world", "DC=HELLO WORLD" },
{ "dc = hello world", "dc=hello world",
"dc=hello world" },
{ " dc = hello world ", "dc=hello world",
"dc=hello world" },
{ "givenName=John+cn=Doe", "cn=doe+givenname=john",
"givenName=John+cn=Doe" },
{ "givenName=John\\+cn=Doe", "givenname=john\\+cn=doe",
"givenName=John\\+cn=Doe" },
{ "cn=Doe\\, John", "cn=doe\\, john", "cn=Doe\\, John" },
{ "OU=Sales+CN=J. Smith", "cn=j. smith+ou=sales",
"OU=Sales+CN=J. Smith" },
{ "CN=James \\\"Jim\\\" Smith\\, III",
"cn=james \\\"jim\\\" smith\\, iii",
"CN=James \\\"Jim\\\" Smith\\, III" },
//\0d is a hex representation of Carriage return. It is mapped
//to a SPACE as defined in the MAP ( RFC 4518)
{ "CN=Before\\0dAfter", "cn=before after",
"CN=Before\\0dAfter" },
{ "1.3.6.1.4.1.1466.0=#04024869",
//Unicode codepoints from 0000-0008 are mapped to nothing.
"1.3.6.1.4.1.1466.0=hi",
"1.3.6.1.4.1.1466.0=\\04\\02Hi" },
{ "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107",
"CN=Lu\u010di\u0107" },
{ "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8",
"ou=\u55b6\u696d\u90e8",
"ou=\u55b6\u696d\u90e8" },
{ "photo=\\ john \\ ", "photo=\\ john \\ ",
"photo=\\ john \\ " },
// { "AB-global=", "ab-global=", "AB-global=" },
{ "cn=John+a=", "a=+cn=john", "cn=John+a=" },
{ "OID.1.3.6.1.4.1.1466.0=#04024869",
//Unicode codepoints from 0000-0008 are mapped to nothing.
"1.3.6.1.4.1.1466.0=hi",
"1.3.6.1.4.1.1466.0=\\04\\02Hi" },
{ "O=\"Sue, Grabbit and Runn\"", "o=sue\\, grabbit and runn",
"O=Sue\\, Grabbit and Runn" }, };
}
/**
* Test RDN string decoder.
*
* @param rawRDN
* Raw RDN string representation.
* @param normRDN
* Normalized RDN string representation.
* @param stringRDN
* String representation.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "testRDNs")
public void testDecodeString(String rawRDN, String normRDN,
String stringRDN) throws Exception {
RDN rdn = RDN.decode(rawRDN);
StringBuilder buffer = new StringBuilder();
buffer.append(normRDN);
Platform.normalize(buffer);
assertEquals(rdn.toNormalizedString(), buffer.toString());
}
/**
* Illegal RDN test data provider.
*
* @return The array of illegal test RDN strings.
*/
@DataProvider(name = "illegalRDNs")
public Object[][] createIllegalData() {
return new Object[][] { { null }, { "" }, { " " }, { "=" }, { "manager" },
{ "manager " }, { "cn+"}, { "cn+Jim" }, { "cn=Jim+" }, { "cn=Jim +" },
{ "cn=Jim+ " }, { "cn=Jim+sn" }, { "cn=Jim+sn " },
{ "cn=Jim+sn equals" }, { "cn=Jim," }, { "cn=Jim;" }, { "cn=Jim, " },
{ "cn=Jim+sn=a," }, { "cn=Jim, sn=Jam " }, { "cn+uid=Jim" },
{ "-cn=Jim" }, { "/tmp=a" }, { "\\tmp=a" }, { "cn;lang-en=Jim" },
{ "@cn=Jim" }, { "_name_=Jim" }, { "\u03c0=pi" }, { "v1.0=buggy" },
{ "cn=Jim+sn=Bob++" }, { "cn=Jim+sn=Bob+," },
{ "1.3.6.1.4.1.1466..0=#04024869" }, };
}
/**
* Test RDN string decoder against illegal strings.
*
* @param rawRDN
* Illegal RDN string representation.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "illegalRDNs", expectedExceptions = DirectoryException.class)
public void testDecodeString(String rawRDN) throws Exception {
RDN.decode(rawRDN);
fail("Expected exception for value \"" + rawRDN + "\"");
}
/**
* Test getAttributeName.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testGetAttributeName() throws Exception {
AttributeType[] attrTypes = { AT_DC, AT_CN };
String[] attrNames = { AT_DC.getNameOrOID(),
AT_CN.getNameOrOID() };
AttributeValue[] attrValues = { AV_DC_ORG, AV_CN };
RDN rdn = new RDN(attrTypes, attrNames, attrValues);
assertEquals(rdn.getAttributeName(0), AT_DC.getNameOrOID());
assertEquals(rdn.getAttributeName(1), AT_CN.getNameOrOID());
}
/**
* Test getAttributeName IndexOutOfBoundsException.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(expectedExceptions = IndexOutOfBoundsException.class)
public void testGetAttributeNameException() throws Exception {
RDN rdn = new RDN(new AttributeType[0], new String[0],
new AttributeValue[0]);
rdn.getAttributeName(1);
}
/**
* Test getAttributeType.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testGetAttributeType() throws Exception {
AttributeType[] attrTypes = { AT_DC, AT_CN };
String[] attrNames = { AT_DC.getNameOrOID(),
AT_CN.getNameOrOID() };
AttributeValue[] attrValues = { AV_DC_ORG, AV_CN };
RDN rdn = new RDN(attrTypes, attrNames, attrValues);
assertEquals(rdn.getAttributeType(0), AT_DC);
assertEquals(rdn.getAttributeType(1), AT_CN);
}
/**
* Test getAttributeType IndexOutOfBoundsException.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(expectedExceptions = IndexOutOfBoundsException.class)
public void testGetAttributeTypeException() throws Exception {
RDN rdn = new RDN(new AttributeType[0], new String[0],
new AttributeValue[0]);
rdn.getAttributeType(1);
}
/**
* Test getAttributeValue.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testGetAttributeValue() throws Exception {
AttributeType[] attrTypes = { AT_DC, AT_CN };
String[] attrNames = { AT_DC.getNameOrOID(),
AT_CN.getNameOrOID() };
AttributeValue[] attrValues = { AV_DC_ORG, AV_CN };
RDN rdn = new RDN(attrTypes, attrNames, attrValues);
assertEquals(rdn.getAttributeValue(0), AV_DC_ORG);
assertEquals(rdn.getAttributeValue(1), AV_CN);
}
/**
* Test getAttributeValue IndexOutOfBoundsException.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(expectedExceptions = IndexOutOfBoundsException.class)
public void testGetAttributeValueException() throws Exception {
RDN rdn = new RDN(new AttributeType[0], new String[0],
new AttributeValue[0]);
rdn.getAttributeValue(1);
}
/**
* Test getAttributeValue.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testGetAttributeValueByType() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertEquals(rdn.getAttributeValue(AT_DC), AV_DC_ORG);
assertNull(rdn.getAttributeValue(AT_CN));
}
/**
* Test getNumValues.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testGetNumValues() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertEquals(rdn.getNumValues(), 1);
rdn.addValue(AT_CN, AT_CN.getNameOrOID(), AV_CN);
assertEquals(rdn.getNumValues(), 2);
}
/**
* Test hasAttributeType.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testHasAttributeType1() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertTrue(rdn.hasAttributeType(AT_DC));
assertTrue(rdn.hasAttributeType("dc"));
assertTrue(rdn.hasAttributeType(AT_DC.getOID()));
assertFalse(rdn.hasAttributeType(AT_CN));
assertFalse(rdn.hasAttributeType("cn"));
}
/**
* Test isMultiValued.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testIsMultiValued() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertEquals(rdn.getNumValues(), 1);
assertFalse(rdn.isMultiValued());
rdn.addValue(AT_CN, AT_CN.getNameOrOID(), AV_CN);
assertTrue(rdn.isMultiValued());
}
/**
* Tests hasValue.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testHasValue() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertTrue(rdn.hasValue(AT_DC, AV_DC_ORG));
assertFalse(rdn.hasValue(AT_CN, AV_CN));
rdn.addValue(AT_CN, AT_CN.getNameOrOID(), AV_CN);
assertTrue(rdn.hasValue(AT_DC, AV_DC_ORG));
assertTrue(rdn.hasValue(AT_CN, AV_CN));
}
/**
* Tests addValue with a duplicate value.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testAddDuplicateValue() throws Exception {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertFalse(rdn.addValue(AT_DC, AT_DC.getNameOrOID(), AV_DC_ORG));
}
/**
* Test RDN string decoder.
*
* @param rawRDN
* Raw RDN string representation.
* @param normRDN
* Normalized RDN string representation.
* @param stringRDN
* String representation.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "testRDNs")
public void testToString(String rawRDN, String normRDN,
String stringRDN) throws Exception {
RDN rdn = RDN.decode(rawRDN);
assertEquals(rdn.toString(), stringRDN);
}
/**
* Tests the duplicate method with a single-valued RDN.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testDuplicateSingle() {
RDN rdn1 = new RDN(AT_DC, AV_DC_ORG);
RDN rdn2 = rdn1.duplicate();
assertFalse(rdn1 == rdn2);
assertEquals(rdn1, rdn2);
}
/**
* Tests the duplicate method with a multivalued RDN.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testDuplicateMultiValued() {
AttributeType[] types = new AttributeType[] { AT_DC, AT_CN };
String[] names = new String[] { "dc", "cn" };
AttributeValue[] values = new AttributeValue[] { AV_DC_ORG, AV_CN };
RDN rdn1 = new RDN(types, names, values);
RDN rdn2 = rdn1.duplicate();
assertFalse(rdn1 == rdn2);
assertEquals(rdn1, rdn2);
}
/**
* RDN equality test data provider.
*
* @return The array of test RDN strings.
*/
@DataProvider(name = "createRDNEqualityData")
public Object[][] createRDNEqualityData() {
return new Object[][] {
{ "cn=hello world", "cn=hello world", 0 },
{ "cn=hello world", "CN=hello world", 0 },
{ "cn=hello world", "cn=hello world", 0 },
{ " cn = hello world ", "cn=hello world", 0 },
{ "cn=hello world\\ ", "cn=hello world", 0 },
{ "cn=HELLO WORLD", "cn=hello world", 0 },
{ "cn=HELLO+sn=WORLD", "sn=world+cn=hello", 0 },
{ "cn=HELLO+sn=WORLD", "cn=hello+sn=nurse", 1 },
{ "cn=HELLO+sn=WORLD", "cn=howdy+sn=yall", -1 },
{ "cn=hello", "cn=hello+sn=world", -1 },
{ "cn=hello+sn=world", "cn=hello", 1 },
{ "cn=hello+sn=world", "cn=hello+description=world", 1 },
{ "cn=hello", "sn=world", -1 },
{ "sn=hello", "cn=world", 1 },
{ "x-test-integer-type=10", "x-test-integer-type=9", 1 },
{ "x-test-integer-type=999", "x-test-integer-type=1000", -1 },
{ "x-test-integer-type=-1", "x-test-integer-type=0", -1 },
{ "x-test-integer-type=0", "x-test-integer-type=-1", 1 },
{ "cn=aaa", "cn=aaaa", -1 }, { "cn=AAA", "cn=aaaa", -1 },
{ "cn=aaa", "cn=AAAA", -1 }, { "cn=aaaa", "cn=aaa", 1 },
{ "cn=AAAA", "cn=aaa", 1 }, { "cn=aaaa", "cn=AAA", 1 },
{ "cn=aaab", "cn=aaaa", 1 }, { "cn=aaaa", "cn=aaab", -1 } };
}
/**
* Test RDN equality
*
* @param first
* First RDN to compare.
* @param second
* Second RDN to compare.
* @param result
* Expected comparison result.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
public void testEquality(String first, String second, int result)
throws Exception {
RDN rdn1 = RDN.decode(first);
RDN rdn2 = RDN.decode(second);
if (result == 0) {
assertTrue(rdn1.equals(rdn2), "RDN equality for <" + first
+ "> and <" + second + ">");
} else {
assertFalse(rdn1.equals(rdn2), "RDN equality for <" + first
+ "> and <" + second + ">");
}
}
/**
* Test RDN hashCode
*
* @param first
* First RDN to compare.
* @param second
* Second RDN to compare.
* @param result
* Expected comparison result.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
public void testHashCode(String first, String second, int result)
throws Exception {
RDN rdn1 = RDN.decode(first);
RDN rdn2 = RDN.decode(second);
int h1 = rdn1.hashCode();
int h2 = rdn2.hashCode();
if (result == 0) {
if (h1 != h2) {
fail("Hash codes for <" + first + "> and <" + second
+ "> should be the same.");
}
} else {
if (h1 == h2) {
fail("Hash codes for <" + first + "> and <" + second
+ "> should be the same.");
}
}
}
/**
* Test RDN compareTo
*
* @param first
* First RDN to compare.
* @param second
* Second RDN to compare.
* @param result
* Expected comparison result.
* @throws Exception
* If the test failed unexpectedly.
*/
@Test(dataProvider = "createRDNEqualityData")
public void testCompareTo(String first, String second, int result)
throws Exception {
RDN rdn1 = RDN.decode(first);
RDN rdn2 = RDN.decode(second);
int rc = rdn1.compareTo(rdn2);
// Normalize the result.
if (rc < 0) {
rc = -1;
} else if (rc > 0) {
rc = 1;
}
assertEquals(rc, result, "Comparison for <" + first + "> and <"
+ second + ">.");
}
/**
* Tests the equals method with a null argument.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testEqualityNull() {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertFalse(rdn.equals(null));
}
/**
* Tests the equals method with a non-RDN argument.
*
* @throws Exception
* If the test failed unexpectedly.
*/
@Test
public void testEqualityNonRDN() {
RDN rdn = new RDN(AT_DC, AV_DC_ORG);
assertFalse(rdn.equals("this isn't an RDN"));
}
}