Motr  M0
fmt.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2014-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 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_BE
24 #include "lib/trace.h"
25 
26 #include "be/fmt.h"
27 
28 #include "lib/misc.h"
29 #include "lib/buf.h" /* m0_buf */
30 #include "lib/errno.h" /* EPROTO */
31 #include "lib/memory.h" /* m0_alloc */
32 #include "lib/thread.h" /* LAMBDA */
33 
34 #include "ut/ut.h"
35 #include "ut/misc.h" /* m0_ut_random_shuffle */
36 
43 /*
44  * encode
45  * decode
46  * valid
47  * invalid
48  * change random bytes
49  * size > valid size
50  * size < valid size
51  * size = 0
52  */
54 {
55  struct m0_be_fmt_log_header lh = {};
56  struct m0_be_fmt_log_header *lh_decoded;
58  struct m0_buf encoded;
59  struct m0_bufvec bvec_encoded;
60  struct m0_bufvec_cursor cur_encoded;
61  bool equal;
62  int rc;
63 
64  bvec_encoded = M0_BUFVEC_INIT_BUF(&encoded.b_addr, &encoded.b_nob);
65  /* encode + decode */
66  rc = m0_be_fmt_log_header_init(&lh, NULL);
67  M0_UT_ASSERT(rc == 0);
68  size = m0_be_fmt_log_header_size(&lh);
69  m0_buf_init(&encoded, m0_alloc(size), size);
70 
71  lh.flh_group_size = 0x10;
72  lh.flh_group_lsn = 0x20;
73 
74  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
75  rc = m0_be_fmt_log_header_encode(&lh, &cur_encoded);
76  M0_UT_ASSERT(rc == 0);
77 
78  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
79  rc = m0_be_fmt_log_header_decode(&lh_decoded, &cur_encoded,
81  M0_UT_ASSERT(rc == 0);
82 
83  equal = memcmp(&lh, lh_decoded, sizeof lh) == 0;
84  M0_UT_ASSERT(equal);
85 
86  m0_be_fmt_log_header_decoded_free(lh_decoded);
87  m0_be_fmt_log_header_fini(&lh);
88  m0_buf_free(&encoded);
89 
90  /* decode when buf size is greater than encoded size */
91  m0_buf_init(&encoded, m0_alloc(size + 1), size + 1);
92 
93  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
94  rc = m0_be_fmt_log_header_decode(&lh_decoded, &cur_encoded,
96  M0_UT_ASSERT(rc == 0);
97 
98  m0_be_fmt_log_header_decoded_free(lh_decoded);
99  m0_buf_free(&encoded);
100 
101  /* decode when buf size is less than encoded size */
102  m0_buf_init(&encoded, m0_alloc(size - 1), size - 1);
103 
104  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
105  rc = m0_be_fmt_log_header_decode(&lh_decoded, &cur_encoded,
107  M0_UT_ASSERT(rc != 0);
108 
109  m0_be_fmt_log_header_decoded_free(lh_decoded);
110  m0_buf_free(&encoded);
111 
112  /* decode when buf size is 0 */
113  m0_buf_init(&encoded, NULL, 0);
114 
115  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
116  rc = m0_be_fmt_log_header_decode(&lh_decoded, &cur_encoded,
118  M0_UT_ASSERT(rc != 0);
119 
120  m0_be_fmt_log_header_decoded_free(lh_decoded);
121  m0_buf_free(&encoded);
122 }
123 
124 /*
125  * encode
126  * decode
127  * valid
128  * invalid
129  * change random bytes
130  * size > valid size
131  * size < valid size
132  * size = 0
133  */
135 {
136  struct m0_be_fmt_cblock cb = {};
137  struct m0_be_fmt_cblock *cb_decoded;
139  struct m0_buf encoded;
140  struct m0_bufvec bvec_encoded;
141  struct m0_bufvec_cursor cur_encoded;
142  bool equal;
143  int rc;
144 
145  bvec_encoded = M0_BUFVEC_INIT_BUF(&encoded.b_addr, &encoded.b_nob);
146  /* encode + decode */
147  rc = m0_be_fmt_cblock_init(&cb, NULL);
148  M0_UT_ASSERT(rc == 0);
149  size = m0_be_fmt_cblock_size(&cb);
150  m0_buf_init(&encoded, m0_alloc(size), size);
151 
152  cb.gcb_lsn = 0x01;
153  cb.gcb_magic = 0xcafebabe;
154  cb.gcb_size = 128;
155  cb.gcb_tx_nr = 10;
156 
157  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
158  rc = m0_be_fmt_cblock_encode(&cb, &cur_encoded);
159  M0_UT_ASSERT(rc == 0);
160 
161  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
162  rc = m0_be_fmt_cblock_decode(&cb_decoded, &cur_encoded,
164  M0_UT_ASSERT(rc == 0);
165 
166  equal = memcmp(&cb, cb_decoded, sizeof cb) == 0;
167  M0_UT_ASSERT(equal);
168 
169  m0_be_fmt_cblock_decoded_free(cb_decoded);
170  m0_be_fmt_cblock_fini(&cb);
171  m0_buf_free(&encoded);
172 
173  /* decode when buf size is greater than encoded size */
174  m0_buf_init(&encoded, m0_alloc(size + 1), size + 1);
175 
176  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
177  rc = m0_be_fmt_cblock_decode(&cb_decoded, &cur_encoded,
179  M0_UT_ASSERT(rc == 0);
180 
181  m0_be_fmt_cblock_decoded_free(cb_decoded);
182  m0_buf_free(&encoded);
183 
184  /* decode when buf size is less than encoded size */
185  m0_buf_init(&encoded, m0_alloc(size - 1), size - 1);
186 
187  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
188  rc = m0_be_fmt_cblock_decode(&cb_decoded, &cur_encoded,
190  M0_UT_ASSERT(rc != 0);
191 
192  m0_be_fmt_cblock_decoded_free(cb_decoded);
193  m0_buf_free(&encoded);
194 
195  /* decode when buf size is 0 */
196  m0_buf_init(&encoded, NULL, 0);
197 
198  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
199  rc = m0_be_fmt_cblock_decode(&cb_decoded, &cur_encoded,
201  M0_UT_ASSERT(rc != 0);
202 
203  m0_be_fmt_cblock_decoded_free(cb_decoded);
204  m0_buf_free(&encoded);
205 }
206 
207 static bool fmt_group_eq(struct m0_be_fmt_group *left,
208  struct m0_be_fmt_group *right)
209 {
210  uint32_t rnr = left->fg_content_header.fch_reg_area.chr_nr;
211  uint32_t tnr = left->fg_content_header.fch_txs.cht_nr;
212  uint32_t pnr = left->fg_content.fmc_payloads.fcp_nr;
213 
215  &left->fg_content_header.fch_reg_area;
218  struct m0_be_fmt_content_header_txs *ltxs =
219  &left->fg_content_header.fch_txs;
220  struct m0_be_fmt_content_header_txs *rtxs =
221  &right->fg_content_header.fch_txs;
222  struct m0_buf *lps =
223  left->fg_content.fmc_payloads.fcp_payload;
224  struct m0_buf *rps =
226  struct m0_buf *lreg =
227  left->fg_content.fmc_reg_area.cra_reg;
228  struct m0_buf *rreg =
230 
231  return memcmp(&left->fg_header, &right->fg_header,
232  sizeof left->fg_header) == 0 &&
233  left->fg_content_header.fch_reg_area.chr_nr ==
235  left->fg_content_header.fch_txs.cht_nr ==
237  m0_forall(i, rnr, memcmp(&lra->chr_reg[i], &rra->chr_reg[i],
238  sizeof lra->chr_reg[i]) == 0) &&
239  m0_forall(i, tnr, memcmp(&ltxs->cht_tx[i], &rtxs->cht_tx[i],
240  sizeof ltxs->cht_tx[i]) == 0) &&
241  left->fg_content.fmc_payloads.fcp_nr ==
242  right->fg_content.fmc_payloads.fcp_nr &&
243  left->fg_content.fmc_reg_area.cra_nr ==
244  right->fg_content.fmc_reg_area.cra_nr &&
245  m0_forall(i, pnr, m0_buf_eq(&lps[i], &rps[i])) &&
246  m0_forall(i, rnr, m0_buf_eq(&lreg[i], &rreg[i])) &&
248 }
249 
250 #define CFG(tx_nr_max, reg_nr_max, payload_sz_max, ra_sz_max) \
251  (const struct m0_be_fmt_group_cfg) { \
252  .fgc_tx_nr_max = tx_nr_max, \
253  .fgc_reg_nr_max = reg_nr_max, \
254  .fgc_payload_size_max = payload_sz_max, \
255  .fgc_reg_size_max = ra_sz_max, \
256  }
257 #define REG(size, addr, buf) \
258  (const struct m0_be_fmt_reg) { \
259  .fr_size = size, \
260  .fr_addr = addr, \
261  .fr_buf = buf \
262  }
263 #define TX(p_addr, p_nob, id) \
264  (const struct m0_be_fmt_tx) { \
265  .bft_payload = { \
266  .b_addr = p_addr, \
267  .b_nob = p_nob, \
268  }, \
269  .bft_id = id, \
270  }
271 
273  void *payload,
274  size_t payload_size,
275  size_t TX_NR_MAX,
276  size_t REG_NR_MAX)
277 {
278  int i;
279 
280  for (i = 0; i < TX_NR_MAX; ++i)
282  &TX(payload, payload_size, i) :
283  &TX( NULL, 0, i));
284 
285  for (i = 0; i < REG_NR_MAX; ++i)
286  m0_be_fmt_group_reg_add(group, &REG(payload_size,
287  (void *) 0x400000000128ULL,
288  payload));
289 }
290 
293  bool buf_lack;
294  bool last;
296  struct m0_be_fmt_group *);
298  struct m0_buf *);
299 };
300 
301 static void spoil_nr(struct m0_be_ut_fmt_group_test *t, struct m0_buf *b)
302 {
303  int i;
304  uint8_t *addr = (uint8_t *)b->b_addr;
305  /* make sure one byte can hold the size */
306  M0_UT_ASSERT((uint8_t) t->cfg.fgc_tx_nr_max == t->cfg.fgc_tx_nr_max);
307  for (i = 0; i < b->b_nob; i++) {
308  if (addr[i] == t->cfg.fgc_tx_nr_max) {
309  /* corrupt size, make it bigger */
310  M0_LOG(M0_DEBUG, "corrupt starting from %p", &addr[i]);
311  addr[i+1] = 0xDE;
312  addr[i+2] = 0xAD;
313  addr[i+3] = 0xBE;
314  addr[i+4] = 0xAF;
315  }
316  }
317 }
318 
320 {
321  struct m0_be_fmt_group_cfg cfg;
322  struct m0_be_fmt_group fg;
324  m0_bcount_t size_max;
325  uint64_t max;
326  uint64_t reg_area_size;
327  void *buf;
328  int rc;
329  int i;
330  int j;
331 
332  uint64_t reg_sizes1[] = { 1024, 1024, 1024 };
333  uint64_t reg_sizes2[] = { 2048, 512, 512 };
334  uint64_t reg_sizes3[] = { 3072, 0, 0 };
335  uint64_t reg_sizes4[] = { 1, 2, 3, 4, 5, 6 };
336  struct {
337  uint64_t tx_nr;
338  uint64_t reg_nr;
339  uint64_t payload_size;
340  uint64_t *reg_sizes;
341  } tests[] = {
342  { 3, ARRAY_SIZE(reg_sizes1), 1024, reg_sizes1 },
343  { 4, ARRAY_SIZE(reg_sizes2), 100, reg_sizes2 },
344  { 5, ARRAY_SIZE(reg_sizes3), 1, reg_sizes3 },
345  { 1, ARRAY_SIZE(reg_sizes4), 99, reg_sizes4 },
346  { 0, 0, 0, NULL },
347  };
348 
349  for (i = 0; i < ARRAY_SIZE(tests); ++i) {
350  reg_area_size = 0;
351  max = tests[i].payload_size;
352  for (j = 0; j < tests[i].reg_nr; ++j) {
353  reg_area_size += tests[i].reg_sizes[j];
354  max = max64u(max, tests[i].reg_sizes[j]);
355  }
356  cfg = CFG(tests[i].tx_nr, tests[i].reg_nr,
357  tests[i].payload_size * tests[i].tx_nr,
358  reg_area_size);
359 
360  buf = max == 0 ? NULL : m0_alloc(max);
361  M0_UT_ASSERT(ergo(max != 0, buf != NULL));
362 
363  M0_SET0(&fg);
364  rc = m0_be_fmt_group_init(&fg, &cfg);
365  M0_UT_ASSERT(rc == 0);
366  for (j = 0; j < tests[i].tx_nr; ++j) {
368  tests[i].payload_size, 0));
369  }
370  for (j = 0; j < tests[i].reg_nr; ++j) {
371  m0_be_fmt_group_reg_add(&fg, &REG(tests[i].reg_sizes[j],
372  NULL, buf));
373  }
374  size_max = m0_be_fmt_group_size_max(&cfg);
375  size = m0_be_fmt_group_size(&fg);
376  M0_UT_ASSERT(size == size_max);
378  m0_free(buf);
379  }
380 }
381 
382 enum {
385 };
386 
387 static m0_bcount_t
389  uint64_t *seed)
390 {
391  struct m0_be_fmt_group *fg;
393  m0_bcount_t size_max;
394  uint64_t *payload_size = NULL;
395  uint64_t *reg_size = NULL;
396  int rc;
397  uint64_t i;
398 
399  if ((fg_cfg->fgc_tx_nr_max == 0 && fg_cfg->fgc_payload_size_max > 0) ||
400  (fg_cfg->fgc_reg_nr_max == 0 && fg_cfg->fgc_reg_size_max > 0))
401  return M0_BCOUNT_MAX;
402 
403  M0_ALLOC_PTR(fg);
404  M0_UT_ASSERT(fg != NULL);
405  if (fg_cfg->fgc_tx_nr_max > 0) {
406  M0_ALLOC_ARR(payload_size, fg_cfg->fgc_tx_nr_max);
407  M0_UT_ASSERT(payload_size != NULL);
408  m0_ut_random_arr_with_sum(payload_size, fg_cfg->fgc_tx_nr_max,
409  fg_cfg->fgc_payload_size_max, seed);
410  m0_ut_random_shuffle(payload_size, fg_cfg->fgc_tx_nr_max, seed);
411  M0_ASSERT(m0_reduce(i, fg_cfg->fgc_tx_nr_max,
412  0, + payload_size[i]) ==
413  fg_cfg->fgc_payload_size_max);
414  }
415  if (fg_cfg->fgc_reg_nr_max > 0) {
416  M0_ALLOC_ARR(reg_size, fg_cfg->fgc_reg_nr_max);
417  M0_UT_ASSERT(reg_size != NULL);
418  m0_ut_random_arr_with_sum(reg_size, fg_cfg->fgc_reg_nr_max,
419  fg_cfg->fgc_reg_size_max, seed);
420  m0_ut_random_shuffle(reg_size, fg_cfg->fgc_reg_nr_max, seed);
421  M0_ASSERT(m0_reduce(i, fg_cfg->fgc_reg_nr_max,
422  0, + reg_size[i]) ==
423  fg_cfg->fgc_reg_size_max);
424  }
426  M0_UT_ASSERT(rc == 0);
427  for (i = 0; i < fg_cfg->fgc_tx_nr_max; ++i)
428  m0_be_fmt_group_tx_add(fg, &TX(NULL, payload_size[i], 0));
429  for (i = 0; i < fg_cfg->fgc_reg_nr_max; ++i)
430  m0_be_fmt_group_reg_add(fg, &REG(reg_size[i], NULL, NULL));
432  size_max = m0_be_fmt_group_size_max(fg_cfg);
433  M0_ASSERT_INFO(size == size_max, "size=%" PRIu64 " size_max=%"PRIu64,
434  size, size_max);
436  m0_free(reg_size);
437  m0_free(payload_size);
438  m0_free(fg);
439  return size_max;
440 }
441 
443  uint64_t *seed)
444 {
445  struct m0_be_fmt_group_cfg fg_cfg = *fg_cfg2;
446  m0_bcount_t size_max;
447  m0_bcount_t size_max_prev;
448  uint64_t *value[] = {
449  &fg_cfg.fgc_tx_nr_max,
450  &fg_cfg.fgc_reg_nr_max,
451  &fg_cfg.fgc_payload_size_max,
452  &fg_cfg.fgc_reg_size_max,
453  &fg_cfg.fgc_seg_nr_max,
454  };
455  int i;
456 
457  size_max_prev = be_ut_fmt_group_size_max_check(&fg_cfg, seed);
458  for (i = 0; i < BE_UT_FMT_GROUP_SIZE_MAX_RND_ITER; ++i) {
461  M0_UT_ASSERT(ergo(size_max_prev != M0_BCOUNT_MAX,
462  size_max >= size_max_prev));
463  size_max_prev = size_max == M0_BCOUNT_MAX ?
464  size_max_prev : size_max;
465  }
466 }
467 
469 {
470  struct m0_be_fmt_group_cfg *fg_cfg;
471  uint64_t seed = 42;
472  int i;
473 
475  .fgc_tx_nr_max = 0,
476  .fgc_reg_nr_max = 0,
477  .fgc_payload_size_max = 0,
478  .fgc_reg_size_max = 0,
479  .fgc_seg_nr_max = 0,
480  }, &seed);
482  .fgc_tx_nr_max = 0x100,
483  .fgc_reg_nr_max = 0x100,
484  .fgc_payload_size_max = 0x100,
485  .fgc_reg_size_max = 0x100,
486  .fgc_seg_nr_max = 0x100,
487  }, &seed);
488 
491  for (i = 0; i < BE_UT_FMT_GROUP_SIZE_MAX_RND_NR; ++i) {
492  *fg_cfg = (struct m0_be_fmt_group_cfg){
493  .fgc_tx_nr_max = m0_rnd64(&seed) % 0x10 + 1,
494  .fgc_reg_nr_max = m0_rnd64(&seed) % 0x10 + 1,
495  .fgc_payload_size_max = m0_rnd64(&seed) % 0x1000,
496  .fgc_reg_size_max = m0_rnd64(&seed) % 0x1000,
497  .fgc_seg_nr_max = m0_rnd64(&seed) % 0x10 + 1,
498  };
500  }
501  m0_free(fg_cfg);
502 }
503 
505 {
506  int rc;
507  int i;
508  struct m0_be_ut_fmt_group_test test[] = {
509  { /* main route of the test, shall pass */
510  .cfg = CFG(10, 100, 99, 800),
511  },
512  { /* main route of the test, shall pass */
513  .cfg = CFG(1, 2, 20, 16),
514  },
515  { /* simulates the lack of space in the buffer for decode */
516  .cfg = CFG(10, 100, 99, 800),
517  .buf_lack = true,
518  },
519  { /* simulates data corruption after encoding the group */
520  .cfg = CFG(10, 100, 99, 800),
521  .encoded_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
522  struct m0_buf *b) {
523  memset(b->b_addr, 0xCC, b->b_nob / 10);
524  }),
525  },
526  { /* simulates group data sizes mismatch: tx header size exceeds
527  * reasonable values */
528  .cfg = CFG(10, 100, 99, 800),
529  .group_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
530  struct m0_be_fmt_group *g){
531  g->fg_content_header.fch_txs.cht_nr =
532  1 << 10;
533  }),
534 
535  },
536  { /* simulates group data sizes mismatch: reg area size exceeds
537  * reasonable values */
538  .cfg = CFG(10, 100, 99, 800),
539  .group_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
540  struct m0_be_fmt_group *g){
541  g->fg_content_header.fch_reg_area.chr_nr =
542  1 << 10;
543  }),
544 
545  },
546 #if 0 /* XXX: crashes in xcode. */
547 fmt-group motr: fb00 FATAL : [lib/assert.c:46:m0_panic] panic: fatal signal delivered at unknown() (unknown:0) [git: jenkins-OSAINT_motr-294-230-g2d11e2b-dirty]
548 Motr panic: fatal signal delivered at unknown() unknown:0 (errno: 2) (last failed: none) [git: jenkins-OSAINT_motr-294-230-g2d11e2b-dirty] pid: 76277
549 Motr panic reason: signo: 11
550 /.libs/libmotr-0.1.0.so(m0_arch_backtrace+0x1f)[0x7f3e679b3431]
551 /.libs/libmotr-0.1.0.so(m0_arch_panic+0x124)[0x7f3e679b3578]
552 /.libs/libmotr-0.1.0.so(m0_panic+0x1e5)[0x7f3e6799e9a8]
553 /.libs/libmotr-0.1.0.so(+0x22b6ee)[0x7f3e679b36ee]
554 /lib64/libpthread.so.0[0x3593e0f4a0]
555 /lib64/libc.so.6[0x3593a889e8]
556 /lib64/libc.so.6(memmove+0x7e)[0x3593a8252e]
557 /.libs/libmotr-0.1.0.so(m0_bufvec_cursor_copy+0xa2)[0x7f3e679ad75b]
558 /.libs/libmotr-0.1.0.so(+0x2d4ccb)[0x7f3e67a5cccb]
559 /.libs/libmotr-0.1.0.so(m0_xcode_encode+0x1d)[0x7f3e67a5cdbc]
560 /.libs/libmotr-0.1.0.so(+0x18ee45)[0x7f3e67916e45]
561 /.libs/libmotr-0.1.0.so(m0_be_fmt_group_encode+0x41)[0x7f3e67917897]
562 /.libs/libmotr-ut.so.0(m0_be_ut_fmt_group+0x3d0)[0x7f3e68699484]
563 #endif
564 #if 0
565  { /* simulates group data sizes mismatch: payload size exceeds
566  * reasonable values */
567  .cfg = CFG(10, 100, 99, 99),
568  .group_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
569  struct m0_be_fmt_group *g){
570  g->fg_content.fmc_payloads.fcp_nr =
571  1 << 10;
572  }),
573 
574  },
575  { /* simulates group data sizes mismatch: payload buf size
576  * exceeds reasonable values */
577  .cfg = CFG(10, 100, 99, 99),
578  .group_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
579  struct m0_be_fmt_group *g){
580  g->fg_content.fmc_payloads.fcp_payload[0].b_nob =
581  1 << 24;
582  }),
583 
584  },
585  { /* simulates group data sizes mismatch: reg area size exceeds
586  * reasonable values */
587  .cfg = CFG(10, 100, 99, 99),
588  .group_spoil = LAMBDA(void, (struct m0_be_ut_fmt_group_test *t,
589  struct m0_be_fmt_group *g){
590  g->fg_content.fmc_reg_area.cra_nr =
591  1 << 10;
592  }),
593 
594  },
595 #endif
596  /* The following tests simulate data corruption after encoding
597  the group. Make sure that even such combination will not
598  crash xcode.
599  */
600  {
601  .cfg = CFG(0xEA, 100, 99, 800),
602  .encoded_spoil = spoil_nr,
603  },
604  {
605  .cfg = CFG(10, 0xEA, 99, 0xEA * 8),
606  .encoded_spoil = spoil_nr,
607  },
608  {
609  .cfg = CFG(10, 100, 0xEA, 800),
610  .encoded_spoil = spoil_nr,
611  },
612  {
613  .last = true,
614  }
615  };
616 
617  for (i = 0; !test[i].last; ++i) {
618  struct m0_be_fmt_group group = {};
619  struct m0_be_fmt_group *group_decoded;
621  struct m0_buf encoded;
622  struct m0_bufvec bvec_encoded;
623  struct m0_bufvec_cursor cur_encoded;
624  bool reseted = false;
625 
626  M0_LOG(M0_DEBUG, "test: %i, cfg:"
627  "(%" PRId64 ", %" PRId64 ", %" PRId64 ", %" PRId64 ")", i,
628  test[i].cfg.fgc_tx_nr_max,
629  test[i].cfg.fgc_reg_nr_max,
630  test[i].cfg.fgc_reg_size_max,
631  test[i].cfg.fgc_payload_size_max);
632  bvec_encoded = M0_BUFVEC_INIT_BUF(&encoded.b_addr,
633  &encoded.b_nob);
634  rc = m0_be_fmt_group_init(&group, &test[i].cfg);
635  M0_UT_ASSERT(rc == 0);
636 
637  size = !test[i].buf_lack ?
640 
641  m0_buf_init(&encoded, m0_alloc(size), size);
642 
643  while (true) {
645  test[i].cfg.fgc_tx_nr_max,
646  test[i].cfg.fgc_reg_nr_max);
647 
648  if (test[i].group_spoil != NULL)
649  test[i].group_spoil(&test[i], &group);
650 
651  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
652  rc = m0_be_fmt_group_encode(&group, &cur_encoded);
653  if (test[i].buf_lack || test[i].group_spoil != NULL) {
654  M0_UT_ASSERT(rc == -EPROTO);
655  break;
656  }
657  M0_UT_ASSERT(rc == 0);
658 
659  if (test[i].encoded_spoil != NULL)
660  test[i].encoded_spoil(&test[i], &encoded);
661  m0_bufvec_cursor_init(&cur_encoded, &bvec_encoded);
663  &group_decoded,
664  &cur_encoded,
666  if (test[i].encoded_spoil == NULL)
667  M0_UT_ASSERT(rc == 0 &&
669  group_decoded));
670  else
671  M0_UT_ASSERT(rc != 0 ||
673  group_decoded));
674 
675  m0_be_fmt_group_decoded_free(group_decoded);
676 
677  if (reseted)
678  break;
680  reseted = true;
681  }
682 
684  m0_buf_free(&encoded);
685  }
686 }
687 
690 #undef M0_TRACE_SUBSYSTEM
691 
692 /*
693  * Local variables:
694  * c-indentation-style: "K&R"
695  * c-basic-offset: 8
696  * tab-width: 8
697  * fill-column: 80
698  * scroll-step: 1
699  * End:
700  */
701 /*
702  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
703  */
#define TX(p_addr, p_nob, id)
Definition: fmt.c:263
#define M0_BUFVEC_INIT_BUF(addr_ptr, count_ptr)
Definition: vec.h:165
M0_INTERNAL void m0_ut_random_arr_with_sum(uint64_t *arr, uint64_t nr, uint64_t sum, uint64_t *seed)
Definition: misc.c:47
#define M0_ALLOC_ARR(arr, nr)
Definition: memory.h:84
#define M0_BE_FMT_DECODE_CFG_DEFAULT
Definition: fmt.h:291
uint64_t gcb_magic
Definition: fmt.h:234
uint64_t gcb_size
Definition: fmt.h:232
#define NULL
Definition: misc.h:38
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL void m0_be_fmt_group_reg_add(struct m0_be_fmt_group *fg, const struct m0_be_fmt_reg *freg)
Definition: fmt.c:367
void * b_addr
Definition: buf.h:39
M0_INTERNAL bool m0_buf_eq(const struct m0_buf *x, const struct m0_buf *y)
Definition: buf.c:90
#define M0_LOG(level,...)
Definition: trace.h:167
void m0_panic(const struct m0_panic_ctx *ctx,...)
Definition: assert.c:40
static char * tests
Definition: st_kmain.c:52
static void spoil_nr(struct m0_be_ut_fmt_group_test *t, struct m0_buf *b)
Definition: fmt.c:301
M0_INTERNAL void m0_buf_init(struct m0_buf *buf, void *data, uint32_t nob)
Definition: buf.c:37
#define REG(size, addr, buf)
Definition: fmt.c:257
int const char const void * value
Definition: dir.c:325
uint64_t gcb_tx_nr
Definition: fmt.h:233
uint64_t m0_bcount_t
Definition: types.h:77
static int left
Definition: locality.c:280
static int void * buf
Definition: dir.c:1019
#define M0_SET0(obj)
Definition: misc.h:64
struct m0_be_fmt_group_cfg cfg
Definition: fmt.c:292
void m0_be_ut_fmt_log_header(void)
Definition: fmt.c:53
Definition: sock.c:887
M0_INTERNAL int m0_be_fmt_group_decode(struct m0_be_fmt_group **fg, struct m0_bufvec_cursor *cur, const struct m0_be_fmt_decode_cfg *cfg)
Definition: fmt.c:355
Definition: buf.h:37
int i
Definition: dir.c:1033
void(* encoded_spoil)(struct m0_be_ut_fmt_group_test *, struct m0_buf *)
Definition: fmt.c:297
#define PRIu64
Definition: types.h:58
struct m0_be_fmt_content_header_txs fch_txs
Definition: fmt.h:162
M0_INTERNAL void m0_be_fmt_group_decoded_free(struct m0_be_fmt_group *fg)
Definition: fmt.c:362
#define LAMBDA(T,...)
Definition: thread.h:153
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
#define CFG(tx_nr_max, reg_nr_max, payload_sz_max, ra_sz_max)
Definition: fmt.c:250
m0_bcount_t b_nob
Definition: buf.h:38
#define M0_ASSERT(cond)
struct m0_be_fmt_content fg_content
Definition: fmt.h:217
static struct m0_thread t[8]
Definition: service_ut.c:1230
static void be_fmt_group_populate(struct m0_be_fmt_group *group, void *payload, size_t payload_size, size_t TX_NR_MAX, size_t REG_NR_MAX)
Definition: fmt.c:272
M0_INTERNAL m0_bcount_t m0_be_fmt_group_size_max(const struct m0_be_fmt_group_cfg *cfg)
Definition: fmt.c:324
static long long max(long long a, long long b)
Definition: crate.c:196
M0_INTERNAL void m0_bufvec_cursor_init(struct m0_bufvec_cursor *cur, const struct m0_bufvec *bvec)
Definition: vec.c:563
M0_INTERNAL void m0_arch_backtrace(void)
Definition: kassert.c:40
char * fmt(const char *format,...) __attribute__((format(printf
void * m0_alloc(size_t size)
Definition: memory.c:126
struct m0_be_fmt_group_header fg_header
Definition: fmt.h:215
Definition: xcode.h:73
static void group(void)
Definition: sm.c:386
void m0_be_ut_fmt_group(void)
Definition: fmt.c:504
m0_bindex_t flh_group_lsn
Definition: fmt.h:205
uint64_t fg_cfg
Definition: fmt.h:99
M0_INTERNAL void m0_buf_free(struct m0_buf *buf)
Definition: buf.c:55
struct m0_be_fmt_content_header_tx * cht_tx
Definition: fmt.h:148
static m0_bcount_t be_ut_fmt_group_size_max_check(struct m0_be_fmt_group_cfg *fg_cfg, uint64_t *seed)
Definition: fmt.c:388
#define PRId64
Definition: types.h:57
struct m0_be_fmt_content_header_reg_area fch_reg_area
Definition: fmt.h:163
M0_INTERNAL m0_bcount_t m0_be_fmt_group_size(struct m0_be_fmt_group *fg)
Definition: fmt.c:318
#define m0_forall(var, nr,...)
Definition: misc.h:112
void m0_be_ut_fmt_group_size_max_rnd(void)
Definition: fmt.c:468
static bool at(struct ff2c_context *ctx, char c)
Definition: lex.c:77
M0_INTERNAL void m0_be_fmt_group_fini(struct m0_be_fmt_group *fg)
Definition: fmt.c:286
struct m0_be_fmt_content_header fg_content_header
Definition: fmt.h:216
M0_INTERNAL uint64_t m0_rnd64(uint64_t *seed)
Definition: misc.c:100
struct m0_buf * fcp_payload
Definition: fmt.h:168
void m0_be_ut_fmt_cblock(void)
Definition: fmt.c:134
void m0_be_ut_fmt_group_size_max(void)
Definition: fmt.c:319
struct m0_buf * cra_reg
Definition: fmt.h:173
#define M0_ALLOC_PTR(ptr)
Definition: memory.h:86
struct m0_motr motr
Definition: list.c:42
M0_INTERNAL void m0_arch_panic(const struct m0_panic_ctx *ctx, va_list ap) __attribute__((noreturn))
Definition: kassert.c:45
struct m0_be_fmt_content_header_reg * chr_reg
Definition: fmt.h:158
m0_bcount_t size
Definition: di.c:39
M0_INTERNAL int m0_xcode_encode(struct m0_xcode_ctx *ctx)
Definition: xcode.c:385
#define M0_BE_FMT_DECODE_CFG_DEFAULT_WITH_TRACE
Definition: fmt.h:298
M0_INTERNAL void m0_ut_random_shuffle(uint64_t *arr, uint64_t nr, uint64_t *seed)
Definition: misc.c:37
M0_INTERNAL void m0_be_fmt_group_tx_add(struct m0_be_fmt_group *fg, const struct m0_be_fmt_tx *ftx)
Definition: fmt.c:414
static void be_ut_fmt_group_size_max_test(struct m0_be_fmt_group_cfg *fg_cfg2, uint64_t *seed)
Definition: fmt.c:442
#define M0_ASSERT_INFO(cond, fmt,...)
struct m0_be_fmt_content_payloads fmc_payloads
Definition: fmt.h:177
M0_INTERNAL void m0_be_fmt_group_reset(struct m0_be_fmt_group *fg)
Definition: fmt.c:297
static struct gen g[MAX_GEN]
Definition: beck.c:521
void m0_free(void *data)
Definition: memory.c:146
M0_INTERNAL int m0_be_fmt_group_init(struct m0_be_fmt_group *fg, const struct m0_be_fmt_group_cfg *cfg)
Definition: fmt.c:237
M0_INTERNAL int m0_be_fmt_group_encode(struct m0_be_fmt_group *fg, struct m0_bufvec_cursor *cur)
Definition: fmt.c:347
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
struct m0_be_fmt_content_reg_area fmc_reg_area
Definition: fmt.h:178
static uint64_t max64u(uint64_t a, uint64_t b)
Definition: arith.h:71
static struct m0_addb2_frame_header last
Definition: storage.c:93
void(* group_spoil)(struct m0_be_ut_fmt_group_test *, struct m0_be_fmt_group *)
Definition: fmt.c:295
m0_bcount_t flh_group_size
Definition: fmt.h:206
Definition: vec.h:145
static bool fmt_group_eq(struct m0_be_fmt_group *left, struct m0_be_fmt_group *right)
Definition: fmt.c:207
const uint64_t payload[]
Definition: base.c:65
uint64_t gcb_lsn
Definition: fmt.h:231