From patchwork Mon Nov 2 14:28:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Michelson X-Patchwork-Id: 1392288 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=UCKy6st3; dkim-atps=neutral Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CPwJq5gLrz9sVM for ; Tue, 3 Nov 2020 01:28:59 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 5E7D6873D5; Mon, 2 Nov 2020 14:28:58 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TEpNofAH1zGh; Mon, 2 Nov 2020 14:28:57 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 42B5387222; Mon, 2 Nov 2020 14:28:57 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 2F088C1AD8; Mon, 2 Nov 2020 14:28:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 9C54FC0889 for ; Mon, 2 Nov 2020 14:28:55 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 84563204E1 for ; Mon, 2 Nov 2020 14:28:55 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zDRgO6ZwVGXV for ; Mon, 2 Nov 2020 14:28:45 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by silver.osuosl.org (Postfix) with ESMTPS id AFB3E204CA for ; Mon, 2 Nov 2020 14:28:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1604327320; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=05n9FGVjm1sn/o0K9axD2REMeOo1NjqdotNpc7jvJIo=; b=UCKy6st3p6g2FYUO4RMCN+BX40aWdu58zIqth2/rksO/CKxGVhlaVXKkeAjkFlFOgqzyO6 crr/vuQSOgJ2eMVcnHa4/4gkmid+joVH/k8ga06CMQDGV3Wey9GnoZ1HP65ZZbffu5amCP IBG0c9tNeWy8zs8Zee4bMuFIF/i++6w= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-172-n9x3s55EMly6HuhLQjX0NA-1; Mon, 02 Nov 2020 09:28:30 -0500 X-MC-Unique: n9x3s55EMly6HuhLQjX0NA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F162E8030D1 for ; Mon, 2 Nov 2020 14:28:29 +0000 (UTC) Received: from monae.redhat.com (ovpn-112-233.rdu2.redhat.com [10.10.112.233]) by smtp.corp.redhat.com (Postfix) with ESMTP id 865F555766 for ; Mon, 2 Nov 2020 14:28:29 +0000 (UTC) From: Mark Michelson To: dev@openvswitch.org Date: Mon, 2 Nov 2020 09:28:26 -0500 Message-Id: <20201102142828.3444732-2-mmichels@redhat.com> In-Reply-To: <20201102142828.3444732-1-mmichels@redhat.com> References: <20201102142828.3444732-1-mmichels@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mmichels@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [RFC PATCH ovn v3 1/3] Add unit test framework. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This creates an API that allows for unit tests to be registered in code by OVN. This change enables the following: * At configure time, "--enable-unit-tests" can be specified to allow for unit tests to be compiled. * This configure-time variable also enables a testsuite variable to be defined, allowing for unit tests to be run from the testsuite. * Testsuite tests are defined using OVS_CONSTRUCTOR, meaning they are automatically registered prior to main() being run in whichever program the unit test is defined in. * Unit tests can be written as standalone programs using the ovstest framework. This works so long as the symbols referenced in the unit test can be found in a header file. Unit tests written in this way don't rely on anything introduced in this commit and have existed in the testsuite via the test-ovn.c file for a while. * Unit tests can also be written within the source of a file and accessed using ovn-appctl. This can be useful for testing private functions within source code. Example: `ovn-appctl -t northd unit-test my-unit-test [args]`. Unit tests written this way require the use of the library introduced in this commit. This commit does not define any unit tests. That is saved for a later commit in this series. Signed-off-by: Mark Michelson --- acinclude.m4 | 12 +++++ configure.ac | 1 + lib/automake.mk | 4 +- lib/unit-test.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++ lib/unit-test.h | 34 ++++++++++++++ tests/atlocal.in | 1 + 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 lib/unit-test.c create mode 100644 lib/unit-test.h diff --git a/acinclude.m4 b/acinclude.m4 index a797adc82..8b1888075 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -366,3 +366,15 @@ AC_DEFUN([OVN_CHECK_OVS], [ AC_SUBST(OVSVERSION) AC_MSG_RESULT([OVS version is $OVSVERSION]) ]) + +AC_DEFUN([OVN_ENABLE_UNIT_TESTS], + [AC_ARG_ENABLE( + [unit_tests], + [AC_HELP_STRING([--enable-unit-tests], [Enable unit test framework])], + [], [enable_unit_tests=no]) + AC_CONFIG_COMMANDS_PRE( + [if test "X$enable_unit_tests" = Xyes; then + OVS_CFLAGS="$OVS_CFLAGS -DENABLE_UNIT_TESTS" + fi]) + + AC_SUBST([enable_unit_tests])]) diff --git a/configure.ac b/configure.ac index 0b17f05b9..613e2ba3d 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,7 @@ OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED]) OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER]) OVS_ENABLE_WERROR OVS_ENABLE_SPARSE +OVN_ENABLE_UNIT_TESTS OVS_CHECK_PRAGMA_MESSAGE OVN_CHECK_OVS diff --git a/lib/automake.mk b/lib/automake.mk index f3e9c8818..3e9c2a697 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -23,7 +23,9 @@ lib_libovn_la_SOURCES = \ lib/ovn-util.h \ lib/logical-fields.c \ lib/inc-proc-eng.c \ - lib/inc-proc-eng.h + lib/inc-proc-eng.h \ + lib/unit-test.c \ + lib/unit-test.h nodist_lib_libovn_la_SOURCES = \ lib/ovn-dirs.c \ lib/ovn-nb-idl.c \ diff --git a/lib/unit-test.c b/lib/unit-test.c new file mode 100644 index 000000000..3a12727c6 --- /dev/null +++ b/lib/unit-test.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020 Red Hat, 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. + */ + +#include + +#include "openvswitch/shash.h" +#include "openvswitch/dynamic-string.h" +#include "util.h" +#include "unixctl.h" +#include "command-line.h" + +#include "lib/unit-test.h" + +#ifdef ENABLE_UNIT_TESTS +static struct shash unit_tests = SHASH_INITIALIZER(&unit_tests); + +struct unit_test_data { + size_t min_args; + size_t max_args; + ovs_cmdl_handler cb; +}; + +void +register_unit_test(const char *name, size_t min_args, size_t max_args, + ovs_cmdl_handler cb) +{ + struct unit_test_data *test_data = xmalloc(sizeof *test_data); + test_data->min_args = min_args; + test_data->max_args = max_args; + test_data->cb = cb; + shash_add_once(&unit_tests, name, test_data); +} + +void +run_unit_test(struct ovs_cmdl_context *ctx) +{ + struct unit_test_data *test_data = shash_find_data(&unit_tests, + ctx->argv[0]); + if (!test_data) { + struct ds *output = ctx->pvt; + ds_put_format(output, "Unable to find unit test %s\n", ctx->argv[0]); + return; + } + + int test_args = ctx->argc - 1; /* Ignore test name */ + if (test_args < test_data->min_args || + test_args > test_data->max_args) { + struct ds *output = ctx->pvt; + ds_put_format(output, "Invalid number of arguments. " + "Minimum: %"PRIuSIZE". Maxium: %"PRIuSIZE". " + "Got: %d\n", + test_data->min_args, test_data->max_args, + test_args); + } + test_data->cb(ctx); +} + +static void +unixctl_run_unit_test(struct unixctl_conn *conn, int argc, + const char *argv[], void *ignore OVS_UNUSED) +{ + if (argc < 2) { + unixctl_command_reply_error(conn, "No unit test specified"); + return; + } + + struct ds reply = DS_EMPTY_INITIALIZER; + struct ovs_cmdl_context ctx = { + .argc = argc - 1, + .argv = (char **) argv + 1, + .pvt = &reply, + }; + run_unit_test(&ctx); + unixctl_command_reply(conn, ds_cstr(&reply)); + + ds_destroy(&reply); +} + +void +register_unixctl_unit_test(void) +{ + unixctl_command_register("unit-test", "", 1, UINT_MAX, + unixctl_run_unit_test, NULL); +} + +#else /* ENABLE_UNIT_TESTS */ + +void +register_unit_test(const char *name OVS_UNUSED, size_t min_args OVS_UNUSED, + size_t max_args OVS_UNUSED, ovs_cmdl_handler cb OVS_UNUSED) +{ + return; +} + +void +run_unit_test(struct ovs_cmdl_context *ctx OVS_UNUSED) +{ + return; +} + +void +register_unixctl_unit_test(void) +{ + return; +} + +#endif /* ENABLE_UNIT_TESTS */ diff --git a/lib/unit-test.h b/lib/unit-test.h new file mode 100644 index 000000000..8dc4e2cd7 --- /dev/null +++ b/lib/unit-test.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Red Hat, 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 OVN_UNIT_TEST_H +#define OVN_UNIT_TEST_H 1 + +#include "openvswitch/compiler.h" +#include "command-line.h" + +void register_unit_test(const char *name, size_t min_args, size_t max_args, + ovs_cmdl_handler cb); + +void run_unit_test(struct ovs_cmdl_context *ctx); + +void register_unixctl_unit_test(void); + +#define UNIT_TEST_DEFINE(NAME, MIN_ARGS, MAX_ARGS, CB) \ + OVS_CONSTRUCTOR(unit_test_##NAME) { \ + register_unit_test(#NAME, MIN_ARGS, MAX_ARGS, CB); \ + } +#endif diff --git a/tests/atlocal.in b/tests/atlocal.in index 26681f02d..ca48ee93d 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -3,6 +3,7 @@ HAVE_OPENSSL='@HAVE_OPENSSL@' OPENSSL_SUPPORTS_SNI='@OPENSSL_SUPPORTS_SNI@' HAVE_UNBOUND='@HAVE_UNBOUND@' EGREP='@EGREP@' +ENABLE_UNIT_TESTS='@enable_unit_tests@' if test x"$PYTHON3" = x; then PYTHON3='@PYTHON3@'