diff options
author | Lukasz Rzasik <lukasz.rzasik@gmail.com> | 2016-12-29 15:55:46 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-01-05 08:48:10 -0800 |
commit | 1ab39058cc1fbe9b2ce48e784284fd0383d537c5 (patch) | |
tree | 9ce73e573c744e65074f920111c8f27d01f312fa | |
parent | 84d0ca5d00fe01b29163236d48fa0f9105687149 (diff) | |
download | openvswitch-1ab39058cc1fbe9b2ce48e784284fd0383d537c5.tar.gz |
ovsdb-data: Add support for integer ranges in database commands
Adding / removing a range of integers to a column accepting a set of
integers requires enumarating all of the integers. This patch simplifies
it by introducing 'range' concept to the database commands. Two integers
separated by a hyphen represent an inclusive range.
The patch adds positive and negative tests for the new syntax.
The patch was tested by 'make check'. Covarage was tested by
'make check-lcov'.
Signed-off-by: Lukasz Rzasik <lukasz.rzasik@gmail.com>
Suggested-by: <my_ovs_discuss@yahoo.com>
Suggested-by: Ben Pfaff <blp@ovn.org>
Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r-- | AUTHORS.rst | 1 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | lib/db-ctl-base.c | 10 | ||||
-rw-r--r-- | lib/db-ctl-base.man | 6 | ||||
-rw-r--r-- | lib/ovsdb-data.c | 198 | ||||
-rw-r--r-- | lib/ovsdb-data.h | 12 | ||||
-rw-r--r-- | lib/util.c | 32 | ||||
-rw-r--r-- | lib/util.h | 2 | ||||
-rw-r--r-- | tests/ovs-vsctl.at | 2 | ||||
-rw-r--r-- | tests/ovsdb-data.at | 69 | ||||
-rw-r--r-- | tests/test-ovsdb.c | 16 |
11 files changed, 284 insertions, 67 deletions
diff --git a/AUTHORS.rst b/AUTHORS.rst index 1efb33218..b7f5943e5 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -190,6 +190,7 @@ Luca Giraudo lgiraudo@nicira.com Lucian Petrut lpetrut@cloudbasesolutions.com Luigi Rizzo rizzo@iet.unipi.it Luis E. P. l31g@hotmail.com +Lukasz Rzasik lukasz.rzasik@gmail.com Madhu Challa challa@noironetworks.com Mario Cabrera mario.cabrera@hpe.com Mark D. Gray mark.d.gray@intel.com @@ -59,6 +59,9 @@ Post-v2.6.0 * Ports now have a "protected" flag. Protected ports can not forward frames to other protected ports. Unprotected ports can receive and forward frames to protected and other unprotected ports. + - ovs-vsctl, ovn-nbctl, ovn-sbctl, vtep-ctl: + * Database commands now accept integer ranges, e.g. "set port + eth0 trunks=1-10" to enable trunking VLANs 1 to 10. v2.6.0 - 27 Sep 2016 --------------------- diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c index 02eb328e2..e32e94541 100644 --- a/lib/db-ctl-base.c +++ b/lib/db-ctl-base.c @@ -677,7 +677,7 @@ is_condition_satisfied(const struct ctl_table_class *table, column->name); } - die_if_error(ovsdb_atom_from_string(&want_key, &column->type.key, + die_if_error(ovsdb_atom_from_string(&want_key, NULL, &column->type.key, key_string, symtab)); type.key = type.value; @@ -823,7 +823,7 @@ cmd_get(struct ctl_context *ctx) column->name); } - die_if_error(ovsdb_atom_from_string(&key, + die_if_error(ovsdb_atom_from_string(&key, NULL, &column->type.key, key_string, ctx->symtab)); @@ -1118,13 +1118,13 @@ set_column(const struct ctl_table_class *table, column->name); } - die_if_error(ovsdb_atom_from_string(&key, &column->type.key, + die_if_error(ovsdb_atom_from_string(&key, NULL, &column->type.key, key_string, symtab)); - die_if_error(ovsdb_atom_from_string(&value, &column->type.value, + die_if_error(ovsdb_atom_from_string(&value, NULL, &column->type.value, value_string, symtab)); ovsdb_datum_init_empty(&datum); - ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type); + ovsdb_datum_add_unsafe(&datum, &key, &value, &column->type, NULL); ovsdb_atom_destroy(&key, column->type.key.type); ovsdb_atom_destroy(&value, column->type.value.type); diff --git a/lib/db-ctl-base.man b/lib/db-ctl-base.man index 7b30501c5..88529b5fe 100644 --- a/lib/db-ctl-base.man +++ b/lib/db-ctl-base.man @@ -29,7 +29,11 @@ single comma. When multiple values are present, duplicates are not allowed, and order is not important. Conversely, some database columns can have an empty set of values, represented as \fB[]\fR, and square brackets may optionally enclose other non-empty sets or single -values as well. +values as well. For a column accepting a set of integers, database commands +accept a range. A range is represented by two integers separated by +\fB-\fR. A range is inclusive. A range has a maximum size of 4096 +elements. If more elements are needed, they can be specified in seperate +ranges. .PP A few database columns are ``maps'' of key-value pairs, where the key and the value are each some fixed database type. These are specified diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c index 0dda73a7e..840e18fa1 100644 --- a/lib/ovsdb-data.c +++ b/lib/ovsdb-data.c @@ -305,6 +305,25 @@ ovsdb_symbol_referenced(struct ovsdb_symbol *symbol, } } +static union ovsdb_atom * +alloc_default_atoms(enum ovsdb_atomic_type type, size_t n) +{ + if (type != OVSDB_TYPE_VOID && n) { + union ovsdb_atom *atoms; + unsigned int i; + + atoms = xmalloc(n * sizeof *atoms); + for (i = 0; i < n; i++) { + ovsdb_atom_init_default(&atoms[i], type); + } + return atoms; + } else { + /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is + * treated as xmalloc(1). */ + return NULL; + } +} + static struct ovsdb_error * OVS_WARN_UNUSED_RESULT ovsdb_atom_parse_uuid(struct uuid *uuid, const struct json *json, struct ovsdb_symbol_table *symtab, @@ -468,6 +487,7 @@ ovsdb_atom_to_json(const union ovsdb_atom *atom, enum ovsdb_atomic_type type) static char * ovsdb_atom_from_string__(union ovsdb_atom *atom, + union ovsdb_atom **range_end_atom, const struct ovsdb_base_type *base, const char *s, struct ovsdb_symbol_table *symtab) { @@ -478,9 +498,20 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, OVS_NOT_REACHED(); case OVSDB_TYPE_INTEGER: { - long long int integer; - if (!str_to_llong(s, 10, &integer)) { - return xasprintf("\"%s\" is not a valid integer", s); + long long int integer, end; + if (range_end_atom + && str_to_llong_range(s, 10, &integer, &end)) { + if (end < integer) { + return xasprintf("\"%s\" is not a valid range. " + "Range end cannot be before start.", s); + } + *range_end_atom = alloc_default_atoms(type, 1); + if (!(*range_end_atom)) { + return xasprintf("\"%s\" is not a valid range", s); + } + (*range_end_atom)->integer = end; + } else if (!str_to_llong(s, 10, &integer)) { + return xasprintf("\"%s\" is not a valid integer or range", s); } atom->integer = integer; } @@ -549,10 +580,13 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, return NULL; } -/* Initializes 'atom' to a value of type 'base' parsed from 's', which takes - * one of the following forms: +/* Initializes 'atom' and optionally 'range_end_atom' to a value of type 'base' + * parsed from 's', which takes one of the following forms: * - * - OVSDB_TYPE_INTEGER: A decimal integer optionally preceded by a sign. + * - OVSDB_TYPE_INTEGER: A decimal integer optionally preceded by a sign + * or two decimal integers optionally preceded by a sign and separated + * by a hyphen, representing inclusive range of integers + * ['atom', 'range_end_atom']. * * - OVSDB_TYPE_REAL: A floating-point number in the format accepted by * strtod(). @@ -574,23 +608,62 @@ ovsdb_atom_from_string__(union ovsdb_atom *atom, * Returns a null pointer if successful, otherwise an error message describing * the problem. On failure, the contents of 'atom' are indeterminate. The * caller is responsible for freeing the atom or the error. + * + * Does not attempt to parse range if 'range_end_atom' is a null pointer. + * Dynamically allocates ovdsb_atom and stores its address in '*range_end_atom' + * if successfully parses range. Caller is responsible for deallocating + * the memory by calling 'ovsdb_atom_destroy' and then 'free' on the address. + * Does not allocate memory and sets '*range_end_atom' to a null pointer + * if does not parse a range or fails for any reason. */ char * ovsdb_atom_from_string(union ovsdb_atom *atom, + union ovsdb_atom **range_end_atom, const struct ovsdb_base_type *base, const char *s, struct ovsdb_symbol_table *symtab) { struct ovsdb_error *error; char *msg; - msg = ovsdb_atom_from_string__(atom, base, s, symtab); + if (range_end_atom) { + *range_end_atom = NULL; + } + + msg = ovsdb_atom_from_string__(atom, range_end_atom, base, s, symtab); if (msg) { return msg; } error = ovsdb_atom_check_constraints(atom, base); + + if (!error && range_end_atom && *range_end_atom) { + /* Check range constraints */ + int64_t start = atom->integer; + int64_t end = (*range_end_atom)->integer; + if (base->enum_) { + for (int64_t i = start + 1; i <= end; i++) { + union ovsdb_atom ai = { .integer = i }; + error = ovsdb_atom_check_constraints(&ai, base); + if (error) { + break; + } + } + } else { + error = ovsdb_atom_check_constraints(*range_end_atom, base); + } + + if (!error) { + error = ovsdb_atom_range_check_size(start, end); + } + } + if (error) { ovsdb_atom_destroy(atom, base->type); + if (range_end_atom && *range_end_atom) { + ovsdb_atom_destroy(*range_end_atom, base->type); + free(*range_end_atom); + *range_end_atom = NULL; + } msg = ovsdb_error_to_string(error); ovsdb_error_destroy(error); } @@ -811,25 +884,6 @@ ovsdb_atom_check_constraints(const union ovsdb_atom *atom, } } -static union ovsdb_atom * -alloc_default_atoms(enum ovsdb_atomic_type type, size_t n) -{ - if (type != OVSDB_TYPE_VOID && n) { - union ovsdb_atom *atoms; - unsigned int i; - - atoms = xmalloc(n * sizeof *atoms); - for (i = 0; i < n; i++) { - ovsdb_atom_init_default(&atoms[i], type); - } - return atoms; - } else { - /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is - * treated as xmalloc(1). */ - return NULL; - } -} - /* Initializes 'datum' as an empty datum. (An empty datum can be treated as * any type.) */ void @@ -1336,13 +1390,15 @@ skip_spaces(const char *p) static char * parse_atom_token(const char **s, const struct ovsdb_base_type *base, - union ovsdb_atom *atom, struct ovsdb_symbol_table *symtab) + union ovsdb_atom *atom, union ovsdb_atom **range_end_atom, + struct ovsdb_symbol_table *symtab) { char *token, *error; error = ovsdb_token_parse(s, &token); if (!error) { - error = ovsdb_atom_from_string(atom, base, token, symtab); + error = ovsdb_atom_from_string(atom, range_end_atom, + base, token, symtab); free(token); } return error; @@ -1351,37 +1407,50 @@ parse_atom_token(const char **s, const struct ovsdb_base_type *base, static char * parse_key_value(const char **s, const struct ovsdb_type *type, union ovsdb_atom *key, union ovsdb_atom *value, - struct ovsdb_symbol_table *symtab) + struct ovsdb_symbol_table *symtab, + union ovsdb_atom **range_end_key) { const char *start = *s; char *error; - error = parse_atom_token(s, &type->key, key, symtab); + error = parse_atom_token(s, &type->key, key, range_end_key, symtab); + if (!error && type->value.type != OVSDB_TYPE_VOID) { *s = skip_spaces(*s); if (**s == '=') { (*s)++; *s = skip_spaces(*s); - error = parse_atom_token(s, &type->value, value, symtab); + error = parse_atom_token(s, &type->value, value, NULL, symtab); } else { error = xasprintf("%s: syntax error at \"%c\" expecting \"=\"", start, **s); } if (error) { ovsdb_atom_destroy(key, type->key.type); + if (range_end_key && *range_end_key) { + ovsdb_atom_destroy(*range_end_key, type->key.type); + free(*range_end_key); + *range_end_key = NULL; + } } } return error; } static void -free_key_value(const struct ovsdb_type *type, - union ovsdb_atom *key, union ovsdb_atom *value) +free_key_value_range(const struct ovsdb_type *type, + union ovsdb_atom *key, union ovsdb_atom *value, + union ovsdb_atom **range_end_atom) { ovsdb_atom_destroy(key, type->key.type); if (type->value.type != OVSDB_TYPE_VOID) { ovsdb_atom_destroy(value, type->value.type); } + if (range_end_atom && *range_end_atom) { + ovsdb_atom_destroy(*range_end_atom, type->key.type); + free(*range_end_atom); + *range_end_atom = NULL; + } } /* Initializes 'datum' as a datum of the given 'type', parsing its contents @@ -1423,6 +1492,7 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum, while (*p && *p != end_delim) { union ovsdb_atom key, value; + union ovsdb_atom *range_end_key = NULL; if (ovsdb_token_is_delim(*p)) { char *type_str = ovsdb_type_to_english(type); @@ -1433,12 +1503,13 @@ ovsdb_datum_from_string(struct ovsdb_datum *datum, } /* Add to datum. */ - error = parse_key_value(&p, type, &key, &value, symtab); + error = parse_key_value(&p, type, &key, &value, + symtab, &range_end_key); if (error) { goto error; } - ovsdb_datum_add_unsafe(datum, &key, &value, type); - free_key_value(type, &key, &value); + ovsdb_datum_add_unsafe(datum, &key, &value, type, range_end_key); + free_key_value_range(type, &key, &value, &range_end_key); /* Skip optional white space and comma. */ p = skip_spaces(p); @@ -1760,11 +1831,16 @@ ovsdb_datum_remove_unsafe(struct ovsdb_datum *datum, size_t idx, } /* Adds the element with the given 'key' and 'value' to 'datum', which must - * have the specified 'type'. + * have the specified 'type'. Optionally if 'range_end_atom' is not + * a null pointer, adds a set of integers to 'datum' from inclusive + * range ['key', 'range_end_atom']. * * This function always allocates memory, so it is not an efficient way to add * a number of elements to a datum. * + * When adding a range of integers, this function allocates the memory once + * for the whole range. + * * This function does not maintain ovsdb_datum invariants. Use * ovsdb_datum_sort() to check and restore these invariants. (But a datum with * 0 or 1 elements cannot violate the invariants anyhow.) */ @@ -1772,15 +1848,24 @@ void ovsdb_datum_add_unsafe(struct ovsdb_datum *datum, const union ovsdb_atom *key, const union ovsdb_atom *value, - const struct ovsdb_type *type) + const struct ovsdb_type *type, + const union ovsdb_atom *range_end_atom) { - size_t idx = datum->n++; + size_t idx = datum->n; + datum->n += range_end_atom ? + (range_end_atom->integer - key->integer + 1) : 1; datum->keys = xrealloc(datum->keys, datum->n * sizeof *datum->keys); - ovsdb_atom_clone(&datum->keys[idx], key, type->key.type); - if (type->value.type != OVSDB_TYPE_VOID) { - datum->values = xrealloc(datum->values, - datum->n * sizeof *datum->values); - ovsdb_atom_clone(&datum->values[idx], value, type->value.type); + if (range_end_atom && key->integer <= range_end_atom->integer) { + for (int64_t i = key->integer; i <= range_end_atom->integer; i++) { + datum->keys[idx++].integer = i; + } + } else { + ovsdb_atom_clone(&datum->keys[idx], key, type->key.type); + if (type->value.type != OVSDB_TYPE_VOID) { + datum->values = xrealloc(datum->values, + datum->n * sizeof *datum->values); + ovsdb_atom_clone(&datum->values[idx], value, type->value.type); + } } } @@ -1937,29 +2022,31 @@ ovsdb_datum_diff(struct ovsdb_datum *diff, type->key.type); if (c < 0) { ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi], - type); + type, NULL); oi++; } else if (c > 0) { ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni], - type); + type, NULL); ni++; } else { if (type->value.type != OVSDB_TYPE_VOID && ovsdb_atom_compare_3way(&old->values[oi], &new->values[ni], type->value.type)) { ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni], - type); + type, NULL); } oi++; ni++; } } for (; oi < old->n; oi++) { - ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi], type); + ovsdb_datum_add_unsafe(diff, &old->keys[oi], &old->values[oi], + type, NULL); } for (; ni < new->n; ni++) { - ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni], type); + ovsdb_datum_add_unsafe(diff, &new->keys[ni], &new->values[ni], + type, NULL); } } @@ -2051,3 +2138,16 @@ ovsdb_token_is_delim(unsigned char c) { return strchr(":=, []{}!<>", c) != NULL; } + +struct ovsdb_error * +ovsdb_atom_range_check_size(int64_t range_start, int64_t range_end) +{ + if ((uint64_t) range_end - (uint64_t) range_start + >= MAX_OVSDB_ATOM_RANGE_SIZE) { + return ovsdb_error("constraint violation", + "Range \"%"PRId64"-%"PRId64"\" is too big. " + "Maximum allowed size is %d.", + range_start, range_end, MAX_OVSDB_ATOM_RANGE_SIZE); + } + return NULL; +} diff --git a/lib/ovsdb-data.h b/lib/ovsdb-data.h index 9fce380cf..1bf90d59c 100644 --- a/lib/ovsdb-data.h +++ b/lib/ovsdb-data.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2015, 2016 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2012, 2015, 2016, 2017 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ #include "ovsdb-types.h" #include "openvswitch/shash.h" +#define MAX_OVSDB_ATOM_RANGE_SIZE 4096 + struct ds; struct ovsdb_symbol_table; struct smap; @@ -89,7 +91,7 @@ struct ovsdb_error *ovsdb_atom_from_json(union ovsdb_atom *, struct json *ovsdb_atom_to_json(const union ovsdb_atom *, enum ovsdb_atomic_type); -char *ovsdb_atom_from_string(union ovsdb_atom *, +char *ovsdb_atom_from_string(union ovsdb_atom *, union ovsdb_atom **, const struct ovsdb_base_type *, const char *, struct ovsdb_symbol_table *) OVS_WARN_UNUSED_RESULT; @@ -235,7 +237,8 @@ void ovsdb_datum_remove_unsafe(struct ovsdb_datum *, size_t idx, void ovsdb_datum_add_unsafe(struct ovsdb_datum *, const union ovsdb_atom *key, const union ovsdb_atom *value, - const struct ovsdb_type *); + const struct ovsdb_type *, + const union ovsdb_atom *range_end_atom); /* Type checking. */ static inline bool @@ -276,4 +279,7 @@ struct ovsdb_symbol *ovsdb_symbol_table_insert(struct ovsdb_symbol_table *, char *ovsdb_token_parse(const char **, char **outp) OVS_WARN_UNUSED_RESULT; bool ovsdb_token_is_delim(unsigned char); +struct ovsdb_error *ovsdb_atom_range_check_size(int64_t range_start, + int64_t range_end); + #endif /* ovsdb-data.h */ diff --git a/lib/util.c b/lib/util.c index 4208aa81d..1c06ce0d4 100644 --- a/lib/util.c +++ b/lib/util.c @@ -640,11 +640,22 @@ str_to_long(const char *s, int base, long *li) bool str_to_llong(const char *s, int base, long long *x) { - int save_errno = errno; char *tail; + bool ok = str_to_llong_with_tail(s, &tail, base, x); + if (*tail != '\0') { + *x = 0; + return false; + } + return ok; +} + +bool +str_to_llong_with_tail(const char *s, char **tail, int base, long long *x) +{ + int save_errno = errno; errno = 0; - *x = strtoll(s, &tail, base); - if (errno == EINVAL || errno == ERANGE || tail == s || *tail != '\0') { + *x = strtoll(s, tail, base); + if (errno == EINVAL || errno == ERANGE || *tail == s) { errno = save_errno; *x = 0; return false; @@ -668,6 +679,21 @@ str_to_uint(const char *s, int base, unsigned int *u) } } +bool +str_to_llong_range(const char *s, int base, long long *begin, + long long *end) +{ + char *tail; + if (str_to_llong_with_tail(s, &tail, base, begin) + && *tail == '-' + && str_to_llong(tail + 1, base, end)) { + return true; + } + *begin = 0; + *end = 0; + return false; +} + /* Converts floating-point string 's' into a double. If successful, stores * the double in '*d' and returns true; on failure, stores 0 in '*d' and * returns false. diff --git a/lib/util.h b/lib/util.h index 5ad25cbb1..aa38122ee 100644 --- a/lib/util.h +++ b/lib/util.h @@ -153,7 +153,9 @@ void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii); bool str_to_int(const char *, int base, int *); bool str_to_long(const char *, int base, long *); bool str_to_llong(const char *, int base, long long *); +bool str_to_llong_with_tail(const char *, char **, int base, long long *); bool str_to_uint(const char *, int base, unsigned int *); +bool str_to_llong_range(const char *, int base, long long *, long long *); bool ovs_scan(const char *s, const char *format, ...) OVS_SCANF_FORMAT(2, 3); bool ovs_scan_len(const char *s, int *n, const char *format, ...); diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at index 87ee96715..94b431f92 100644 --- a/tests/ovs-vsctl.at +++ b/tests/ovs-vsctl.at @@ -860,7 +860,7 @@ AT_CHECK([RUN_OVS_VSCTL([remove bridge br0 name br1])], [1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge ], [OVS_VSCTL_CLEANUP]) AT_CHECK([RUN_OVS_VSCTL([remove bridge br1 flood-vlans true])], - [1], [], [ovs-vsctl: "true" is not a valid integer + [1], [], [ovs-vsctl: "true" is not a valid integer or range ], [OVS_VSCTL_CLEANUP]) AT_CHECK([RUN_OVS_VSCTL([clear bridge br1 name])], [1], [], [ovs-vsctl: cannot modify read-only column name in table Bridge diff --git a/tests/ovsdb-data.at b/tests/ovsdb-data.at index a8c092f39..8c40bcfbf 100644 --- a/tests/ovsdb-data.at +++ b/tests/ovsdb-data.at @@ -92,12 +92,26 @@ OVSDB_CHECK_POSITIVE([integer atom from string], '-1' \ '+1000' \ '9223372036854775807' \ - '-9223372036854775808' ]], + '-9223372036854775808' \ + '0-1000' \ + '-1000-+1000' \ + '-1000--10' \ + '+10-+1000' \ + '1-4096' \ + '-4096--1' \ + '-2000-2095']], [0 -1 1000 9223372036854775807 --9223372036854775808]) +-9223372036854775808 +0-1000 +-1000-1000 +-1000--10 +10-1000 +1-4096 +-4096--1 +-2000-2095]) OVSDB_CHECK_POSITIVE_CPY([real atom from JSON], [[parse-atoms '["real"]' \ @@ -258,6 +272,30 @@ OVSDB_CHECK_NEGATIVE([real not acceptable integer string atom], [[parse-atom-strings '["integer"]' '0.5' ]], ["0.5" is not a valid integer]) +OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom positive and negative], + [[parse-atom-strings -- '["integer"]' '10--10' ]], + ["10--10" is not a valid range. Range end cannot be before start.]) + +OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom negative], + [[parse-atom-strings -- '["integer"]' '-10--100' ]], + ["-10--100" is not a valid range. Range end cannot be before start.]) + +OVSDB_CHECK_NEGATIVE([inverted range is not acceptable integer string atom positive], + [[parse-atom-strings -- '["integer"]' '100-10' ]], + ["100-10" is not a valid range. Range end cannot be before start.]) + +OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom positive and negative], + [[parse-atom-strings -- '["integer"]' '-2000-2096' ]], + [Range "-2000-2096" is too big.]) + +OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom negative], + [[parse-atom-strings -- '["integer"]' '-4097--1' ]], + [Range "-4097--1" is too big.]) + +OVSDB_CHECK_NEGATIVE([too big range is not acceptable integer string atom positive], + [[parse-atom-strings -- '["integer"]' '1-4097' ]], + [Range "1-4097" is too big.]) + OVSDB_CHECK_POSITIVE_CPY([string "true" not acceptable boolean JSON atom], [[parse-atoms '["boolean"]' '["true"]' ]], [syntax ""true"": syntax error: expected boolean]) @@ -323,6 +361,27 @@ constraint violation: 9 is not one of the allowed values ([1, 6, 8, 10]) 10 constraint violation: 11 is not one of the allowed values ([1, 6, 8, 10])]]) +OVSDB_CHECK_POSITIVE([integer atom enum from string], + [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10, 20, 21, 22, 23, 24, 25]]}]' \ + '1' \ + '6' \ + '8' \ + '10' \ + '20-25']], + [[1 +6 +8 +10 +20-25]]) + +OVSDB_CHECK_NEGATIVE([integer not in enum set from string], + [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10]]}]' '0' ]], + [[constraint violation: 0 is not one of the allowed values ([1, 6, 8, 10])]]) + +OVSDB_CHECK_NEGATIVE([integer range not in enum set from string], + [[parse-atom-strings '[{"type": "integer", "enum": ["set", [1, 6, 8, 10]]}]' '8-10' ]], + [[constraint violation: 9 is not one of the allowed values ([1, 6, 8, 10])]]) + OVSDB_CHECK_POSITIVE_CPY([real atom enum], [[parse-atoms '[{"type": "real", "enum": ["set", [-1.5, 1.5]]}]' \ '[-2]' \ @@ -590,12 +649,16 @@ OVSDB_CHECK_POSITIVE([string set of 0 or more integers], '0, 1, 2' \ '[0, 1,2, 3, 4, 5]' \ '0, 1,2, 3,4, 5, 6, 7, 8' \ - '[0, 1, 2, 3, 4,5, 6,7, 8, 9, 10]']], + '[0, 1, 2, 3, 4,5, 6,7, 8, 9, 10]' \ + '0-8' \ + '[0-10']]], [[[0] [0, 1] [0, 1, 2] [0, 1, 2, 3, 4, 5] [0, 1, 2, 3, 4, 5, 6, 7, 8] +[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +[0, 1, 2, 3, 4, 5, 6, 7, 8] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]) OVSDB_CHECK_POSITIVE_CPY([JSON set of 1 to 3 uuids], diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c index 968c1de22..e297f9f9d 100644 --- a/tests/test-ovsdb.c +++ b/tests/test-ovsdb.c @@ -554,17 +554,29 @@ do_parse_atom_strings(struct ovs_cmdl_context *ctx) json_destroy(json); for (i = 2; i < ctx->argc; i++) { - union ovsdb_atom atom; + union ovsdb_atom atom, *range_end_atom = NULL; struct ds out; - die_if_error(ovsdb_atom_from_string(&atom, &base, ctx->argv[i], NULL)); + die_if_error(ovsdb_atom_from_string(&atom, &range_end_atom, &base, + ctx->argv[i], NULL)); ds_init(&out); ovsdb_atom_to_string(&atom, base.type, &out); + if (range_end_atom) { + struct ds range_end_ds; + ds_init(&range_end_ds); + ovsdb_atom_to_string(range_end_atom, base.type, &range_end_ds); + ds_put_char(&out, '-'); + ds_put_cstr(&out, ds_cstr(&range_end_ds));; + ds_destroy(&range_end_ds); + } puts(ds_cstr(&out)); ds_destroy(&out); ovsdb_atom_destroy(&atom, base.type); + if (range_end_atom) { + ovsdb_atom_destroy(range_end_atom, base.type); + } } ovsdb_base_type_destroy(&base); } |