blob: 37591cbf6fa1a642dfa912540286d344926b0f77 [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;
aPiecekb54dbdb2021-09-02 14:39:15 +0200119 char k1_val[32], k2_val[32], l_val[32], lfl_val[32];
Michal Vasko99544ca2021-06-29 10:45:19 +0200120 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
aPiecekb54dbdb2021-09-02 14:39:15 +0200139 /* Last list contains a "lfl" leaf-list with @p count terms. */
140 for (i = 0; i < count; ++i) {
141 sprintf(lfl_val, "%" PRIu32, i + offset);
142 if ((ret = lyd_new_term(list, NULL, "lfl", lfl_val, 0, NULL))) {
143 return ret;
144 }
145 }
146
Michal Vasko99544ca2021-06-29 10:45:19 +0200147 return LY_SUCCESS;
148}
149
150/**
151 * @brief Execute a test.
152 *
153 * @param[in] setup Setup callback to call once.
154 * @param[in] test Test callback.
155 * @param[in] name Name of the test.
156 * @param[in] mod Module of testing data.
157 * @param[in] count Count of list instances, size of the testing data set.
158 * @param[in] tries Number of (re)tries of the test to get more accurate measurements.
159 * @return LY_ERR value.
160 */
161static LY_ERR
162exec_test(setup_cb setup, test_cb test, const char *name, const struct lys_module *mod, uint32_t count, uint32_t tries)
163{
164 LY_ERR ret;
165 struct timespec ts_start, ts_end;
166 struct test_state state = {0};
Michal Vasko4318ac32021-07-02 09:18:30 +0200167 const uint32_t name_fixed_len = 38;
Michal Vasko99544ca2021-06-29 10:45:19 +0200168 char str[name_fixed_len + 1];
169 uint32_t i, printed;
170 uint64_t time_usec = 0;
171
172 /* print test start */
173 printed = sprintf(str, "| %s ", name);
Michal Vasko4318ac32021-07-02 09:18:30 +0200174 while (printed + 2 < name_fixed_len) {
Michal Vasko99544ca2021-06-29 10:45:19 +0200175 printed += sprintf(str + printed, ".");
176 }
Michal Vasko4318ac32021-07-02 09:18:30 +0200177 if (printed + 1 < name_fixed_len) {
Michal Vasko99544ca2021-06-29 10:45:19 +0200178 printed += sprintf(str + printed, " ");
179 }
180 sprintf(str + printed, "|");
181 fputs(str, stdout);
182 fflush(stdout);
183
184 /* setup */
185 if ((ret = setup(mod, count, &state))) {
186 return ret;
187 }
188
189 /* test */
190 for (i = 0; i < tries; ++i) {
191 if ((ret = test(&state, &ts_start, &ts_end))) {
192 return ret;
193 }
194 time_usec += time_diff(&ts_start, &ts_end);
195 }
196 time_usec /= tries;
197
198 /* teardown */
199 lyd_free_siblings(state.data1);
200 lyd_free_siblings(state.data2);
201
202 /* print time */
203 printf(" %" PRIu64 ".%06" PRIu64 " s |\n", time_usec / 1000000, time_usec % 1000000);
204
205 return LY_SUCCESS;
206}
207
208static void
209TEST_START(struct timespec *ts)
210{
211 time_get(ts);
212
213#ifdef HAVE_CALLGRIND
214 CALLGRIND_START_INSTRUMENTATION;
215#endif
216}
217
218static void
219TEST_END(struct timespec *ts)
220{
221 time_get(ts);
222
223#ifdef HAVE_CALLGRIND
224 CALLGRIND_STOP_INSTRUMENTATION;
225#endif
226}
227
228/* TEST SETUP */
229static LY_ERR
230setup_basic(const struct lys_module *mod, uint32_t count, struct test_state *state)
231{
232 state->mod = mod;
233 state->count = count;
234
235 return LY_SUCCESS;
236}
237
238static LY_ERR
239setup_data_single_tree(const struct lys_module *mod, uint32_t count, struct test_state *state)
240{
241 state->mod = mod;
242 state->count = count;
243
244 return create_list_inst(mod, 0, count, &state->data1);
245}
246
247static LY_ERR
248setup_data_same_trees(const struct lys_module *mod, uint32_t count, struct test_state *state)
249{
250 LY_ERR ret;
251
252 state->mod = mod;
253 state->count = count;
254
255 if ((ret = create_list_inst(mod, 0, count, &state->data1))) {
256 return ret;
257 }
258 if ((ret = create_list_inst(mod, 0, count, &state->data2))) {
259 return ret;
260 }
261
262 return LY_SUCCESS;
263}
264
265static LY_ERR
266setup_data_no_same_trees(const struct lys_module *mod, uint32_t count, struct test_state *state)
267{
268 LY_ERR ret;
269
270 state->mod = mod;
271 state->count = count;
272
273 if ((ret = create_list_inst(mod, 0, count, &state->data1))) {
274 return ret;
275 }
276 if ((ret = create_list_inst(mod, count, count, &state->data2))) {
277 return ret;
278 }
279
280 return LY_SUCCESS;
281}
282
283static LY_ERR
aPieceka7a1de92024-02-12 14:07:12 +0100284setup_data_empty_and_full_trees(const struct lys_module *mod, uint32_t count, struct test_state *state)
285{
286 LY_ERR ret;
287
288 state->mod = mod;
289 state->count = count;
290
291 if ((ret = create_list_inst(mod, 0, 0, &state->data1))) {
292 return ret;
293 }
294 if ((ret = create_list_inst(mod, 0, count, &state->data2))) {
295 return ret;
296 }
297
298 return LY_SUCCESS;
299}
300
301static LY_ERR
Michal Vasko99544ca2021-06-29 10:45:19 +0200302setup_data_offset_tree(const struct lys_module *mod, uint32_t count, struct test_state *state)
303{
304 LY_ERR ret;
305
306 state->mod = mod;
307 state->count = count;
308
309 if ((ret = create_list_inst(mod, count, count, &state->data2))) {
310 return ret;
311 }
312
313 return LY_SUCCESS;
314}
315
316/* TEST CB */
317static LY_ERR
318test_create_new_text(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
319{
320 LY_ERR r;
321 struct lyd_node *data = NULL;
322
323 TEST_START(ts_start);
324
325 if ((r = create_list_inst(state->mod, 0, state->count, &data))) {
326 return r;
327 }
328
329 TEST_END(ts_end);
330
331 lyd_free_siblings(data);
332
333 return LY_SUCCESS;
334}
335
336static LY_ERR
337test_create_new_bin(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
338{
339 LY_ERR r;
340 struct lyd_node *data = NULL;
341 uint32_t i, k2_len, l_len;
342 char k2_val[32], l_val[32];
343 struct lyd_node *list;
344
345 TEST_START(ts_start);
346
347 if ((r = lyd_new_inner(NULL, state->mod, "cont", 0, &data))) {
348 return r;
349 }
350
351 for (i = 0; i < state->count; ++i) {
352 k2_len = sprintf(k2_val, "str%" PRIu32, i);
353 l_len = sprintf(l_val, "l%" PRIu32, i);
354
Michal Vasko381d9782024-03-07 13:28:23 +0100355 if ((r = lyd_new_list(data, NULL, "lst", LYD_NEW_VAL_BIN, &list, &i, sizeof i, k2_val, k2_len))) {
Michal Vasko99544ca2021-06-29 10:45:19 +0200356 return r;
357 }
358 if ((r = lyd_new_term_bin(list, NULL, "l", l_val, l_len, 0, NULL))) {
359 return r;
360 }
361 }
362
363 TEST_END(ts_end);
364
365 lyd_free_siblings(data);
366
367 return LY_SUCCESS;
368}
369
370static LY_ERR
371test_create_path(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
372{
373 LY_ERR r;
374 struct lyd_node *data = NULL;
375 uint32_t i;
376 char path[64], l_val[32];
377
378 TEST_START(ts_start);
379
380 if ((r = lyd_new_inner(NULL, state->mod, "cont", 0, &data))) {
381 return r;
382 }
383
384 for (i = 0; i < state->count; ++i) {
385 sprintf(path, "/perf:cont/lst[k1='%" PRIu32 "'][k2='str%" PRIu32 "']/l", i, i);
386 sprintf(l_val, "l%" PRIu32, i);
387
388 if ((r = lyd_new_path(data, NULL, path, l_val, 0, NULL))) {
389 return r;
390 }
391 }
392
393 TEST_END(ts_end);
394
395 lyd_free_siblings(data);
396
397 return LY_SUCCESS;
398}
399
400static LY_ERR
Michal Vaskoc606f312021-06-30 14:08:54 +0200401test_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
402{
403 LY_ERR r;
404
405 TEST_START(ts_start);
406
407 if ((r = lyd_validate_all(&state->data1, NULL, LYD_VALIDATE_PRESENT, NULL))) {
408 return r;
409 }
410
411 TEST_END(ts_end);
412
413 return LY_SUCCESS;
414}
415
416static LY_ERR
Michal Vasko99544ca2021-06-29 10:45:19 +0200417_test_parse(struct test_state *state, LYD_FORMAT format, ly_bool use_file, uint32_t print_options, uint32_t parse_options,
418 uint32_t validate_options, struct timespec *ts_start, struct timespec *ts_end)
419{
420 LY_ERR ret = LY_SUCCESS;
421 struct lyd_node *data = NULL;
422 char *buf = NULL;
423 struct ly_in *in = NULL;
424
425 if (use_file) {
426 if ((ret = lyd_print_path(TEMP_FILE, state->data1, format, print_options))) {
427 goto cleanup;
428 }
429 if ((ret = ly_in_new_filepath(TEMP_FILE, 0, &in))) {
430 goto cleanup;
431 }
432 } else {
433 if ((ret = lyd_print_mem(&buf, state->data1, format, print_options))) {
434 goto cleanup;
435 }
436 if ((ret = ly_in_new_memory(buf, &in))) {
437 goto cleanup;
438 }
439 }
440
441 TEST_START(ts_start);
442
443 if ((ret = lyd_parse_data(state->mod->ctx, NULL, in, format, parse_options, validate_options, &data))) {
444 goto cleanup;
445 }
446
447 TEST_END(ts_end);
448
449cleanup:
450 free(buf);
451 ly_in_free(in, 0);
452 lyd_free_siblings(data);
453 return ret;
454}
455
456static LY_ERR
457test_parse_xml_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
458{
459 return _test_parse(state, LYD_XML, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
460}
461
462static LY_ERR
463test_parse_xml_mem_no_validate(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_XML, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
466 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200467}
468
469static LY_ERR
470test_parse_xml_file_no_validate_format(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
471{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200472 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 +0200473}
474
475static LY_ERR
476test_parse_json_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
477{
478 return _test_parse(state, LYD_JSON, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
479}
480
481static LY_ERR
482test_parse_json_mem_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_JSON, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
485 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200486}
487
488static LY_ERR
489test_parse_json_file_no_validate_format(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
490{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200491 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 +0200492}
493
494static LY_ERR
495test_parse_lyb_mem_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
496{
497 return _test_parse(state, LYD_LYB, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, ts_start, ts_end);
498}
499
500static LY_ERR
501test_parse_lyb_mem_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
502{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200503 return _test_parse(state, LYD_LYB, 0, LYD_PRINT_SHRINK, LYD_PARSE_STRICT | LYD_PARSE_ONLY | LYD_PARSE_ORDERED, 0,
504 ts_start, ts_end);
Michal Vasko99544ca2021-06-29 10:45:19 +0200505}
506
507static LY_ERR
508test_parse_lyb_file_no_validate(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
509{
Michal Vasko6ee6f432021-07-16 09:49:14 +0200510 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 +0200511}
512
513static LY_ERR
514_test_print(struct test_state *state, LYD_FORMAT format, uint32_t print_options, struct timespec *ts_start,
515 struct timespec *ts_end)
516{
517 LY_ERR ret = LY_SUCCESS;
518 char *buf = NULL;
519
520 TEST_START(ts_start);
521
522 if ((ret = lyd_print_mem(&buf, state->data1, format, print_options))) {
523 goto cleanup;
524 }
525
526 TEST_END(ts_end);
527
528cleanup:
529 free(buf);
530 return ret;
531}
532
533static LY_ERR
534test_print_xml(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
535{
536 return _test_print(state, LYD_XML, LYD_PRINT_SHRINK, ts_start, ts_end);
537}
538
539static LY_ERR
540test_print_json(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
541{
542 return _test_print(state, LYD_JSON, LYD_PRINT_SHRINK, ts_start, ts_end);
543}
544
545static LY_ERR
546test_print_lyb(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
547{
548 return _test_print(state, LYD_LYB, LYD_PRINT_SHRINK, ts_start, ts_end);
549}
550
551static LY_ERR
552test_dup(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
553{
554 LY_ERR r;
555 struct lyd_node *data;
556
557 TEST_START(ts_start);
558
559 if ((r = lyd_dup_siblings(state->data1, NULL, LYD_DUP_RECURSIVE, &data))) {
560 return r;
561 }
562
563 TEST_END(ts_end);
564
565 lyd_free_siblings(data);
566
567 return LY_SUCCESS;
568}
569
570static LY_ERR
aPieceka7a1de92024-02-12 14:07:12 +0100571test_dup_siblings_to_empty(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
572{
573 LY_ERR r;
574
575 TEST_START(ts_start);
576
577 if ((r = lyd_dup_siblings(lyd_child(state->data2), (struct lyd_node_inner *)state->data1, 0, NULL))) {
578 return r;
579 }
580
581 TEST_END(ts_end);
582
Michal Vasko072086c2024-09-06 13:31:45 +0200583 /* need to remove the duplicated nodes if the test is repeated */
584 lyd_free_siblings(lyd_child(state->data1));
585
aPieceka7a1de92024-02-12 14:07:12 +0100586 return LY_SUCCESS;
587}
588
589static LY_ERR
Michal Vasko99544ca2021-06-29 10:45:19 +0200590test_free(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
591{
592 LY_ERR r;
593 struct lyd_node *data;
594
595 if ((r = create_list_inst(state->mod, 0, state->count, &data))) {
596 return r;
597 }
598
599 TEST_START(ts_start);
600
601 lyd_free_siblings(data);
602
603 TEST_END(ts_end);
604
605 return LY_SUCCESS;
606}
607
608static LY_ERR
609test_xpath_find(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
610{
611 LY_ERR r;
612 struct ly_set *set;
613 char path[64];
614
615 sprintf(path, "/perf:cont/lst[k1=%" PRIu32 " and k2='str%" PRIu32 "']", state->count / 2, state->count / 2);
616
617 TEST_START(ts_start);
618
619 if ((r = lyd_find_xpath(state->data1, path, &set))) {
620 return r;
621 }
622
623 TEST_END(ts_end);
624
625 ly_set_free(set, NULL);
626
627 return LY_SUCCESS;
628}
629
630static LY_ERR
631test_xpath_find_hash(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
632{
633 LY_ERR r;
634 struct ly_set *set;
635 char path[64];
636
637 sprintf(path, "/perf:cont/lst[k1=%" PRIu32 "][k2='str%" PRIu32 "']", state->count / 2, state->count / 2);
638
639 TEST_START(ts_start);
640
641 if ((r = lyd_find_xpath(state->data1, path, &set))) {
642 return r;
643 }
644
645 TEST_END(ts_end);
646
647 ly_set_free(set, NULL);
648
649 return LY_SUCCESS;
650}
651
652static LY_ERR
653test_compare_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
654{
655 LY_ERR r;
656
657 TEST_START(ts_start);
658
659 if ((r = lyd_compare_siblings(state->data1, state->data2, LYD_COMPARE_FULL_RECURSION))) {
660 return r;
661 }
662
663 TEST_END(ts_end);
664
665 return LY_SUCCESS;
666}
667
668static LY_ERR
669test_diff_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
670{
671 LY_ERR r;
672 struct lyd_node *diff;
673
674 TEST_START(ts_start);
675
676 if ((r = lyd_diff_siblings(state->data1, state->data2, 0, &diff))) {
677 return r;
678 }
679
680 TEST_END(ts_end);
681
682 lyd_free_siblings(diff);
683
684 return LY_SUCCESS;
685}
686
687static LY_ERR
688test_diff_no_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
689{
690 LY_ERR r;
691 struct lyd_node *diff;
692
693 TEST_START(ts_start);
694
695 if ((r = lyd_diff_siblings(state->data1, state->data2, 0, &diff))) {
696 return r;
697 }
698
699 TEST_END(ts_end);
700
701 lyd_free_siblings(diff);
702
703 return LY_SUCCESS;
704}
705
706static LY_ERR
707test_merge_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
708{
709 LY_ERR r;
710
711 TEST_START(ts_start);
712
713 if ((r = lyd_merge_siblings(&state->data1, state->data2, 0))) {
714 return r;
715 }
716
717 TEST_END(ts_end);
718
719 return LY_SUCCESS;
720}
721
722static LY_ERR
723test_merge_no_same(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
724{
725 LY_ERR r;
726 struct lyd_node *data1;
727
728 if ((r = create_list_inst(state->mod, 0, state->count, &data1))) {
729 return r;
730 }
731
732 TEST_START(ts_start);
733
734 if ((r = lyd_merge_siblings(&data1, state->data2, 0))) {
735 return r;
736 }
737
738 TEST_END(ts_end);
739
740 lyd_free_siblings(data1);
741
742 return LY_SUCCESS;
743}
744
745static LY_ERR
746test_merge_no_same_destruct(struct test_state *state, struct timespec *ts_start, struct timespec *ts_end)
747{
748 LY_ERR r;
749 struct lyd_node *data1, *data2;
750
751 if ((r = create_list_inst(state->mod, 0, state->count, &data1))) {
752 return r;
753 }
754 if ((r = create_list_inst(state->mod, state->count, state->count, &data2))) {
755 return r;
756 }
757
758 TEST_START(ts_start);
759
760 if ((r = lyd_merge_siblings(&data1, data2, LYD_MERGE_DESTRUCT))) {
761 return r;
762 }
763
764 TEST_END(ts_end);
765
766 lyd_free_siblings(data1);
767
768 return LY_SUCCESS;
769}
770
771struct test tests[] = {
Michal Vasko37705092021-07-01 13:32:46 +0200772 {"create new text", setup_basic, test_create_new_text},
773 {"create new bin", setup_basic, test_create_new_bin},
774 {"create path", setup_basic, test_create_path},
775 {"validate", setup_data_single_tree, test_validate},
776 {"parse xml mem validate", setup_data_single_tree, test_parse_xml_mem_validate},
777 {"parse xml mem no validate", setup_data_single_tree, test_parse_xml_mem_no_validate},
778 {"parse xml file no validate format", setup_data_single_tree, test_parse_xml_file_no_validate_format},
779 {"parse json mem validate", setup_data_single_tree, test_parse_json_mem_validate},
780 {"parse json mem no validate", setup_data_single_tree, test_parse_json_mem_no_validate},
781 {"parse json file no validate format", setup_data_single_tree, test_parse_json_file_no_validate_format},
782 {"parse lyb mem validate", setup_data_single_tree, test_parse_lyb_mem_validate},
783 {"parse lyb mem no validate", setup_data_single_tree, test_parse_lyb_mem_no_validate},
784 {"parse lyb file no validate", setup_data_single_tree, test_parse_lyb_file_no_validate},
785 {"print xml", setup_data_single_tree, test_print_xml},
786 {"print json", setup_data_single_tree, test_print_json},
787 {"print lyb", setup_data_single_tree, test_print_lyb},
788 {"dup", setup_data_single_tree, test_dup},
aPieceka7a1de92024-02-12 14:07:12 +0100789 {"dup_siblings_to_empty", setup_data_empty_and_full_trees, test_dup_siblings_to_empty},
Michal Vasko37705092021-07-01 13:32:46 +0200790 {"free", setup_basic, test_free},
791 {"xpath find", setup_data_single_tree, test_xpath_find},
792 {"xpath find hash", setup_data_single_tree, test_xpath_find_hash},
793 {"compare same", setup_data_same_trees, test_compare_same},
794 {"diff same", setup_data_same_trees, test_diff_same},
795 {"diff no same", setup_data_no_same_trees, test_diff_no_same},
796 {"merge same", setup_data_same_trees, test_merge_same},
797 {"merge no same", setup_data_offset_tree, test_merge_no_same},
798 {"merge no same destruct", setup_basic, test_merge_no_same_destruct},
Michal Vasko99544ca2021-06-29 10:45:19 +0200799};
800
801int
802main(int argc, char **argv)
803{
804 LY_ERR ret = LY_SUCCESS;
805 struct ly_ctx *ctx = NULL;
806 const struct lys_module *mod;
807 uint32_t i, count, tries;
808
809 if (argc < 3) {
810 fprintf(stderr, "Usage:\n%s list-instance-count test-tries\n\n", argv[0]);
811 return LY_EINVAL;
812 }
813
814 count = atoi(argv[1]);
815 if (!count) {
816 fprintf(stderr, "Invalid count \"%s\".\n", argv[1]);
817 return LY_EINVAL;
818 }
819
820 tries = atoi(argv[2]);
821 if (!tries) {
822 fprintf(stderr, "Invalid tries \"%s\".\n", argv[2]);
823 return LY_EINVAL;
824 }
825
826 printf("\nly_perf:\n\tdata set size: %" PRIu32 "\n\teach test executed: %" PRIu32 " %s\n\n", count, tries,
827 (tries > 1) ? "times" : "time");
828
829 /* create context */
830 if ((ret = ly_ctx_new(TESTS_SRC "/perf", 0, &ctx))) {
831 goto cleanup;
832 }
833
834 /* load modules */
835 if (!(mod = ly_ctx_load_module(ctx, "perf", NULL, NULL))) {
836 ret = LY_ENOTFOUND;
837 goto cleanup;
838 }
839
840 /* tests */
841 for (i = 0; i < (sizeof tests / sizeof(struct test)); ++i) {
842 if ((ret = exec_test(tests[i].setup, tests[i].test, tests[i].name, mod, count, tries))) {
843 goto cleanup;
844 }
845 }
846
847 printf("\n");
848
849cleanup:
850 ly_ctx_destroy(ctx);
851 return ret;
852}