1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.operations.compare;
21
22
23 import javax.naming.NamingEnumeration;
24 import javax.naming.NamingException;
25 import javax.naming.directory.DirContext;
26 import javax.naming.directory.SearchControls;
27 import javax.naming.directory.SearchResult;
28
29 import org.apache.directory.server.core.integ.Level;
30 import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
31 import org.apache.directory.server.core.integ.annotations.CleanupLevel;
32 import org.apache.directory.server.integ.ServerIntegrationUtils;
33 import org.apache.directory.server.integ.SiRunner;
34 import org.apache.directory.server.ldap.LdapService;
35
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import static org.junit.Assert.assertEquals;
39
40
41 /**
42 * Tests with compare operations on attributes which use different matching
43 * rules. Created to demonstrate JIRA DIREVE-243 ("Compare operation does not
44 * adhere to some matching rules").
45 *
46 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47 * @version $Rev: 692919 $
48 */
49 @RunWith ( SiRunner.class )
50 @CleanupLevel ( Level.SUITE )
51 @ApplyLdifs( {
52 // Entry # 1
53 "dn: cn=Tori Amos,ou=system\n" +
54 "objectClass: person\n" +
55 "objectClass: top\n" +
56 "telephoneNumber: 1234567890\n" +
57 "userPassword: Secret1!\n" +
58 "cn: Tori Amos\n" +
59 "sn: Amos\n\n" +
60 // Entry # 2
61 "dn: cn=Artists,ou=system\n" +
62 "objectClass: groupOfNames\n" +
63 "objectClass: top\n" +
64 "cn: Artists\n" +
65 "member: cn=Tori Amos,ou=system\n\n"
66 }
67 )
68 public class MatchingRuleCompareIT
69 {
70 public static LdapService ldapService;
71
72 public static final String PERSON_CN = "Tori Amos";
73 public static final String PERSON_SN = "Amos";
74 public static final String PERSON_RDN = "cn=" + PERSON_CN;
75 public static final String PERSON_TELEPHONE = "1234567890";
76 public static final String PERSON_PWD = "Secret1!";
77
78 public static final String GROUP_CN = "Artists";
79 public static final String GROUP_RDN = "cn=" + GROUP_CN;
80
81
82 /**
83 * Compare with caseIgnoreMatch matching rule.
84 *
85 * @throws NamingException
86 */
87 @Test
88 public void testCaseIgnoreMatch() throws Exception
89 {
90 DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
91
92 // Setting up search controls for compare op
93 SearchControls ctls = new SearchControls();
94 ctls.setReturningAttributes( new String[]
95 {} ); // no attributes
96 ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
97
98 String[] values =
99 { PERSON_SN, PERSON_SN.toUpperCase(), PERSON_SN.toLowerCase(), PERSON_SN + "X" };
100 boolean[] expected =
101 { true, true, true, false };
102
103 for ( int i = 0; i < values.length; i++ )
104 {
105 String value = values[i];
106
107 NamingEnumeration<SearchResult> enumeration = ctx.search( PERSON_RDN, "sn={0}", new String[]
108 { value }, ctls );
109 boolean result = enumeration.hasMore();
110
111 assertEquals( "compare sn value '" + PERSON_SN + "' with '" + value + "'", expected[i], result );
112
113 enumeration.close();
114 }
115 }
116
117
118 //
119
120 /**
121 * Compare with telephoneNumberMatch matching rule.
122 *
123 * @throws NamingException
124 */
125
126 // Comment this out until we have the telephone number match working.
127 // public void testTelephoneNumberMatch() throws NamingException
128 // {
129 // // Setting up search controls for compare op
130 // SearchControls ctls = new SearchControls();
131 // ctls.setReturningAttributes(new String[] {}); // no attributes
132 // ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
133 //
134 // String[] values = { "", "1234567890abc", " 1234567890 A B C", "123 456 7890 abc", "123-456-7890 abC",
135 // "123456-7890 A bc" };
136 // boolean[] expected = { false, true, true, true, true, true };
137 //
138 // for (int i = 0; i < values.length; i++) {
139 // String value = values[i];
140 //
141 // NamingEnumeration enumeration = ctx.search(PERSON_RDN, "telephoneNumber={0}", new String[] { value }, ctls);
142 // boolean result = enumeration.hasMore();
143 //
144 // assertEquals("compare '" + PERSON_TELEPHONE + "' with '" + value + "'", expected[i], result);
145 //
146 // enumeration.close();
147 // }
148 // }
149 /**
150 * Compare with octetStringMatch matching rule.
151 *
152 * @throws NamingException
153 */
154
155 // Cannot search the directory using binary attributes. I don't know if this
156 // is valid according to specifications but this is the case with respect to apacheds
157 // and userPassword is a binary attribute type. This is why we get class cast
158 // exceptions for this search which fails. To make this succeed some simple changes
159 // are needed.
160
161 // public void testOctetStringMatch() throws NamingException
162 // {
163 // // Setting up search controls for compare op
164 // SearchControls ctls = new SearchControls();
165 // ctls.setReturningAttributes( new String[]
166 // {} ); // no attributes
167 // ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
168 //
169 // String[] values =
170 // { "", PERSON_PWD, PERSON_PWD.toUpperCase(), PERSON_PWD.toLowerCase(), PERSON_PWD + "X" };
171 // boolean[] expected =
172 // { false, true, false, false, false };
173 //
174 // for ( int i = 0; i < values.length; i++ )
175 // {
176 // String value = values[i];
177 //
178 // NamingEnumeration enumeration = ctx.search( PERSON_RDN, "userPassword={0}", new String[]
179 // { value }, ctls );
180 // boolean result = enumeration.hasMore();
181 //
182 // assertEquals( "compare '" + PERSON_PWD + "' with '" + value + "'", expected[i], result );
183 //
184 // enumeration.close();
185 // }
186 // }
187
188
189 /**
190 * Compare with distinguishedNameMatch matching rule.
191 *
192 * @throws NamingException
193 */
194 @Test
195 public void testDistinguishedNameMatch() throws Exception
196 {
197 DirContext ctx = ( DirContext ) ServerIntegrationUtils.getWiredContext( ldapService ).lookup( "ou=system" );
198
199 // determine member DN of person
200 DirContext member = ( DirContext ) ctx.lookup( PERSON_RDN );
201 String memberDN = member.getNameInNamespace();
202
203 // Setting up search controls for compare op
204 SearchControls ctls = new SearchControls();
205 ctls.setReturningAttributes( new String[]
206 {} ); // no attributes
207 ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
208
209 String[] values =
210 { "", memberDN, "cn=nobody", memberDN, PERSON_RDN + " , " + ctx.getNameInNamespace() };
211 boolean[] expected =
212 { false, true, false, true, true };
213
214 for ( int i = 0; i < values.length; i++ )
215 {
216 String value = values[i];
217
218 NamingEnumeration<SearchResult> enumeration = ctx.search( GROUP_RDN, "member={0}", new Object[]
219 { value }, ctls );
220 boolean result = enumeration.hasMore();
221
222 assertEquals( "compare '" + memberDN + "' with '" + value + "'", expected[i], result );
223
224 enumeration.close();
225 }
226 }
227 }