Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Copyright (C) Noel Power
4 : *
5 : * This program is free software; you can redistribute it and/or modify
6 : * it under the terms of the GNU General Public License as published by
7 : * the Free Software Foundation; either version 3 of the License, or
8 : * (at your option) any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 : */
18 :
19 : #include "includes.h"
20 : #include <setjmp.h>
21 : #include <cmocka.h>
22 : #include <talloc.h>
23 : #include "lib/cmdline/cmdline.h"
24 : #include "libcli/util/ntstatus.h"
25 : #include "lib/util/samba_util.h"
26 : #include "lib/torture/torture.h"
27 : #include "lib/param/param.h"
28 : #include "libcli/wsp/wsp_aqs.h"
29 : #include "bin/default/librpc/gen_ndr/ndr_wsp.h"
30 : #include "librpc/wsp/wsp_util.h"
31 :
32 : /*
33 : * some routines to help stringify the parsed AQS
34 : * query so we can test parsing
35 : */
36 :
37 86 : static bool is_operator_node(t_query *node)
38 : {
39 86 : if (node->type == eVALUE) {
40 : return false;
41 : }
42 : return true;
43 : }
44 :
45 11 : static const char *nodetype_as_string(t_nodetype node)
46 : {
47 11 : const char *result = NULL;
48 11 : switch (node) {
49 : case eNOT:
50 : result = "NOT";
51 : break;
52 5 : case eAND:
53 5 : result = "AND";
54 5 : break;
55 3 : case eOR:
56 3 : result = "OR";
57 3 : break;
58 : case eVALUE:
59 : default:
60 : break;
61 : }
62 11 : return result;
63 : }
64 :
65 32 : static const char *restriction_as_string(TALLOC_CTX *ctx,
66 : struct wsp_crestriction *crestriction )
67 : {
68 32 : const char *result = NULL;
69 32 : if (crestriction->ultype == RTPROPERTY) {
70 30 : struct wsp_cpropertyrestriction *prop_restr =
71 : &crestriction->restriction.cpropertyrestriction;
72 30 : struct wsp_cbasestoragevariant *value = &prop_restr->prval;
73 30 : result = variant_as_string(ctx, value, true);
74 : } else {
75 2 : struct wsp_ccontentrestriction *cont_restr = NULL;
76 2 : cont_restr = &crestriction->restriction.ccontentrestriction;
77 2 : result = talloc_strdup(ctx, cont_restr->pwcsphrase);
78 : }
79 32 : return result;
80 : }
81 :
82 32 : static const char *prop_name_from_restriction(
83 : TALLOC_CTX *ctx,
84 : struct wsp_crestriction *restriction)
85 : {
86 32 : const char *result = NULL;
87 32 : struct wsp_cfullpropspec *prop;
88 32 : if (restriction->ultype == RTCONTENT) {
89 2 : prop = &restriction->restriction.ccontentrestriction.property;
90 : } else {
91 30 : prop = &restriction->restriction.cpropertyrestriction.property;
92 : }
93 32 : result = prop_from_fullprop(ctx, prop);
94 32 : return result;
95 : }
96 :
97 32 : static char *print_basic_query(TALLOC_CTX *ctx,
98 : struct wsp_crestriction *restriction)
99 : {
100 32 : const char *op_str = op_as_string(restriction);
101 32 : const char *val_str = restriction_as_string(ctx, restriction);
102 32 : const char *prop_name = prop_name_from_restriction(ctx, restriction);
103 32 : char *res = talloc_asprintf(ctx,
104 : "%s %s %s", prop_name, op_str ? op_str : "", val_str);
105 32 : return res;
106 : }
107 :
108 43 : static char *print_node(TALLOC_CTX *ctx, t_query *node, bool is_rpn)
109 : {
110 43 : switch(node->type) {
111 11 : case eAND:
112 : case eOR:
113 : case eNOT:
114 19 : return talloc_asprintf(ctx,
115 : " %s ", nodetype_as_string(node->type));
116 32 : break;
117 32 : case eVALUE:
118 : default:
119 32 : return print_basic_query(ctx, node->restriction);
120 43 : break;
121 : }
122 : }
123 :
124 : /*
125 : * Algorithm infix (tree)
126 : * Print the infix expression for an expression tree.
127 : * Pre : tree is a pointer to an expression tree
128 : * Post: the infix expression has been printed
129 : * start infix
130 : * if (tree not empty)
131 : * if (tree token is operator)
132 : * print (open parenthesis)
133 : * end if
134 : * infix (tree left subtree)
135 : * print (tree token)
136 : * infix (tree right subtree)
137 : * if (tree token is operator)
138 : * print (close parenthesis)
139 : * end if
140 : * end if
141 : * end infix
142 : */
143 :
144 110 : static char *infix(TALLOC_CTX *ctx, t_query *tree)
145 : {
146 110 : char *sresult = NULL;
147 110 : char *stree = NULL;
148 110 : char *sleft = NULL;
149 110 : char *sright = NULL;
150 110 : if (tree == NULL) {
151 : return NULL;
152 : }
153 :
154 43 : if (is_operator_node(tree)) {
155 11 : sresult = talloc_strdup(ctx, "(");
156 11 : SMB_ASSERT(sresult != NULL);
157 : }
158 43 : sleft = infix(ctx, tree->left);
159 43 : stree = print_node(ctx, tree, false);
160 43 : sright = infix(ctx, tree->right);
161 142 : sresult = talloc_asprintf(ctx, "%s%s%s%s",
162 : sresult ? sresult : "",
163 : sleft ? sleft : "",
164 : stree? stree : "",
165 : sright ? sright : "");
166 :
167 43 : if (is_operator_node(tree)) {
168 11 : sresult = talloc_asprintf(ctx, "%s)", sresult);
169 11 : SMB_ASSERT(sresult != NULL);
170 : }
171 : return sresult;
172 : }
173 :
174 : static struct {
175 : const char *aqs;
176 : const char *stringified;
177 : } no_col_map_queries [] = {
178 :
179 : /* equals (numeric) */
180 : {
181 : "System.Size:10241",
182 : "System.Size = 10241"
183 : },
184 : {
185 : "System.Size := 10241",
186 : "System.Size = 10241"
187 : },
188 : /* not equals */
189 : {
190 : "System.Size:!=10241",
191 : "System.Size != 10241"
192 : },
193 : /* equals (string property) */
194 : {
195 : "ALL:(somestring)",
196 : "All = 'somestring'"
197 : },
198 : {
199 : "ALL:=somestring",
200 : "All = 'somestring'"
201 : },
202 : {
203 : "ALL:somestring",
204 : "All = 'somestring'"
205 : },
206 : /* not equals (string) */
207 : {
208 : "ALL:!=somestring",
209 : "All != 'somestring'"
210 : },
211 : /* Greater than */
212 : {
213 : "System.Size:(>10241)",
214 : "System.Size > 10241"
215 : },
216 : {
217 : "System.Size:>10241",
218 : "System.Size > 10241"
219 : },
220 : /* Less than */
221 : {
222 : "System.Size:(<10241)",
223 : "System.Size < 10241"
224 : },
225 : /* Greater than or equals */
226 : {
227 : "System.Size:(>=10241)",
228 : "System.Size >= 10241"
229 : },
230 : {
231 : "System.Size:>=10241",
232 : "System.Size >= 10241"
233 : },
234 : /* Less than or equals */
235 : {
236 : "System.Size:(<=10241)",
237 : "System.Size <= 10241"
238 : },
239 : {
240 : "System.Size:<=10241",
241 : "System.Size <= 10241"
242 : },
243 : /* equals (in the sense of matches) */
244 : {
245 : "ALL:($=somestring)",
246 : "All equals somestring"
247 : },
248 : /* starts with */
249 : {
250 : "ALL:($<somestring)",
251 : "All starts with somestring"
252 : },
253 : /* range */
254 : {
255 : "System.Size:10241-102401",
256 : "(System.Size >= 10241 AND System.Size < 102401)"
257 : },
258 : {
259 : "System.Size:small",
260 : "(System.Size >= 10241 AND System.Size < 102401)"
261 : },
262 : /* NOT */
263 : {
264 : "NOT System.Size:10241",
265 : "( NOT System.Size = 10241)"
266 : },
267 : /* AND */
268 : {
269 : "System.Size:(>=10241) AND System.Size:(<102401)",
270 : "(System.Size >= 10241 AND System.Size < 102401)"
271 : },
272 : /* OR */
273 : {
274 : "System.Kind:picture OR System.Kind:video",
275 : "(System.Kind = 'picture' OR System.Kind = 'video')"
276 : },
277 : /* MULTIPLE LOGICAL */
278 : {
279 : "System.Kind:picture AND NOT System.Kind:video OR "
280 : "System.Kind:movie",
281 : "(System.Kind = 'picture' AND (( NOT System.Kind = 'video') OR "
282 : "System.Kind = 'movie'))"
283 : },
284 : /* parenthesized MULTIPLE LOGICAL */
285 : {
286 : "(System.Kind:picture AND NOT System.Kind:video) OR "
287 : "System.Kind:movie",
288 : "((System.Kind = 'picture' AND ( NOT System.Kind = 'video')) "
289 : "OR System.Kind = 'movie')"
290 : },
291 : };
292 :
293 1 : static char *dump_cols(TALLOC_CTX *ctx, t_select_stmt *select)
294 : {
295 1 : t_col_list *cols = select->cols;
296 1 : char *res = NULL;
297 1 : if (cols) {
298 : int i;
299 4 : for (i = 0; i < cols->num_cols; i++) {
300 3 : if (i == 0) {
301 1 : res = talloc_strdup(ctx,
302 1 : cols->cols[i]);
303 : } else {
304 2 : res = talloc_asprintf(ctx,
305 : "%s, %s",
306 2 : res, cols->cols[i]);
307 : }
308 : }
309 : }
310 1 : return res;
311 : }
312 :
313 1 : static void test_wsp_parser(void **state)
314 : {
315 1 : int i;
316 1 : t_select_stmt *select_stmt = NULL;
317 1 : const char *col_query =
318 : "SELECT System.ItemName, System.ItemURL, System.Size WHERE "
319 : "System.Kind:picture";
320 1 : char *res = NULL;
321 :
322 1 : TALLOC_CTX *frame = talloc_stackframe();
323 25 : for (i = 0; i < ARRAY_SIZE(no_col_map_queries); i++) {
324 23 : select_stmt = get_wsp_sql_tree(no_col_map_queries[i].aqs);
325 23 : assert_non_null(select_stmt);
326 23 : assert_null(select_stmt->cols);
327 23 : res = infix(frame, select_stmt->where);
328 23 : DBG_DEBUG("reading query => %s parsed => %s\n",
329 : no_col_map_queries[i].aqs,
330 : res);
331 23 : assert_string_equal(res, no_col_map_queries[i].stringified);
332 : }
333 1 : select_stmt = get_wsp_sql_tree(col_query);
334 1 : res = infix(frame, select_stmt->where);
335 1 : assert_string_equal(res, "System.Kind = 'picture'");
336 1 : assert_non_null(select_stmt->cols);
337 1 : res = dump_cols(frame, select_stmt);
338 1 : assert_string_equal(res,
339 : "System.ItemName, System.ItemURL, System.Size");
340 1 : TALLOC_FREE(frame);
341 1 : }
342 :
343 1 : int main(int argc, const char *argv[])
344 : {
345 1 : const struct CMUnitTest tests[] = {
346 : cmocka_unit_test(test_wsp_parser),
347 : };
348 2 : struct poptOption long_options[] = {
349 : POPT_AUTOHELP
350 1 : POPT_COMMON_SAMBA
351 : POPT_TABLEEND
352 : };
353 1 : poptContext pc;
354 1 : int opt;
355 1 : bool ok;
356 1 : struct loadparm_context *lp_ctx = NULL;
357 :
358 1 : TALLOC_CTX *frame = talloc_stackframe();
359 :
360 1 : smb_init_locale();
361 :
362 1 : ok = samba_cmdline_init(frame,
363 : SAMBA_CMDLINE_CONFIG_CLIENT,
364 : false /* require_smbconf */);
365 1 : if (!ok) {
366 0 : DBG_ERR("Failed to init cmdline parser!\n");
367 0 : TALLOC_FREE(frame);
368 0 : exit(1);
369 : }
370 :
371 1 : lp_ctx = samba_cmdline_get_lp_ctx();
372 1 : if (!lp_ctx) {
373 0 : DBG_ERR("Failed to init cmdline parser!\n");
374 0 : TALLOC_FREE(frame);
375 0 : exit(1);
376 : }
377 :
378 1 : lpcfg_set_cmdline(lp_ctx, "log level", "1");
379 :
380 1 : pc = samba_popt_get_context(getprogname(),
381 : argc,
382 : argv,
383 : long_options,
384 : 0);
385 1 : if (pc == NULL) {
386 0 : DBG_ERR("Failed to setup popt context!\n");
387 0 : TALLOC_FREE(frame);
388 0 : exit(1);
389 : }
390 :
391 1 : while ((opt = poptGetNextOpt(pc)) != -1) {
392 0 : switch(opt) {
393 0 : default:
394 0 : fprintf(stderr, "Unknown Option: %c\n", opt);
395 0 : exit(1);
396 : }
397 : }
398 :
399 1 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
400 :
401 1 : return cmocka_run_group_tests(tests, NULL, NULL);
402 : }
|