blob: 893a2202f3cb9cca9c22527bf6c596d3716c4107 [file] [log] [blame]
Michal Vasko99544ca2021-06-29 10:45:19 +02001/**
2 * @file perf.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief performance tests
5 *
6 * Copyright (c) 2021 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
16
17#include <assert.h>
18#include <inttypes.h>
19#include <stdlib.h>
20#include <sys/time.h>
21#include <time.h>
22
23#include "libyang.h"
24#include "tests_config.h"
25
26#ifdef HAVE_CALLGRIND
27# include <valgrind/callgrind.h>
28#endif
29
30#define TEMP_FILE "perf_tmp"
31
32/**
33 * @brief Test state structure.
34 */
35struct test_state {
36 const struct lys_module *mod;
37 uint32_t count;
38 struct lyd_node *data1;
39 struct lyd_node *data2;
40};
41
42typedef LY_ERR (*setup_cb)(const struct lys_module *mod, uint32_t count, struct test_state *state);
43
44typedef LY_ERR (*test_cb)(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end);
45
46/**
47 * @brief Single test structure.
48 */
49struct test {
50 const char *name;
51 setup_cb setup;
52 test_cb test;
53};
54
55/**
56 * @brief Get current time as timespec.
57 *
58 * @param[out] ts Timespect to fill.
59 */
60static void
61time_get(struct timespec *ts)
62{
63#ifdef CLOCK_MONOTONIC_RAW
64 clock_gettime(CLOCK_MONOTONIC_RAW, ts);
65#elif defined (CLOCK_MONOTONIC)
66 clock_gettime(CLOCK_MONOTONIC, ts);
67#elif defined (CLOCK_REALTIME)
68 /* no monotonic clock available, return realtime */
69 clock_gettime(CLOCK_REALTIME, ts);
70#else
71 int rc;
72 struct timeval tv;
73
74 gettimeofday(&tv, NULL);
75 ts->tv_sec = (time_t)tv.tv_sec;
76 ts->tv_nsec = 1000L * (long)tv.tv_usec;
77#endif
78}
79
80/**
81 * @brief Get the difference of 2 timespecs in microseconds.
82 *
83 * @param[in] ts1 Smaller (older) timespec.
84 * @param[in] ts2 Larger (later) timespec.
85 * @return Difference of timespecs in usec.
86 */
87static uint64_t
88time_diff(const struct timespec *ts1, const struct timespec *ts2)
89{
90 uint64_t usec_diff = 0;
91 int64_t nsec_diff;
92
93 assert(ts1->tv_sec <= ts2->tv_sec);
94
95 /* seconds diff */
96 usec_diff += (ts2->tv_sec - ts1->tv_sec) * 1000000;
97
98 /* nanoseconds diff */
99 nsec_diff = ts2->tv_nsec - ts1->tv_nsec;
100 usec_diff += nsec_diff ? nsec_diff / 1000 : 0;
101
102 return usec_diff;
103}
104
105/**
106 * @brief Create data tree with list instances.
107 *
108 * @param[in] mod Module of the top-level node.
109 * @param[in] offset Starting offset of the identifier number values.
110 * @param[in] count Number of list instances to create, with increasing identifier numbers.
111 * @param[out] data Created data.
112 * @return LY_ERR value.
113 */
114static LY_ERR
115create_list_inst(const struct lys_module *mod, uint32_t offset, uint32_t count, struct lyd_node **data)
116{
117 LY_ERR ret;
118 uint32_t i;
119 char k1_val[32], k2_val[32], l_val[32];
120 struct lyd_node *list;
121
122 if ((ret = lyd_new_inner(NULL, mod, "cont", 0, data))) {
123 return ret;
124 }
125
126 for (i = 0; i < count; ++i) {
127 sprintf(k1_val, "%" PRIu32, i + offset);
128 sprintf(k2_val, "str%" PRIu32, i + offset);
129 sprintf(l_val, "l%" PRIu32, i + offset);
130
131 if ((ret = lyd_new_list(*data, NULL, "lst", 0, &list, k1_val, k2_val))) {
132 return ret;
133 }
134 if ((ret = lyd_new_term(list, NULL, "l", l_val, 0, NULL))) {
135 return ret;
136 }
137 }
138
139 return LY_SUCCESS;
140}
141
142/**
143 * @brief Execute a test.
144 *
145 * @param[in] setup Setup callback to call once.
146 * @param[in] test Test callback.
147 * @param[in] name Name of the test.
148 * @param[in] mod Module of testing data.
149 * @param[in] count Count of list instances, size of the testing data set.
150 * @param[in] tries Number of (re)tries of the test to get more accurate measurements.
151 * @return LY_ERR value.
152 */
153static LY_ERR
154exec_test(setup_cb setup, test_cb test, const char *name, const struct lys_module *mod, uint32_t count, uint32_t tries)
155{
156 LY_ERR ret;
157 struct timespec ts_start, ts_end;
158 struct test_state state = {0};
Michal Vasko4318ac32021-07-02 09:18:30 +0200159 const uint32_t name_fixed_len = 38;
Michal Vasko99544ca2021-06-29 10:45:19 +0200160 char str[name_fixed_len + 1];
161 uint32_t i, printed;
162 uint64_t time_usec = 0;
163
164 /* print test start */
165 printed = sprintf(str, "| %s ", name);
Michal Vasko4318ac32021-07-02 09:18:30 +0200166 while (printed + 2 < name_fixed_len) {
Michal Vasko99544ca2021-06-29 10:45:19 +0200167 printed += sprintf(str + printed, ".");
168 }
Michal Vasko4318ac32021-07-02 09:18:30 +0200169 if (printed + 1 < name_fixed_len) {
Michal Vasko99544ca2021-06-29 10:45:19 +0200170 printed += sprintf(str + printed, " ");
171 }
172 sprintf(str + printed, "|");
173 fputs(str, stdout);
174 fflush(stdout);
175
176 /* setup */
177 if ((ret = setup(mod, count, &state))) {
178 return ret;
179 }
180
181 /* test */
182 for (i = 0; i < tries; ++i) {
183 if ((ret = test(&state, &ts_start, &ts_end))) {
184 return ret;
185 }
186 time_usec += time_diff(&ts_start, &ts_end);
187 }
188 time_usec /= tries;
189
190 /* teardown */
191 lyd_free_siblings(state.data1);
192 lyd_free_siblings(state.data2);
193
194 /* print time */
195 printf(" %" PRIu64 ".%06" PRIu64 " s |\n", time_usec / 1000000, time_usec % 1000000);
196
197 return LY_SUCCESS;
198}
199
200static void
201TEST_START(struct timespec *ts)
202{
203 time_get(ts);
204
205#ifdef HAVE_CALLGRIND
206 CALLGRIND_START_INSTRUMENTATION;
207#endif
208}
209
210static void
211TEST_END(struct timespec *ts)
212{
213 time_get(ts);
214
215#ifdef HAVE_CALLGRIND
216 CALLGRIND_STOP_INSTRUMENTATION;
217#endif
218}
219
220/* TEST SETUP */
221static LY_ERR
222setup_basic(const struct lys_module *mod, uint32_t count, struct test_state *state)
223{
224 state->mod = mod;
225 state->count = count;
226
227 return LY_SUCCESS;
228}
229
230static LY_ERR
231setup_data_single_tree(const struct lys_module *mod, uint32_t count, struct test_state *state)
232{
233 state->mod = mod;
234 state->count = count;
235
236 return create_list_inst(mod, 0, count, &state->data1);
237}
238
239static LY_ERR
240setup_data_same_trees(const struct lys_module *mod, uint32_t count, struct test_state *state)
241{
242 LY_ERR ret;
243
244 state->mod = mod;
245 state->count = count;
246
247 if ((ret = create_list_inst(mod, 0, count, &state->data1))) {
248 return ret;
249 }
250 if ((ret = create_list_inst(mod, 0, count, &state->data2))) {
251 return ret;
252 }
253
254 return LY_SUCCESS;
255}
256
257static LY_ERR
258setup_data_no_same_trees(const struct lys_module *mod, uint32_t count, struct test_state *state)
259{
260 LY_ERR ret;
261
262 state->mod = mod;
263 state->count = count;
264
265 if ((ret = create_list_inst(mod, 0, count, &state->data1))) {
266 return ret;
267 }
268 if ((ret = create_list_inst(mod, count, count, &state->data2))) {
269 return ret;
270 }
271
272 return LY_SUCCESS;
273}
274
275static LY_ERR
276setup_data_offset_tree(const struct lys_module *mod, uint32_t count, struct test_state *state)
277{
278 LY_ERR ret;
279
280 state->mod = mod;
281 state->count = count;
282
283 if ((ret = create_list_inst(mod, count, count, &state->data2))) {
284 return ret;
285 }
286
287 return LY_SUCCESS;
288}
289
290/* TEST CB */
291static LY_ERR
292test_create_new_text(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
293{
294 LY_ERR r;
295 struct lyd_node *data = NULL;
296
297 TEST_START(ts_start);
298
299 if ((r = create_list_inst(state->mod, 0, state->count, &data))) {
300 return r;
301 }
302
303 TEST_END(ts_end);
304
305 lyd_free_siblings(data);
306
307 return LY_SUCCESS;
308}
309
310static LY_ERR
311test_create_new_bin(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
312{
313 LY_ERR r;
314 struct lyd_node *data = NULL;
315 uint32_t i, k2_len, l_len;
316 char k2_val[32], l_val[32];
317 struct lyd_node *list;
318
319 TEST_START(ts_start);
320
321 if ((r = lyd_new_inner(NULL, state->mod, "cont", 0, &data))) {
322 return r;
323 }
324
325 for (i = 0; i < state->count; ++i) {
326 k2_len = sprintf(k2_val, "str%" PRIu32, i);
327 l_len = sprintf(l_val, "l%" PRIu32, i);
328
329 if ((r = lyd_new_list_bin(data, NULL, "lst", 0, &list, &i, sizeof i, k2_val, k2_len))) {
330 return r;
331 }
332 if ((r = lyd_new_term_bin(list, NULL, "l", l_val, l_len, 0, NULL))) {
333 return r;
334 }
335 }
336
337 TEST_END(ts_end);
338
339 lyd_free_siblings(data);
340
341 return LY_SUCCESS;
342}
343
344static LY_ERR
345test_create_path(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
346{
347 LY_ERR r;
348 struct lyd_node *data = NULL;
349 uint32_t i;
350 char path[64], l_val[32];
351
352 TEST_START(ts_start);
353
354 if ((r = lyd_new_inner(NULL, state->mod, "cont", 0, &data))) {
355 return r;
356 }
357
358 for (i = 0; i < state->count; ++i) {
359 sprintf(path, "/perf:cont/lst[k1='%" PRIu32 "'][k2='str%" PRIu32 "']/l", i, i);
360 sprintf(l_val, "l%" PRIu32, i);
361
362 if ((r = lyd_new_path(data, NULL, path, l_val, 0, NULL))) {
363 return r;
364 }
365 }
366
367 TEST_END(ts_end);
368
369 lyd_free_siblings(data);
370
371 return LY_SUCCESS;
372}
373
374static LY_ERR
Michal Vaskoc606f312021-06-30 14:08:54 +0200375test_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
376{
377 LY_ERR r;
378
379 TEST_START(ts_start);
380
381 if ((r = lyd_validate_all(&state->data1, NULL, LYD_VALIDATE_PRESENT, NULL))) {
382 return r;
383 }
384
385 TEST_END(ts_end);
386
387 return LY_SUCCESS;
388}
389
390static LY_ERR
Michal Vasko99544ca2021-06-29 10:45:19 +0200391_test_parse(struct test_state *state, LYD_FORMAT format, ly_bool use_file, uint32_t print_options, uint32_t parse_options,
392 uint32_t validate_options, struct timespec *ts_start, struct timespec *ts_end)
393{
394 LY_ERR ret = LY_SUCCESS;
395 struct lyd_node *data = NULL;
396 char *buf = NULL;
397 struct ly_in *in = NULL;
398
399 if (use_file) {
400 if ((ret = lyd_print_path(TEMP_FILE, state->data1, format, print_options))) {
401 goto cleanup;
402 }
403 if ((ret = ly_in_new_filepath(TEMP_FILE, 0, &in))) {
404 goto cleanup;
405 }
406 } else {
407 if ((ret = lyd_print_mem(&buf, state->data1, format, print_options))) {
408 goto cleanup;
409 }
410 if ((ret = ly_in_new_memory(buf, &in))) {
411 goto cleanup;
412 }
413 }
414
415 TEST_START(ts_start);
416
417 if ((ret = lyd_parse_data(state->mod->ctx, NULL, in, format, parse_options, validate_options, &data))) {
418 goto cleanup;
419 }
420
421 TEST_END(ts_end);
422
423cleanup:
424 free(buf);
425 ly_in_free(in, 0);
426 lyd_free_siblings(data);
427 return ret;
428}
429
430static LY_ERR
431test_parse_xml_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
432{
433 return _test_parse(state, LYD_XML, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
434}
435
436static LY_ERR
437test_parse_xml_mem_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
438{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200439 return _test_parse(state, LYD_XML, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
440 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200441}
442
443static LY_ERR
444test_parse_xml_file_no_validate_format(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
445{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200446 return _test_parse(state, LYD_XML, 1, 0, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0, ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200447}
448
449static LY_ERR
450test_parse_json_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
451{
452 return _test_parse(state, LYD_JSON, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
453}
454
455static LY_ERR
456test_parse_json_mem_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
457{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200458 return _test_parse(state, LYD_JSON, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
459 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200460}
461
462static LY_ERR
463test_parse_json_file_no_validate_format(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
464{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200465 return _test_parse(state, LYD_JSON, 1, 0, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0, ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200466}
467
468static LY_ERR
469test_parse_lyb_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
470{
471 return _test_parse(state, LYD_LYB, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
472}
473
474static LY_ERR
475test_parse_lyb_mem_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
476{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200477 return _test_parse(state, LYD_LYB, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
478 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200479}
480
481static LY_ERR
482test_parse_lyb_file_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
483{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200484 return _test_parse(state, LYD_LYB, 1, 0, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0, ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200485}
486
487static LY_ERR
488_test_print(struct test_state *state, LYD_FORMAT format, uint32_t print_options, struct timespec *ts_start,
489 struct timespec *ts_end)
490{
491 LY_ERR ret = LY_SUCCESS;
492 char *buf = NULL;
493
494 TEST_START(ts_start);
495
496 if ((ret = lyd_print_mem(&buf, state->data1, format, print_options))) {
497 goto cleanup;
498 }
499
500 TEST_END(ts_end);
501
502cleanup:
503 free(buf);
504 return ret;
505}
506
507static LY_ERR
508test_print_xml(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
509{
510 return _test_print(state, LYD_XML, LYD_PRINT_SHRINK, ts_start, ts_end);
511}
512
513static LY_ERR
514test_print_json(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
515{
516 return _test_print(state, LYD_JSON, LYD_PRINT_SHRINK, ts_start, ts_end);
517}
518
519static LY_ERR
520test_print_lyb(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
521{
522 return _test_print(state, LYD_LYB, LYD_PRINT_SHRINK, ts_start, ts_end);
523}
524
525static LY_ERR
526test_dup(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
527{
528 LY_ERR r;
529 struct lyd_node *data;
530
531 TEST_START(ts_start);
532
533 if ((r = lyd_dup_siblings(state->data1, NULL, LYD_DUP_RECURSIVE, &data))) {
534 return r;
535 }
536
537 TEST_END(ts_end);
538
539 lyd_free_siblings(data);
540
541 return LY_SUCCESS;
542}
543
544static LY_ERR
545test_free(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
546{
547 LY_ERR r;
548 struct lyd_node *data;
549
550 if ((r = create_list_inst(state->mod, 0, state->count, &data))) {
551 return r;
552 }
553
554 TEST_START(ts_start);
555
556 lyd_free_siblings(data);
557
558 TEST_END(ts_end);
559
560 return LY_SUCCESS;
561}
562
563static LY_ERR
564test_xpath_find(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
565{
566 LY_ERR r;
567 struct ly_set *set;
568 char path[64];
569
570 sprintf(path, "/perf:cont/lst[k1=%" PRIu32 " and k2='str%" PRIu32 "']", state->count / 2, state->count / 2);
571
572 TEST_START(ts_start);
573
574 if ((r = lyd_find_xpath(state->data1, path, &set))) {
575 return r;
576 }
577
578 TEST_END(ts_end);
579
580 ly_set_free(set, NULL);
581
582 return LY_SUCCESS;
583}
584
585static LY_ERR
586test_xpath_find_hash(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
587{
588 LY_ERR r;
589 struct ly_set *set;
590 char path[64];
591
592 sprintf(path, "/perf:cont/lst[k1=%" PRIu32 "][k2='str%" PRIu32 "']", state->count / 2, state->count / 2);
593
594 TEST_START(ts_start);
595
596 if ((r = lyd_find_xpath(state->data1, path, &set))) {
597 return r;
598 }
599
600 TEST_END(ts_end);
601
602 ly_set_free(set, NULL);
603
604 return LY_SUCCESS;
605}
606
607static LY_ERR
608test_compare_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
609{
610 LY_ERR r;
611
612 TEST_START(ts_start);
613
614 if ((r = lyd_compare_siblings(state->data1, state->data2, LYD_COMPARE_FULL_RECURSION))) {
615 return r;
616 }
617
618 TEST_END(ts_end);
619
620 return LY_SUCCESS;
621}
622
623static LY_ERR
624test_diff_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
625{
626 LY_ERR r;
627 struct lyd_node *diff;
628
629 TEST_START(ts_start);
630
631 if ((r = lyd_diff_siblings(state->data1, state->data2, 0, &diff))) {
632 return r;
633 }
634
635 TEST_END(ts_end);
636
637 lyd_free_siblings(diff);
638
639 return LY_SUCCESS;
640}
641
642static LY_ERR
643test_diff_no_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
644{
645 LY_ERR r;
646 struct lyd_node *diff;
647
648 TEST_START(ts_start);
649
650 if ((r = lyd_diff_siblings(state->data1, state->data2, 0, &diff))) {
651 return r;
652 }
653
654 TEST_END(ts_end);
655
656 lyd_free_siblings(diff);
657
658 return LY_SUCCESS;
659}
660
661static LY_ERR
662test_merge_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
663{
664 LY_ERR r;
665
666 TEST_START(ts_start);
667
668 if ((r = lyd_merge_siblings(&state->data1, state->data2, 0))) {
669 return r;
670 }
671
672 TEST_END(ts_end);
673
674 return LY_SUCCESS;
675}
676
677static LY_ERR
678test_merge_no_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
679{
680 LY_ERR r;
681 struct lyd_node *data1;
682
683 if ((r = create_list_inst(state->mod, 0, state->count, &data1))) {
684 return r;
685 }
686
687 TEST_START(ts_start);
688
689 if ((r = lyd_merge_siblings(&data1, state->data2, 0))) {
690 return r;
691 }
692
693 TEST_END(ts_end);
694
695 lyd_free_siblings(data1);
696
697 return LY_SUCCESS;
698}
699
700static LY_ERR
701test_merge_no_same_destruct(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
702{
703 LY_ERR r;
704 struct lyd_node *data1, *data2;
705
706 if ((r = create_list_inst(state->mod, 0, state->count, &data1))) {
707 return r;
708 }
709 if ((r = create_list_inst(state->mod, state->count, state->count, &data2))) {
710 return r;
711 }
712
713 TEST_START(ts_start);
714
715 if ((r = lyd_merge_siblings(&data1, data2, LYD_MERGE_DESTRUCT))) {
716 return r;
717 }
718
719 TEST_END(ts_end);
720
721 lyd_free_siblings(data1);
722
723 return LY_SUCCESS;
724}
725
726struct test tests[] = {
Michal Vasko37705092021-07-01 13:32:46 +0200727 {"create new text", setup_basic, test_create_new_text},
728 {"create new bin", setup_basic, test_create_new_bin},
729 {"create path", setup_basic, test_create_path},
730 {"validate", setup_data_single_tree, test_validate},
731 {"parse xml mem validate", setup_data_single_tree, test_parse_xml_mem_validate},
732 {"parse xml mem no validate", setup_data_single_tree, test_parse_xml_mem_no_validate},
733 {"parse xml file no validate format", setup_data_single_tree, test_parse_xml_file_no_validate_format},
734 {"parse json mem validate", setup_data_single_tree, test_parse_json_mem_validate},
735 {"parse json mem no validate", setup_data_single_tree, test_parse_json_mem_no_validate},
736 {"parse json file no validate format", setup_data_single_tree, test_parse_json_file_no_validate_format},
737 {"parse lyb mem validate", setup_data_single_tree, test_parse_lyb_mem_validate},
738 {"parse lyb mem no validate", setup_data_single_tree, test_parse_lyb_mem_no_validate},
739 {"parse lyb file no validate", setup_data_single_tree, test_parse_lyb_file_no_validate},
740 {"print xml", setup_data_single_tree, test_print_xml},
741 {"print json", setup_data_single_tree, test_print_json},
742 {"print lyb", setup_data_single_tree, test_print_lyb},
743 {"dup", setup_data_single_tree, test_dup},
744 {"free", setup_basic, test_free},
745 {"xpath find", setup_data_single_tree, test_xpath_find},
746 {"xpath find hash", setup_data_single_tree, test_xpath_find_hash},
747 {"compare same", setup_data_same_trees, test_compare_same},
748 {"diff same", setup_data_same_trees, test_diff_same},
749 {"diff no same", setup_data_no_same_trees, test_diff_no_same},
750 {"merge same", setup_data_same_trees, test_merge_same},
751 {"merge no same", setup_data_offset_tree, test_merge_no_same},
752 {"merge no same destruct", setup_basic, test_merge_no_same_destruct},
Michal Vasko99544ca2021-06-29 10:45:19 +0200753};
754
755int
756main(int argc, char **argv)
757{
758 LY_ERR ret = LY_SUCCESS;
759 struct ly_ctx *ctx = NULL;
760 const struct lys_module *mod;
761 uint32_t i, count, tries;
762
763 if (argc < 3) {
764 fprintf(stderr, "Usage:\n%s list-instance-count test-tries\n\n", argv[0]);
765 return LY_EINVAL;
766 }
767
768 count = atoi(argv[1]);
769 if (!count) {
770 fprintf(stderr, "Invalid count \"%s\".\n", argv[1]);
771 return LY_EINVAL;
772 }
773
774 tries = atoi(argv[2]);
775 if (!tries) {
776 fprintf(stderr, "Invalid tries \"%s\".\n", argv[2]);
777 return LY_EINVAL;
778 }
779
780 printf("\nly_perf:\n\tdata set size: %" PRIu32 "\n\teach test executed: %" PRIu32 " %s\n\n", count, tries,
781 (tries > 1) ? "times" : "time");
782
783 /* create context */
784 if ((ret = ly_ctx_new(TESTS_SRC "/perf", 0, &ctx))) {
785 goto cleanup;
786 }
787
788 /* load modules */
789 if (!(mod = ly_ctx_load_module(ctx, "perf", NULL, NULL))) {
790 ret = LY_ENOTFOUND;
791 goto cleanup;
792 }
793
794 /* tests */
795 for (i = 0; i < (sizeof tests / sizeof(struct test)); ++i) {
796 if ((ret = exec_test(tests[i].setup, tests[i].test, tests[i].name, mod, count, tries))) {
797 goto cleanup;
798 }
799 }
800
801 printf("\n");
802
803cleanup:
804 ly_ctx_destroy(ctx);
805 return ret;
806}