Motr  M0
filter_eval.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2017-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/errno.h"
24 #include "lib/memory.h"
25 #include "fdmi/filter.h"
26 #include "fdmi/filter_xc.h"
27 #include "fdmi/flt_eval.h"
28 #include "lib/finject.h"
29 #include "xcode/xcode.h"
30 #include "ut/ut.h"
31 #include "conf/obj.h" /* m0_conf_fdmi_filter */
32 
33 /* ------------------------------------------------------------------
34  * Helper: initialize and eval simple binary operand.
35  * ------------------------------------------------------------------ */
36 
38  struct m0_fdmi_flt_node *opnd1,
39  struct m0_fdmi_flt_node *opnd2,
40  struct m0_fdmi_eval_ctx *eval_ctx)
41 {
43  struct m0_fdmi_flt_node *root;
44  int rc;
45 
46  root = m0_fdmi_flt_op_node_create(op_code, opnd1, opnd2);
47  m0_fdmi_filter_init(&filter.ff_filter);
48  m0_fdmi_filter_root_set(&filter.ff_filter, root);
50 
51  rc = m0_fdmi_eval_flt(eval_ctx, &filter, NULL);
52 
53  m0_fdmi_filter_fini(&filter.ff_filter);
54 
55  return rc;
56 }
57 
58 /* ------------------------------------------------------------------
59  * Test Case: simple OR (M0_FFO_OR)
60  * ------------------------------------------------------------------ */
61 
62 static void flt_eval_simple_or(void)
63 {
64  bool frst_operand[] = { false, false, true, true };
65  bool sec_operand[] = { false, true, false, true };
66  bool result_vals[] = { false, true, true, true };
67 
68  struct m0_fdmi_eval_ctx eval_ctx;
69  int eval_res;
70  int i;
71 
72  m0_fdmi_eval_init(&eval_ctx);
73 
74  for (i = 0; i < ARRAY_SIZE(result_vals); i++) {
75  eval_res = flt_eval_binary_operator(
76  M0_FFO_OR,
77  m0_fdmi_flt_bool_node_create(frst_operand[i]),
78  m0_fdmi_flt_bool_node_create(sec_operand[i]),
79  &eval_ctx);
80  M0_UT_ASSERT(eval_res == result_vals[i]);
81  }
82  m0_fdmi_eval_fini(&eval_ctx);
83 }
84 
85 /* ------------------------------------------------------------------
86  * Test Case: simple GT (M0_FFO_GT)
87  * ------------------------------------------------------------------ */
88 
89 static void flt_eval_simple_gt(void)
90 {
91  struct pair0 {
92  int64_t lft_arg;
93  int64_t rgt_arg;
94  } args0[] = { {0,0}, {0,1}, {1,0}, {1,1}, {1,2}, {2,1}, {2,2},
95  {0,-1}, {-1,0}, {-1,-1}, {-1,2}, {2,-1},
96  {INT64_MIN, 0}, {0, INT64_MIN},
97  {INT64_MAX, 0}, {0, INT64_MAX},
100  };
101 
102  struct pair1 {
103  uint64_t lft_arg;
104  uint64_t rgt_arg;
105  } args1[] = { {0,0}, {0,1}, {1,0}, {1,1}, {1,2}, {2,1}, {2,2},
106  {UINT64_MAX, 0}, {0, UINT64_MAX},
108  };
109 
110  struct m0_fdmi_eval_ctx eval_ctx;
111  int eval_res;
112  int eval_expected;
113  int i;
114 
115  m0_fdmi_eval_init(&eval_ctx);
116 
117  /* Incompatible args */
118 
119  /* Incompatible args, #1 */
120  eval_res = flt_eval_binary_operator(
121  M0_FFO_GT,
124  &eval_ctx);
125  M0_UT_ASSERT(eval_res == -EINVAL);
126 
127  /* Incompatible args, #2 */
128  eval_res = flt_eval_binary_operator(
129  M0_FFO_GT,
132  &eval_ctx);
133  M0_UT_ASSERT(eval_res == -EINVAL);
134 
135  /* Incompatible args, #3 */
136  eval_res = flt_eval_binary_operator(
137  M0_FFO_GT,
140  &eval_ctx);
141  M0_UT_ASSERT(eval_res == -EINVAL);
142 
143  /* Incompatible args, #4 */
144  eval_res = flt_eval_binary_operator(
145  M0_FFO_GT,
148  &eval_ctx);
149  M0_UT_ASSERT(eval_res == -EINVAL);
150 
151  /* Int comparison */
152  for (i = 0; i < ARRAY_SIZE(args0); i++) {
153  eval_res = flt_eval_binary_operator(
154  M0_FFO_GT,
155  m0_fdmi_flt_int_node_create(args0[i].lft_arg),
156  m0_fdmi_flt_int_node_create(args0[i].rgt_arg),
157  &eval_ctx);
158  eval_expected = !!(args0[i].lft_arg > args0[i].rgt_arg);
159  M0_UT_ASSERT(eval_res >= 0);
160  M0_UT_ASSERT(eval_res == eval_expected);
161  }
162 
163  /* UInt comparison */
164  for (i = 0; i < ARRAY_SIZE(args1); i++) {
165  eval_res = flt_eval_binary_operator(
166  M0_FFO_GT,
167  m0_fdmi_flt_uint_node_create(args1[i].lft_arg),
168  m0_fdmi_flt_uint_node_create(args1[i].rgt_arg),
169  &eval_ctx);
170  eval_expected = !!(args1[i].lft_arg > args1[i].rgt_arg);
171  M0_UT_ASSERT(eval_res >= 0);
172  M0_UT_ASSERT(eval_res == eval_expected);
173  }
174 
175  m0_fdmi_eval_fini(&eval_ctx);
176 }
177 
178 /* ------------------------------------------------------------------
179  * Test Case: Register/deregister custom evaluator callback
180  * ------------------------------------------------------------------ */
181 
182 static bool flt_test_op_cb_called = false;
183 
184 static int flt_test_op_cb(struct m0_fdmi_flt_operands *opnds,
185  struct m0_fdmi_flt_operand *res)
186 {
188  flt_test_op_cb_called = true;
189  return 0;
190 }
191 
192 static void flt_set_op_cb(void)
193 {
194  struct m0_fdmi_eval_ctx eval_ctx;
195  int eval_res;
196  int rc;
197 
198  m0_fdmi_eval_init(&eval_ctx);
199 
200  /* first set must succeed */
202  M0_UT_ASSERT(rc == 0);
203 
204  /* second set must fail */
206  M0_UT_ASSERT(rc == -EEXIST);
207 
208  /* delete the CB */
210 
211  /* set must succeed */
213  M0_UT_ASSERT(rc == 0);
214 
215  /* try evaluate, must succeed */
216  eval_res = flt_eval_binary_operator(
217  M0_FFO_TEST,
220  &eval_ctx);
222  M0_UT_ASSERT(eval_res == true);
223 
224  m0_fdmi_eval_fini(&eval_ctx);
225 }
226 
227 /* ------------------------------------------------------------------
228  * Test Case: XCode conversions
229  * ------------------------------------------------------------------ */
230 
231 static void flt_eval_flt_xcode_str(void)
232 {
233  struct m0_fdmi_filter flt;
234  struct m0_fdmi_flt_node *root;
235  /* New root constructed by m0_xcode_read() */
236  struct m0_fdmi_flt_node *root_read;
237  char str[256];
238  int res;
239 
241  M0_FFO_OR,
244 
245  m0_fdmi_filter_init(&flt);
246 
248 
249  res = m0_xcode_print(&M0_XCODE_OBJ(m0_fdmi_flt_node_xc, flt.ff_root),
250  str, sizeof(str));
251 
252  M0_UT_ASSERT(res > 0);
253 
254  m0_fdmi_filter_fini(&flt);
255 
256  /* Read back searialized root node */
257  M0_ALLOC_PTR(root_read);
258  M0_ASSERT(root_read != NULL);
259 
260  m0_xcode_read(&M0_XCODE_OBJ(m0_fdmi_flt_node_xc, root_read), str);
261 
262  m0_fdmi_filter_init(&flt);
263  m0_fdmi_filter_root_set(&flt, root_read);
264  m0_fdmi_filter_fini(&flt);
265 }
266 
267 /* ------------------------------------------------------------------
268  * Test Case: Filter to string/from string operations
269  * ------------------------------------------------------------------ */
270 
271 static void flt_str_ops(void)
272 {
273  struct m0_fdmi_filter flt = {};
274  struct m0_fdmi_flt_node *root = NULL;
275  struct m0_fdmi_flt_node *root_read = NULL;
276  char *str = NULL;
277  int res;
278  int i;
279 
281  M0_FFO_OR,
284  M0_UT_ASSERT(root != NULL);
285 
286  m0_fdmi_filter_init(&flt);
287 
289 
290  /* Conversion fail (malloc fail) */
291  m0_fi_enable_off_n_on_m("m0_alloc", "fail_allocation", 0, 1);
293  m0_fi_disable("m0_alloc", "fail_allocation");
294  M0_UT_ASSERT(res == -ENOMEM);
295 
296  /* Conversion success when xcode print rc < FIRST_SIZE_GUESS*/
297  m0_fi_enable_off_n_on_m("m0_fdmi_flt_node_print",
298  "rc_bigger_than_size_guess", 0, 1);
300  m0_fi_disable("m0_fdmi_flt_node_print", "rc_bigger_than_size_guess");
301  M0_UT_ASSERT(res == 0);
302 
303  /* Conversion fail (malloc failed) */
304  m0_fi_enable_off_n_on_m("m0_alloc", "fail_allocation", 1, 1);
305  m0_fi_enable_off_n_on_m("m0_fdmi_flt_node_print",
306  "rc_bigger_than_size_guess", 0, 1);
308  m0_fi_disable("m0_fdmi_flt_node_print", "rc_bigger_than_size_guess");
309  m0_fi_disable("m0_alloc", "fail_allocation");
310  M0_UT_ASSERT(res == -ENOMEM);
311 
312  /* Conversion success */
314  M0_UT_ASSERT(res >= 0);
315  M0_UT_ASSERT(str != NULL);
316 
317  /* Back conversion */
318  M0_ALLOC_PTR(root_read);
319  M0_ASSERT(root_read != NULL);
320  res = m0_fdmi_flt_node_parse(str, root_read);
321  M0_UT_ASSERT(res >= 0);
322  M0_UT_ASSERT(root->ffn_type == root_read->ffn_type);
323  M0_UT_ASSERT(root->ffn_u.ffn_oper.ffon_op_code ==
324  root_read->ffn_u.ffn_oper.ffon_op_code);
325  M0_UT_ASSERT(root->ffn_u.ffn_oper.ffon_opnds.fno_cnt ==
326  root_read->ffn_u.ffn_oper.ffon_opnds.fno_cnt);
327 
328  /* deinit */
329  m0_free0(&str);
330 
331  m0_fdmi_filter_fini(&flt);
332 
333  m0_fdmi_filter_init(&flt);
334  m0_fdmi_filter_root_set(&flt, root_read);
335  m0_fdmi_filter_fini(&flt);
336 
337  /* Test case with nested tree (it's separate branch in str encode
338  * function. */
340  M0_FFO_OR,
343  M0_UT_ASSERT(root != NULL);
344  for (i = 0; i < 1; i++) {
346  M0_FFO_OR,
348  root);
349  M0_UT_ASSERT(root != NULL);
350  }
351 
352  m0_fdmi_filter_init(&flt);
353 
355 
356 #if 0
357  /* FIXME: fails; XCode is not able to process our nested structures. */
358  /* This functionality is not required for Phase1, so commenting the
359  * test out. */
360  {
361  /* Approach one: use our node-to-str; this is the target test,
362  * to get higher coverage, this is the latest non-covered code
363  * branch in filter.c */
364  // res = m0_fdmi_flt_node_to_str(root, &str);
365  // M0_UT_ASSERT(res >= 0);
366  // M0_UT_ASSERT(str != NULL);
367  }
368  { /* Hard-core approach, use core xcode functions. */
369  /* In my case, it fails on data_size call, not able to
370  * traverse the tree. */
371  struct m0_bufvec_cursor cur = {};
372  struct m0_bufvec bvec = {};
373  struct m0_xcode_ctx ctx = {};
374  struct m0_xcode_obj obj = {};
375  int len;
376 
377  obj = M0_XCODE_OBJ(m0_fdmi_flt_node_xc, root);
379  len = m0_xcode_data_size(&ctx, &obj);
380  res = m0_bufvec_alloc(&bvec, 1, len);
382 
383  res = m0_xcode_encdec(&M0_XCODE_OBJ(m0_fdmi_flt_node_xc, root),
384  &cur, M0_XCODE_ENCODE);
385  }
386 #endif
387 
388  /* deinit */
389  // m0_free0(&str);
390  m0_fdmi_filter_fini(&flt);
391 }
392 
393 /* ------------------------------------------------------------------
394  * Test Sute definition
395  * ------------------------------------------------------------------ */
396 
398  .ts_name = "fdmi-filter-eval-ut",
399  .ts_tests = {
400  { "simple-or", flt_eval_simple_or },
401  { "simple-gt", flt_eval_simple_gt },
402  { "callback", flt_set_op_cb },
404  { "filter-xcode-str", flt_eval_flt_xcode_str },
405  { "filter-str-ops", flt_str_ops },
406  { NULL, NULL },
407  },
408 };
409 
410 /*
411  * Local variables:
412  * c-indentation-style: "K&R"
413  * c-basic-offset: 8
414  * tab-width: 8
415  * fill-column: 80
416  * scroll-step: 1
417  * End:
418  */
419 /*
420  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
421  */
M0_INTERNAL int m0_fdmi_eval_add_op_cb(struct m0_fdmi_eval_ctx *ctx, enum m0_fdmi_flt_op_code op, m0_fdmi_flt_op_cb_t cb)
Definition: flt_eval.c:101
M0_INTERNAL int m0_xcode_encdec(struct m0_xcode_obj *obj, struct m0_bufvec_cursor *cur, enum m0_xcode_what what)
Definition: xcode.c:416
M0_INTERNAL int m0_xcode_print(const struct m0_xcode_obj *obj, char *str, int nr)
Definition: string.c:278
#define NULL
Definition: misc.h:38
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
M0_INTERNAL void m0_fdmi_filter_init(struct m0_fdmi_filter *flt)
Definition: filter.c:39
struct m0_fdmi_flt_node * m0_fdmi_flt_uint_node_create(uint64_t value)
Definition: filter.c:192
static void flt_str_ops(void)
Definition: filter_eval.c:271
M0_INTERNAL void m0_fdmi_flt_bool_opnd_fill(struct m0_fdmi_flt_operand *opnd, bool value)
Definition: filter.c:125
M0_INTERNAL int m0_xcode_read(struct m0_xcode_obj *obj, const char *str)
Definition: string.c:162
m0_fdmi_flt_op_code
Definition: filter.h:96
static bool flt_test_op_cb_called
Definition: filter_eval.c:182
#define INT64_MAX
Definition: types.h:46
static int flt_test_op_cb(struct m0_fdmi_flt_operands *opnds, struct m0_fdmi_flt_operand *res)
Definition: filter_eval.c:184
static int flt_eval_binary_operator(enum m0_fdmi_flt_op_code op_code, struct m0_fdmi_flt_node *opnd1, struct m0_fdmi_flt_node *opnd2, struct m0_fdmi_eval_ctx *eval_ctx)
Definition: filter_eval.c:37
Definition: ut.h:77
static struct foo * obj
Definition: tlist.c:302
M0_INTERNAL void m0_fdmi_eval_del_op_cb(struct m0_fdmi_eval_ctx *ctx, enum m0_fdmi_flt_op_code op)
Definition: flt_eval.c:119
uint32_t ffn_type
Definition: filter.h:237
M0_INTERNAL int m0_bufvec_alloc(struct m0_bufvec *bufvec, uint32_t num_segs, m0_bcount_t seg_size)
Definition: vec.c:220
M0_INTERNAL void m0_fdmi_eval_init(struct m0_fdmi_eval_ctx *ctx)
Definition: flt_eval.c:130
struct m0_fdmi_flt_node * m0_fdmi_flt_bool_node_create(bool value)
Definition: filter.c:136
struct m0_fdmi_flt_node * m0_fdmi_flt_int_node_create(int64_t value)
Definition: filter.c:164
Definition: filter.py:1
int i
Definition: dir.c:1033
struct m0_conf_root * root
Definition: note.c:50
struct m0_fdmi_flt_node * m0_fdmi_flt_op_node_create(enum m0_fdmi_flt_op_code op_code, struct m0_fdmi_flt_node *left, struct m0_fdmi_flt_node *right)
Definition: filter.c:227
M0_INTERNAL void m0_fi_disable(const char *fp_func, const char *fp_tag)
Definition: finject.c:485
#define m0_free0(pptr)
Definition: memory.h:77
#define M0_ASSERT(cond)
M0_INTERNAL int m0_fdmi_flt_node_parse(const char *str, struct m0_fdmi_flt_node *node)
Definition: filter.c:298
static struct m0_bufvec bvec
Definition: xcode.c:169
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
struct m0_ut_suite fdmi_filter_eval_ut
Definition: filter_eval.c:397
static void flt_set_op_cb(void)
Definition: filter_eval.c:192
#define UINT64_MAX
Definition: types.h:44
M0_INTERNAL void m0_fdmi_filter_fini(struct m0_fdmi_filter *flt)
Definition: filter.c:113
M0_INTERNAL int m0_fdmi_eval_flt(struct m0_fdmi_eval_ctx *ctx, struct m0_conf_fdmi_filter *filter, struct m0_fdmi_eval_var_info *var_info)
Definition: flt_eval.c:184
M0_INTERNAL int m0_xcode_data_size(struct m0_xcode_ctx *ctx, const struct m0_xcode_obj *obj)
Definition: xcode.c:437
M0_INTERNAL int m0_fdmi_flt_node_print(struct m0_fdmi_flt_node *node, char **out)
Definition: filter.c:252
static void m0_fi_enable_off_n_on_m(const char *func, const char *tag, uint32_t n, uint32_t m)
Definition: finject.h:346
M0_INTERNAL void m0_fdmi_filter_root_set(struct m0_fdmi_filter *flt, struct m0_fdmi_flt_node *root)
Definition: filter.c:49
struct m0_fdmi_flt_node * ff_root
Definition: filter.h:120
const char * ts_name
Definition: ut.h:99
static void flt_eval_flt_xcode_str(void)
Definition: filter_eval.c:231
union m0_fdmi_flt_node::@170 ffn_u
static void flt_eval_simple_or(void)
Definition: filter_eval.c:62
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
#define INT64_MIN
Definition: types.h:45
#define M0_XCODE_OBJ(type, ptr)
Definition: xcode.h:962
Definition: nucleus.c:42
M0_INTERNAL void m0_xcode_ctx_init(struct m0_xcode_ctx *ctx, const struct m0_xcode_obj *obj)
Definition: xcode.c:373
M0_INTERNAL void m0_fdmi_eval_fini(struct m0_fdmi_eval_ctx *ctx)
Definition: flt_eval.c:204
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
#define M0_UT_ASSERT(a)
Definition: ut.h:46
static void flt_eval_simple_gt(void)
Definition: filter_eval.c:89
Definition: vec.h:145