/*
* 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
* 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 2008 Sun Microsystems, Inc.
* Portions Copyright 2013-2014 Manuel Gaupp
* Portions Copyright 2014-2015 ForgeRock AS
*/
/**
* Tests for the org.opends.server.types.SearchFilter class
*
* This class covers the SearchFilter class fairly well. The main gaps are
* with extensible match, attribute options, and there is a lot of code
* that is not reachable because it's in exception handling code that
* is not exercisable externally.
*/
@SuppressWarnings("javadoc")
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// createFilterFromString
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// -------------------------------------------------------------------------
//
// Test valid filters.
//
// -------------------------------------------------------------------------
// These are valid filters.
return new Object[][]{
{"(&)", "(&)"},
{"(|)", "(|)"},
{"(sn=test)", "(sn=test)"},
{"(sn=*)", "(sn=*)"},
{"(sn=)", "(sn=)"},
{"(sn=*test*)", "(sn=*test*)"},
{"(!(sn=test))", "(!(sn=test))"},
{"(|(sn=test)(sn=test2))", "(|(sn=test)(sn=test2))"},
{"(&(sn=test))", "(&(sn=test))"},
{"(|(sn=test))", "(|(sn=test))"},
};
}
public void testCreateFilterFromStringValidFilters(
) throws DirectoryException {
}
private void runRecreateFilterTest(
) throws DirectoryException {
Assert.assertEquals(regenerated, expectedToStringFilter, "original=" + originalFilter + ", expected=" + expectedToStringFilter);
}
/** These are valid filters. */
'a', 'b', 'c', 'd', 'e', 'f',
'A', 'B', 'C', 'D', 'E', 'F'};
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
char highNibble = CHAR_NIBBLES[i];
byte highByteNibble = BYTE_NIBBLES[i];
char lowNibble = CHAR_NIBBLES[j];
byte lowByteNibble = BYTE_NIBBLES[j];
// Exact match
// Substring
// <=
// >=
// =~
// =~
}
}
}
/** These are filters with invalid escape sequences. */
'a', 'b', 'c', 'd', 'e', 'f',
'A', 'B', 'C', 'D', 'E', 'F'};
'n', 't', '\\'};
for (char validNibble : VALID_NIBBLES)
{
for (char invalidNibble : INVALID_NIBBBLES)
{
}
// Also do a test case where we only have one character in the escape sequence.
}
// Exact match
// Substring
allParameters.add(new String[]{"(sn=" + invalidEscape + "*" + invalidEscape + "*" + invalidEscape + ")"});
allParameters.add(new String[]{"(sn=" + invalidEscape + "*" + invalidEscape + "*" + invalidEscape});
// <=
// >=
// =~
// =~
}
}
/**
* @return a value that can be used in an LDAP filter.
*/
{
}
}
public void testRecreateFilterWithEscape(
) throws DirectoryException {
}
expectedExceptions = DirectoryException.class)
public void testFilterWithInvalidEscape(
throws DirectoryException {
// This should fail with a parse error.
}
// -------------------------------------------------------------------------
//
// Test invalid filters.
//
// -------------------------------------------------------------------------
/** Invalid filters that are detected. */
return new Object[][]{
{null},
{"(cn)"},
{"()"},
{"("},
{"(&(sn=test)"},
{"(|(sn=test)"},
{"(!(sn=test)"},
{"(&(sn=test)))"},
{"(|(sn=test)))"},
{"(!(sn=test)))"},
{"(sn=\\A)"},
{"(sn=\\1H)"},
{"(sn=\\H1)"},
{"(!(sn=test)(cn=test))"},
{"(!)"},
{"(:dn:=Sally)"}
};
}
expectedExceptions = DirectoryException.class)
throws DirectoryException {
}
/**
* This is more or less the same as what's above, but it's for invalid
* filters that are not currently detected by the parser. To turn these
* on, remove them from the broken group. As the code is modified to handle
* these cases, please add these test cases to the
* paramsCreateFilterFromStringInvalidFilters DataProvider.
*/
return new Object[][]{
{"(cn=**)"},
{"( sn = test )"},
{"&(cn=*)"},
{"(!(sn=test)(sn=test2))"},
{"(objectclass=**)"},
};
}
expectedExceptions = DirectoryException.class,
// FIXME: These currently aren't detected
enabled = false)
throws DirectoryException {
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// matches
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
"dn: cn=John Smith,dc=example,dc=com",
"objectclass: inetorgperson",
"cn: John Smith",
"cn;lang-en: Jonathan Smith",
"sn: Smith",
"givenname: John",
"internationaliSDNNumber: 12345",
"displayName: *",
"title: tattoos",
"labeledUri: http://opends.org/john"
);
return new Object[][]{
{JOHN_SMITH_LDIF, "(objectclass=inetorgperson)", true},
{JOHN_SMITH_LDIF, "(objectclass=iNetOrgPeRsOn)", true},
{JOHN_SMITH_LDIF, "(objectclass=*)", true},
{JOHN_SMITH_LDIF, "(objectclass=person)", false},
{JOHN_SMITH_LDIF, "(cn=John Smith)", true},
{JOHN_SMITH_LDIF, "(cn=Jonathan Smith)", true},
{JOHN_SMITH_LDIF, "(cn=JOHN SmITh)", true},
{JOHN_SMITH_LDIF, "(cn=*)", true},
{JOHN_SMITH_LDIF, "(cn=*John Smith*)", true},
{JOHN_SMITH_LDIF, "(cn=*Jo*ith*)", true},
{JOHN_SMITH_LDIF, "(cn=*Jo*i*th*)", true},
{JOHN_SMITH_LDIF, "(cn=*o*n*)", true},
{JOHN_SMITH_LDIF, "(cn=*n*o*)", false},
// attribute options
{JOHN_SMITH_LDIF, "(cn;lang-en=Jonathan Smith)", true},
{JOHN_SMITH_LDIF, "(cn;lang-EN=Jonathan Smith)", true},
{JOHN_SMITH_LDIF, "(cn;lang-en=Jonathan Smithe)", false},
{JOHN_SMITH_LDIF, "(cn;lang-fr=Jonathan Smith)", false},
{JOHN_SMITH_LDIF, "(cn;lang-en=*jon*an*)", true},
{JOHN_SMITH_LDIF, "(cn;lAnG-En=*jon*an*)", true},
// attribute subtypes. Enable this once 593 is fixed.
{JOHN_SMITH_LDIF, "(name=John Smith)", true},
{JOHN_SMITH_LDIF, "(name=*Smith*)", true},
{JOHN_SMITH_LDIF, "(name;lang-en=Jonathan Smith)", true},
{JOHN_SMITH_LDIF, "(name;lang-EN=Jonathan Smith)", true},
{JOHN_SMITH_LDIF, "(name;lang-en=*Jonathan*)", true},
// Enable this once
// {JOHN_SMITH_LDIF, "(cn=*Jo**i*th*)", true},
{JOHN_SMITH_LDIF, "(|(cn=Jane Smith)(cn=John Smith))", true},
{JOHN_SMITH_LDIF, "(title~=tattoos)", true},
{JOHN_SMITH_LDIF, "(title~=tattos)", true},
{JOHN_SMITH_LDIF, "(labeledUri=http://opends.org/john)", true},
{JOHN_SMITH_LDIF, "(labeledUri=http://opends.org/JOHN)", false},
{JOHN_SMITH_LDIF, "(labeledUri=http://*/john)", true},
{JOHN_SMITH_LDIF, "(labeledUri=http://*/JOHN)", false},
{JOHN_SMITH_LDIF, "(cn>=John Smith)", true},
{JOHN_SMITH_LDIF, "(cn>=J)", true},
{JOHN_SMITH_LDIF, "(cn<=J)", false},
{JOHN_SMITH_LDIF, "(cn=Jane Smith)", false},
// 2.5.4.4 is Smith
{JOHN_SMITH_LDIF, "(2.5.4.4=Smith)", true},
{JOHN_SMITH_LDIF, "(sn:caseExactMatch:=Smith)", true},
{JOHN_SMITH_LDIF, "(sn:caseExactMatch:=smith)", false},
// Test cases for 730
{JOHN_SMITH_LDIF, "(internationaliSDNNumber=*12*45*)", true},
{JOHN_SMITH_LDIF, "(internationaliSDNNumber=*45*12*)", false},
// TODO: open a bug for all of these.
// {JOHN_SMITH_LDIF, "(:caseExactMatch:=Smith)", true},
// {JOHN_SMITH_LDIF, "(:caseExactMatch:=NotSmith)", false},
// Look at 4515 for some more examples. Ask Neil.
// {JOHN_SMITH_LDIF, "(:dn:caseExactMatch:=example)", true},
// {JOHN_SMITH_LDIF, "(:dn:caseExactMatch:=notexample)", false},
};
}
}
private void runMatchTest(String ldifEntry, String filterStr, boolean expectMatch) throws Exception {
}
private void runSingleMatchTest(Entry entry, String filterStr, boolean expectMatch) throws Exception {
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//
// Filter construction
//
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
return TestCaseUtils.makeLdif(
"objectclass: inetorgperson",
"cn: " + cn,
"sn: " + sn,
"givenname: " + givenname
);
}
return unmatched;
}
private static class FilterDescription {
private boolean dnAttributes;
}
}
return "FilterDescription: \n" +
}
// Flip-flop these
return negation;
}
return that;
}
}
String... matchedEntries) {
} else {
}
return description;
}
String... matchedEntries) {
return assertionFilterDescription(FilterType.EQUALITY, attributeType, attributeValue, matchedEntries);
}
String... matchedEntries) {
return assertionFilterDescription(FilterType.LESS_OR_EQUAL, attributeType, attributeValue, matchedEntries);
}
String... matchedEntries) {
return assertionFilterDescription(FilterType.GREATER_OR_EQUAL, attributeType, attributeValue, matchedEntries);
}
String... matchedEntries) {
return assertionFilterDescription(FilterType.APPROXIMATE_MATCH, attributeType, attributeValue, matchedEntries);
}
{
{
}
}
return description;
}
}
return notFilters;
}
}
return andFilter;
}
}
}
return andFilters;
}
}
// Since we're not using Sets, we've whittled down unmatched entries from
// the full set instead of adding to matchedEntries, which would lead
// to duplicates.
return orFilter;
}
}
}
return orFilters;
}
return asList(
}
}
return asList(substringFilterDescription(
"sn",
}
return asList(
}
/**
* Updates to this should also be made in getMinimalFilterDescriptionList.
* @see #getMinimalFilterDescriptionList
*/
return allDescriptions;
}
return allDescriptions;
}
// Now convert to [][]
}
return descriptionArray;
}
}
}
}
// TODO: test more on extensible match and attribute options
// TODO: test that we fail when creating filters without specifying all of the parameters
// TODO: we need to test attribute options!
// TODO: test the audio attribute since it's octetStringMatch
// TODO: test the homePhone attribute since EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstringsMatch
// TODO: test labeledURI since it's caseExactMatch SUBSTR caseExactSubstringsMatch
// TODO: test mail since it's EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch
// TODO: test secretary since it's distinguishedNameMatch
// TODO: test x500UniqueIdentifier since it's bitStringMatch
// These have duplicates, and their String representation should even reflect that.
{"(&(sn=Smith))", "(&(sn=Smith)(sn=Smith))", true, true},
{"(|(sn=Smith))", "(|(sn=Smith)(sn=Smith))", true, true},
// These are reordered, so they are equivalent, but their String representations will differ
{"(&(sn=Smith)(sn<=Aus))", "(&(sn<=Aus)(sn=Smith))", true, false},
{"(|(sn=Smith)(sn<=Aus))", "(|(sn<=Aus)(sn=Smith))", true, false},
// These should be case insensitive
{"(SN=Smith)", "(sn=Smith)", true, true},
{"(SN=S*th)", "(sn=S*th)", true, true},
// We no longer normalize assertion values,
// so these filters are not equal
{"(sn=smith)", "(sn=Smith)", false, false},
{"(sn:caseExactMatch:=Smith)", "(sn:caseExactMatch:=Smith)", true, true},
// This demonstrates bug 704.
{"(sn:caseExactMatch:=Smith)", "(sn:caseExactMatch:=smith)", false, false},
// Ensure that ":dn:" is treated in a case-insensitive manner.
{"(:dn:caseExactMatch:=example)", "(:DN:caseExactMatch:=example)", true, true}, // ? String not match
// 2.5.4.4 is 'sn'
{"(2.5.4.4=Smith)", "(2.5.4.4=Smith)", true, true},
{"(2.5.4.4=Smith)", "(sn=Smith)", true, true},
{"(sn;lang-en=Smith)", "(sn;lang-en=Smith)", true, true},
// This demonstrates bug 706
{"(sn;lang-en=Smith)", "(sn=Smith)", false, false},
// This was initially to demonstrates bug 705.
// But we reverted back to old behavior,
// because we no longer normalize assertion values.
{"(sn=s*t*h)", "(sn=S*T*H)", false, false},
// These should be case sensitive
{"(labeledURI=http://opends.org)", "(labeledURI=http://OpenDS.org)", false, false},
{"(labeledURI=http://opends*)", "(labeledURI=http://OpenDS*)", false, false},
// These are WYSIWIG
{"(sn=*)", "(sn=*)", true, true},
{"(sn=S*)", "(sn=S*th)", false, false},
{"(sn=*S)", "(sn=S*th)", false, false},
{"(sn=S*t)", "(sn=S*th)", false, false},
{"(sn=*i*t*)", "(sn=*i*t*)", true, true},
{"(sn=*t*i*)", "(sn=*i*t*)", false, false}, // Test case for 695
{"(sn=S*i*t)", "(sn=S*th)", false, false},
{"(sn=Smith)", "(sn=Smith)", true, true},
{"(sn=Smith)", "(sn<=Aus)", false, false},
{"(sn=Smith)", "(sn>=Aus)", false, false},
{"(sn=Smith)", "(sn=S*i*th)", false, false},
{"(sn=Smith)", "(!(sn=Smith))", false, false},
{"(sn=Smith)", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(sn=Smith)", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(sn<=Aus)", "(sn<=Aus)", true, true},
{"(sn<=Aus)", "(sn>=Aus)", false, false},
{"(sn<=Aus)", "(sn=S*i*th)", false, false},
{"(sn<=Aus)", "(!(sn=Smith))", false, false},
{"(sn<=Aus)", "(&(sn=Smith)(sn=Smith))", false, false},
{"(sn<=Aus)", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(sn<=Aus)", "(|(sn=Smith)(sn=Smith))", false, false},
{"(sn<=Aus)", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(sn>=Aus)", "(sn>=Aus)", true, true},
{"(sn>=Aus)", "(sn=S*i*th)", false, false},
{"(sn>=Aus)", "(!(sn=Smith))", false, false},
{"(sn>=Aus)", "(&(sn=Smith)(sn=Smith))", false, false},
{"(sn>=Aus)", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(sn>=Aus)", "(|(sn=Smith)(sn=Smith))", false, false},
{"(sn>=Aus)", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(sn=S*i*th)", "(sn=S*i*th)", true, true},
{"(sn=S*i*th)", "(!(sn=Smith))", false, false},
{"(sn=S*i*th)", "(&(sn=Smith)(sn=Smith))", false, false},
{"(sn=S*i*th)", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(sn=S*i*th)", "(|(sn=Smith)(sn=Smith))", false, false},
{"(sn=S*i*th)", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(!(sn=Smith))", "(!(sn=Smith))", true, true},
{"(!(sn=Smith))", "(&(sn=Smith)(sn=Smith))", false, false},
{"(!(sn=Smith))", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(!(sn=Smith))", "(|(sn=Smith)(sn=Smith))", false, false},
{"(!(sn=Smith))", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(&(sn=Smith)(sn=Smith))", "(&(sn=Smith)(sn=Smith))", true, true},
{"(&(sn=Smith)(sn=Smith))", "(&(sn=Smith)(sn<=Aus))", false, false},
{"(&(sn=Smith)(sn=Smith))", "(|(sn=Smith)(sn=Smith))", false, false},
{"(&(sn=Smith)(sn=Smith))", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(&(sn=Smith)(sn<=Aus))", "(&(sn=Smith)(sn<=Aus))", true, true},
{"(&(sn=Smith)(sn<=Aus))", "(|(sn=Smith)(sn=Smith))", false, false},
{"(&(sn=Smith)(sn<=Aus))", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(|(sn=Smith)(sn=Smith))", "(|(sn=Smith)(sn=Smith))", true, true},
{"(|(sn=Smith)(sn=Smith))", "(|(sn=Smith)(sn<=Aus))", false, false},
{"(|(sn=Smith)(sn<=Aus))", "(|(sn=Smith)(sn<=Aus))", true, true},
{"(&(sn=Smith)(sn<=Aus))", "(&(sn=Smith)(sn>=Aus))", false, false},
{"(|(sn=Smith)(sn<=Aus))", "(|(sn=Smith)(sn>=Aus))", false, false},
// Test cases for issue #1245
{"(cn=*bowen*)", "(cn=*bowen*)", true, true},
{"(cn=*bowen*)", "(sn=*bowen*)", false, false}
};
return TEST_EQUALS_PARAMS;
}
public void testEquals(String stringFilter1, String stringFilter2, boolean expectEquals, boolean expectStringEquals) throws Exception {
// Test symmetry
if (expectEquals) {
}
// Test toString
}
/**
* Dataprovider for testing different normalization for value and assertion.
*/
{
final String BASE64_CERT_VALUE =
"BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" +
"dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" +
"Fw0xMjEyMjExNjM0MzVaMFYxCzAJBgNVBAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRp" +
"b25lMRwwGgYDVQQLExNQcm9kdWN0IERldmVsb3BtZW50MRQwEgYDVQQDEwtCYWJz" +
"IEplbnNlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApysa0c9qc8FB8gIJ" +
"mKeNUPitwiKOjoFDmtimcZ4bx5UTAYLbbHMpEdwSpMC5iF2UioM7qdiwpAfZBd6Z" +
"69vqNxuUJ6tP+hxtr/aSgMH2i8ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB" +
"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE" +
"FLlZD3aKDa8jdhzoByOFMAJDs2osMB8GA1UdIwQYMBaAFLlZD3aKDa8jdhzoByOF" +
"MAJDs2osMA0GCSqGSIb3DQEBBQUAA4GBAE5vccY8Ydd7by2bbwiDKgQqVyoKrkUg" +
"6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" +
"axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" +
"1AIUXiE3Qcck";
final String CERT_EXACT_ASSERTION =
"{ serialNumber 13233831500277100508, issuer rdnSequence:\""+
"CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }";
"dn: cn=John Smith,dc=example,dc=com",
"objectclass: inetorgperson",
"cn: John Smith",
"sn: Smith",
"userCertificate;binary:: "+BASE64_CERT_VALUE
);
return new Object[][]{
};
}
boolean expectMatch) throws Exception
{
}
}