s4:torture Add test for correct server-side sorting over LDAP
[ira/wip.git] / source4 / torture / ldap / ldap_sort.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Test LDB attribute functions
5    
6    Copyright (C) Andrew Bartlet <abartlet@samba.org> 2008-2009
7    Copyright (C) Matthieu Patou <mat@matws.net> 2009
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.     If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "ldb_wrap.h"
28 #include "param/param.h"
29 #include "lib/cmdline/popt_common.h" 
30 #include "torture/smbtorture.h"
31 #include "torture/local/proto.h"
32 #include <ctype.h>
33 bool torture_ldap_sort(struct torture_context *torture)
34 {
35
36         struct ldb_context *ldb;
37
38         bool ret = false;
39         const char *host = torture_setting_string(torture, "host", NULL);
40         char *url;
41         int i;
42         codepoint_t j;
43         struct ldb_message_element *elem;
44         struct ldb_message *msg;
45
46         struct ldb_server_sort_control **control;
47         struct ldb_request *req;
48         struct ldb_result *ctx;
49         struct ldb_val* prev = NULL;
50         const char *prev_txt = NULL;
51         int prev_len = 0;
52         struct ldb_val* cur = NULL;
53         const char *cur_txt = NULL;
54         int cur_len = 0;
55         struct ldb_dn* dn;
56                  
57                  
58         /* TALLOC_CTX* ctx;*/
59
60         url = talloc_asprintf(torture, "ldap://%s/", host);
61
62         ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, url,
63                                                  NULL,
64                                                  cmdline_credentials,
65                                                  0, NULL);
66         torture_assert(torture, ldb, "Failed to make LDB connection to target");
67
68         ctx = talloc_zero(ldb, struct ldb_result);
69
70         control = talloc_array(ctx, struct ldb_server_sort_control *, 2);
71         control[0] = talloc(control, struct ldb_server_sort_control);
72         control[0]->attributeName = talloc_strdup(control, "cn");
73         control[0]->orderingRule = NULL;
74         control[0]->reverse = 0;
75         control[1] = NULL;
76
77         dn = ldb_get_root_basedn(ldb);
78         ldb_dn_add_child_fmt(dn, "cn=users");
79         ret = ldb_build_search_req(&req, ldb, ctx,
80                                    dn,
81                                    LDB_SCOPE_SUBTREE,
82                                    "(objectClass=*)", NULL,
83                                    NULL,
84                                    ctx, ldb_search_default_callback, NULL);
85         torture_assert(torture, ret == LDB_SUCCESS, "Failed to build search request");
86
87         ret = ldb_request_add_control(req, LDB_CONTROL_SERVER_SORT_OID, true, control);
88         torture_assert(torture, ret == LDB_SUCCESS, "Failed to add control to search request");
89
90         ret = ldb_request(ldb, req);
91         torture_assert(torture, ret == LDB_SUCCESS, ldb_errstring(ldb));
92
93         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
94         torture_assert(torture, ret == LDB_SUCCESS, ldb_errstring(ldb));
95
96         ret = true;
97         if (ctx->count > 1) {
98                 for (i=0;i<ctx->count;i++) {
99                         msg = ctx->msgs[i];
100                         elem = ldb_msg_find_element(msg,"cn");
101                         cur = elem->values;
102                         torture_comment(torture, "cn: %s\n",cur->data);
103                         if (prev != NULL)
104                         {
105                                 /* Do only the ascii case right now ... */
106                                 cur_txt=cur->data;
107                                 cur_len=cur->length;
108                                 prev_txt=prev->data;
109                                 prev_len=prev->length;
110                                 /* Remove leading whitespace as the sort function do so ... */
111                                 while ( cur_txt[0] == cur_txt[1] ) { cur_txt++; cur_len--;}
112                                 while ( prev_txt[0] == prev_txt[1] ) { prev_txt++; prev_len--;}
113                                 while( *(cur_txt) && *(prev_txt) && cur_len && prev_len ) {
114                                         j = toupper_m(*(prev_txt))-toupper_m(*(cur_txt));
115                                         if ( j > 0 ) {
116                                                 /* Just check that is not due to trailling white space in prev_txt 
117                                                  * That is to say *cur_txt = 0 and prev_txt = 20 */
118                                                 /* Remove trailling whitespace */
119                                                 while ( *prev_txt == ' ' ) { prev_txt++; prev_len--;}
120                                                 while ( *cur_txt == ' ' ) { cur_txt++; cur_len--;}
121                                                 /* Now that potential whitespace are removed if we are at the end 
122                                                  * of the cur_txt then it means that in fact strings were identical
123                                                  */
124                                                 torture_assert(torture, *cur_txt && *prev_txt, "Data wrongly sorted");
125                                                 break;
126                                         }
127                                         else
128                                         {
129                                                 if ( j == 0 )
130                                                 {
131                                                         if ( *(cur_txt) == ' ') {
132                                                                 while ( cur_txt[0] == cur_txt[1] ) { cur_txt++; cur_len--;}
133                                                                 while ( prev_txt[0] == prev_txt[1] ) { prev_txt++; prev_len--;}
134                                                         }
135                                                         cur_txt++;
136                                                         prev_txt++;
137                                                         prev_len--;
138                                                         cur_len--;
139                                                 }
140                                                 else
141                                                 {
142                                                         break;
143                                                 } 
144                                         }
145                                 }
146                                 if ( ret != 1 ) {
147                                         break;
148                                 }
149                         }
150                         prev = cur; 
151                 }
152
153         }
154
155         return ret;
156 }