mirror of
https://github.com/samba-team/samba.git
synced 2025-08-14 09:49:28 +03:00
libcli/wsp: Test AQS parser
Signed-off-by: Noel Power <noel.power@suse.com> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
committed by
Andrew Bartlett
parent
68ce6cf684
commit
86d4342180
402
libcli/wsp/test_wsp_parser.c
Normal file
402
libcli/wsp/test_wsp_parser.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
#include <talloc.h>
|
||||
#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:($<somestring)",
|
||||
"All starts with somestring"
|
||||
},
|
||||
/* range */
|
||||
{
|
||||
"System.Size:10241-102401",
|
||||
"(System.Size >= 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);
|
||||
}
|
@ -31,3 +31,11 @@ bld.SAMBA_SUBSYSTEM('LIBSAMBA_WSP',
|
||||
public_deps='LIBSAMBA_WSP_PARSER',
|
||||
enabled=bld.env.with_wsp
|
||||
)
|
||||
|
||||
bld.SAMBA_BINARY('test_wsp_parser',
|
||||
source='test_wsp_parser.c',
|
||||
deps= 'dcerpc CMDLINE_S3 LIBSAMBA_WSP NDR_WSP NDR_WSP_DATA WSP_UTIL cmocka',
|
||||
enabled=bld.env.with_wsp,
|
||||
install=False
|
||||
)
|
||||
|
||||
|
@ -457,6 +457,8 @@ plantestsuite("samba.unittests.auth.sam", "none",
|
||||
if have_heimdal_support and not using_system_gssapi:
|
||||
plantestsuite("samba.unittests.auth.heimdal_gensec_unwrap_des", "none",
|
||||
[valgrindify(os.path.join(bindir(), "test_heimdal_gensec_unwrap_des"))])
|
||||
plantestsuite("samba.unittests.test_wsp_parser", "none",
|
||||
[os.path.join(bindir(), "default/libcli/wsp/test_wsp_parser")] + [configuration])
|
||||
if with_elasticsearch_backend:
|
||||
plantestsuite("samba.unittests.mdsparser_es", "none",
|
||||
[os.path.join(bindir(), "default/source3/test_mdsparser_es")] + [configuration])
|
||||
|
Reference in New Issue
Block a user