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 }