From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- libcli/wsp/test_wsp_parser.c | 402 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 libcli/wsp/test_wsp_parser.c (limited to 'libcli/wsp/test_wsp_parser.c') diff --git a/libcli/wsp/test_wsp_parser.c b/libcli/wsp/test_wsp_parser.c new file mode 100644 index 0000000..9edebda --- /dev/null +++ b/libcli/wsp/test_wsp_parser.c @@ -0,0 +1,402 @@ +/* + * Unix SMB/CIFS implementation. + * Copyright (C) Noel Power + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "includes.h" +#include +#include +#include +#include "lib/cmdline/cmdline.h" +#include "libcli/util/ntstatus.h" +#include "lib/util/samba_util.h" +#include "lib/torture/torture.h" +#include "lib/param/param.h" +#include "libcli/wsp/wsp_aqs.h" +#include "bin/default/librpc/gen_ndr/ndr_wsp.h" +#include "librpc/wsp/wsp_util.h" + +/* + * some routines to help stringify the parsed AQS + * query so we can test parsing + */ + +static bool is_operator_node(t_query *node) +{ + if (node->type == eVALUE) { + return false; + } + return true; +} + +static const char *nodetype_as_string(t_nodetype node) +{ + const char *result = NULL; + switch (node) { + case eNOT: + result = "NOT"; + break; + case eAND: + result = "AND"; + break; + case eOR: + result = "OR"; + break; + case eVALUE: + default: + break; + } + return result; +} + +static const char *restriction_as_string(TALLOC_CTX *ctx, + struct wsp_crestriction *crestriction ) +{ + const char *result = NULL; + if (crestriction->ultype == RTPROPERTY) { + struct wsp_cpropertyrestriction *prop_restr = + &crestriction->restriction.cpropertyrestriction; + struct wsp_cbasestoragevariant *value = &prop_restr->prval; + result = variant_as_string(ctx, value, true); + } else { + struct wsp_ccontentrestriction *cont_restr = NULL; + cont_restr = &crestriction->restriction.ccontentrestriction; + result = talloc_strdup(ctx, cont_restr->pwcsphrase); + } + return result; +} + +static const char *prop_name_from_restriction( + TALLOC_CTX *ctx, + struct wsp_crestriction *restriction) +{ + const char *result = NULL; + struct wsp_cfullpropspec *prop; + if (restriction->ultype == RTCONTENT) { + prop = &restriction->restriction.ccontentrestriction.property; + } else { + prop = &restriction->restriction.cpropertyrestriction.property; + } + result = prop_from_fullprop(ctx, prop); + return result; +} + +static char *print_basic_query(TALLOC_CTX *ctx, + struct wsp_crestriction *restriction) +{ + const char *op_str = op_as_string(restriction); + const char *val_str = restriction_as_string(ctx, restriction); + const char *prop_name = prop_name_from_restriction(ctx, restriction); + char *res = talloc_asprintf(ctx, + "%s %s %s", prop_name, op_str ? op_str : "", val_str); + return res; +} + +static char *print_node(TALLOC_CTX *ctx, t_query *node, bool is_rpn) +{ + switch(node->type) { + case eAND: + case eOR: + case eNOT: + return talloc_asprintf(ctx, + " %s ", nodetype_as_string(node->type)); + break; + case eVALUE: + default: + return print_basic_query(ctx, node->restriction); + break; + } +} + +/* + * Algorithm infix (tree) + * Print the infix expression for an expression tree. + * Pre : tree is a pointer to an expression tree + * Post: the infix expression has been printed + * start infix + * if (tree not empty) + * if (tree token is operator) + * print (open parenthesis) + * end if + * infix (tree left subtree) + * print (tree token) + * infix (tree right subtree) + * if (tree token is operator) + * print (close parenthesis) + * end if + * end if + * end infix + */ + +static char *infix(TALLOC_CTX *ctx, t_query *tree) +{ + char *sresult = NULL; + char *stree = NULL; + char *sleft = NULL; + char *sright = NULL; + if (tree == NULL) { + return NULL; + } + + if (is_operator_node(tree)) { + sresult = talloc_strdup(ctx, "("); + SMB_ASSERT(sresult != NULL); + } + sleft = infix(ctx, tree->left); + stree = print_node(ctx, tree, false); + sright = infix(ctx, tree->right); + sresult = talloc_asprintf(ctx, "%s%s%s%s", + sresult ? sresult : "", + sleft ? sleft : "", + stree? stree : "", + sright ? sright : ""); + + if (is_operator_node(tree)) { + sresult = talloc_asprintf(ctx, "%s)", sresult); + SMB_ASSERT(sresult != NULL); + } + return sresult; +} + +static struct { + const char *aqs; + const char *stringified; +} no_col_map_queries [] = { + + /* equals (numeric) */ + { + "System.Size:10241", + "System.Size = 10241" + }, + { + "System.Size := 10241", + "System.Size = 10241" + }, + /* not equals */ + { + "System.Size:!=10241", + "System.Size != 10241" + }, + /* equals (string property) */ + { + "ALL:(somestring)", + "All = 'somestring'" + }, + { + "ALL:=somestring", + "All = 'somestring'" + }, + { + "ALL:somestring", + "All = 'somestring'" + }, + /* not equals (string) */ + { + "ALL:!=somestring", + "All != 'somestring'" + }, + /* Greater than */ + { + "System.Size:(>10241)", + "System.Size > 10241" + }, + { + "System.Size:>10241", + "System.Size > 10241" + }, + /* Less than */ + { + "System.Size:(<10241)", + "System.Size < 10241" + }, + /* Greater than or equals */ + { + "System.Size:(>=10241)", + "System.Size >= 10241" + }, + { + "System.Size:>=10241", + "System.Size >= 10241" + }, + /* Less than or equals */ + { + "System.Size:(<=10241)", + "System.Size <= 10241" + }, + { + "System.Size:<=10241", + "System.Size <= 10241" + }, + /* equals (in the sense of matches) */ + { + "ALL:($=somestring)", + "All equals somestring" + }, + /* starts with */ + { + "ALL:($= 10241 AND System.Size < 102401)" + }, + { + "System.Size:small", + "(System.Size >= 10241 AND System.Size < 102401)" + }, + /* NOT */ + { + "NOT System.Size:10241", + "( NOT System.Size = 10241)" + }, + /* AND */ + { + "System.Size:(>=10241) AND System.Size:(<102401)", + "(System.Size >= 10241 AND System.Size < 102401)" + }, + /* OR */ + { + "System.Kind:picture OR System.Kind:video", + "(System.Kind = 'picture' OR System.Kind = 'video')" + }, + /* MULTIPLE LOGICAL */ + { + "System.Kind:picture AND NOT System.Kind:video OR " + "System.Kind:movie", + "(System.Kind = 'picture' AND (( NOT System.Kind = 'video') OR " + "System.Kind = 'movie'))" + }, + /* parenthesized MULTIPLE LOGICAL */ + { + "(System.Kind:picture AND NOT System.Kind:video) OR " + "System.Kind:movie", + "((System.Kind = 'picture' AND ( NOT System.Kind = 'video')) " + "OR System.Kind = 'movie')" + }, +}; + +static char *dump_cols(TALLOC_CTX *ctx, t_select_stmt *select) +{ + t_col_list *cols = select->cols; + char *res = NULL; + if (cols) { + int i; + for (i = 0; i < cols->num_cols; i++) { + if (i == 0) { + res = talloc_strdup(ctx, + cols->cols[i]); + } else { + res = talloc_asprintf(ctx, + "%s, %s", + res, cols->cols[i]); + } + } + } + return res; +} + +static void test_wsp_parser(void **state) +{ + int i; + t_select_stmt *select_stmt = NULL; + const char *col_query = + "SELECT System.ItemName, System.ItemURL, System.Size WHERE " + "System.Kind:picture"; + char *res = NULL; + + TALLOC_CTX *frame = talloc_stackframe(); + for (i = 0; i < ARRAY_SIZE(no_col_map_queries); i++) { + select_stmt = get_wsp_sql_tree(no_col_map_queries[i].aqs); + assert_non_null(select_stmt); + assert_null(select_stmt->cols); + res = infix(frame, select_stmt->where); + DBG_DEBUG("reading query => %s parsed => %s\n", + no_col_map_queries[i].aqs, + res); + assert_string_equal(res, no_col_map_queries[i].stringified); + } + select_stmt = get_wsp_sql_tree(col_query); + res = infix(frame, select_stmt->where); + assert_string_equal(res, "System.Kind = 'picture'"); + assert_non_null(select_stmt->cols); + res = dump_cols(frame, select_stmt); + assert_string_equal(res, + "System.ItemName, System.ItemURL, System.Size"); + TALLOC_FREE(frame); +} + +int main(int argc, const char *argv[]) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_wsp_parser), + }; + struct poptOption long_options[] = { + POPT_AUTOHELP + POPT_COMMON_SAMBA + POPT_TABLEEND + }; + poptContext pc; + int opt; + bool ok; + struct loadparm_context *lp_ctx = NULL; + + TALLOC_CTX *frame = talloc_stackframe(); + + smb_init_locale(); + + ok = samba_cmdline_init(frame, + SAMBA_CMDLINE_CONFIG_CLIENT, + false /* require_smbconf */); + if (!ok) { + DBG_ERR("Failed to init cmdline parser!\n"); + TALLOC_FREE(frame); + exit(1); + } + + lp_ctx = samba_cmdline_get_lp_ctx(); + if (!lp_ctx) { + DBG_ERR("Failed to init cmdline parser!\n"); + TALLOC_FREE(frame); + exit(1); + } + + lpcfg_set_cmdline(lp_ctx, "log level", "1"); + + pc = samba_popt_get_context(getprogname(), + argc, + argv, + long_options, + 0); + if (pc == NULL) { + DBG_ERR("Failed to setup popt context!\n"); + TALLOC_FREE(frame); + exit(1); + } + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "Unknown Option: %c\n", opt); + exit(1); + } + } + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} -- cgit v1.2.3