/*
* 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-2014 ForgeRock AS
*/
package org.opends.server.types;
import org.forgerock.opendj.ldap.SearchScope;
import org.opends.server.TestCaseUtils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.*;
import static org.testng.Assert.*;
@SuppressWarnings("javadoc")
@Test(groups = { "precommit", "types" }, sequential = true)
public class LDAPURLTest extends TypesTestCase
{
private static final String DEFAULT_SEARCH_FILTER = "(objectClass=*)";
private static final String DEFAULT_END_URL = "??base?" + DEFAULT_SEARCH_FILTER;
@BeforeClass
public void setup() throws Exception
{
TestCaseUtils.startServer();
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeWithNoSchemeSeparator() throws Exception
{
final String sample = "";
LDAPURL.decode(sample, true);
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeNoSchemeWithSchemeSeparator() throws Exception
{
final String sample = "://localhost:389/??sub?objectclass=person";
LDAPURL.decode(sample, true);
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeNoHost() throws Exception
{
final String sample = "ldap://:389";
LDAPURL.decode(sample, true);
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeNoPort() throws Exception
{
final String sample = "ldap://localhost:";
LDAPURL.decode(sample, true);
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeNotAPortNumber() throws Exception
{
final String sample = "ldap://localhost:port";
LDAPURL.decode(sample, true);
}
@Test
public void decodeSampleLDAP() throws Exception
{
final String sample = "ldap://";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isNull();
assertDefaultValues(ldapURL);
assertThat(ldapURL.toString()).isEqualTo(sample + "/" + DEFAULT_END_URL);
}
@Test
public void decodeSampleLDAPS() throws Exception
{
final String sample = "ldaps://";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldaps");
assertThat(ldapURL.getHost()).isNull();
assertDefaultValues(ldapURL);
assertThat(ldapURL.toString()).isEqualTo(sample + "/" + DEFAULT_END_URL);
}
@Test
public void decodeSampleLDAPWithUselessSlash() throws Exception
{
final String sample = "ldap:///";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isNull();
assertDefaultValues(ldapURL);
assertThat(ldapURL.toString()).isEqualTo(sample + DEFAULT_END_URL);
}
@DataProvider
public Object[][] numberQuestionsMarks()
{
return new Object[][] { { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, };
}
@Test(dataProvider = "numberQuestionsMarks")
public void decodeSampleLDAPWithUselessQuestionMarks(int nbQuestionMarks)
throws Exception
{
StringBuilder sb = new StringBuilder("ldap://localhost/");
for (int i = 0; i < nbQuestionMarks; i++)
{
sb.append("?");
}
final String sample = sb.toString();
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isEqualTo("localhost");
assertDefaultValues(ldapURL);
assertThat(ldapURL.toString()).isEqualTo("ldap://localhost:389/" + DEFAULT_END_URL);
}
private void assertDefaultValues(final LDAPURL ldapURL) throws Exception
{
assertThat(ldapURL.getPort()).isEqualTo(389);
assertThat(ldapURL.getRawBaseDN()).isNullOrEmpty();
assertThat(ldapURL.getAttributes()).isEmpty();
assertThat(ldapURL.getScope()).isEqualTo(SearchScope.BASE_OBJECT);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase(DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getFilter()).isEqualTo(LDAPURL.DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getExtensions()).isEmpty();
}
@Test
public void decodeSampleLDAPWithAttributes() throws Exception
{
final String sample = "ldap://localhost/?cn,tel,mail";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isEqualTo("localhost");
assertThat(ldapURL.getPort()).isEqualTo(389);
assertThat(ldapURL.getRawBaseDN()).isNullOrEmpty();
assertThat(ldapURL.getAttributes()).containsOnly("cn", "tel", "mail");
assertThat(ldapURL.getScope()).isEqualTo(SearchScope.BASE_OBJECT);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase("(objectClass=*)");
assertThat(ldapURL.getExtensions()).isEmpty();
assertThat(ldapURL.toString()).isEqualTo("ldap://localhost:389/?cn,tel,mail?base?" + DEFAULT_SEARCH_FILTER);
}
@Test
public void decodeSampleLDAPWithExtensions() throws Exception
{
final String sample = "ldap://localhost/????ext1,ext2,ext3";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isEqualTo("localhost");
assertThat(ldapURL.getPort()).isEqualTo(389);
assertThat(ldapURL.getRawBaseDN()).isNullOrEmpty();
assertThat(ldapURL.getAttributes()).isEmpty();
assertThat(ldapURL.getScope()).isEqualTo(SearchScope.BASE_OBJECT);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase(DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getFilter()).isEqualTo(LDAPURL.DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getExtensions()).containsOnly("ext1", "ext2", "ext3");
assertThat(ldapURL.toString()).isEqualTo("ldap://localhost:389/" + DEFAULT_END_URL + "?ext1,ext2,ext3");
}
@DataProvider
public Object[][] allSearchScopes()
{
return new Object[][] {
{ "", SearchScope.BASE_OBJECT }, // this is the default
{ "base", SearchScope.BASE_OBJECT },
{ "one", SearchScope.SINGLE_LEVEL },
{ "sub", SearchScope.WHOLE_SUBTREE },
{ "subord", SearchScope.SUBORDINATES },
{ "subordinate", SearchScope.SUBORDINATES },
};
}
@Test(dataProvider = "allSearchScopes")
public void decodeSimpleSample(String actualSearchScope,
SearchScope expectedSearchScope) throws Exception
{
final String sample = "ldap://localhost/??" + actualSearchScope;
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isEqualTo("localhost");
assertThat(ldapURL.getPort()).isEqualTo(389);
assertThat(ldapURL.getRawBaseDN()).isEqualTo("");
assertThat(ldapURL.getAttributes()).isEmpty();
assertThat(ldapURL.getScope()).isEqualTo(expectedSearchScope);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase(DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getFilter()).isEqualTo(LDAPURL.DEFAULT_SEARCH_FILTER);
assertThat(ldapURL.getExtensions()).isEmpty();
// tweaks for the next assert
if ("".equals(actualSearchScope))
{
actualSearchScope = "base";
}
else if ("subord".equals(actualSearchScope))
{
actualSearchScope = "subordinate";
}
assertThat(ldapURL.toString()).isEqualTo(
"ldap://localhost:389/??" + actualSearchScope + "?" + DEFAULT_SEARCH_FILTER);
}
@Test(expectedExceptions = DirectoryException.class)
public void decodeInvalidSearchScope() throws Exception
{
final String sample = "ldap://localhost/??unheardOf";
LDAPURL.decode(sample, true);
}
@Test
public void decodeComplexSample() throws Exception
{
final String sample =
"ldap://ldap.netscape.com:1389/ou=Sales,o=Netscape,c=US?cn,tel,mail?sub?(objectclass=person)?ext1,ext2,ext3";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ldap");
assertThat(ldapURL.getHost()).isEqualTo("ldap.netscape.com");
assertThat(ldapURL.getPort()).isEqualTo(1389);
assertThat(ldapURL.getRawBaseDN()).isEqualTo("ou=Sales,o=Netscape,c=US");
assertThat(ldapURL.getAttributes()).containsOnly("cn", "tel", "mail");
assertThat(ldapURL.getScope()).isEqualTo(SearchScope.WHOLE_SUBTREE);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase("(objectClass=person)");
assertThat(ldapURL.getExtensions()).containsOnly("ext1", "ext2", "ext3");
assertThat(ldapURL.toString()).isEqualToIgnoringCase(sample);
}
@Test
public void decodeComplexSampleWithUrlDecode() throws Exception
{
final String sample =
"ld%2Fap://ldap.netsca%2Fpe.com:1389/ou=Sa%2Fles,o=Netscape,c=US?c%2Fn,tel,mail?sub?(objectclass=per%2Fson)?ext%2F1,ext%2F2,ext%2F3";
final LDAPURL ldapURL = LDAPURL.decode(sample, true);
assertThat(ldapURL.getScheme()).isEqualTo("ld/ap");
assertThat(ldapURL.getHost()).isEqualTo("ldap.netsca/pe.com");
assertThat(ldapURL.getPort()).isEqualTo(1389);
assertThat(ldapURL.getRawBaseDN()).isEqualTo("ou=Sa/les,o=Netscape,c=US");
assertThat(ldapURL.getAttributes()).containsOnly("c/n", "tel", "mail");
assertThat(ldapURL.getScope()).isEqualTo(SearchScope.WHOLE_SUBTREE);
assertThat(ldapURL.getRawFilter()).isEqualToIgnoringCase("(objectClass=per/son)");
assertThat(ldapURL.getExtensions()).containsOnly("ext/1", "ext/2", "ext/3");
// FIXME, why does toString() do not URL encode the "/"?
assertThat(ldapURL.toString()).isEqualToIgnoringCase(
sample.replaceAll("%2F", "/"));
}
@Test
public void urlDecodeNull() throws Exception
{
assertEquals(LDAPURL.urlDecode(null), "");
}
@Test(expectedExceptions = DirectoryException.class)
public void urlDecodeNeedMoreBytesAfterPercentSign() throws Exception
{
assertNull(LDAPURL.urlDecode("%"));
}
@Test(expectedExceptions = DirectoryException.class)
public void urlDecodeNotHexOneAfterPercentSign() throws Exception
{
assertNull(LDAPURL.urlDecode("%z1"));
}
@Test(expectedExceptions = DirectoryException.class)
public void urlDecodeNotHexTwoAfterPercentSign() throws Exception
{
assertNull(LDAPURL.urlDecode("%1z"));
}
@Test
public void urlDecodeAllPercentSigns() throws Exception
{
String decoded1 = LDAPURL.urlDecode("%21%23%24%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D");
assertThat(decoded1).isEqualTo("!#$&'()*+,/:;=?@[]");
String decoded2 = LDAPURL.urlDecode("%20%22%25%2D%2E%3C%3E%5C%5E%5F%60%7B%7C%7D%7E");
assertThat(decoded2).isEqualTo(" \"%-.<>\\^_`{|}~");
// unix, then MacOS, then windows style newlines
String decoded3 = LDAPURL.urlDecode("%0A %0D %0D%0A");
assertThat(decoded3).isEqualTo("\n \r \r\n");
}
}