Motr  M0
xcode.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2015-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 #ifndef __KERNEL__
24 #include <stdio.h> /* printf */
25 #include <ctype.h> /* isspace */
26 #endif
27 
28 #include "lib/memory.h"
29 #include "lib/vec.h" /* m0_bufvec */
30 #include "lib/misc.h" /* M0_SET0 */
31 #include "lib/arith.h" /* m0_rnd64 */
32 #include "lib/errno.h" /* ENOENT */
33 #include "lib/string.h" /* m0_streq */
34 #include "ut/ut.h"
35 
36 #include "xcode/xcode.h"
37 
38 struct foo {
39  uint64_t f_x;
40  uint64_t f_y;
41 };
42 
43 typedef uint32_t tdef;
44 
45 struct un {
46  uint32_t u_tag;
47  union {
48  uint64_t u_x;
49  char u_y;
50  } u;
51 };
52 
53 enum { N = 6 };
54 
55 struct ar {
56  struct foo a_el[N];
57 };
58 
59 struct top {
60  struct foo t_foo;
61  uint32_t t_flag;
62  struct v {
63  uint32_t v_nr;
64  char *v_data;
65  } t_v;
67  struct un t_un;
68  union {
69  uint32_t *o_32;
70  uint64_t *o_64;
71  } t_opaq;
72  struct ar t_ar;
73 };
74 
75 enum { CHILDREN_MAX = 16 };
76 
77 struct static_xt {
78  struct m0_xcode_type xt;
80 };
81 
82 static struct static_xt xut_un = {
83  .xt = {
85  .xct_name = "un",
86  .xct_sizeof = sizeof (struct un),
87  .xct_nr = 3
88  }
89 };
90 
91 static struct static_xt xut_tdef = {
92  .xt = {
94  .xct_name = "tdef",
95  .xct_sizeof = sizeof (tdef),
96  .xct_nr = 1
97  }
98 };
99 
100 static struct static_xt xut_v = {
101  .xt = {
103  .xct_name = "v",
104  .xct_sizeof = sizeof (struct v),
105  .xct_nr = 2
106  }
107 };
108 
109 static struct static_xt xut_foo = {
110  .xt = {
112  .xct_name = "foo",
113  .xct_sizeof = sizeof (struct foo),
114  .xct_nr = 2
115  }
116 };
117 
118 static struct static_xt xut_ar = {
119  .xt = {
121  .xct_name = "ar",
122  .xct_sizeof = sizeof (struct ar),
123  .xct_nr = 1
124  }
125 };
126 
127 static struct static_xt xut_top = {
128  .xt = {
130  .xct_name = "top",
131  .xct_sizeof = sizeof (struct top),
132  .xct_nr = 7
133  }
134 };
135 
136 static char data[] = "Hello, world!\n";
137 
138 static struct top T = {
139  .t_foo = {
140  .f_x = 7,
141  .f_y = 8
142  },
143  .t_flag = 0xF,
144  .t_v = {
145  .v_nr = sizeof data,
146  .v_data = data
147  },
148  .t_un = {
149  .u_tag = 4
150  },
151  .t_opaq = {
152  .o_32 = &T.t_v.v_nr
153  },
154  .t_ar = {
155  .a_el = {
156  [0] = { 0, 1 },
157  [1] = { 1, 1 },
158  [2] = { 2, 1 },
159  [3] = { 3, 1 },
160  [4] = { 4, 1 },
161  [5] = { 5, 1 }
162  }
163  }
164 };
165 
166 static char ebuf[1000];
168 static void *vec = ebuf;
170 static struct m0_xcode_ctx ctx;
172 static struct tdata {
173  struct _foo {
174  uint64_t f_x;
175  uint64_t f_y;
176  } __attribute__((packed)) t_foo;
177  uint32_t __attribute__((packed)) t_flag;
178  struct _v {
179  uint32_t v_nr;
180  char v_data[sizeof data];
181  } __attribute__((packed)) t_v;
182  uint32_t __attribute__((packed)) t_def;
183  struct t_un {
184  uint32_t u_tag;
185  char u_y;
186  } __attribute__((packed)) t_un;
187  uint32_t __attribute__((packed)) t_opaq;
188  struct t_ar {
189  struct _foo1 {
190  uint64_t f_x;
191  uint64_t f_y;
192  } a_el[N];
193  } __attribute__((packed)) t_ar;
194 } __attribute__((packed)) TD;
195 
196 M0_BASSERT(sizeof TD < sizeof ebuf);
197 
198 static int failure;
199 
200 static int opaq_type(const struct m0_xcode_obj *par,
201  const struct m0_xcode_type **out)
202 {
203  struct top *t = par->xo_ptr;
204 
205  M0_UT_ASSERT(par->xo_type == &xut_top.xt);
206 
207  if (!failure) {
208  *out = t->t_flag == 0xf ? &M0_XT_U32 : &M0_XT_U64;
209  return 0;
210  } else
211  return -ENOENT;
212 }
213 
214 static int xcode_init(void)
215 {
216  xut_v.xt.xct_child[0] = (struct m0_xcode_field){
217  .xf_name = "v_nr",
218  .xf_type = &M0_XT_U32,
219  .xf_offset = offsetof(struct v, v_nr)
220  };
221  xut_v.xt.xct_child[1] = (struct m0_xcode_field){
222  .xf_name = "v_data",
223  .xf_type = &M0_XT_U8,
224  .xf_offset = offsetof(struct v, v_data)
225  };
226 
227  xut_foo.xt.xct_child[0] = (struct m0_xcode_field){
228  .xf_name = "f_x",
229  .xf_type = &M0_XT_U64,
230  .xf_offset = offsetof(struct foo, f_x)
231  };
232  xut_foo.xt.xct_child[1] = (struct m0_xcode_field){
233  .xf_name = "f_y",
234  .xf_type = &M0_XT_U64,
235  .xf_offset = offsetof(struct foo, f_y)
236  };
237 
238  xut_top.xt.xct_child[0] = (struct m0_xcode_field){
239  .xf_name = "t_foo",
240  .xf_type = &xut_foo.xt,
241  .xf_offset = offsetof(struct top, t_foo)
242  };
243  xut_top.xt.xct_child[1] = (struct m0_xcode_field){
244  .xf_name = "t_flag",
245  .xf_type = &M0_XT_U32,
246  .xf_offset = offsetof(struct top, t_flag)
247  };
248  xut_top.xt.xct_child[2] = (struct m0_xcode_field){
249  .xf_name = "t_v",
250  .xf_type = &xut_v.xt,
251  .xf_offset = offsetof(struct top, t_v)
252  };
253  xut_top.xt.xct_child[3] = (struct m0_xcode_field){
254  .xf_name = "t_def",
255  .xf_type = &xut_tdef.xt,
256  .xf_offset = offsetof(struct top, t_def)
257  };
258  xut_top.xt.xct_child[4] = (struct m0_xcode_field){
259  .xf_name = "t_un",
260  .xf_type = &xut_un.xt,
261  .xf_offset = offsetof(struct top, t_un)
262  };
263  xut_top.xt.xct_child[5] = (struct m0_xcode_field){
264  .xf_name = "t_opaq",
265  .xf_type = &M0_XT_OPAQUE,
266  .xf_opaque = opaq_type,
267  .xf_offset = offsetof(struct top, t_opaq)
268  };
269  xut_top.xt.xct_child[6] = (struct m0_xcode_field){
270  .xf_name = "t_ar",
271  .xf_type = &xut_ar.xt,
272  .xf_offset = offsetof(struct top, t_ar)
273  };
274 
275  xut_tdef.xt.xct_child[0] = (struct m0_xcode_field){
276  .xf_name = "def",
277  .xf_type = &M0_XT_U32,
278  .xf_offset = 0
279  };
280 
281  xut_un.xt.xct_child[0] = (struct m0_xcode_field){
282  .xf_name = "u_tag",
283  .xf_type = &M0_XT_U32,
284  .xf_offset = offsetof(struct un, u_tag)
285  };
286  xut_un.xt.xct_child[1] = (struct m0_xcode_field){
287  .xf_name = "u_x",
288  .xf_type = &M0_XT_U64,
289  .xf_tag = 1,
290  .xf_offset = offsetof(struct un, u.u_x)
291  };
292  xut_un.xt.xct_child[2] = (struct m0_xcode_field){
293  .xf_name = "u_y",
294  .xf_type = &M0_XT_U8,
295  .xf_tag = 4,
296  .xf_offset = offsetof(struct un, u.u_y)
297  };
298 
299  xut_ar.xt.xct_child[0] = (struct m0_xcode_field){
300  .xf_name = "a_el",
301  .xf_type = &xut_foo.xt,
302  .xf_offset = offsetof(struct ar, a_el),
303  .xf_tag = N,
304  };
305 
306  TD.t_foo.f_x = T.t_foo.f_x;
307  TD.t_foo.f_y = T.t_foo.f_y;
308  TD.t_flag = T.t_flag;
309  TD.t_v.v_nr = T.t_v.v_nr;
310  M0_ASSERT(T.t_v.v_nr == ARRAY_SIZE(TD.t_v.v_data));
311  memcpy(TD.t_v.v_data, T.t_v.v_data, T.t_v.v_nr);
312  TD.t_def = T.t_def;
313  TD.t_un.u_tag = T.t_un.u_tag;
314  TD.t_un.u_y = T.t_un.u.u_y;
315  TD.t_opaq = *T.t_opaq.o_32;
316  memcpy(&TD.t_ar, &T.t_ar, sizeof T.t_ar);
317  return 0;
318 }
319 
320 #ifndef __KERNEL__
321 __attribute__((unused)) static void it_print(const struct m0_xcode_cursor *it)
322 {
323  int i;
324  const struct m0_xcode_cursor_frame *f;
325 
326  for (i = 0, f = &it->xcu_stack[0]; i < it->xcu_depth; ++i, ++f) {
327  printf(".%s[%" PRId64 "]",
328  f->s_obj.xo_type->xct_child[f->s_fieldno].xf_name,
329  f->s_elno);
330  }
331  printf(":%s ", m0_xcode_aggr_name[f->s_obj.xo_type->xct_aggr]);
332  if (f->s_obj.xo_type->xct_aggr == M0_XA_ATOM) {
333  switch (f->s_obj.xo_type->xct_atype) {
334  case M0_XAT_VOID:
335  printf("void");
336  break;
337  case M0_XAT_U8:
338  printf("%c", *(char *)f->s_obj.xo_ptr);
339  break;
340  case M0_XAT_U32:
341  printf("%x", *(uint32_t *)f->s_obj.xo_ptr);
342  break;
343  case M0_XAT_U64:
344  printf("%x", (unsigned)*(uint64_t *)f->s_obj.xo_ptr);
345  break;
346  default:
347  M0_IMPOSSIBLE("atom");
348  }
349  }
350  printf("\n");
351 }
352 #endif
353 
354 static void chk(struct m0_xcode_cursor *it, int depth,
355  const struct m0_xcode_type *xt,
356  void *addr, int fieldno, int elno,
358 {
359  int rc;
360  struct m0_xcode_obj *obj;
361  struct m0_xcode_cursor_frame *f;
362 
363  rc = m0_xcode_next(it);
364  M0_UT_ASSERT(rc > 0);
365 
366  M0_UT_ASSERT(it->xcu_depth == depth);
367  M0_UT_ASSERT(IS_IN_ARRAY(depth, it->xcu_stack));
368 
370  obj = &f->s_obj;
371 
372  M0_UT_ASSERT(obj->xo_type == xt);
373  M0_UT_ASSERT(obj->xo_ptr == addr);
374  M0_UT_ASSERT(f->s_fieldno == fieldno);
375  M0_UT_ASSERT(f->s_elno == elno);
376  M0_UT_ASSERT(f->s_flag == flag);
377 }
378 
379 static void xcode_cursor_test(void)
380 {
381  int i;
382  struct m0_xcode_cursor it;
383 
384  M0_SET0(&it);
385 
386  it.xcu_stack[0].s_obj.xo_type = &xut_top.xt;
387  it.xcu_stack[0].s_obj.xo_ptr = &T;
388 
389  chk(&it, 0, &xut_top.xt, &T, 0, 0, M0_XCODE_CURSOR_PRE);
390  chk(&it, 1, &xut_foo.xt, &T.t_foo, 0, 0, M0_XCODE_CURSOR_PRE);
391  chk(&it, 2, &M0_XT_U64, &T.t_foo.f_x, 0, 0, M0_XCODE_CURSOR_PRE);
392  chk(&it, 2, &M0_XT_U64, &T.t_foo.f_x, 0, 0, M0_XCODE_CURSOR_POST);
393  chk(&it, 1, &xut_foo.xt, &T.t_foo, 0, 0, M0_XCODE_CURSOR_IN);
394  chk(&it, 2, &M0_XT_U64, &T.t_foo.f_y, 0, 0, M0_XCODE_CURSOR_PRE);
395  chk(&it, 2, &M0_XT_U64, &T.t_foo.f_y, 0, 0, M0_XCODE_CURSOR_POST);
396  chk(&it, 1, &xut_foo.xt, &T.t_foo, 1, 0, M0_XCODE_CURSOR_IN);
397  chk(&it, 1, &xut_foo.xt, &T.t_foo, 2, 0, M0_XCODE_CURSOR_POST);
398  chk(&it, 0, &xut_top.xt, &T, 0, 0, M0_XCODE_CURSOR_IN);
399  chk(&it, 1, &M0_XT_U32, &T.t_flag, 0, 0, M0_XCODE_CURSOR_PRE);
400  chk(&it, 1, &M0_XT_U32, &T.t_flag, 0, 0, M0_XCODE_CURSOR_POST);
401  chk(&it, 0, &xut_top.xt, &T, 1, 0, M0_XCODE_CURSOR_IN);
402  chk(&it, 1, &xut_v.xt, &T.t_v, 0, 0, M0_XCODE_CURSOR_PRE);
403  chk(&it, 2, &M0_XT_U32, &T.t_v.v_nr, 0, 0, M0_XCODE_CURSOR_PRE);
404  chk(&it, 2, &M0_XT_U32, &T.t_v.v_nr, 0, 0, M0_XCODE_CURSOR_POST);
405  chk(&it, 1, &xut_v.xt, &T.t_v, 0, 0, M0_XCODE_CURSOR_IN);
406  for (i = 0; i < ARRAY_SIZE(data); ++i) {
407  chk(&it, 2, &M0_XT_U8,
408  &T.t_v.v_data[i], 0, 0, M0_XCODE_CURSOR_PRE);
409  chk(&it, 2, &M0_XT_U8,
410  &T.t_v.v_data[i], 0, 0, M0_XCODE_CURSOR_POST);
411  M0_UT_ASSERT(*(char *)it.xcu_stack[2].s_obj.xo_ptr == data[i]);
412  chk(&it, 1, &xut_v.xt, &T.t_v, 1, i, M0_XCODE_CURSOR_IN);
413  }
414  chk(&it, 1, &xut_v.xt, &T.t_v, 2, 0, M0_XCODE_CURSOR_POST);
415  chk(&it, 0, &xut_top.xt, &T, 2, 0, M0_XCODE_CURSOR_IN);
416  chk(&it, 1, &xut_tdef.xt, &T.t_def, 0, 0, M0_XCODE_CURSOR_PRE);
417  chk(&it, 2, &M0_XT_U32, &T.t_def, 0, 0, M0_XCODE_CURSOR_PRE);
418  chk(&it, 2, &M0_XT_U32, &T.t_def, 0, 0, M0_XCODE_CURSOR_POST);
419  chk(&it, 1, &xut_tdef.xt, &T.t_def, 0, 0, M0_XCODE_CURSOR_IN);
420  chk(&it, 1, &xut_tdef.xt, &T.t_def, 1, 0, M0_XCODE_CURSOR_POST);
421  chk(&it, 0, &xut_top.xt, &T, 3, 0, M0_XCODE_CURSOR_IN);
422  chk(&it, 1, &xut_un.xt, &T.t_un, 0, 0, M0_XCODE_CURSOR_PRE);
423  chk(&it, 2, &M0_XT_U32, &T.t_un.u_tag, 0, 0, M0_XCODE_CURSOR_PRE);
424  chk(&it, 2, &M0_XT_U32, &T.t_un.u_tag, 0, 0, M0_XCODE_CURSOR_POST);
425  chk(&it, 1, &xut_un.xt, &T.t_un, 0, 0, M0_XCODE_CURSOR_IN);
426  chk(&it, 2, &M0_XT_U8, &T.t_un.u.u_y, 0, 0, M0_XCODE_CURSOR_PRE);
427  chk(&it, 2, &M0_XT_U8, &T.t_un.u.u_y, 0, 0, M0_XCODE_CURSOR_POST);
428  chk(&it, 1, &xut_un.xt, &T.t_un, 2, 0, M0_XCODE_CURSOR_IN);
429  chk(&it, 1, &xut_un.xt, &T.t_un, 3, 0, M0_XCODE_CURSOR_POST);
430  chk(&it, 0, &xut_top.xt, &T, 4, 0, M0_XCODE_CURSOR_IN);
433  chk(&it, 0, &xut_top.xt, &T, 5, 0, M0_XCODE_CURSOR_IN);
434  chk(&it, 1, &xut_ar.xt, &T.t_ar, 0, 0, M0_XCODE_CURSOR_PRE);
435  for (i = 0; i < N; ++i) {
436  struct foo *el = &T.t_ar.a_el[i];
437 
438  chk(&it, 2, &xut_foo.xt, el, 0, 0, M0_XCODE_CURSOR_PRE);
439  chk(&it, 3, &M0_XT_U64, &el->f_x, 0, 0, M0_XCODE_CURSOR_PRE);
440  chk(&it, 3, &M0_XT_U64, &el->f_x, 0, 0, M0_XCODE_CURSOR_POST);
441  chk(&it, 2, &xut_foo.xt, el, 0, 0, M0_XCODE_CURSOR_IN);
442  chk(&it, 3, &M0_XT_U64, &el->f_y, 0, 0, M0_XCODE_CURSOR_PRE);
443  chk(&it, 3, &M0_XT_U64, &el->f_y, 0, 0, M0_XCODE_CURSOR_POST);
444  chk(&it, 2, &xut_foo.xt, el, 1, 0, M0_XCODE_CURSOR_IN);
445  chk(&it, 2, &xut_foo.xt, el, 2, 0, M0_XCODE_CURSOR_POST);
446  chk(&it, 1, &xut_ar.xt, &T.t_ar, 0, i, M0_XCODE_CURSOR_IN);
447  }
448  chk(&it, 1, &xut_ar.xt, &T.t_ar, 2, 0, M0_XCODE_CURSOR_POST);
449  chk(&it, 0, &xut_top.xt, &T, 6, 0, M0_XCODE_CURSOR_IN);
450  chk(&it, 0, &xut_top.xt, &T, 7, 0, M0_XCODE_CURSOR_POST);
451 
452  M0_UT_ASSERT(m0_xcode_next(&it) == 0);
453 }
454 
455 static void xcode_length_test(void)
456 {
457  int result;
458 
459  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, &T });
460  result = m0_xcode_length(&ctx);
461  M0_UT_ASSERT(result == sizeof TD);
462 }
463 
464 static void xcode_encode_test(void)
465 {
466  int result;
467 
468  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, &T });
469  m0_bufvec_cursor_init(&ctx.xcx_buf, &bvec);
470  result = m0_xcode_encode(&ctx);
471  M0_UT_ASSERT(result == 0);
472 
473  M0_UT_ASSERT(memcmp(&TD, ebuf, sizeof TD) == 0);
474 }
475 
476 static void xcode_opaque_test(void)
477 {
478  int result;
479 
480  failure = 1;
481  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, &T });
482  result = m0_xcode_length(&ctx);
483  M0_UT_ASSERT(result == -ENOENT);
484  failure = 0;
485 }
486 
487 static void decode(struct m0_xcode_obj *obj)
488 {
489  int result;
490 
491  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, NULL });
492  ctx.xcx_alloc = m0_xcode_alloc;
493  m0_bufvec_cursor_init(&ctx.xcx_buf, &bvec);
494 
495  result = m0_xcode_decode(&ctx);
496  M0_UT_ASSERT(result == 0);
497 
498  *obj = ctx.xcx_it.xcu_stack[0].s_obj;
499 }
500 
501 static void xcode_decode_test(void)
502 {
503  struct m0_xcode_obj decoded;
504  struct top *TT;
505 
506  decode(&decoded);
507  TT = decoded.xo_ptr;
508  M0_UT_ASSERT( TT != NULL);
509  M0_UT_ASSERT( TT->t_foo.f_x == T.t_foo.f_x);
510  M0_UT_ASSERT( TT->t_foo.f_y == T.t_foo.f_y);
511  M0_UT_ASSERT( TT->t_flag == T.t_flag);
512  M0_UT_ASSERT( TT->t_v.v_nr == T.t_v.v_nr);
513  M0_UT_ASSERT(memcmp(TT->t_v.v_data, T.t_v.v_data, T.t_v.v_nr) == 0);
514  M0_UT_ASSERT( TT->t_def == T.t_def);
515  M0_UT_ASSERT( TT->t_un.u_tag == T.t_un.u_tag);
516  M0_UT_ASSERT( TT->t_un.u.u_y == T.t_un.u.u_y);
517  M0_UT_ASSERT(*TT->t_opaq.o_32 == *T.t_opaq.o_32);
518  M0_UT_ASSERT(memcmp(TT->t_ar.a_el, T.t_ar.a_el, sizeof T.t_ar) == 0);
519 
520  m0_xcode_free_obj(&decoded);
521 }
522 
523 enum {
524  FSIZE = sizeof(uint64_t) + sizeof(uint64_t)
525 };
526 
527 static char foo_buf[FSIZE];
528 static void *foo_addr = foo_buf;
531 
532 static int foo_length(struct m0_xcode_ctx *ctx, const void *obj)
533 {
534  return ARRAY_SIZE(foo_buf);
535 }
536 
537 static void foo_xor(char *buf)
538 {
539  int i;
540 
541  for (i = 0; i < ARRAY_SIZE(foo_buf); ++i)
542  buf[i] ^= 42;
543 }
544 
545 static int foo_encode(struct m0_xcode_ctx *ctx, const void *obj)
546 {
547  struct m0_bufvec_cursor cur;
548 
550  memcpy(foo_buf, obj, sizeof(struct foo));
551  foo_xor(foo_buf);
552  return m0_bufvec_cursor_copy(&ctx->xcx_buf, &cur, FSIZE) != FSIZE ?
553  -EPROTO : 0;
554 }
555 
556 static int foo_decode(struct m0_xcode_ctx *ctx, void *obj)
557 {
558  struct m0_bufvec_cursor cur;
559 
561  if (m0_bufvec_cursor_copy(&cur, &ctx->xcx_buf, FSIZE) == FSIZE) {
562  foo_xor(foo_buf);
563  memcpy(obj, foo_buf, sizeof(struct foo));
564  return 0;
565  } else
566  return -EPROTO;
567 }
568 
569 static const struct m0_xcode_type_ops foo_ops = {
571  .xto_encode = foo_encode,
572  .xto_decode = foo_decode
573 };
574 
575 static void xcode_nonstandard_test(void)
576 {
577  int result;
578  int i;
579 
581 
582  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, &T });
583  result = m0_xcode_length(&ctx);
584  M0_UT_ASSERT(result == sizeof TD);
585 
586  m0_xcode_ctx_init(&ctx, &(struct m0_xcode_obj){ &xut_top.xt, &T });
587  m0_bufvec_cursor_init(&ctx.xcx_buf, &bvec);
588  result = m0_xcode_encode(&ctx);
589  M0_UT_ASSERT(result == 0);
590 
591  foo_xor(ebuf);
592  for (i = 0; i < N; ++i)
593  foo_xor((void *)&((struct tdata *)ebuf)->t_ar.a_el[i]);
594  M0_UT_ASSERT(memcmp(&TD, ebuf, sizeof TD) == 0);
595  foo_xor(ebuf);
596  for (i = 0; i < N; ++i)
597  foo_xor((void *)&((struct tdata *)ebuf)->t_ar.a_el[i]);
600 }
601 
602 static void xcode_cmp_test(void)
603 {
604  struct m0_xcode_obj obj0;
605  struct m0_xcode_obj obj1;
606  struct top *t0;
607  struct top *t1;
608  int cmp;
609 
611 
612  decode(&obj0);
613  decode(&obj1);
614 
615  t0 = obj0.xo_ptr;
616  t1 = obj1.xo_ptr;
617 
618  cmp = m0_xcode_cmp(&obj0, &obj0);
619  M0_UT_ASSERT(cmp == 0);
620 
621  cmp = m0_xcode_cmp(&obj0, &obj1);
622  M0_UT_ASSERT(cmp == 0);
623 
624  cmp = m0_xcode_cmp(&obj1, &obj0);
625  M0_UT_ASSERT(cmp == 0);
626 
627  t1->t_foo.f_x--;
628  cmp = m0_xcode_cmp(&obj0, &obj1);
629  M0_UT_ASSERT(cmp > 0);
630  cmp = m0_xcode_cmp(&obj1, &obj0);
631  M0_UT_ASSERT(cmp < 0);
632 
633  t1->t_foo.f_x++;
634  cmp = m0_xcode_cmp(&obj0, &obj1);
635  M0_UT_ASSERT(cmp == 0);
636 
637  t1->t_v.v_data[0] = 'J';
638  cmp = m0_xcode_cmp(&obj0, &obj1);
639  M0_UT_ASSERT(cmp < 0);
640  t1->t_v.v_data[0] = t0->t_v.v_data[0];
641 
642  t1->t_v.v_nr++;
643  cmp = m0_xcode_cmp(&obj0, &obj1);
644  M0_UT_ASSERT(cmp < 0);
645  cmp = m0_xcode_cmp(&obj1, &obj0);
646  M0_UT_ASSERT(cmp > 0);
647  t1->t_v.v_nr--;
648 
649  m0_xcode_free_obj(&obj0);
650  m0_xcode_free_obj(&obj1);
651 }
652 
653 static int custom_read(const struct m0_xcode_cursor *it,
654  struct m0_xcode_obj *obj, const char *str)
655 {
656  static const char pattern[] = "!EXPECTED!";
657 
658  M0_UT_ASSERT(obj->xo_type == &xut_v.xt);
659  return strncmp(str, pattern, ARRAY_SIZE(pattern) - 1) == 0 ?
660  ARRAY_SIZE(pattern) - 1 : -EPERM;
661 }
662 
663 static const struct m0_xcode_type_ops read_ops = {
665 };
666 
667 #define OBJ(xt, ptr) (&(struct m0_xcode_obj){ .xo_type = (xt), .xo_ptr = (ptr) })
668 
669 static void literal(const char *input, const char *output)
670 {
671  struct v *V;
672  struct m0_xcode_obj *obj;
673  char *buf;
674  int result;
675 
676  output = output ?: input;
677  buf = m0_alloc(strlen(input) + 1);
678  M0_UT_ASSERT(buf != NULL);
679  M0_ALLOC_PTR(V);
680  obj = OBJ(&xut_v.xt, V);
681  result = m0_xcode_read(obj, input);
682  M0_UT_ASSERT(result == 0);
683  M0_UT_ASSERT(V->v_nr == strlen(output) - 2);
684  M0_UT_ASSERT(strncmp(V->v_data, output + 1, V->v_nr) == 0);
685  result = m0_xcode_print(obj, buf, strlen(input) + 1);
686  M0_UT_ASSERT(result == strlen(output));
687  M0_UT_ASSERT(strcmp(output, buf) == 0);
688  m0_free(buf);
690 }
691 
692 static void xcode_read_test(void)
693 {
694  int result;
695  int i;
696  struct foo F;
697  struct un U;
698  struct v *V;
699  struct ar A;
700  struct top *_T;
701  struct top _Tmp;
702 
703  M0_SET0(&F);
704  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "(10, 0xff)");
705  M0_UT_ASSERT(result == 0);
706  M0_UT_ASSERT(F.f_x == 10);
707  M0_UT_ASSERT(F.f_y == 0xff);
708 
709  M0_SET0(&F);
710  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), " ( 10 , 0xff ) ");
711  M0_UT_ASSERT(result == 0);
712  M0_UT_ASSERT(F.f_x == 10);
713  M0_UT_ASSERT(F.f_y == 0xff);
714 
715  M0_SET0(&F);
716  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "(10,010)");
717  M0_UT_ASSERT(result == 0);
718  M0_UT_ASSERT(F.f_x == 10);
719  M0_UT_ASSERT(F.f_y == 8);
720 
721  M0_SET0(&F);
722  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), " ( 10 , 0xff ) rest");
723  M0_UT_ASSERT(result == -EINVAL);
724 
725  M0_SET0(&F);
726  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "(10,)");
727  M0_UT_ASSERT(result == -EPROTO);
728 
729  M0_SET0(&F);
730  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "(10 12)");
731  M0_UT_ASSERT(result == -EPROTO);
732 
733  M0_SET0(&F);
734  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "()");
735  M0_UT_ASSERT(result == -EPROTO);
736 
737  M0_SET0(&F);
738  result = m0_xcode_read(OBJ(&xut_foo.xt, &F), "");
739  M0_UT_ASSERT(result == -EPROTO);
740 
741  M0_SET0(&U);
742  result = m0_xcode_read(OBJ(&xut_un.xt, &U), "{1| 42}");
743  M0_UT_ASSERT(result == 0);
744  M0_UT_ASSERT(U.u_tag == 1);
745  M0_UT_ASSERT(U.u.u_x == 42);
746 
747  M0_SET0(&U);
748  result = m0_xcode_read(OBJ(&xut_un.xt, &U), "{4| 8}");
749  M0_UT_ASSERT(result == 0);
750  M0_UT_ASSERT(U.u_tag == 4);
751  M0_UT_ASSERT(U.u.u_y == 8);
752 
753  M0_SET0(&U);
754  result = m0_xcode_read(OBJ(&xut_un.xt, &U), "{3| 0}");
755  M0_UT_ASSERT(result == -EPROTO);
756 
757  M0_SET0(&U);
758  result = m0_xcode_read(OBJ(&xut_un.xt, &U), "{3}");
759  M0_UT_ASSERT(result == 0);
760  M0_UT_ASSERT(U.u_tag == 3);
761 
762  M0_ALLOC_PTR(V);
763  result = m0_xcode_read(OBJ(&xut_v.xt, V), "[0]");
764  M0_UT_ASSERT(result == 0);
765  M0_UT_ASSERT(V->v_nr == 0);
767 
768  M0_ALLOC_PTR(V);
769  result = m0_xcode_read(OBJ(&xut_v.xt, V), "[1: 42]");
770  M0_UT_ASSERT(result == 0);
771  M0_UT_ASSERT(V->v_nr == 1);
772  M0_UT_ASSERT(V->v_data[0] == 42);
774 
775  M0_ALLOC_PTR(V);
776  result = m0_xcode_read(OBJ(&xut_v.xt, V), "[3: 42, 43, 44]");
777  M0_UT_ASSERT(result == 0);
778  M0_UT_ASSERT(V->v_nr == 3);
779  M0_UT_ASSERT(V->v_data[0] == 42);
780  M0_UT_ASSERT(V->v_data[1] == 43);
781  M0_UT_ASSERT(V->v_data[2] == 44);
783 
784  M0_SET0(&A);
785  result = m0_xcode_read(OBJ(&xut_ar.xt, &A), "<>");
786  M0_UT_ASSERT(result == -EPROTO);
787 
788  M0_SET0(&A);
789  result = m0_xcode_read(OBJ(&xut_ar.xt, &A), "<6>");
790  M0_UT_ASSERT(result == -EPROTO);
791 
792  M0_SET0(&A);
793  result = m0_xcode_read(OBJ(&xut_ar.xt, &A), "<(2, 2)>");
794  M0_UT_ASSERT(result == -EPROTO);
795 
796 #define ARS "<(0, 0x1), (0, 0x1), (0, 0x1), (0, 0x1), (0, 0x1), (0, 0x1)>"
797  M0_SET0(&A);
798  result = m0_xcode_read(OBJ(&xut_ar.xt, &A), ARS);
799  M0_UT_ASSERT(result == 0);
800 
801 
802 /* MOTR-1396 <- */
803  literal("\"/dev/disk/by-id/wwn-0x5000c50078c12486\"", NULL);
804  literal("[0x15:0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,"
805  "0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30]",
806  "\"000000000000000000000\"");
807  literal("[0x16:0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,"
808  "0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30]",
809  "\"0000000000000000000000\"");
810 /* -!> */
811  literal("\"a\"", NULL);
812  literal("\"abcdef\"", NULL);
813  literal("\"\"", NULL);
814 
815  M0_ALLOC_PTR(V);
816  result = m0_xcode_read(OBJ(&xut_v.xt, V), "\"");
817  M0_UT_ASSERT(result == -EPROTO);
819 
820  M0_ALLOC_PTR(_T);
821  result = m0_xcode_read(OBJ(&xut_top.xt, _T),
822  "((1, 2), 8, [4: 1, 2, 3, 4], 4, {1| 42}, 7," ARS ")");
823  M0_UT_ASSERT(result == 0);
824  M0_SET0(&_Tmp);
825  _Tmp.t_foo.f_x = 1;
826  _Tmp.t_foo.f_y = 2;
827  _Tmp.t_flag = 8;
828  _Tmp.t_v.v_nr = 4;
829  _Tmp.t_v.v_data = _T->t_v.v_data;
830  _Tmp.t_def = 4;
831  _Tmp.t_un.u_tag = 1;
832  _Tmp.t_un.u.u_x = 42;
833  _Tmp.t_opaq.o_32 = _T->t_opaq.o_32;
834  for (i = 0; i < N; ++i) {
835  _Tmp.t_ar.a_el[i].f_x = 0;
836  _Tmp.t_ar.a_el[i].f_y = 1;
837  }
838  M0_UT_ASSERT(memcmp(_T, &_Tmp, sizeof(struct top)) == 0);
840 
841  /* Test custom reader. */
842  M0_ALLOC_PTR(_T);
844  result = m0_xcode_read(OBJ(&xut_top.xt, _T),
845  "((1, 2), 8, ^!EXPECTED!, 4, {1| 42}, 7," ARS ")");
846  M0_UT_ASSERT(result == 0);
848 
849  M0_ALLOC_PTR(_T);
850  result = m0_xcode_read(OBJ(&xut_top.xt, _T), "((1, 2), 8, ^WRONG ...");
851  M0_UT_ASSERT(result == -EPERM);
853 
854  M0_ALLOC_PTR(_T);
855  result = m0_xcode_read(OBJ(&xut_top.xt, _T),
856  "((1, 2), 8, [4: 1, 2, 3, 4], 4, {1| 42}, 7," ARS ")");
857  M0_UT_ASSERT(result == 0);
859  xut_v.xt.xct_ops = NULL;
860 }
861 
862 #ifndef __KERNEL__
863 static void xcode_print_test(void)
864 {
865  char buf[300];
866  const char *s0;
867  const char *s1;
868  int rc;
869  char data[] = { 1, 2, 3, 4 };
870  uint64_t o64 = 7;
871  struct top T = (struct top){
872  .t_foo = { 1, 2 },
873  .t_flag = 8,
874  .t_v = { .v_nr = 4, .v_data = data },
875  .t_def = 4,
876  .t_un = { .u_tag = 1, .u = { .u_x = 42 }},
877  .t_opaq = { .o_64 = &o64 },
878  .t_ar = {
879  .a_el = {
880  { 0, 1 },
881  { 0, 1 },
882  { 0, 1 },
883  { 0, 1 },
884  { 0, 1 },
885  { 0, 1 }
886  }
887  }
888  };
889  struct top *V;
890 
892  M0_UT_ASSERT(rc == strlen(buf));
893  for (s0 = buf, s1 = ""
894  "((0x1, 0x2),"
895  " 0x8,"
896  " [0x4: 0x1, 0x2, 0x3, 0x4],"
897  " 0x4,"
898  " {0x1| 0x2a},"
899  " 0x7, " ARS ")";
900  *s0 != 0 && *s1 != 0; ++s0, ++s1) {
901  while (isspace(*s0))
902  ++s0;
903  while (isspace(*s1))
904  ++s1;
905  M0_UT_ASSERT(*s0 == *s1);
906  }
907  M0_UT_ASSERT(*s0 == 0);
908  M0_UT_ASSERT(*s1 == 0);
909 
910  /* Read back printed obj */
911  M0_ALLOC_PTR(V);
912  rc = m0_xcode_read(OBJ(&xut_top.xt, V), buf);
913  M0_UT_ASSERT(rc == 0);
915  OBJ(&xut_top.xt, V), OBJ(&xut_top.xt, &T)) == 0);
917 
918  rc = m0_xcode_print(OBJ(&xut_top.xt, &T), NULL, 0);
919  M0_UT_ASSERT(rc == strlen(buf));
920 }
921 #endif
922 
923 static void xcode_find_test(void)
924 {
925  struct m0_xcode_obj top = { &xut_top.xt, &T };
926  void *place;
927  int result;
928 
929  result = m0_xcode_find(&top, &xut_top.xt, &place);
930  M0_UT_ASSERT(result == 0 && place == &T);
931 
932  result = m0_xcode_find(&top, &xut_foo.xt, &place);
933  M0_UT_ASSERT(result == 0 && place == &T.t_foo);
934 
935  result = m0_xcode_find(&top, &xut_v.xt, &place);
936  M0_UT_ASSERT(result == 0 && place == &T.t_v);
937 
938  result = m0_xcode_find(&top, &M0_XT_U64, &place);
939  M0_UT_ASSERT(result == 0 && place == &T.t_foo.f_x);
940 
941  result = m0_xcode_find(&top, &M0_XT_U32, &place);
942  M0_UT_ASSERT(result == 0 && place == &T.t_flag);
943 
944  result = m0_xcode_find(&top, &M0_XT_VOID, &place);
945  M0_UT_ASSERT(result == -ENOENT);
946 }
947 
948 #define __ENUM_ONLY
949 #include "test_gccxml_simple.h"
950 #include "test_gccxml_simple_xc.h"
951 
952 static void xcode_enum_gccxml(void)
953 {
954  M0_UT_ASSERT(m0_streq(m0_xc_testenum_enum.xe_name, "testenum"));
955  M0_UT_ASSERT(m0_xc_testenum_enum.xe_nr == 4);
956  M0_UT_ASSERT(m0_xc_testenum_enum.xe_maxlen == 5);
957  M0_UT_ASSERT(m0_xc_testenum_enum.xe_val[1].xev_val == 1);
958  M0_UT_ASSERT(m0_streq(m0_xc_testenum_enum.xe_val[1].xev_name, "TE_1"));
959 
960  M0_UT_ASSERT(m0_streq(m0_xc_testbitmask_enum.xe_name, "testbitmask"));
961  M0_UT_ASSERT(m0_xc_testbitmask_enum.xe_nr == 5);
962  M0_UT_ASSERT(m0_xc_testbitmask_enum.xe_val[1].xev_val == M0_BITS(6));
963  M0_UT_ASSERT(m0_streq(m0_xc_testbitmask_enum.xe_val[1].xev_name,
964  "BM_SIX"));
965 }
966 
967 static void xcode_enum_print(void)
968 {
969  char buf[30];
970 #define CHECK(v) \
971 m0_streq(m0_xcode_enum_print(&m0_xc_testenum_enum, v, NULL), #v)
976 #undef CHECK
977  M0_UT_ASSERT(strncmp(m0_xcode_enum_print(&m0_xc_testenum_enum,
978  77, NULL),
979  "Invalid", 7) == 0);
980  M0_UT_ASSERT(strncmp(m0_xcode_enum_print(&m0_xc_testenum_enum,
981  0x4d, buf),
982  "4d", 2) == 0);
983 }
984 
985 static void enum_read_check(const char *name, int nr, uint64_t v, int rc)
986 {
987  uint64_t read = 0;
988 
989  M0_UT_ASSERT(m0_xcode_enum_read(&m0_xc_testenum_enum,
990  name, nr, &read) == rc);
991  M0_UT_ASSERT(ergo(rc == 0, read == v));
992 }
993 
994 static void xcode_enum_read(void)
995 {
996 #define C(v) (enum_read_check(#v, strlen(#v), v, 0))
997  C(TE_0);
998  C(TE_1);
999  C(TE_33);
1000  C(TE_5);
1001 #undef C
1002  enum_read_check("4d", 2, 0x4d, 0);
1003  enum_read_check("4d ", 3, 0, -EPROTO);
1004  enum_read_check("4dZ", 3, 0, -EPROTO);
1005  enum_read_check("", 0, 0, 0);
1006  enum_read_check("TE_", 3, 0, -EPROTO);
1007  enum_read_check("TE_02", 4, 0, 0);
1008 }
1009 
1010 static void bitmask_print_check(uint64_t mask,
1011  int nr, bool ok, const char *out)
1012 {
1013  char buf[256] = {};
1014  int result;
1015 
1017  result = m0_xcode_bitmask_print(&m0_xc_testbitmask_enum,
1018  mask, buf, nr);
1019  M0_UT_ASSERT(ergo(!ok, result > nr));
1020  M0_UT_ASSERT(ergo(ok, m0_streq(buf, out)));
1021 }
1022 
1023 static void xcode_bitmask_print(void)
1024 {
1025  const struct test {
1026  uint64_t t_mask;
1027  int t_nr;
1028  bool t_ok;
1029  const char *t_out;
1030  } test[] = {
1031  { 0, 1, true, "" },
1032  { BM_ZERO, 10, true, "BM_ZERO" },
1033  { BM_SIX, 10, true, "BM_SIX" },
1034  { BM_FOUR, 10, true, "BM_FOUR" },
1035  { BM_NINE, 10, true, "BM_NINE" },
1036  { BM_FIVE, 10, true, "BM_FIVE" },
1037  { BM_ZERO|BM_FOUR, 20, true, "BM_ZERO|BM_FOUR" },
1038  { BM_FOUR|BM_ZERO, 20, true, "BM_ZERO|BM_FOUR" },
1039  { BM_ZERO|BM_FOUR, 10, false, "" },
1040  { 1024, 10, true, "400" },
1041  { 1024|BM_ZERO, 20, true, "BM_ZERO|400" },
1042 
1043  };
1044  int i;
1045 
1046  for (i = 0; i < ARRAY_SIZE(test); ++i) {
1047  const struct test *t = &test[i];
1048 
1049  bitmask_print_check(t->t_mask, t->t_nr, t->t_ok, t->t_out);
1050  }
1051 }
1052 
1053 static void bitmask_read_check(uint64_t mask, int nr, bool ok, const char *buf)
1054 {
1055  uint64_t val;
1056  int result;
1057 
1058  if (nr == -1)
1059  nr = strlen(buf);
1060  result = m0_xcode_bitmask_read(&m0_xc_testbitmask_enum, buf, nr, &val);
1061  M0_UT_ASSERT(ok == (result == 0));
1062  M0_UT_ASSERT(!ok == (result == -EPROTO));
1063  M0_UT_ASSERT(ergo(ok, val == mask));
1064 }
1065 
1066 static void xcode_bitmask_read(void)
1067 {
1068  const struct test {
1069  uint64_t t_mask;
1070  int t_nr;
1071  bool t_ok;
1072  const char *t_out;
1073  } test[] = {
1074  { 0, 0, true, "" },
1075  { BM_ZERO, -1, true, "BM_ZERO" },
1076  { BM_SIX, -1, true, "BM_SIX" },
1077  { BM_FOUR, -1, true, "BM_FOUR" },
1078  { BM_NINE, -1, true, "BM_NINE" },
1079  { BM_FIVE, -1, true, "BM_FIVE" },
1080  { BM_ZERO|BM_FOUR, -1, true, "BM_ZERO|BM_FOUR" },
1081  { BM_FOUR|BM_ZERO, -1, true, "BM_FOUR|BM_ZERO" },
1082  { BM_FOUR|BM_ZERO|BM_NINE, -1, true, "BM_FOUR|BM_NINE|BM_ZERO" },
1083  { BM_FOUR|BM_NINE|0x400, -1, true, "BM_FOUR|BM_NINE|400" },
1084  { 0, -1, false, "BM_FOUR|BM_NINE|400Z" },
1085  { 0, -1, false, "BM_FOUR|BM_NINE|Z" },
1086  { 0, -1, false, "ZZZZZZZZZZZZZZZZZ" },
1087  { BM_FOUR|BM_NINE|0x400, -1, true, "BM_FOUR|BM_NINE|400|" },
1088  { 0, -1, false, "BM_FOUR|BM_NINE||" },
1089  { BM_FOUR|BM_NINE, -1, true, "BM_FOUR|BM_NINE|" },
1090  { 0, -1, false, "|BM_FOUR|BM_NINE||" },
1091  { 0, -1, false, "|||" },
1092  { 0, -1, false, "||" },
1093  { 0, -1, false, "|" },
1094  { 0, -1, false, "|0" },
1095  { 0, -1, false, "|0|0|" },
1096  { 0, -1, false, "|0|" },
1097  { 0, -1, true, "0|0" },
1098  { 1, -1, true, "1|" },
1099  { BM_FOUR|BM_NINE|0x4400, -1, true,"BM_FOUR|4000|BM_NINE|400" },
1100 
1101  };
1102  int i;
1103 
1104  for (i = 0; i < ARRAY_SIZE(test); ++i) {
1105  const struct test *t = &test[i];
1106 
1107  bitmask_read_check(t->t_mask, t->t_nr, t->t_ok, t->t_out);
1108  }
1109 }
1110 
1111 static void xcode_enum_loop(void)
1112 {
1113  char buf[300];
1114  int i;
1115  uint64_t val;
1116  uint64_t val1;
1117  uint64_t seed = (uint64_t)buf;
1118  int result;
1119 
1120  for (i = 0; i < 2000; ++i) {
1121  const char *out;
1122  val = m0_rnd64(&seed);
1123 
1124  out = m0_xcode_enum_print(&m0_xc_testenum_enum, val, buf);
1125  result = m0_xcode_enum_read(&m0_xc_testenum_enum,
1126  out, strlen(out), &val1);
1127  M0_UT_ASSERT(result == 0);
1128  M0_UT_ASSERT(val == val1);
1129  result = m0_xcode_bitmask_print(&m0_xc_testbitmask_enum,
1130  val, buf, sizeof buf);
1131  M0_UT_ASSERT(result > 0);
1132  result = m0_xcode_bitmask_read(&m0_xc_testbitmask_enum,
1133  buf, strlen(buf), &val1);
1134  M0_UT_ASSERT(result == 0);
1135  M0_UT_ASSERT(val == val1);
1136  }
1137 }
1138 
1139 static void xcode_enum_field(void)
1140 {
1141  struct enumfield ef = {
1142  .ef_0 = 1,
1143  .ef_enum = TE_5,
1144  .ef_bitm = BM_ZERO|BM_NINE,
1145  .ef_1 = 2
1146  };
1147  struct enumfield buf;
1148  struct m0_xcode_obj obj = {
1149  .xo_type = enumfield_xc,
1150  .xo_ptr = &buf
1151  };
1152  int result;
1153 
1154  /* Initialise enumfield_xc. */
1155  m0_xc_xcode_ut_test_gccxml_simple_init();
1156 
1157  result = m0_xcode_read(&obj, "(1, @TE_5, @BM_ZERO|BM_NINE, 2)");
1158  M0_UT_ASSERT(result == 0);
1159  M0_UT_ASSERT(memcmp(&buf, &ef, sizeof ef) == 0);
1160 }
1161 
1162 static int ecount;
1163 static void t_count(struct m0_xcode_type *xt, void *data)
1164 {
1165  ++ecount;
1166 }
1167 
1168 static void f_count(struct m0_xcode_type *xt,
1169  struct m0_xcode_field *field, void *data)
1170 {
1171  ++ecount;
1172 }
1173 
1174 static void xcode_iterate(void)
1175 {
1176  ecount = 0;
1178  /* top + foo + uint32_t + v + tdef + un + opaq + ar +
1179  foo:uint64_t + foo:uint64_t + v_nr + v_data + tdef:uint32_t +
1180  un:u_tag + un:u_x + un:u_y + ar:e_al + foo:uint64_t +
1181  foo:uint64_t */
1182  M0_UT_ASSERT(ecount == 19);
1183  ecount = 0;
1185  /* Same as above sans top. */
1186  M0_UT_ASSERT(ecount == 18);
1187 }
1188 
1189 static void flagset(struct m0_xcode_type *xt, uint32_t flags)
1190 {
1191  xt->xct_flags = flags;
1192 }
1193 
1194 struct pair {
1195  const struct m0_xcode_type *p_src;
1197 } builtins[] = {
1198  { &M0_XT_U8, {} },
1199  { &M0_XT_U32, {} },
1200  { &M0_XT_U64, {} },
1201  { &M0_XT_OPAQUE, {} }
1202 };
1203 
1204 static void fieldset(struct m0_xcode_type *xt,
1205  struct m0_xcode_field *field,
1206  void *unused)
1207 {
1208  int i;
1209 
1210  for (i = 0; i < ARRAY_SIZE(builtins); ++i) {
1211  if (field->xf_type == builtins[i].p_src) {
1212  builtins[i].p_dst = *builtins[i].p_src;
1213  field->xf_type = &builtins[i].p_dst;
1214  break;
1215  }
1216  }
1217 }
1218 
1219 static void fieldclear(struct m0_xcode_type *xt,
1220  struct m0_xcode_field *field,
1221  void *unused)
1222 {
1223  int i;
1224 
1225  for (i = 0; i < ARRAY_SIZE(builtins); ++i) {
1226  if (field->xf_type == &builtins[i].p_dst) {
1227  field->xf_type = builtins[i].p_src;
1228  break;
1229  }
1230  }
1231 }
1232 
1233 static void xcode_flags(void)
1234 {
1235  /*
1236  * First, go through type tree and replace all built-in types (which
1237  * are const objects) with local replicas.
1238  */
1239  m0_xcode_type_iterate(&xut_top.xt, NULL, &fieldset, (void *)0);
1240 
1243  M0_UT_ASSERT( m0_xcode_type_flags(&xut_top.xt, 0, 0xffffffff, 0));
1244  xut_top.xt.xct_flags = 1;
1245  M0_UT_ASSERT(!m0_xcode_type_flags(&xut_top.xt, 0, 0xffffffff, 0));
1248  xut_top.xt.xct_flags = 0;
1249  xut_foo.xt.xct_flags = 1;
1250  M0_UT_ASSERT(!m0_xcode_type_flags(&xut_top.xt, 0, 0xffffffff, 0));
1253  xut_foo.xt.xct_flags = 0;
1254  m0_xcode_type_iterate(&xut_top.xt, (void *)&flagset, NULL, (void *)5);
1258  m0_xcode_type_iterate(&xut_top.xt, (void *)&flagset, NULL, (void *)0);
1260 }
1261 
1262 /*
1263  * Stub function, it's not meant to be used anywhere, it's defined to calm down
1264  * linker, which throws an "undefined reference to `m0_package_cred_get'"
1265  * otherwise.
1266  */
1267 int m0_package_cred_get(const struct m0_xcode_obj *par,
1268  const struct m0_xcode_type **out)
1269 {
1270  return 0;
1271 }
1272 
1274  .ts_name = "xcode-ut",
1275  .ts_init = xcode_init,
1276  .ts_fini = NULL,
1277  .ts_tests = {
1278  { "xcode-cursor", xcode_cursor_test },
1279  { "xcode-length", xcode_length_test },
1280  { "xcode-encode", xcode_encode_test },
1281  { "xcode-opaque", xcode_opaque_test },
1282  { "xcode-decode", xcode_decode_test },
1283  { "xcode-nonstandard", xcode_nonstandard_test },
1284  { "xcode-cmp", xcode_cmp_test },
1285  { "xcode-read", xcode_read_test },
1286 #ifndef __KERNEL__
1287  { "xcode-print", xcode_print_test },
1288 #endif
1289  { "xcode-find", xcode_find_test },
1290 
1291  { "xcode-enum-gccxml", xcode_enum_gccxml, "Nikita" },
1292  { "xcode-enum-print", xcode_enum_print, "Nikita" },
1293  { "xcode-enum-read", xcode_enum_read, "Nikita" },
1294  { "xcode-bitmask-print", xcode_bitmask_print, "Nikita" },
1295  { "xcode-bitmask-read", xcode_bitmask_read, "Nikita" },
1296  { "xcode-enum-loop", xcode_enum_loop, "Nikita" },
1297  { "xcode-enum-field", xcode_enum_field, "Nikita" },
1298  { "xcode-iterate", xcode_iterate, "Nikita" },
1299  { "xcode-flags", xcode_flags, "Nikita" },
1300  { NULL, NULL }
1301  }
1302 };
1303 M0_EXPORTED(xcode_ut);
1304 
1305 /*
1306  * Local variables:
1307  * c-indentation-style: "K&R"
1308  * c-basic-offset: 8
1309  * tab-width: 8
1310  * fill-column: 79
1311  * scroll-step: 1
1312  * End:
1313  */
M0_INTERNAL struct m0_xcode_cursor_frame * m0_xcode_cursor_top(struct m0_xcode_cursor *it)
Definition: cursor.c:41
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
char f_x[7]
Definition: bob.c:35
static void foo_xor(char *buf)
Definition: xcode.c:537
M0_INTERNAL int m0_xcode_print(const struct m0_xcode_obj *obj, char *str, int nr)
Definition: string.c:278
static size_t nr
Definition: dump.c:1505
static struct static_xt xut_v
Definition: xcode.c:100
static void xcode_find_test(void)
Definition: xcode.c:923
const struct m0_xcode_type * xo_type
Definition: xcode.h:351
char v_data[WADDR_LEN]
Definition: xcode.h:66
int const char const void size_t int flags
Definition: dir.c:328
union un::@539 u
static int ecount
Definition: xcode.c:1162
#define NULL
Definition: misc.h:38
uint32_t v_nr
Definition: xcode.c:63
uint32_t * o_32
Definition: xcode.c:69
M0_INTERNAL void m0_xcode_type_iterate(struct m0_xcode_type *xt, void(*t)(struct m0_xcode_type *, void *), void(*f)(struct m0_xcode_type *, struct m0_xcode_field *, void *), void *datum)
Definition: xcode.c:395
uint64_t f_x
Definition: xcode.c:39
static struct buffer * cur(struct m0_addb2_mach *mach, m0_bcount_t space)
Definition: addb2.c:791
Definition: idx_mock.c:52
#define ergo(a, b)
Definition: misc.h:293
struct foo t_foo
Definition: xcode.c:60
static FILE * f
Definition: adieu.c:79
Definition: xcode.c:172
union @126 u
Definition: bob.c:32
M0_INTERNAL int m0_xcode_read(struct m0_xcode_obj *obj, const char *str)
Definition: string.c:162
struct m0_xcode_type xt
Definition: xcode.c:78
static m0_bcount_t foo_count
Definition: xcode.c:529
static int xcode_init(void)
Definition: xcode.c:214
Definition: xcode.c:53
static const struct m0_xcode_type_ops foo_ops
Definition: xcode.c:569
static void xcode_length_test(void)
Definition: xcode.c:455
static struct static_xt xut_top
Definition: xcode.c:127
static void xcode_enum_gccxml(void)
Definition: xcode.c:952
struct un t_un
Definition: xcode.c:67
static struct m0_be_emap_cursor it
Definition: extmap.c:46
static void xcode_opaque_test(void)
Definition: xcode.c:476
struct m0_xcode_field xct_child[0]
Definition: xcode.h:345
static void xcode_encode_test(void)
Definition: xcode.c:464
int(* xto_length)(struct m0_xcode_ctx *ctx, const void *obj)
Definition: xcode.h:365
M0_INTERNAL void m0_xcode_free_obj(struct m0_xcode_obj *obj)
Definition: xcode.c:248
#define M0_BITS(...)
Definition: misc.h:236
Definition: xcode.c:59
static void xcode_decode_test(void)
Definition: xcode.c:501
uint64_t m0_bcount_t
Definition: types.h:77
M0_INTERNAL int m0_xcode_decode(struct m0_xcode_ctx *ctx)
Definition: xcode.c:380
static void decode(struct m0_xcode_obj *obj)
Definition: xcode.c:487
const struct m0_xcode_type_ops * xct_ops
Definition: xcode.h:320
static int void * buf
Definition: dir.c:1019
tdef t_def
Definition: xcode.c:66
#define M0_SET0(obj)
Definition: misc.h:64
static struct m0_xcode_type ** xt[]
Definition: protocol.c:64
Definition: ut.h:77
static char data[]
Definition: xcode.c:136
static struct foo * obj
Definition: tlist.c:302
Definition: sock.c:887
static m0_bcount_t count
Definition: xcode.c:167
static void * foo_addr
Definition: xcode.c:528
static void xcode_enum_read(void)
Definition: xcode.c:994
char u_y
Definition: xcode.c:49
const struct m0_xcode_type * p_src
Definition: xcode.c:1195
Definition: xcode.c:524
static char foo_buf[FSIZE]
Definition: xcode.c:527
static void xcode_nonstandard_test(void)
Definition: xcode.c:575
M0_INTERNAL int m0_xcode_length(struct m0_xcode_ctx *ctx)
Definition: xcode.c:390
enum @538 __attribute__
static void xcode_read_test(void)
Definition: xcode.c:692
int i
Definition: dir.c:1033
int(* xto_read)(const struct m0_xcode_cursor *it, struct m0_xcode_obj *obj, const char *str)
Definition: xcode.h:379
static unsigned depth
Definition: base.c:377
struct m0_xcode_type p_dst
Definition: xcode.c:1196
struct pair builtins[]
static char ebuf[1000]
Definition: xcode.c:166
static void xcode_cursor_test(void)
Definition: xcode.c:379
static void flagset(struct m0_xcode_type *xt, uint32_t flags)
Definition: xcode.c:1189
uint64_t f_x
Definition: xcode.c:174
const char * name
Definition: trace.c:110
M0_INTERNAL m0_bcount_t m0_bufvec_cursor_copy(struct m0_bufvec_cursor *dcur, struct m0_bufvec_cursor *scur, m0_bcount_t num_bytes)
Definition: vec.c:620
Definition: xcode.c:45
const struct m0_xcode_type M0_XT_OPAQUE
Definition: xcode.c:948
static void * vec
Definition: xcode.c:168
#define M0_ASSERT(cond)
int m0_package_cred_get(const struct m0_xcode_obj *par, const struct m0_xcode_type **out)
Definition: xcode.c:1267
static void xcode_enum_field(void)
Definition: xcode.c:1139
uint64_t u_x
Definition: xcode.c:48
static int field(struct ff2c_context *ctx, struct ff2c_term *term)
Definition: parser.c:84
static void fieldset(struct m0_xcode_type *xt, struct m0_xcode_field *field, void *unused)
Definition: xcode.c:1204
M0_INTERNAL int m0_xcode_cmp(const struct m0_xcode_obj *o0, const struct m0_xcode_obj *o1)
Definition: xcode.c:572
uint64_t f_y
Definition: xcode.c:175
struct foo a_el[N]
Definition: xcode.c:56
static void xcode_enum_loop(void)
Definition: xcode.c:1111
uint64_t f_y
Definition: xcode.c:72
static struct m0_thread t[8]
Definition: service_ut.c:1230
const struct m0_xcode_type M0_XT_VOID
Definition: xcode.c:916
#define m0_streq(a, b)
Definition: string.h:34
static struct m0_bufvec bvec
Definition: xcode.c:169
Definition: xcode.c:62
static struct static_xt xut_un
Definition: xcode.c:82
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
#define OBJ(xt, ptr)
Definition: xcode.c:667
static int cmp(const struct m0_ut_suite **s0, const struct m0_ut_suite **s1)
Definition: ut.c:654
void * m0_alloc(size_t size)
Definition: memory.c:126
struct top::v t_v
static int foo_length(struct m0_xcode_ctx *ctx, const void *obj)
Definition: xcode.c:532
Definition: xcode.h:73
struct tdata::_foo __attribute__((packed))
Definition: xcode.c:176
struct ar t_ar
Definition: xcode.c:72
char * v_data
Definition: xcode.c:64
Definition: xcode.c:55
M0_INTERNAL int m0_xcode_next(struct m0_xcode_cursor *it)
Definition: cursor.c:59
static struct static_xt xut_tdef
Definition: xcode.c:91
uint64_t * o_64
Definition: xcode.c:70
static void xcode_flags(void)
Definition: xcode.c:1233
static void t0(int self)
Definition: chan.c:39
static void t_count(struct m0_xcode_type *xt, void *data)
Definition: xcode.c:1163
int m0_xcode_bitmask_print(const struct m0_xcode_enum *en, uint64_t val, char *buf, int nr)
Definition: enum.c:85
int m0_xcode_bitmask_read(const struct m0_xcode_enum *en, const char *buf, int nr, uint64_t *val)
Definition: enum.c:112
static void xcode_print_test(void)
Definition: xcode.c:863
static struct top T
Definition: xcode.c:138
M0_INTERNAL void * m0_xcode_alloc(struct m0_xcode_cursor *it, size_t nob)
Definition: xcode.c:444
#define ARS
static int custom_read(const struct m0_xcode_cursor *it, struct m0_xcode_obj *obj, const char *str)
Definition: xcode.c:653
const char * m0_xcode_enum_print(const struct m0_xcode_enum *en, uint64_t val, char *buf)
Definition: enum.c:51
static void xcode_iterate(void)
Definition: xcode.c:1174
#define PRId64
Definition: types.h:57
const char * m0_xcode_aggr_name[M0_XA_NR]
Definition: xcode.c:955
static char pattern[CHAR_NUM]
Definition: layout.c:48
union top::@540 t_opaq
static int foo_decode(struct m0_xcode_ctx *ctx, void *obj)
Definition: xcode.c:556
static void bitmask_read_check(uint64_t mask, int nr, bool ok, const char *buf)
Definition: xcode.c:1053
const char * ts_name
Definition: ut.h:99
uint32_t u_tag
Definition: xcode.c:46
const struct m0_xcode_type M0_XT_U32
Definition: xcode.c:932
static struct static_xt xut_foo
Definition: xcode.c:109
enum m0_xcode_aggr xct_aggr
Definition: xcode.h:316
M0_INTERNAL uint64_t m0_rnd64(uint64_t *seed)
Definition: misc.c:100
m0_xcode_cursor_flag
Definition: xcode.h:408
static int foo_encode(struct m0_xcode_ctx *ctx, const void *obj)
Definition: xcode.c:545
uint32_t v_nr
Definition: vec.h:1317
uint32_t tdef
Definition: xcode.c:43
struct m0_ut_suite xcode_ut
Definition: xcode.c:1273
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
Definition: list.c:42
static void bitmask_print_check(uint64_t mask, int nr, bool ok, const char *out)
Definition: xcode.c:1010
#define CHECK(v)
static void xcode_enum_print(void)
Definition: xcode.c:967
static const struct m0_xcode_type_ops read_ops
Definition: xcode.c:663
static bool flag
Definition: nucleus.c:266
static struct m0_bufvec foo_bvec
Definition: xcode.c:530
M0_INTERNAL int m0_xcode_find(struct m0_xcode_obj *obj, const struct m0_xcode_type *xt, void **place)
Definition: xcode.c:713
M0_INTERNAL int m0_xcode_encode(struct m0_xcode_ctx *ctx)
Definition: xcode.c:385
Definition: xcode.c:1194
Definition: module.c:67
const struct m0_xcode_type M0_XT_U8
Definition: xcode.c:924
static void literal(const char *input, const char *output)
Definition: xcode.c:669
#define IS_IN_ARRAY(idx, array)
Definition: misc.h:311
int m0_xcode_enum_read(const struct m0_xcode_enum *en, const char *buf, int nr, uint64_t *val)
Definition: enum.c:65
void * xo_ptr
Definition: xcode.h:353
#define C(v)
static void t1(int n)
Definition: mutex.c:48
#define _T(name, str, field, ops)
Definition: beck.c:423
static struct elevator el
Definition: chs_test.c:102
static struct static_xt xut_ar
Definition: xcode.c:118
static void enum_read_check(const char *name, int nr, uint64_t v, int rc)
Definition: xcode.c:985
static void xcode_bitmask_print(void)
Definition: xcode.c:1023
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
static void fieldclear(struct m0_xcode_type *xt, struct m0_xcode_field *field, void *unused)
Definition: xcode.c:1219
#define out(...)
Definition: gen.c:41
const char * xf_name
Definition: xcode.h:251
M0_INTERNAL bool m0_xcode_type_flags(struct m0_xcode_type *xt, uint32_t on, uint32_t off, uint64_t aggr_umask)
Definition: xcode.c:878
Definition: module.c:67
static void chk(struct m0_xcode_cursor *it, int depth, const struct m0_xcode_type *xt, void *addr, int fieldno, int elno, enum m0_xcode_cursor_flag flag)
Definition: xcode.c:354
static void f_count(struct m0_xcode_type *xt, struct m0_xcode_field *field, void *data)
Definition: xcode.c:1168
static void xcode_cmp_test(void)
Definition: xcode.c:602
void m0_free(void *data)
Definition: memory.c:146
const struct m0_xcode_type M0_XT_U64
Definition: xcode.c:940
static void xcode_bitmask_read(void)
Definition: xcode.c:1066
int32_t rc
Definition: trigger_fop.h:47
#define ARRAY_SIZE(a)
Definition: misc.h:45
uint64_t f_y
Definition: xcode.c:40
struct m0_xcode_field field[CHILDREN_MAX]
Definition: xcode.c:79
#define offsetof(typ, memb)
Definition: misc.h:29
uint64_t f_x
Definition: xcode.c:71
uint32_t xct_flags
Definition: xcode.h:331
#define M0_BASSERT(cond)
#define M0_UT_ASSERT(a)
Definition: ut.h:46
Definition: vec.h:145
uint32_t t_flag
Definition: xcode.c:61
#define M0_IMPOSSIBLE(fmt,...)