LCOV - code coverage report
Current view: top level - libcli/wsp - test_wsp_parser.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 112 125 89.6 %
Date: 2024-04-21 15:09:00 Functions: 7 7 100.0 %

          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             : }

Generated by: LCOV version 1.14