From 3ae52c45ce5b9c304fb0cc02859e7e1d5fac3deb Mon Sep 17 00:00:00 2001 From: Raphael Herouart Date: Tue, 16 Jan 2024 12:44:53 +0000 Subject: [PATCH] tipc-test: Allow tipc tests to be run as benchmarks Adding one command line parameter -B to allow tipc test to be run as benchmarks. Bug: 314130383 Test: /data/nativetest64/vendor/tipc-test/tipc-test -t echo -r 1 -B 100 Change-Id: I5cdd643ce6e9e289033180cff433e45f77206729 --- trusty/libtrusty/tipc-test/tipc_test.c | 480 ++++++++++++++----------- 1 file changed, 275 insertions(+), 205 deletions(-) diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c index 0f5078753..dabe118e1 100644 --- a/trusty/libtrusty/tipc-test/tipc_test.c +++ b/trusty/libtrusty/tipc-test/tipc_test.c @@ -22,8 +22,10 @@ #include #include #define __USE_GNU +#include #include #include +#include #include @@ -31,8 +33,27 @@ #define TIPC_DEFAULT_DEVNAME "/dev/trusty-ipc-dev0" -static const char *dev_name = NULL; -static const char *test_name = NULL; +/* clang-format off */ +#define BENCH_RESULT_TPL \ +"{" \ +" \"schema_version\": 3," \ +" \"suite_name\": \"crypto\"," \ +" \"bench_name\": \"%s\"," \ +" \"results\": [" \ +" {" \ +" \"metric_name\": \"time_micro_sec\"," \ +" \"min\": \"%" PRId64 "\"," \ +" \"max\": \"%" PRId64 "\"," \ +" \"avg\": \"%" PRId64 "\"," \ +" \"cold\": \"%" PRId64 "\"," \ +" \"raw_min\": %" PRId64 "," \ +" \"raw_max\": %" PRId64 "," \ +" \"raw_avg\": %" PRId64 "," \ +" \"raw_cold\": %" PRId64 "" \ +" }," \ +" ]" \ +"}" +/* clang-format on */ static const char *uuid_name = "com.android.ipc-unittest.srv.uuid"; static const char *echo_name = "com.android.ipc-unittest.srv.echo"; @@ -46,7 +67,7 @@ static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl"; static const char* receiver_name = "com.android.trusty.memref.receiver"; static const size_t memref_chunk_size = 4096; -static const char* _sopts = "hsvDS:t:r:m:b:"; +static const char* _sopts = "hsvDS:t:r:m:b:B:"; /* clang-format off */ static const struct option _lopts[] = { {"help", no_argument, 0, 'h'}, @@ -57,6 +78,8 @@ static const struct option _lopts[] = { {"repeat", required_argument, 0, 'r'}, {"burst", required_argument, 0, 'b'}, {"msgsize", required_argument, 0, 'm'}, + {"test", required_argument, 0, 't'}, + {"bench", required_argument, 0, 'B'}, {0, 0, 0, 0} }; /* clang-format on */ @@ -74,6 +97,7 @@ static const char* usage = " -m, --msgsize size max message size\n" " -v, --variable variable message size\n" " -s, --silent silent\n" + " -B, --bench Run as Benchmark N times\n" "\n"; static const char* usage_long = @@ -96,12 +120,34 @@ static const char* usage_long = " send-fd - transmit dma_buf to trusty, use as shm\n" "\n"; -static uint opt_repeat = 1; -static uint opt_msgsize = 32; -static uint opt_msgburst = 32; -static bool opt_variable = false; -static bool opt_silent = false; -static char* srv_name = NULL; +struct tipc_test_params { + uint repeat; + uint msgsize; + uint msgburst; + bool variable; + bool silent; + uint bench; + char* srv_name; + char* dev_name; + char* test_name; +}; +typedef int (*tipc_test_func_t)(const struct tipc_test_params*); + +struct tipc_test_def { + char* test_name; + tipc_test_func_t func; +}; + +static void init_params(struct tipc_test_params* params) { + params->repeat = 1; + params->msgsize = 32; + params->msgburst = 32; + params->variable = false; + params->silent = false; + params->bench = 0; + params->srv_name = NULL; + params->test_name = NULL; +} static void print_usage_and_exit(const char *prog, int code, bool verbose) { @@ -110,8 +156,7 @@ static void print_usage_and_exit(const char *prog, int code, bool verbose) exit(code); } -static void parse_options(int argc, char **argv) -{ +static void parse_options(int argc, char** argv, struct tipc_test_params* params) { int c; int oidx = 0; @@ -121,35 +166,39 @@ static void parse_options(int argc, char **argv) switch (c) { case 'D': - dev_name = strdup(optarg); + params->dev_name = strdup(optarg); break; case 'S': - srv_name = strdup(optarg); + params->srv_name = strdup(optarg); break; case 't': - test_name = strdup(optarg); + params->test_name = strdup(optarg); break; case 'v': - opt_variable = true; + params->variable = true; break; case 'r': - opt_repeat = atoi(optarg); + params->repeat = atoi(optarg); break; case 'm': - opt_msgsize = atoi(optarg); + params->msgsize = atoi(optarg); break; case 'b': - opt_msgburst = atoi(optarg); + params->msgburst = atoi(optarg); break; case 's': - opt_silent = true; + params->silent = true; + break; + + case 'B': + params->bench = atoi(optarg); break; case 'h': @@ -162,32 +211,31 @@ static void parse_options(int argc, char **argv) } } -static int connect_test(uint repeat) -{ +static int connect_test(const struct tipc_test_params* params) { uint i; int echo_fd; int dsink_fd; int custom_fd; - if (!opt_silent) { - printf("%s: repeat = %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat = %u\n", __func__, params->repeat); } - for (i = 0; i < repeat; i++) { - if (srv_name) { - custom_fd = tipc_connect(dev_name, srv_name); + for (i = 0; i < params->repeat; i++) { + if (params->srv_name) { + custom_fd = tipc_connect(params->dev_name, params->srv_name); if (custom_fd < 0) { - fprintf(stderr, "Failed to connect to '%s' service\n", srv_name); + fprintf(stderr, "Failed to connect to '%s' service\n", params->srv_name); } if (custom_fd >= 0) { tipc_close(custom_fd); } } else { - echo_fd = tipc_connect(dev_name, echo_name); + echo_fd = tipc_connect(params->dev_name, echo_name); if (echo_fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "echo"); } - dsink_fd = tipc_connect(dev_name, datasink_name); + dsink_fd = tipc_connect(params->dev_name, datasink_name); if (dsink_fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "datasink"); } @@ -201,79 +249,75 @@ static int connect_test(uint repeat) } } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int connect_foo(uint repeat) -{ +static int connect_foo(const struct tipc_test_params* params) { uint i; int fd; - if (!opt_silent) { - printf("%s: repeat = %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat = %u\n", __func__, params->repeat); } - for (i = 0; i < repeat; i++) { - fd = tipc_connect(dev_name, "foo"); + for (i = 0; i < params->repeat; i++) { + fd = tipc_connect(params->dev_name, "foo"); if (fd >= 0) { fprintf(stderr, "succeeded to connect to '%s' service\n", "foo"); tipc_close(fd); } } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } - -static int closer1_test(uint repeat) -{ +static int closer1_test(const struct tipc_test_params* params) { uint i; int fd; - if (!opt_silent) { - printf("%s: repeat = %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat = %u\n", __func__, params->repeat); } - for (i = 0; i < repeat; i++) { - fd = tipc_connect(dev_name, closer1_name); + for (i = 0; i < params->repeat; i++) { + fd = tipc_connect(params->dev_name, closer1_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "closer1"); continue; } - if (!opt_silent) { + if (!params->silent) { printf("%s: connected\n", __func__); } tipc_close(fd); } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int closer2_test(uint repeat) -{ +static int closer2_test(const struct tipc_test_params* params) { uint i; int fd; - if (!opt_silent) { - printf("%s: repeat = %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat = %u\n", __func__, params->repeat); } - for (i = 0; i < repeat; i++) { - fd = tipc_connect(dev_name, closer2_name); + for (i = 0; i < params->repeat; i++) { + fd = tipc_connect(params->dev_name, closer2_name); if (fd < 0) { - if (!opt_silent) { + if (!params->silent) { printf("failed to connect to '%s' service\n", "closer2"); } } else { @@ -283,38 +327,37 @@ static int closer2_test(uint repeat) } } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int closer3_test(uint repeat) -{ +static int closer3_test(const struct tipc_test_params* params) { uint i, j; ssize_t rc; int fd[4]; char buf[64]; - if (!opt_silent) { - printf("%s: repeat = %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat = %u\n", __func__, params->repeat); } - for (i = 0; i < repeat; i++) { + for (i = 0; i < params->repeat; i++) { /* open 4 connections to closer3 service */ for (j = 0; j < 4; j++) { - fd[j] = tipc_connect(dev_name, closer3_name); + fd[j] = tipc_connect(params->dev_name, closer3_name); if (fd[j] < 0) { fprintf(stderr, "fd[%d]: failed to connect to '%s' service\n", j, "closer3"); } else { - if (!opt_silent) { + if (!params->silent) { printf("%s: fd[%d]=%d: connected\n", __func__, j, fd[j]); } memset(buf, i + j, sizeof(buf)); rc = write(fd[j], buf, sizeof(buf)); if (rc != sizeof(buf)) { - if (!opt_silent) { + if (!params->silent) { printf("%s: fd[%d]=%d: write returned = %zd\n", __func__, j, fd[j], rc); } perror("closer3_test: write"); @@ -330,7 +373,7 @@ static int closer3_test(uint repeat) if (fd[j] < 0) continue; rc = write(fd[j], buf, sizeof(buf)); if (rc != sizeof(buf)) { - if (!opt_silent) { + if (!params->silent) { printf("%s: fd[%d]=%d: write returned = %zd\n", __func__, j, fd[j], rc); } perror("closer3_test: write"); @@ -345,38 +388,36 @@ static int closer3_test(uint repeat) } } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } - -static int echo_test(uint repeat, uint msgsz, bool var) -{ +static int echo_test(const struct tipc_test_params* params) { uint i; ssize_t rc; size_t msg_len; int echo_fd = -1; - char tx_buf[msgsz]; - char rx_buf[msgsz]; + char tx_buf[params->msgsize]; + char rx_buf[params->msgsize]; - if (!opt_silent) { - printf("%s: repeat %u: msgsz %u: variable %s\n", __func__, repeat, msgsz, - var ? "true" : "false"); + if (!params->silent) { + printf("%s: repeat %u: params->msgsize %u: variable %s\n", __func__, params->repeat, + params->msgsize, params->variable ? "true" : "false"); } - echo_fd = tipc_connect(dev_name, echo_name); + echo_fd = tipc_connect(params->dev_name, echo_name); if (echo_fd < 0) { fprintf(stderr, "Failed to connect to service\n"); return echo_fd; } - for (i = 0; i < repeat; i++) { - msg_len = msgsz; - if (opt_variable && msgsz) { - msg_len = rand() % msgsz; + for (i = 0; i < params->repeat; i++) { + msg_len = params->msgsize; + if (params->variable && params->msgsize) { + msg_len = rand() % params->msgsize; } memset(tx_buf, i + 1, msg_len); @@ -406,37 +447,37 @@ static int echo_test(uint repeat, uint msgsz, bool var) tipc_close(echo_fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int burst_write_test(uint repeat, uint msgburst, uint msgsz, bool var) -{ +static int burst_write_test(const struct tipc_test_params* params) { int fd; uint i, j; ssize_t rc; size_t msg_len; - char tx_buf[msgsz]; + char tx_buf[params->msgsize]; - if (!opt_silent) { - printf("%s: repeat %u: burst %u: msgsz %u: variable %s\n", __func__, repeat, msgburst, - msgsz, var ? "true" : "false"); + if (!params->silent) { + printf("%s: repeat %u: burst %u: params->msgsize %u: variable %s\n", __func__, + params->repeat, params->msgburst, params->msgsize, + params->variable ? "true" : "false"); } - for (i = 0; i < repeat; i++) { - fd = tipc_connect(dev_name, datasink_name); + for (i = 0; i < params->repeat; i++) { + fd = tipc_connect(params->dev_name, datasink_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "datasink"); break; } - for (j = 0; j < msgburst; j++) { - msg_len = msgsz; - if (var && msgsz) { - msg_len = rand() % msgsz; + for (j = 0; j < params->msgburst; j++) { + msg_len = params->msgsize; + if (params->variable && params->msgsize) { + msg_len = rand() % params->msgsize; } memset(tx_buf, i + 1, msg_len); @@ -450,23 +491,21 @@ static int burst_write_test(uint repeat, uint msgburst, uint msgsz, bool var) tipc_close(fd); } - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } - -static int _wait_for_msg(int fd, uint msgsz, int timeout) -{ +static int _wait_for_msg(int fd, int timeout, const struct tipc_test_params* params) { int rc; fd_set rfds; uint msgcnt = 0; - char rx_buf[msgsz]; + char rx_buf[params->msgsize]; struct timeval tv; - if (!opt_silent) { + if (!params->silent) { printf("waiting (%d) for msg\n", timeout); } @@ -480,7 +519,7 @@ static int _wait_for_msg(int fd, uint msgsz, int timeout) rc = select(fd + 1, &rfds, NULL, NULL, &tv); if (rc == 0) { - if (!opt_silent) { + if (!params->silent) { printf("select timedout\n"); } break; @@ -502,42 +541,40 @@ static int _wait_for_msg(int fd, uint msgsz, int timeout) } } - if (!opt_silent) { + if (!params->silent) { printf("got %u messages\n", msgcnt); } return 0; } - -static int select_test(uint repeat, uint msgburst, uint msgsz) -{ +static int select_test(const struct tipc_test_params* params) { int fd; uint i, j; ssize_t rc; - char tx_buf[msgsz]; + char tx_buf[params->msgsize]; - if (!opt_silent) { - printf("%s: repeat %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat %u\n", __func__, params->repeat); } - fd = tipc_connect(dev_name, echo_name); + fd = tipc_connect(params->dev_name, echo_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "echo"); return fd; } - for (i = 0; i < repeat; i++) { - _wait_for_msg(fd, msgsz, 1); + for (i = 0; i < params->repeat; i++) { + _wait_for_msg(fd, 1, params); - if (!opt_silent) { - printf("sending burst: %u msg\n", msgburst); + if (!params->silent) { + printf("sending burst: %u msg\n", params->msgburst); } - for (j = 0; j < msgburst; j++) { - memset(tx_buf, i + j, msgsz); - rc = write(fd, tx_buf, msgsz); - if ((size_t)rc != msgsz) { + for (j = 0; j < params->msgburst; j++) { + memset(tx_buf, i + j, params->msgsize); + rc = write(fd, tx_buf, params->msgsize); + if ((size_t)rc != params->msgsize) { perror("burst_test: write"); break; } @@ -546,37 +583,36 @@ static int select_test(uint repeat, uint msgburst, uint msgsz) tipc_close(fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int blocked_read_test(uint repeat) -{ +static int blocked_read_test(const struct tipc_test_params* params) { int fd; uint i; ssize_t rc; char rx_buf[512]; - if (!opt_silent) { - printf("%s: repeat %u\n", __func__, repeat); + if (!params->silent) { + printf("%s: repeat %u\n", __func__, params->repeat); } - fd = tipc_connect(dev_name, echo_name); + fd = tipc_connect(params->dev_name, echo_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "echo"); return fd; } - for (i = 0; i < repeat; i++) { + for (i = 0; i < params->repeat; i++) { rc = read(fd, rx_buf, sizeof(rx_buf)); if (rc < 0) { perror("select_test: read"); break; } else { - if (!opt_silent) { + if (!params->silent) { printf("got %zd bytes\n", rc); } } @@ -584,15 +620,14 @@ static int blocked_read_test(uint repeat) tipc_close(fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int ta2ta_ipc_test(void) -{ +static int ta2ta_ipc_test(const struct tipc_test_params* params) { enum test_message_header { TEST_PASSED = 0, TEST_FAILED = 1, @@ -604,11 +639,11 @@ static int ta2ta_ipc_test(void) int ret; unsigned char rx_buf[256]; - if (!opt_silent) { + if (!params->silent) { printf("%s:\n", __func__); } - fd = tipc_connect(dev_name, main_ctrl_name); + fd = tipc_connect(params->dev_name, main_ctrl_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "main_ctrl"); return fd; @@ -658,13 +693,12 @@ static void print_uuid(const char *dev, uuid_t *uuid) uuid->clock_seq_and_node[7]); } -static int dev_uuid_test(void) -{ +static int dev_uuid_test(const struct tipc_test_params* params) { int fd; ssize_t rc; uuid_t uuid; - fd = tipc_connect(dev_name, uuid_name); + fd = tipc_connect(params->dev_name, uuid_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "uuid"); return fd; @@ -677,7 +711,7 @@ static int dev_uuid_test(void) } else if (rc != sizeof(uuid)) { fprintf(stderr, "unexpected uuid size (%d vs. %d)\n", (int)rc, (int)sizeof(uuid)); } else { - print_uuid(dev_name, &uuid); + print_uuid(params->dev_name, &uuid); } tipc_close(fd); @@ -685,61 +719,58 @@ static int dev_uuid_test(void) return 0; } -static int ta_access_test(void) -{ +static int ta_access_test(const struct tipc_test_params* params) { int fd; - if (!opt_silent) { + if (!params->silent) { printf("%s:\n", __func__); } - fd = tipc_connect(dev_name, ta_only_name); + fd = tipc_connect(params->dev_name, ta_only_name); if (fd >= 0) { fprintf(stderr, "Succeed to connect to '%s' service\n", "ta_only"); tipc_close(fd); } - fd = tipc_connect(dev_name, ns_only_name); + fd = tipc_connect(params->dev_name, ns_only_name); if (fd < 0) { fprintf(stderr, "Failed to connect to '%s' service\n", "ns_only"); return fd; } tipc_close(fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } - -static int writev_test(uint repeat, uint msgsz, bool var) -{ +static int writev_test(const struct tipc_test_params* params) { uint i; ssize_t rc; size_t msg_len; int echo_fd = -1; - char tx0_buf[msgsz]; - char tx1_buf[msgsz]; - char rx_buf[msgsz]; + char tx0_buf[params->msgsize]; + char tx1_buf[params->msgsize]; + char rx_buf[params->msgsize]; struct iovec iovs[2] = {{tx0_buf, 0}, {tx1_buf, 0}}; - if (!opt_silent) { - printf("%s: repeat %u: msgsz %u: variable %s\n", __func__, repeat, msgsz, - var ? "true" : "false"); + if (!params->silent) { + printf("%s: repeat %u: params->msgsize %u: variable %s\n", __func__, params->repeat, + params->msgsize, params->variable ? "true" : "false"); } - echo_fd = tipc_connect(dev_name, echo_name); + echo_fd = tipc_connect(params->dev_name, echo_name); if (echo_fd < 0) { fprintf(stderr, "Failed to connect to service\n"); return echo_fd; } - for (i = 0; i < repeat; i++) { - msg_len = msgsz; - if (opt_variable && msgsz) { - msg_len = rand() % msgsz; + for (i = 0; i < params->repeat; i++) { + msg_len = params->msgsize; + if (params->variable && params->msgsize) { + msg_len = rand() % params->msgsize; } iovs[0].iov_len = msg_len / 3; @@ -786,39 +817,38 @@ static int writev_test(uint repeat, uint msgsz, bool var) tipc_close(echo_fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int readv_test(uint repeat, uint msgsz, bool var) -{ +static int readv_test(const struct tipc_test_params* params) { uint i; ssize_t rc; size_t msg_len; int echo_fd = -1; - char tx_buf[msgsz]; - char rx0_buf[msgsz]; - char rx1_buf[msgsz]; + char tx_buf[params->msgsize]; + char rx0_buf[params->msgsize]; + char rx1_buf[params->msgsize]; struct iovec iovs[2] = {{rx0_buf, 0}, {rx1_buf, 0}}; - if (!opt_silent) { - printf("%s: repeat %u: msgsz %u: variable %s\n", __func__, repeat, msgsz, - var ? "true" : "false"); + if (!params->silent) { + printf("%s: repeat %u: params->msgsize %u: variable %s\n", __func__, params->repeat, + params->msgsize, params->variable ? "true" : "false"); } - echo_fd = tipc_connect(dev_name, echo_name); + echo_fd = tipc_connect(params->dev_name, echo_name); if (echo_fd < 0) { fprintf(stderr, "Failed to connect to service\n"); return echo_fd; } - for (i = 0; i < repeat; i++) { - msg_len = msgsz; - if (opt_variable && msgsz) { - msg_len = rand() % msgsz; + for (i = 0; i < params->repeat; i++) { + msg_len = params->msgsize; + if (params->variable && params->msgsize) { + msg_len = rand() % params->msgsize; } iovs[0].iov_len = msg_len / 3; @@ -865,14 +895,14 @@ static int readv_test(uint repeat, uint msgsz, bool var) tipc_close(echo_fd); - if (!opt_silent) { + if (!params->silent) { printf("%s: done\n", __func__); } return 0; } -static int send_fd_test(void) { +static int send_fd_test(const struct tipc_test_params* params) { int ret; int dma_buf = -1; int fd = -1; @@ -881,7 +911,7 @@ static int send_fd_test(void) { const size_t num_chunks = 10; - fd = tipc_connect(dev_name, receiver_name); + fd = tipc_connect(params->dev_name, receiver_name); if (fd < 0) { fprintf(stderr, "Failed to connect to test support TA - is it missing?\n"); ret = -1; @@ -948,6 +978,73 @@ cleanup: return ret; } +uint64_t get_time_us(void) { + struct timespec spec; + + clock_gettime(CLOCK_MONOTONIC, &spec); + return spec.tv_sec * 1000000 + spec.tv_nsec / 1000; +} + +static const struct tipc_test_def tipc_tests[] = { + {"connect", connect_test}, + {"connect_foo", connect_foo}, + {"burst_write", burst_write_test}, + {"select", select_test}, + {"blocked_read", blocked_read_test}, + {"closer1", closer1_test}, + {"closer2", closer2_test}, + {"closer3", closer3_test}, + {"echo", echo_test}, + {"ta2ta-ipc", ta2ta_ipc_test}, + {"dev-uuid", dev_uuid_test}, + {"ta-access", ta_access_test}, + {"writev", writev_test}, + {"readv", readv_test}, + {"send-fd", send_fd_test}, +}; + +tipc_test_func_t get_test_function(const struct tipc_test_params* params) { + for (size_t i = 0; i < sizeof(tipc_tests) / sizeof(tipc_tests[0]); i++) { + if (strcmp(params->test_name, tipc_tests[i].test_name) == 0) { + return tipc_tests[i].func; + } + } + fprintf(stderr, "Unrecognized test name '%s'\n", params->test_name); + exit(1); +} + +static int run_as_bench(const struct tipc_test_params* params) { + int rc = 0; + int64_t min = INT64_MAX; + int64_t max = 0; + int64_t avg = 0; + int64_t cold = 0; + + uint64_t start; + uint64_t end; + + tipc_test_func_t test = get_test_function(params); + + for (size_t i = 0; (i < params->bench + 1) && rc == 0; ++i) { + start = get_time_us(); + rc |= test(params); + end = get_time_us(); + int64_t t = end - start; + + if (i == 0) { + cold = t; + } else { + min = (t < min) ? t : min; + max = (t > max) ? t : max; + avg += t; + } + } + avg /= params->bench; + + fprintf(stderr, BENCH_RESULT_TPL, params->test_name, min, max, avg, cold, min, max, avg, cold); + return rc; +} + int main(int argc, char **argv) { int rc = 0; @@ -955,52 +1052,25 @@ int main(int argc, char **argv) if (argc <= 1) { print_usage_and_exit(argv[0], EXIT_FAILURE, false); } + struct tipc_test_params params; + init_params(¶ms); + parse_options(argc, argv, ¶ms); - parse_options(argc, argv); - - if (!dev_name) { - dev_name = TIPC_DEFAULT_DEVNAME; + if (!params.dev_name) { + params.dev_name = TIPC_DEFAULT_DEVNAME; } - if (!test_name) { + if (!params.test_name) { fprintf(stderr, "need a Test to run\n"); print_usage_and_exit(argv[0], EXIT_FAILURE, true); } - if (strcmp(test_name, "connect") == 0) { - rc = connect_test(opt_repeat); - } else if (strcmp(test_name, "connect_foo") == 0) { - rc = connect_foo(opt_repeat); - } else if (strcmp(test_name, "burst_write") == 0) { - rc = burst_write_test(opt_repeat, opt_msgburst, opt_msgsize, opt_variable); - } else if (strcmp(test_name, "select") == 0) { - rc = select_test(opt_repeat, opt_msgburst, opt_msgsize); - } else if (strcmp(test_name, "blocked_read") == 0) { - rc = blocked_read_test(opt_repeat); - } else if (strcmp(test_name, "closer1") == 0) { - rc = closer1_test(opt_repeat); - } else if (strcmp(test_name, "closer2") == 0) { - rc = closer2_test(opt_repeat); - } else if (strcmp(test_name, "closer3") == 0) { - rc = closer3_test(opt_repeat); - } else if (strcmp(test_name, "echo") == 0) { - rc = echo_test(opt_repeat, opt_msgsize, opt_variable); - } else if (strcmp(test_name, "ta2ta-ipc") == 0) { - rc = ta2ta_ipc_test(); - } else if (strcmp(test_name, "dev-uuid") == 0) { - rc = dev_uuid_test(); - } else if (strcmp(test_name, "ta-access") == 0) { - rc = ta_access_test(); - } else if (strcmp(test_name, "writev") == 0) { - rc = writev_test(opt_repeat, opt_msgsize, opt_variable); - } else if (strcmp(test_name, "readv") == 0) { - rc = readv_test(opt_repeat, opt_msgsize, opt_variable); - } else if (strcmp(test_name, "send-fd") == 0) { - rc = send_fd_test(); + if (params.bench > 0) { + rc = run_as_bench(¶ms); + params.bench = 0; } else { - fprintf(stderr, "Unrecognized test name '%s'\n", test_name); - print_usage_and_exit(argv[0], EXIT_FAILURE, true); + tipc_test_func_t test = get_test_function(¶ms); + rc = test(¶ms); } - return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }