[ovs-dev] [PATCH ovn v2 05/10] lflow-cache: Add unit tests.

Numan Siddique numans at ovn.org
Tue Feb 9 05:59:07 UTC 2021


On Thu, Feb 4, 2021 at 6:56 PM Dumitru Ceara <dceara at redhat.com> wrote:
>
> Signed-off-by: Dumitru Ceara <dceara at redhat.com>

Acked-by: Numan Siddique <numans at ovn.org>

Numan

> ---
>  controller/test-lflow-cache.c  |  224 +++++++++++++++++++++++++++++++++++
>  controller/test-ofctrl-seqno.c |   18 ---
>  tests/automake.mk              |    8 +
>  tests/ovn-lflow-cache.at       |  257 ++++++++++++++++++++++++++++++++++++++++
>  tests/ovn.at                   |   68 +++++++++++
>  tests/test-utils.c             |   49 ++++++++
>  tests/test-utils.h             |   26 ++++
>  tests/testsuite.at             |    1
>  8 files changed, 633 insertions(+), 18 deletions(-)
>  create mode 100644 controller/test-lflow-cache.c
>  create mode 100644 tests/ovn-lflow-cache.at
>  create mode 100644 tests/test-utils.c
>  create mode 100644 tests/test-utils.h
>
> diff --git a/controller/test-lflow-cache.c b/controller/test-lflow-cache.c
> new file mode 100644
> index 0000000..d6e962e
> --- /dev/null
> +++ b/controller/test-lflow-cache.c
> @@ -0,0 +1,224 @@
> +/* Copyright (c) 2021, 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 <config.h>
> +
> +#include "ovn/expr.h"
> +#include "ovn-sb-idl.h"
> +#include "tests/ovstest.h"
> +#include "tests/test-utils.h"
> +#include "util.h"
> +
> +#include "lflow-cache.h"
> +
> +static void
> +test_lflow_cache_add__(struct lflow_cache *lc, const char *op_type,
> +                       const struct sbrec_logical_flow *lflow,
> +                       unsigned int conj_id_ofs,
> +                       struct expr *e)
> +{
> +    printf("ADD %s:\n", op_type);
> +    printf("  conj-id-ofs: %u\n", conj_id_ofs);
> +
> +    if (!strcmp(op_type, "conj-id")) {
> +        lflow_cache_add_conj_id(lc, lflow, conj_id_ofs);
> +    } else if (!strcmp(op_type, "expr")) {
> +        lflow_cache_add_expr(lc, lflow, conj_id_ofs, expr_clone(e));
> +    } else if (!strcmp(op_type, "matches")) {
> +        struct hmap *matches = xmalloc(sizeof *matches);
> +        ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0);
> +        ovs_assert(hmap_count(matches) == 1);
> +        lflow_cache_add_matches(lc, lflow, matches);
> +    } else {
> +        OVS_NOT_REACHED();
> +    }
> +}
> +
> +static void
> +test_lflow_cache_lookup__(struct lflow_cache *lc,
> +                          const struct sbrec_logical_flow *lflow)
> +{
> +    struct lflow_cache_value *lcv = lflow_cache_get(lc, lflow);
> +
> +    printf("LOOKUP:\n");
> +    if (!lcv) {
> +        printf("  not found\n");
> +        return;
> +    }
> +
> +    printf("  conj_id_ofs: %"PRIu32"\n", lcv->conj_id_ofs);
> +    switch (lcv->type) {
> +    case LCACHE_T_CONJ_ID:
> +        printf("  type: conj-id\n");
> +        break;
> +    case LCACHE_T_EXPR:
> +        printf("  type: expr\n");
> +        break;
> +    case LCACHE_T_MATCHES:
> +        printf("  type: matches\n");
> +        break;
> +    case LCACHE_T_NONE:
> +        OVS_NOT_REACHED();
> +        break;
> +    }
> +}
> +
> +static void
> +test_lflow_cache_delete__(struct lflow_cache *lc,
> +                          const struct sbrec_logical_flow *lflow)
> +{
> +    printf("DELETE\n");
> +    lflow_cache_delete(lc, lflow);
> +}
> +
> +static void
> +test_lflow_cache_stats__(struct lflow_cache *lc)
> +{
> +    struct lflow_cache_stats *lcs = lflow_cache_get_stats(lc);
> +
> +    if (!lcs) {
> +        return;
> +    }
> +    printf("Enabled: %s\n", lflow_cache_is_enabled(lc) ? "true" : "false");
> +    for (size_t i = 0; i < LCACHE_T_MAX; i++) {
> +        printf("  %s: %"PRIuSIZE"\n", lflow_cache_type_names[i],
> +               lcs->n_entries[i]);
> +    }
> +    free(lcs);
> +}
> +
> +static void
> +test_lflow_cache_operations(struct ovs_cmdl_context *ctx)
> +{
> +    struct lflow_cache *lc = lflow_cache_create();
> +    struct expr *e = expr_create_boolean(true);
> +    bool enabled = !strcmp(ctx->argv[1], "true");
> +    unsigned int shift = 2;
> +    unsigned int n_ops;
> +
> +    lflow_cache_enable(lc, enabled);
> +    test_lflow_cache_stats__(lc);
> +
> +    if (!test_read_uint_value(ctx, shift++, "n_ops", &n_ops)) {
> +        goto done;
> +    }
> +
> +    for (unsigned int i = 0; i < n_ops; i++) {
> +        const char *op = test_read_value(ctx, shift++, "op");
> +
> +        if (!op) {
> +            goto done;
> +        }
> +
> +        struct sbrec_logical_flow lflow;
> +        uuid_generate(&lflow.header_.uuid);
> +
> +        if (!strcmp(op, "add")) {
> +            const char *op_type = test_read_value(ctx, shift++, "op_type");
> +            if (!op_type) {
> +                goto done;
> +            }
> +
> +            unsigned int conj_id_ofs;
> +            if (!test_read_uint_value(ctx, shift++, "conj-id-ofs",
> +                                      &conj_id_ofs)) {
> +                goto done;
> +            }
> +
> +            test_lflow_cache_add__(lc, op_type, &lflow, conj_id_ofs, e);
> +            test_lflow_cache_lookup__(lc, &lflow);
> +        } else if (!strcmp(op, "add-del")) {
> +            const char *op_type = test_read_value(ctx, shift++, "op_type");
> +            if (!op_type) {
> +                goto done;
> +            }
> +
> +            unsigned int conj_id_ofs;
> +            if (!test_read_uint_value(ctx, shift++, "conj-id-ofs",
> +                                      &conj_id_ofs)) {
> +                goto done;
> +            }
> +
> +            test_lflow_cache_add__(lc, op_type, &lflow, conj_id_ofs, e);
> +            test_lflow_cache_lookup__(lc, &lflow);
> +            test_lflow_cache_delete__(lc, &lflow);
> +            test_lflow_cache_lookup__(lc, &lflow);
> +        } else if (!strcmp(op, "enable")) {
> +            printf("ENABLE\n");
> +            lflow_cache_enable(lc, true);
> +        } else if (!strcmp(op, "disable")) {
> +            printf("DISABLE\n");
> +            lflow_cache_enable(lc, false);
> +        } else if (!strcmp(op, "flush")) {
> +            printf("FLUSH\n");
> +            lflow_cache_flush(lc);
> +        } else {
> +            OVS_NOT_REACHED();
> +        }
> +        test_lflow_cache_stats__(lc);
> +    }
> +done:
> +    lflow_cache_destroy(lc);
> +    expr_destroy(e);
> +}
> +
> +static void
> +test_lflow_cache_negative(struct ovs_cmdl_context *ctx OVS_UNUSED)
> +{
> +    lflow_cache_flush(NULL);
> +    lflow_cache_destroy(NULL);
> +    lflow_cache_enable(NULL, true);
> +    ovs_assert(!lflow_cache_is_enabled(NULL));
> +    ovs_assert(!lflow_cache_get_stats(NULL));
> +
> +    struct lflow_cache *lcs[] = {
> +        NULL,
> +        lflow_cache_create(),
> +    };
> +
> +    for (size_t i = 0; i < ARRAY_SIZE(lcs); i++) {
> +        struct expr *e = expr_create_boolean(true);
> +        struct hmap *matches = xmalloc(sizeof *matches);
> +
> +        ovs_assert(expr_to_matches(e, NULL, NULL, matches) == 0);
> +        ovs_assert(hmap_count(matches) == 1);
> +
> +        lflow_cache_add_conj_id(lcs[i], NULL, 0);
> +        lflow_cache_add_expr(lcs[i], NULL, 0, NULL);
> +        lflow_cache_add_expr(lcs[i], NULL, 0, e);
> +        lflow_cache_add_matches(lcs[i], NULL, NULL);
> +        lflow_cache_add_matches(lcs[i], NULL, matches);
> +        lflow_cache_destroy(lcs[i]);
> +    }
> +}
> +
> +static void
> +test_lflow_cache_main(int argc, char *argv[])
> +{
> +    set_program_name(argv[0]);
> +    static const struct ovs_cmdl_command commands[] = {
> +        {"lflow_cache_operations", NULL, 3, INT_MAX,
> +         test_lflow_cache_operations, OVS_RO},
> +        {"lflow_cache_negative", NULL, 0, 0,
> +         test_lflow_cache_negative, OVS_RO},
> +        {NULL, NULL, 0, 0, NULL, OVS_RO},
> +    };
> +    struct ovs_cmdl_context ctx;
> +    ctx.argc = argc - 1;
> +    ctx.argv = argv + 1;
> +    ovs_cmdl_run_command(&ctx, commands);
> +}
> +
> +OVSTEST_REGISTER("test-lflow-cache", test_lflow_cache_main);
> diff --git a/controller/test-ofctrl-seqno.c b/controller/test-ofctrl-seqno.c
> index fce88d4..b96da9d 100644
> --- a/controller/test-ofctrl-seqno.c
> +++ b/controller/test-ofctrl-seqno.c
> @@ -16,6 +16,7 @@
>  #include <config.h>
>
>  #include "tests/ovstest.h"
> +#include "tests/test-utils.h"
>  #include "sort.h"
>  #include "util.h"
>
> @@ -27,23 +28,6 @@ test_init(void)
>      ofctrl_seqno_init();
>  }
>
> -static bool
> -test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index,
> -                     const char *descr, unsigned int *result)
> -{
> -    if (index >= ctx->argc) {
> -        fprintf(stderr, "Missing %s argument\n", descr);
> -        return false;
> -    }
> -
> -    const char *arg = ctx->argv[index];
> -    if (!str_to_uint(arg, 10, result)) {
> -        fprintf(stderr, "Invalid %s: %s\n", descr, arg);
> -        return false;
> -    }
> -    return true;
> -}
> -
>  static int
>  test_seqno_compare(size_t a, size_t b, void *values_)
>  {
> diff --git a/tests/automake.mk b/tests/automake.mk
> index 282d1b1..df6d0a2 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -33,7 +33,8 @@ TESTSUITE_AT = \
>         tests/ovn-macros.at \
>         tests/ovn-performance.at \
>         tests/ovn-ofctrl-seqno.at \
> -       tests/ovn-ipam.at
> +       tests/ovn-ipam.at \
> +       tests/ovn-lflow-cache.at
>
>  SYSTEM_KMOD_TESTSUITE_AT = \
>         tests/system-common-macros.at \
> @@ -207,8 +208,13 @@ noinst_PROGRAMS += tests/ovstest
>  tests_ovstest_SOURCES = \
>         tests/ovstest.c \
>         tests/ovstest.h \
> +       tests/test-utils.c \
> +       tests/test-utils.h \
>         tests/test-ovn.c \
> +       controller/test-lflow-cache.c \
>         controller/test-ofctrl-seqno.c \
> +       controller/lflow-cache.c \
> +       controller/lflow-cache.h \
>         controller/ofctrl-seqno.c \
>         controller/ofctrl-seqno.h \
>         northd/test-ipam.c \
> diff --git a/tests/ovn-lflow-cache.at b/tests/ovn-lflow-cache.at
> new file mode 100644
> index 0000000..f7e8959
> --- /dev/null
> +++ b/tests/ovn-lflow-cache.at
> @@ -0,0 +1,257 @@
> +#
> +# Unit tests for the controller/lflow-cache.c module.
> +#
> +AT_BANNER([OVN unit tests - lflow-cache])
> +
> +AT_SETUP([ovn -- unit test -- lflow-cache single add/lookup])
> +AT_CHECK(
> +    [ovstest test-lflow-cache lflow_cache_operations \
> +        true 3 \
> +        add conj-id 1 \
> +        add expr 2 \
> +        add matches 3],
> +    [0], [dnl
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 1
> +LOOKUP:
> +  conj_id_ofs: 1
> +  type: conj-id
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 2
> +LOOKUP:
> +  conj_id_ofs: 2
> +  type: expr
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 3
> +LOOKUP:
> +  conj_id_ofs: 0
> +  type: matches
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 1
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([ovn -- unit test -- lflow-cache single add/lookup/del])
> +AT_CHECK(
> +    [ovstest test-lflow-cache lflow_cache_operations \
> +        true 3 \
> +        add-del conj-id 1 \
> +        add-del expr 2 \
> +        add-del matches 3],
> +    [0], [dnl
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 1
> +LOOKUP:
> +  conj_id_ofs: 1
> +  type: conj-id
> +DELETE
> +LOOKUP:
> +  not found
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 2
> +LOOKUP:
> +  conj_id_ofs: 2
> +  type: expr
> +DELETE
> +LOOKUP:
> +  not found
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 3
> +LOOKUP:
> +  conj_id_ofs: 0
> +  type: matches
> +DELETE
> +LOOKUP:
> +  not found
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([ovn -- unit test -- lflow-cache disabled single add/lookup/del])
> +AT_CHECK(
> +    [ovstest test-lflow-cache lflow_cache_operations \
> +        false 3 \
> +        add conj-id 1 \
> +        add expr 2 \
> +        add matches 3],
> +    [0], [dnl
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 1
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 2
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 3
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([ovn -- unit test -- lflow-cache disable/enable/flush])
> +AT_CHECK(
> +    [ovstest test-lflow-cache lflow_cache_operations \
> +        true 12 \
> +        add conj-id 1 \
> +        add expr 2 \
> +        add matches 3 \
> +        disable \
> +        add conj-id 4 \
> +        add expr 5 \
> +        add matches 6 \
> +        enable \
> +        add conj-id 7 \
> +        add expr 8 \
> +        add matches 9 \
> +        flush],
> +    [0], [dnl
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 1
> +LOOKUP:
> +  conj_id_ofs: 1
> +  type: conj-id
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 2
> +LOOKUP:
> +  conj_id_ofs: 2
> +  type: expr
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 3
> +LOOKUP:
> +  conj_id_ofs: 0
> +  type: matches
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 1
> +DISABLE
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 4
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 5
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 6
> +LOOKUP:
> +  not found
> +Enabled: false
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ENABLE
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD conj-id:
> +  conj-id-ofs: 7
> +LOOKUP:
> +  conj_id_ofs: 7
> +  type: conj-id
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 0
> +  cache-matches: 0
> +ADD expr:
> +  conj-id-ofs: 8
> +LOOKUP:
> +  conj_id_ofs: 8
> +  type: expr
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 0
> +ADD matches:
> +  conj-id-ofs: 9
> +LOOKUP:
> +  conj_id_ofs: 0
> +  type: matches
> +Enabled: true
> +  cache-conj-id: 1
> +  cache-expr: 1
> +  cache-matches: 1
> +FLUSH
> +Enabled: true
> +  cache-conj-id: 0
> +  cache-expr: 0
> +  cache-matches: 0
> +])
> +AT_CLEANUP
> +
> +AT_SETUP([ovn -- unit test -- lflow-cache negative tests])
> +AT_CHECK([ovstest test-lflow-cache lflow_cache_negative], [0], [])
> +AT_CLEANUP
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 4a75acc..0e114cf 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -22235,6 +22235,74 @@ OVN_CLEANUP([hv1])
>
>  AT_CLEANUP
>
> +AT_SETUP([ovn -- lflow cache operations])
> +ovn_start
> +net_add n1
> +sim_add hv1
> +
> +as hv1
> +ovs-vsctl add-br br-phys
> +ovn_attach n1 br-phys 192.168.0.1
> +
> +as hv1
> +ovs-vsctl -- add-port br-int hv1-vif1 \
> +    -- set interface hv1-vif1 external-ids:iface-id=lsp1 \
> +    -- add-port br-int hv1-vif2 \
> +    -- set interface hv1-vif2 external-ids:iface-id=lsp2
> +
> +ovn-nbctl ls-add ls1 \
> +    -- lsp-add ls1 lsp1 \
> +    -- lsp-add ls1 lsp2 \
> +    -- pg-add pg1 lsp1 lsp2 \
> +    -- create Address_Set name=as1 addresses=\"10.0.0.1\",\"10.0.0.2\"
> +check ovn-nbctl --wait=hv sync
> +wait_for_ports_up lsp1 lsp2
> +
> +get_cache_count () {
> +    local cache_name=$1
> +    as hv1 ovn-appctl -t ovn-controller lflow-cache/show-stats | grep ${cache_name} | awk '{ print $3 }'
> +}
> +
> +AS_BOX([Check matches caching])
> +conj_id_cnt=$(get_cache_count cache-conj-id)
> +expr_cnt=$(get_cache_count cache-expr)
> +matches_cnt=$(get_cache_count cache-matches)
> +
> +check ovn-nbctl acl-add ls1 from-lport 1 '1' drop
> +check ovn-nbctl --wait=hv sync
> +
> +AT_CHECK([test "$conj_id_cnt" = "$(get_cache_count cache-conj-id)"], [0], [])
> +AT_CHECK([test "$expr_cnt" = "$(get_cache_count cache-expr)"], [0], [])
> +AT_CHECK([test "$(($matches_cnt + 1))" = "$(get_cache_count cache-matches)"], [0], [])
> +
> +AS_BOX([Check expr caching for is_chassis_resident() matches])
> +conj_id_cnt=$(get_cache_count cache-conj-id)
> +expr_cnt=$(get_cache_count cache-expr)
> +matches_cnt=$(get_cache_count cache-matches)
> +
> +check ovn-nbctl acl-add ls1 from-lport 1 'is_chassis_resident("lsp1")' drop
> +check ovn-nbctl --wait=hv sync
> +
> +AT_CHECK([test "$conj_id_cnt" = "$(get_cache_count cache-conj-id)"], [0], [])
> +AT_CHECK([test "$(($expr_cnt + 1))" = "$(get_cache_count cache-expr)"], [0], [])
> +AT_CHECK([test "$matches_cnt" = "$(get_cache_count cache-matches)"], [0], [])
> +
> +AS_BOX([Check conj-id caching for conjunctive port group/address set matches])
> +conj_id_cnt=$(get_cache_count cache-conj-id)
> +expr_cnt=$(get_cache_count cache-expr)
> +matches_cnt=$(get_cache_count cache-matches)
> +
> +check ovn-nbctl acl-add ls1 from-lport 1 'inport == @pg1 && outport == @pg1 && is_chassis_resident("lsp1")' drop
> +check ovn-nbctl acl-add ls1 from-lport 1 'ip4.src == $as1 && ip4.dst == $as1 && is_chassis_resident("lsp1")' drop
> +check ovn-nbctl --wait=hv sync
> +
> +AT_CHECK([test "$(($conj_id_cnt + 2))" = "$(get_cache_count cache-conj-id)"], [0], [])
> +AT_CHECK([test "$expr_cnt" = "$(get_cache_count cache-expr)"], [0], [])
> +AT_CHECK([test "$matches_cnt" = "$(get_cache_count cache-matches)"], [0], [])
> +
> +OVN_CLEANUP([hv1])
> +AT_CLEANUP
> +
>  AT_SETUP([ovn -- Delete Port_Binding and OVS port Incremental Processing])
>  ovn_start
>
> diff --git a/tests/test-utils.c b/tests/test-utils.c
> new file mode 100644
> index 0000000..6a3b198
> --- /dev/null
> +++ b/tests/test-utils.c
> @@ -0,0 +1,49 @@
> +/* Copyright (c) 2021, 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 <config.h>
> +
> +#include "test-utils.h"
> +
> +#include "util.h"
> +
> +bool
> +test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index,
> +                     const char *descr, unsigned int *result)
> +{
> +    if (index >= ctx->argc) {
> +        fprintf(stderr, "Missing %s argument\n", descr);
> +        return false;
> +    }
> +
> +    const char *arg = ctx->argv[index];
> +    if (!str_to_uint(arg, 10, result)) {
> +        fprintf(stderr, "Invalid %s: %s\n", descr, arg);
> +        return false;
> +    }
> +    return true;
> +}
> +
> +const char *
> +test_read_value(struct ovs_cmdl_context *ctx, unsigned int index,
> +                const char *descr)
> +{
> +    if (index >= ctx->argc) {
> +        fprintf(stderr, "Missing %s argument\n", descr);
> +        return NULL;
> +    }
> +
> +    return ctx->argv[index];
> +}
> diff --git a/tests/test-utils.h b/tests/test-utils.h
> new file mode 100644
> index 0000000..721032f
> --- /dev/null
> +++ b/tests/test-utils.h
> @@ -0,0 +1,26 @@
> +/* Copyright (c) 2021, 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 TEST_UTILS_H
> +#define TEST_UTILS_H 1
> +
> +#include "ovstest.h"
> +
> +bool test_read_uint_value(struct ovs_cmdl_context *ctx, unsigned int index,
> +                          const char *descr, unsigned int *result);
> +const char *test_read_value(struct ovs_cmdl_context *ctx, unsigned int index,
> +                            const char *descr);
> +
> +#endif /* tests/test-utils.h */
> diff --git a/tests/testsuite.at b/tests/testsuite.at
> index 6253d11..35908ad 100644
> --- a/tests/testsuite.at
> +++ b/tests/testsuite.at
> @@ -27,6 +27,7 @@ m4_include([tests/ovn.at])
>  m4_include([tests/ovn-performance.at])
>  m4_include([tests/ovn-northd.at])
>  m4_include([tests/ovn-nbctl.at])
> +m4_include([tests/ovn-lflow-cache.at])
>  m4_include([tests/ovn-ofctrl-seqno.at])
>  m4_include([tests/ovn-sbctl.at])
>  m4_include([tests/ovn-ic-nbctl.at])
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list