/* * xs-test.c * * Do Xenstore tests. * * Copyright (C) 2016 Juergen Gross , * SUSE Linux GmbH * * This program is free software; you can redistribute it and/or * modify it under the terms and conditions of the GNU General Public * License, version 2, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; If not, see . */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #define TEST_PATH "xenstore-test" #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define WRITE_BUFFERS_N 10 #define WRITE_BUFFERS_SIZE 4000 #define MAX_TA_LOOPS 100 struct test { char *name; int (*func_init)(uintptr_t par); int (*func)(uintptr_t par); int (*func_deinit)(uintptr_t par); uintptr_t par; char *descr; }; static struct xs_handle *xsh; static char *path; static char *paths[WRITE_BUFFERS_N]; static char write_buffers[WRITE_BUFFERS_N][WRITE_BUFFERS_SIZE]; static int ta_loops; static struct option options[] = { { "list-tests", 0, NULL, 'l' }, { "test", 1, NULL, 't' }, { "random", 1, NULL, 'r' }, { "help", 0, NULL, 'h' }, { "iterations", 1, NULL, 'i' }, { NULL, 0, NULL, 0 } }; static int call_test(struct test *tst, int iters, bool no_clock) { char *stage = "?"; struct timespec tp1, tp2; uint64_t nsec, nsec_min, nsec_max, nsec_sum; int i, ret; nsec_min = -1; nsec_max = 0; nsec_sum = 0; for ( i = 0; i < iters; i++ ) { stage = "pre-init"; xs_rm(xsh, XBT_NULL, path); if ( !xs_write(xsh, XBT_NULL, path, "", 0) ) { ret = errno; break; } stage = "init"; ret = tst->func_init(tst->par); if ( ret ) break; if ( clock_gettime(CLOCK_REALTIME, &tp1) ) no_clock = true; stage = "run"; ret = tst->func(tst->par); if ( ret ) break; if ( clock_gettime(CLOCK_REALTIME, &tp2) ) no_clock = true; if ( !no_clock ) { nsec = tp2.tv_sec * 1000000000 + tp2.tv_nsec - tp1.tv_sec * 1000000000 - tp1.tv_nsec; if ( nsec < nsec_min ) nsec_min = nsec; if ( nsec > nsec_max ) nsec_max = nsec; nsec_sum += nsec; } stage = "deinit"; ret = tst->func_deinit(tst->par); if ( ret ) break; } if ( ret ) printf("%-10s: failed (ret = %d, stage %s)\n", tst->name, ret, stage); else if ( !no_clock ) { printf("%-10s:", tst->name); if ( iters > 1 ) printf(" avg: %"PRIu64" ns (%"PRIu64" ns .. %"PRIu64" ns)", nsec_sum / iters, nsec_min, nsec_max); else printf(" %"PRIu64" ns", nsec_sum); printf("\n"); } return ret; } static void usage(int ret) { FILE *out; out = ret ? stderr : stdout; fprintf(out, "usage: xs-test []\n"); fprintf(out, " are:\n"); fprintf(out, " -i|--iterations perform each test times (default 1)\n"); fprintf(out, " -l|--list-tests list available tests\n"); fprintf(out, " -r|--random