From 3932d8db7556d2fe4088535443e172a461cc6e9e Mon Sep 17 00:00:00 2001 From: Andy Zhou Date: Fri, 28 Mar 2014 18:13:00 -0700 Subject: [PATCH] unit-test: Add ovstest Changing one of the files in the Open vSwitch ``lib'' directory causes 43 binaries to be relinked, which takes a lot of time even with parallel ``make''. 31 of those binaries are in the ``tests'' directory. ovs-test attemps to combine most of those binaries into a single test program that just takes a subcommand name as its first command-line argument. The following patch makes use of this infrastructure. Signed-off-by: Andy Zhou Acked-by: Ben Pfaff --- tests/automake.mk | 6 +++ tests/ovstest.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ tests/ovstest.h | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+) create mode 100644 tests/ovstest.c create mode 100644 tests/ovstest.h diff --git a/tests/automake.mk b/tests/automake.mk index 739d79e09..fc584d612 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -94,6 +94,7 @@ check-pycov: all tests/atconfig tests/atlocal $(TESTSUITE) clean-pycov valgrind_wrappers = \ tests/valgrind/ovs-appctl \ tests/valgrind/ovs-ofctl \ + tests/valgrind/ovstest \ tests/valgrind/ovs-vsctl \ tests/valgrind/ovs-vswitchd \ tests/valgrind/ovsdb-client \ @@ -297,6 +298,11 @@ tests/idltest.ovsidl: $(IDLTEST_IDL_FILES) tests/idltest.c: tests/idltest.h +noinst_PROGRAMS += tests/ovstest +tests_ovstest_SOURCES = tests/ovstest.c \ + tests/ovstest.h +tests_ovstest_LDADD = lib/libopenvswitch.la + noinst_PROGRAMS += tests/test-reconnect tests_test_reconnect_SOURCES = tests/test-reconnect.c tests_test_reconnect_LDADD = lib/libopenvswitch.la diff --git a/tests/ovstest.c b/tests/ovstest.c new file mode 100644 index 000000000..b8f5bfa3f --- /dev/null +++ b/tests/ovstest.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* The mother of all test programs that links with libopevswitch.la */ + +#include +#include +#include +#include +#include "command-line.h" +#include "ovstest.h" +#include "util.h" + +static struct command *commands = NULL; +static size_t n_commands = 0; +static size_t allocated_commands = 0; + +static void +add_command(struct command *cmd) +{ + const struct command nil = {NULL, 0, 0, NULL}; + + while (n_commands + 1 >= allocated_commands) { + commands = x2nrealloc(commands, &allocated_commands, + sizeof *cmd); + } + + commands[n_commands] = *cmd; + commands[n_commands + 1] = nil; + n_commands++; +} + +static void +list(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + const struct command *p; + + for(p = commands; p->name != NULL; p++) { + printf("%s, %d, %d\n", p->name,p->min_args, p->max_args); + } +} + +static void +add_top_level_commands(void) +{ + struct command help_cmd = {"--help", 0, 0, list}; + + add_command(&help_cmd); +} + +void +ovstest_register(const char *test_name, ovstest_func f, + const struct command *sub_commands) +{ + struct command test_cmd; + int max_args = 0; + + if (sub_commands) { + const struct command *p; + + for(p = sub_commands; p->name != NULL; p++) { + if (p->max_args > max_args) { + max_args = p->max_args; + } + } + } + max_args++; /* adding in the sub program */ + + test_cmd.name = test_name; + test_cmd.min_args = 1; + test_cmd.max_args = max_args; + test_cmd.handler = f; + + add_command(&test_cmd); +} + +static void +cleanup(void) +{ + if (allocated_commands) { + free(commands); + } +} + +int +main(int argc, char *argv[]) +{ + set_program_name(argv[0]); + + add_top_level_commands(); + if (argc > 1) { + run_command(argc - 1, argv + 1, commands); + } + cleanup(); + + return 0; +} diff --git a/tests/ovstest.h b/tests/ovstest.h new file mode 100644 index 000000000..6d10a5de8 --- /dev/null +++ b/tests/ovstest.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVSTEST_H +#define OVSTEST_H + +/* Overview + * ======== + * + * OVS tests directory contains many small test programs. One down side + * of building them as individual programs is that they all have to be + * linked whenever a library function is modified. + * + * ovstest is an attempt to improve the overall build time by linking + * all test programs into a single program, ovs-test. Regardless of + * the number of test programs, linking will be done only once to produce + * ovstest. + * + * With ovs-test, each test programs now becomes a sub program of ovstest. + * For example, 'mytest' program, can now be invoked as 'ovs mytest'. + * + * 'ovstest --help' will list all test programs can be invoked. + * + * The Usage comment section below documents how a new test program can + * be added to ovs-test. + */ + +typedef void (*ovstest_func)(int argc, char *argv[]); + +void +ovstest_register(const char *test_name, ovstest_func f, + const struct command * sub_commands); + +/* Usage + * ===== + * + * For each test sub program, its 'main' program should be named as + * '_main()'. + * + * OVSTEST_REGISTER register the sub program with ovs-test top level + * command line parser. is expected as argv[1] when invoking + * ovs-test. + * + * In case the test program has sub commands, its command array can be + * passed in as . Otherwise, NULL can be used instead. + * + * Example: + * ---------- + * + * Suppose the test program is called my-test.c + * ... + * + * static void + * my_test_main(int argc, char *argv[]) + * { + * .... + * } + * + * // The last parameter is NULL in case my-test.c does + * // not have sub commands. Otherwise, its command + * // array can replace the NULL here. + * + * OVSTEST_REGISTER("my-test", my_test_main, NULL); + */ + +#define OVSTEST_REGISTER(name, function, sub_commands) \ + OVS_CONSTRUCTOR(register_##function) { \ + ovstest_register(name, function, sub_commands); \ + } + +#endif -- 2.43.0