2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00
ovs/tests/test-util.c
Ilya Maximets 1876b2796f tests: Fix build failure with Clang 18 due to -Wformat-truncation.
Cirrus CI is broken on FreeBSD 13.3 due to clang version update.
It now complains about snprintf truncation the same way GCC does:

  tests/test-util.c:1129:16: error: 'snprintf' will always be truncated;
          specified size is 5, but format string expands to at least 6
          [-Werror,-Wformat-truncation]

  1129 |     ovs_assert(snprintf(s, 5, "abcde") == 5);
       |                ^

Clang 17 on FreeBSD 14.0 works fine, but new Clang 18.1.4 on 13.3
fails to build.

Fix that by disabling Clang diagnostic the same way as we do for GCC.

Unfortunately, the pragma's are compiler-specific, so cannot be
combined, AFAIK.

Acked-by: Ales Musil <amusil@redhat.com>
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2024-04-30 17:23:00 +02:00

1277 lines
39 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2019 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.
*/
#include <config.h>
#undef NDEBUG
#include "util.h"
#include <assert.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "byte-order.h"
#include "command-line.h"
#include "ovstest.h"
#include "random.h"
#include "sat-math.h"
#include "openvswitch/vlog.h"
static void
check_log_2_floor(uint32_t x, int n)
{
if (log_2_floor(x) != n) {
fprintf(stderr, "log_2_floor(%"PRIu32") is %d but should be %d\n",
x, log_2_floor(x), n);
abort();
}
}
static void
test_log_2_floor(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
for (uint32_t n = 0; n < 32; n++) {
/* Check minimum x such that f(x) == n. */
check_log_2_floor(UINT32_C(1) << n, n);
/* Check maximum x such that f(x) == n. */
check_log_2_floor((UINT32_C(1) << n) | ((UINT32_C(1) << n) - 1), n);
/* Check a random value in the middle. */
check_log_2_floor((random_uint32() & ((UINT32_C(1) << n) - 1))
| (UINT32_C(1) << n), n);
}
/* log_2_floor(0) is undefined, so don't check it. */
}
static void
check_ctz32(uint32_t x, int n)
{
if (ctz32(x) != n) {
fprintf(stderr, "ctz32(%"PRIu32") is %d but should be %d\n",
x, ctz32(x), n);
abort();
}
}
static void
check_ctz64(uint64_t x, int n)
{
if (ctz64(x) != n) {
fprintf(stderr, "ctz64(%"PRIu64") is %d but should be %d\n",
x, ctz64(x), n);
abort();
}
}
static void
test_ctz(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int n;
for (n = 0; n < 32; n++) {
/* Check minimum x such that f(x) == n. */
check_ctz32(UINT32_C(1) << n, n);
/* Check maximum x such that f(x) == n. */
check_ctz32(UINT32_MAX << n, n);
/* Check a random value in the middle. */
check_ctz32((random_uint32() | 1) << n, n);
}
for (n = 0; n < 64; n++) {
/* Check minimum x such that f(x) == n. */
check_ctz64(UINT64_C(1) << n, n);
/* Check maximum x such that f(x) == n. */
check_ctz64(UINT64_MAX << n, n);
/* Check a random value in the middle. */
check_ctz64((random_uint64() | UINT64_C(1)) << n, n);
}
/* Check ctz(0). */
check_ctz32(0, 32);
check_ctz64(0, 64);
}
static void
check_clz32(uint32_t x, int n)
{
if (clz32(x) != n) {
fprintf(stderr, "clz32(%"PRIu32") is %d but should be %d\n",
x, clz32(x), n);
abort();
}
}
static void
check_clz64(uint64_t x, int n)
{
if (clz64(x) != n) {
fprintf(stderr, "clz64(%"PRIu64") is %d but should be %d\n",
x, clz64(x), n);
abort();
}
}
static void
test_clz(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int n;
for (n = 0; n < 32; n++) {
/* Check minimum x such that f(x) == n. */
check_clz32((1u << 31) >> n, n);
/* Check maximum x such that f(x) == n. */
check_clz32(UINT32_MAX >> n, n);
/* Check a random value in the middle. */
check_clz32((random_uint32() | 1u << 31) >> n, n);
}
for (n = 0; n < 64; n++) {
/* Check minimum x such that f(x) == n. */
check_clz64((UINT64_C(1) << 63) >> n, n);
/* Check maximum x such that f(x) == n. */
check_clz64(UINT64_MAX >> n, n);
/* Check a random value in the middle. */
check_clz64((random_uint64() | UINT64_C(1) << 63) >> n, n);
}
/* Check clz(0). */
check_clz32(0, 32);
check_clz64(0, 64);
}
/* Returns a random number in the range 'min'...'max' inclusive. */
static uint32_t
random_in_range(uint32_t min, uint32_t max)
{
return min == max ? min : min + random_range(max - min + 1);
}
static void
check_rup2(uint32_t x, int n)
{
uint32_t rup2 = ROUND_UP_POW2(x);
if (rup2 != n) {
fprintf(stderr, "ROUND_UP_POW2(%#"PRIx32") is %#"PRIx32" "
"but should be %#"PRIx32"\n", x, rup2, n);
abort();
}
}
static void
test_round_up_pow2(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int n;
for (n = 0; n < 32; n++) {
/* Min, max value for which ROUND_UP_POW2 should yield (1 << n). */
uint32_t min = ((1u << n) >> 1) + 1;
uint32_t max = 1u << n;
check_rup2(min, 1u << n);
check_rup2(max, 1u << n);
check_rup2(random_in_range(min, max), 1u << n);
}
check_rup2(0, 0);
}
static void
check_rdp2(uint32_t x, int n)
{
uint32_t rdp2 = ROUND_DOWN_POW2(x);
if (rdp2 != n) {
fprintf(stderr, "ROUND_DOWN_POW2(%#"PRIx32") is %#"PRIx32" "
"but should be %#"PRIx32"\n", x, rdp2, n);
abort();
}
}
static void
test_round_down_pow2(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int n;
for (n = 0; n < 32; n++) {
/* Min, max value for which ROUND_DOWN_POW2 should yield (1 << n). */
uint32_t min = 1u << n;
uint32_t max = ((1u << n) << 1) - 1;
check_rdp2(min, 1u << n);
check_rdp2(max, 1u << n);
check_rdp2(random_in_range(min, max), 1u << n);
}
check_rdp2(0, 0);
}
static void
shuffle(uint64_t *p, size_t n)
{
for (; n > 1; n--, p++) {
uint64_t *q = &p[random_range(n)];
uint64_t tmp = *p;
*p = *q;
*q = tmp;
}
}
static void
check_count_1bits(uint64_t x, int n)
{
if (count_1bits(x) != n) {
fprintf(stderr, "count_1bits(%#"PRIx64") is %d but should be %d\n",
x, count_1bits(x), n);
abort();
}
}
static void
test_count_1bits(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
uint64_t bits[64];
int i;
for (i = 0; i < ARRAY_SIZE(bits); i++) {
bits[i] = UINT64_C(1) << i;
}
check_count_1bits(0, 0);
for (i = 0; i < 1000; i++) {
uint64_t x = 0;
int j;
shuffle(bits, ARRAY_SIZE(bits));
for (j = 0; j < 64; j++) {
x |= bits[j];
check_count_1bits(x, j + 1);
}
assert(x == UINT64_MAX);
shuffle(bits, ARRAY_SIZE(bits));
for (j = 63; j >= 0; j--) {
x &= ~bits[j];
check_count_1bits(x, j);
}
assert(x == 0);
}
}
/* Returns the sum of the squares of the first 'n' positive integers. */
static unsigned int
sum_of_squares(int n)
{
return n * (n + 1) * (2 * n + 1) / 6;
}
static void
test_bitwise_copy(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
unsigned int n_loops;
int src_ofs;
int dst_ofs;
int n_bits;
n_loops = 0;
for (n_bits = 0; n_bits <= 64; n_bits++) {
for (src_ofs = 0; src_ofs < 64 - n_bits; src_ofs++) {
for (dst_ofs = 0; dst_ofs < 64 - n_bits; dst_ofs++) {
ovs_be64 src = htonll(random_uint64());
ovs_be64 dst = htonll(random_uint64());
ovs_be64 orig_dst = dst;
ovs_be64 expect;
if (n_bits == 64) {
expect = dst;
} else {
uint64_t mask = (UINT64_C(1) << n_bits) - 1;
expect = orig_dst & ~htonll(mask << dst_ofs);
expect |= htonll(((ntohll(src) >> src_ofs) & mask)
<< dst_ofs);
}
bitwise_copy(&src, sizeof src, src_ofs,
&dst, sizeof dst, dst_ofs,
n_bits);
if (expect != dst) {
fprintf(stderr,"copy_bits(0x%016"PRIx64",8,%d, "
"0x%016"PRIx64",8,%d, %d) yielded 0x%016"PRIx64" "
"instead of the expected 0x%016"PRIx64"\n",
ntohll(src), src_ofs,
ntohll(orig_dst), dst_ofs,
n_bits,
ntohll(dst), ntohll(expect));
abort();
}
n_loops++;
}
}
}
if (n_loops != sum_of_squares(64)) {
abort();
}
}
static void
test_bitwise_zero(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
unsigned int n_loops;
int dst_ofs;
int n_bits;
n_loops = 0;
for (n_bits = 0; n_bits <= 64; n_bits++) {
for (dst_ofs = 0; dst_ofs < 64 - n_bits; dst_ofs++) {
ovs_be64 dst = htonll(random_uint64());
ovs_be64 orig_dst = dst;
ovs_be64 expect;
if (n_bits == 64) {
expect = htonll(0);
} else {
uint64_t mask = (UINT64_C(1) << n_bits) - 1;
expect = orig_dst & ~htonll(mask << dst_ofs);
}
bitwise_zero(&dst, sizeof dst, dst_ofs, n_bits);
if (expect != dst) {
fprintf(stderr,"bitwise_zero(0x%016"PRIx64",8,%d, %d) "
"yielded 0x%016"PRIx64" "
"instead of the expected 0x%016"PRIx64"\n",
ntohll(orig_dst), dst_ofs,
n_bits,
ntohll(dst), ntohll(expect));
abort();
}
n_loops++;
}
}
if (n_loops != 64 * (64 + 1) / 2) {
abort();
}
}
static void
test_bitwise_one(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
unsigned int n_loops;
int dst_ofs;
int n_bits;
n_loops = 0;
for (n_bits = 0; n_bits <= 64; n_bits++) {
for (dst_ofs = 0; dst_ofs < 64 - n_bits; dst_ofs++) {
ovs_be64 dst = htonll(random_uint64());
ovs_be64 orig_dst = dst;
ovs_be64 expect;
if (n_bits == 64) {
expect = OVS_BE64_MAX;
} else {
uint64_t mask = (UINT64_C(1) << n_bits) - 1;
expect = orig_dst | htonll(mask << dst_ofs);
}
bitwise_one(&dst, sizeof dst, dst_ofs, n_bits);
if (expect != dst) {
fprintf(stderr,"bitwise_one(0x%016"PRIx64",8,%d, %d) "
"yielded 0x%016"PRIx64" "
"instead of the expected 0x%016"PRIx64"\n",
ntohll(orig_dst), dst_ofs,
n_bits,
ntohll(dst), ntohll(expect));
abort();
}
n_loops++;
}
}
if (n_loops != 64 * (64 + 1) / 2) {
abort();
}
}
static void
test_bitwise_is_all_zeros(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
int n_loops;
for (n_loops = 0; n_loops < 100; n_loops++) {
ovs_be64 x = htonll(0);
int i;
for (i = 0; i < 64; i++) {
ovs_be64 bit;
int ofs, n;
/* Change a random 0-bit into a 1-bit. */
do {
bit = htonll(UINT64_C(1) << (random_range(64)));
} while (x & bit);
x |= bit;
for (ofs = 0; ofs < 64; ofs++) {
for (n = 0; n <= 64 - ofs; n++) {
bool expect;
bool answer;
expect = (n == 64
? x == 0
: !(x & htonll(((UINT64_C(1) << n) - 1)
<< ofs)));
answer = bitwise_is_all_zeros(&x, sizeof x, ofs, n);
if (expect != answer) {
fprintf(stderr,
"bitwise_is_all_zeros(0x%016"PRIx64",8,%d,%d "
"returned %s instead of %s\n",
ntohll(x), ofs, n,
answer ? "true" : "false",
expect ? "true" : "false");
abort();
}
}
}
}
}
}
static int
trivial_bitwise_rscan(const void *p, unsigned int len, bool target,
int start, int end)
{
int ofs;
for (ofs = start; ofs > end; ofs--) {
if (bitwise_get_bit(p, len, ofs) == target) {
break;
}
}
return ofs;
}
static void
test_bitwise_rscan(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
/* All 1s */
uint8_t s1[3] = {0xff, 0xff, 0xff};
/* Target is the first bit */
ovs_assert(23 == bitwise_rscan(s1, 3, 1, 23, -1));
/* Target is not found, return -1 */
ovs_assert(-1 == bitwise_rscan(s1, 3, 0, 23, -1));
/* Target is not found and end != -1, return end */
ovs_assert(20 == bitwise_rscan(s1, 3, 0, 23, 20));
/* bit 20 - 23 are 0s */
uint8_t s2[3] = {0x0f, 0xff, 0xff};
/* Target is in the first byte but not the first bit */
ovs_assert(19 == bitwise_rscan(s2, 3, 1, 23, -1));
/* Target exists before the start postion */
ovs_assert(18 == bitwise_rscan(s2, 3, 1, 18, -1));
/* Target exists after the end postion, return end */
ovs_assert(20 == bitwise_rscan(s2, 3, 1, 23, 20));
/* Target is at the end postion, return end */
ovs_assert(19 == bitwise_rscan(s2, 3, 1, 23, 19));
/* start == end, target at start */
ovs_assert(19 == bitwise_rscan(s2, 3, 1, 19, 19));
/* start == end, target not at start */
ovs_assert(20 == bitwise_rscan(s2, 3, 1, 20, 20));
/* Target is 0 ... */
ovs_assert(22 == bitwise_rscan(s2, 3, 0, 22, -1));
/* bit 4 - 23 are 0s */
uint8_t s3[3] = {0x00, 0x00, 0x0f};
/* Target is in the end byte */
ovs_assert(3 == bitwise_rscan(s3, 3, 1, 16, -1));
/* Target exists after the end byte, return end */
ovs_assert(15 == bitwise_rscan(s3, 3, 1, 23, 15));
/* Target exists in end byte but after the end bit, return end */
ovs_assert(4 == bitwise_rscan(s3, 3, 1, 23, 4));
/* Target is 0 ... */
ovs_assert(12 == bitwise_rscan(s3, 3, 0, 12, -1));
/* All 0s */
uint8_t s4[3] = {0x00, 0x00, 0x00};
/* Target not found */
ovs_assert(-1 == bitwise_rscan(s4, 3, 1, 23, -1));
/* Target is 0 ..., start is 0 */
ovs_assert(0 == bitwise_rscan(s4, 3, 0, 0, -1));
int n_loops;
for (n_loops = 0; n_loops < 100; n_loops++) {
ovs_be64 x = htonll(0);
int i;
for (i = 0; i < 64; i++) {
ovs_be64 bit;
/* Change a random 0-bit into a 1-bit. */
do {
bit = htonll(UINT64_C(1) << (random_range(64)));
} while (x & bit);
x |= bit;
for (int end = -1; end <= 63; end++) {
for (int start = end; start <= 63; start++) {
for (int target = 0; target < 2; target++) {
bool expect = trivial_bitwise_rscan(
&x, sizeof x, target, start, end);
bool answer = bitwise_rscan(
&x, sizeof x, target, start, end);
if (expect != answer) {
fprintf(stderr,
"bitwise_rscan(0x%016"PRIx64",8,%s,%d,%d) "
"returned %s instead of %s\n",
ntohll(x),
target ? "true" : "false",
start, end,
answer ? "true" : "false",
expect ? "true" : "false");
abort();
}
}
}
}
}
}
}
static void
test_follow_symlinks(struct ovs_cmdl_context *ctx)
{
int i;
for (i = 1; i < ctx->argc; i++) {
char *target = follow_symlinks(ctx->argv[i]);
puts(target);
free(target);
}
}
static void
test_assert(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
ovs_assert(false);
}
static void
test_ovs_scan(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
char str[16], str2[16], str3[16];
long double ld, ld2;
long long ll, ll2;
signed char c, c2;
ptrdiff_t pd, pd2;
intmax_t im, im2;
size_t sz, sz2;
int n, n2, n3;
double d, d2;
short s, s2;
float f, f2;
long l, l2;
int i, i2;
ovs_assert(ovs_scan("", " "));
ovs_assert(ovs_scan(" ", " "));
ovs_assert(ovs_scan(" ", " "));
ovs_assert(ovs_scan(" \t ", " "));
ovs_assert(ovs_scan("xyzzy", "xyzzy"));
ovs_assert(ovs_scan("xy%zzy", "xy%%zzy"));
ovs_assert(!ovs_scan(" xy%zzy", "xy%%zzy"));
ovs_assert(ovs_scan(" xy%\tzzy", " xy%% zzy"));
ovs_assert(ovs_scan("123", "%d", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0", "%d", &i));
ovs_assert(i == 0);
ovs_assert(!ovs_scan("123", "%d%d", &i, &i2));
ovs_assert(ovs_scan("+123", "%d", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("-123", "%d", &i));
ovs_assert(i == -123);
ovs_assert(ovs_scan("0123", "%d", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan(" 123", "%d", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0x123", "%d", &i));
ovs_assert(i == 0);
ovs_assert(ovs_scan("123", "%2d %d", &i, &i2));
ovs_assert(i == 12);
ovs_assert(i2 == 3);
ovs_assert(ovs_scan("+123", "%2d %d", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%2d %d", &i, &i2));
ovs_assert(i == -1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("0123", "%2d %d", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("123", "%*2d %d", &i));
ovs_assert(i == 3);
ovs_assert(ovs_scan("+123", "%2d %*d", &i));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%*2d %*d"));
ovs_assert(ovs_scan("123", "%u", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0", "%u", &i));
ovs_assert(i == 0);
ovs_assert(!ovs_scan("123", "%u%u", &i, &i2));
ovs_assert(ovs_scan("+123", "%u", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("-123", "%u", &i));
ovs_assert(i == -123);
ovs_assert(ovs_scan("0123", "%u", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan(" 123", "%u", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0x123", "%u", &i));
ovs_assert(i == 0);
ovs_assert(ovs_scan("123", "%2u %u", &i, &i2));
ovs_assert(i == 12);
ovs_assert(i2 == 3);
ovs_assert(ovs_scan("+123", "%2u %u", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%2u %u", &i, &i2));
ovs_assert(i == -1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("0123", "%2u %u", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("123", "%*2u %u", &i));
ovs_assert(i == 3);
ovs_assert(ovs_scan("+123", "%2u %*u", &i));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%*2u %*u"));
ovs_assert(ovs_scan("123", "%i", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0", "%i", &i));
ovs_assert(i == 0);
ovs_assert(!ovs_scan("123", "%i%i", &i, &i2));
ovs_assert(ovs_scan("+123", "%i", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("-123", "%i", &i));
ovs_assert(i == -123);
ovs_assert(ovs_scan("0123", "%i", &i));
ovs_assert(i == 0123);
ovs_assert(ovs_scan(" 123", "%i", &i));
ovs_assert(i == 123);
ovs_assert(ovs_scan("0x123", "%i", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan("123", "%2i %i", &i, &i2));
ovs_assert(i == 12);
ovs_assert(i2 == 3);
ovs_assert(ovs_scan("+123", "%2i %i", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%2i %i", &i, &i2));
ovs_assert(i == -1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("0123", "%2i %i", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("123", "%*2i %i", &i));
ovs_assert(i == 3);
ovs_assert(ovs_scan("+123", "%2i %*i", &i));
ovs_assert(i == 1);
ovs_assert(i2 == 23);
ovs_assert(ovs_scan("-123", "%*2i %*i"));
ovs_assert(ovs_scan("123", "%o", &i));
ovs_assert(i == 0123);
ovs_assert(ovs_scan("0", "%o", &i));
ovs_assert(i == 0);
ovs_assert(!ovs_scan("123", "%o%o", &i, &i2));
ovs_assert(ovs_scan("+123", "%o", &i));
ovs_assert(i == 0123);
ovs_assert(ovs_scan("-123", "%o", &i));
ovs_assert(i == -0123);
ovs_assert(ovs_scan("0123", "%o", &i));
ovs_assert(i == 0123);
ovs_assert(ovs_scan(" 123", "%o", &i));
ovs_assert(i == 0123);
ovs_assert(ovs_scan("0x123", "%o", &i));
ovs_assert(i == 0);
ovs_assert(ovs_scan("123", "%2o %o", &i, &i2));
ovs_assert(i == 012);
ovs_assert(i2 == 3);
ovs_assert(ovs_scan("+123", "%2o %o", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 023);
ovs_assert(ovs_scan("-123", "%2o %o", &i, &i2));
ovs_assert(i == -1);
ovs_assert(i2 == 023);
ovs_assert(ovs_scan("0123", "%2o %o", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 023);
ovs_assert(ovs_scan("123", "%*2o %o", &i));
ovs_assert(i == 3);
ovs_assert(ovs_scan("+123", "%2o %*o", &i));
ovs_assert(i == 1);
ovs_assert(i2 == 023);
ovs_assert(ovs_scan("-123", "%*2o %*o"));
ovs_assert(ovs_scan("123", "%x", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan("0", "%x", &i));
ovs_assert(i == 0);
ovs_assert(!ovs_scan("123", "%x%x", &i, &i2));
ovs_assert(ovs_scan("+123", "%x", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan("-123", "%x", &i));
ovs_assert(i == -0x123);
ovs_assert(ovs_scan("0123", "%x", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan(" 123", "%x", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan("0x123", "%x", &i));
ovs_assert(i == 0x123);
ovs_assert(ovs_scan("123", "%2x %x", &i, &i2));
ovs_assert(i == 0x12);
ovs_assert(i2 == 3);
ovs_assert(ovs_scan("+123", "%2x %x", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 0x23);
ovs_assert(ovs_scan("-123", "%2x %x", &i, &i2));
ovs_assert(i == -1);
ovs_assert(i2 == 0x23);
ovs_assert(ovs_scan("0123", "%2x %x", &i, &i2));
ovs_assert(i == 1);
ovs_assert(i2 == 0x23);
ovs_assert(ovs_scan("123", "%*2x %x", &i));
ovs_assert(i == 3);
ovs_assert(ovs_scan("+123", "%2x %*x", &i));
ovs_assert(i == 1);
ovs_assert(i2 == 0x23);
ovs_assert(ovs_scan("-123", "%*2x %*x"));
ovs_assert(ovs_scan("123", "%hd", &s));
ovs_assert(s == 123);
ovs_assert(!ovs_scan("123", "%hd%hd", &s, &s2));
ovs_assert(ovs_scan("+123", "%hd", &s));
ovs_assert(s == 123);
ovs_assert(ovs_scan("-123", "%hd", &s));
ovs_assert(s == -123);
ovs_assert(ovs_scan("0123", "%hd", &s));
ovs_assert(s == 123);
ovs_assert(ovs_scan(" 123", "%hd", &s));
ovs_assert(s == 123);
ovs_assert(ovs_scan("0x123", "%hd", &s));
ovs_assert(s == 0);
ovs_assert(ovs_scan("123", "%2hd %hd", &s, &s2));
ovs_assert(s == 12);
ovs_assert(s2 == 3);
ovs_assert(ovs_scan("+123", "%2hd %hd", &s, &s2));
ovs_assert(s == 1);
ovs_assert(s2 == 23);
ovs_assert(ovs_scan("-123", "%2hd %hd", &s, &s2));
ovs_assert(s == -1);
ovs_assert(s2 == 23);
ovs_assert(ovs_scan("0123", "%2hd %hd", &s, &s2));
ovs_assert(s == 1);
ovs_assert(s2 == 23);
ovs_assert(ovs_scan("123", "%hhd", &c));
ovs_assert(c == 123);
ovs_assert(ovs_scan("0", "%hhd", &c));
ovs_assert(c == 0);
ovs_assert(!ovs_scan("123", "%hhd%hhd", &c, &c2));
ovs_assert(ovs_scan("+123", "%hhd", &c));
ovs_assert(c == 123);
ovs_assert(ovs_scan("-123", "%hhd", &c));
ovs_assert(c == -123);
ovs_assert(ovs_scan("0123", "%hhd", &c));
ovs_assert(c == 123);
ovs_assert(ovs_scan(" 123", "%hhd", &c));
ovs_assert(c == 123);
ovs_assert(ovs_scan("0x123", "%hhd", &c));
ovs_assert(c == 0);
ovs_assert(ovs_scan("123", "%2hhd %hhd", &c, &c2));
ovs_assert(c == 12);
ovs_assert(c2 == 3);
ovs_assert(ovs_scan("+123", "%2hhd %hhd", &c, &c2));
ovs_assert(c == 1);
ovs_assert(c2 == 23);
ovs_assert(ovs_scan("-123", "%2hhd %hhd", &c, &c2));
ovs_assert(c == -1);
ovs_assert(c2 == 23);
ovs_assert(ovs_scan("0123", "%2hhd %hhd", &c, &c2));
ovs_assert(c == 1);
ovs_assert(c2 == 23);
ovs_assert(ovs_scan("123", "%ld", &l));
ovs_assert(l == 123);
ovs_assert(ovs_scan("0", "%ld", &l));
ovs_assert(l == 0);
ovs_assert(!ovs_scan("123", "%ld%ld", &l, &l2));
ovs_assert(ovs_scan("+123", "%ld", &l));
ovs_assert(l == 123);
ovs_assert(ovs_scan("-123", "%ld", &l));
ovs_assert(l == -123);
ovs_assert(ovs_scan("0123", "%ld", &l));
ovs_assert(l == 123);
ovs_assert(ovs_scan(" 123", "%ld", &l));
ovs_assert(l == 123);
ovs_assert(ovs_scan("0x123", "%ld", &l));
ovs_assert(l == 0);
ovs_assert(ovs_scan("123", "%2ld %ld", &l, &l2));
ovs_assert(l == 12);
ovs_assert(l2 == 3);
ovs_assert(ovs_scan("+123", "%2ld %ld", &l, &l2));
ovs_assert(l == 1);
ovs_assert(l2 == 23);
ovs_assert(ovs_scan("-123", "%2ld %ld", &l, &l2));
ovs_assert(l == -1);
ovs_assert(l2 == 23);
ovs_assert(ovs_scan("0123", "%2ld %ld", &l, &l2));
ovs_assert(l == 1);
ovs_assert(l2 == 23);
ovs_assert(ovs_scan("123", "%lld", &ll));
ovs_assert(ll == 123);
ovs_assert(ovs_scan("0", "%lld", &ll));
ovs_assert(ll == 0);
ovs_assert(!ovs_scan("123", "%lld%lld", &ll, &ll2));
ovs_assert(ovs_scan("+123", "%lld", &ll));
ovs_assert(ll == 123);
ovs_assert(ovs_scan("-123", "%lld", &ll));
ovs_assert(ll == -123);
ovs_assert(ovs_scan("0123", "%lld", &ll));
ovs_assert(ll == 123);
ovs_assert(ovs_scan(" 123", "%lld", &ll));
ovs_assert(ll == 123);
ovs_assert(ovs_scan("0x123", "%lld", &ll));
ovs_assert(ll == 0);
ovs_assert(ovs_scan("123", "%2lld %lld", &ll, &ll2));
ovs_assert(ll == 12);
ovs_assert(ll2 == 3);
ovs_assert(ovs_scan("+123", "%2lld %lld", &ll, &ll2));
ovs_assert(ll == 1);
ovs_assert(ll2 == 23);
ovs_assert(ovs_scan("-123", "%2lld %lld", &ll, &ll2));
ovs_assert(ll == -1);
ovs_assert(ll2 == 23);
ovs_assert(ovs_scan("0123", "%2lld %lld", &ll, &ll2));
ovs_assert(ll == 1);
ovs_assert(ll2 == 23);
ovs_assert(ovs_scan("123", "%jd", &im));
ovs_assert(im == 123);
ovs_assert(ovs_scan("0", "%jd", &im));
ovs_assert(im == 0);
ovs_assert(!ovs_scan("123", "%jd%jd", &im, &im2));
ovs_assert(ovs_scan("+123", "%jd", &im));
ovs_assert(im == 123);
ovs_assert(ovs_scan("-123", "%jd", &im));
ovs_assert(im == -123);
ovs_assert(ovs_scan("0123", "%jd", &im));
ovs_assert(im == 123);
ovs_assert(ovs_scan(" 123", "%jd", &im));
ovs_assert(im == 123);
ovs_assert(ovs_scan("0x123", "%jd", &im));
ovs_assert(im == 0);
ovs_assert(ovs_scan("123", "%2jd %jd", &im, &im2));
ovs_assert(im == 12);
ovs_assert(im2 == 3);
ovs_assert(ovs_scan("+123", "%2jd %jd", &im, &im2));
ovs_assert(im == 1);
ovs_assert(im2 == 23);
ovs_assert(ovs_scan("-123", "%2jd %jd", &im, &im2));
ovs_assert(im == -1);
ovs_assert(im2 == 23);
ovs_assert(ovs_scan("0123", "%2jd %jd", &im, &im2));
ovs_assert(im == 1);
ovs_assert(im2 == 23);
ovs_assert(ovs_scan("123", "%td", &pd));
ovs_assert(pd == 123);
ovs_assert(ovs_scan("0", "%td", &pd));
ovs_assert(pd == 0);
ovs_assert(!ovs_scan("123", "%td%td", &pd, &pd2));
ovs_assert(ovs_scan("+123", "%td", &pd));
ovs_assert(pd == 123);
ovs_assert(ovs_scan("-123", "%td", &pd));
ovs_assert(pd == -123);
ovs_assert(ovs_scan("0123", "%td", &pd));
ovs_assert(pd == 123);
ovs_assert(ovs_scan(" 123", "%td", &pd));
ovs_assert(pd == 123);
ovs_assert(ovs_scan("0x123", "%td", &pd));
ovs_assert(pd == 0);
ovs_assert(ovs_scan("123", "%2td %td", &pd, &pd2));
ovs_assert(pd == 12);
ovs_assert(pd2 == 3);
ovs_assert(ovs_scan("+123", "%2td %td", &pd, &pd2));
ovs_assert(pd == 1);
ovs_assert(pd2 == 23);
ovs_assert(ovs_scan("-123", "%2td %td", &pd, &pd2));
ovs_assert(pd == -1);
ovs_assert(pd2 == 23);
ovs_assert(ovs_scan("0123", "%2td %td", &pd, &pd2));
ovs_assert(pd == 1);
ovs_assert(pd2 == 23);
ovs_assert(ovs_scan("123", "%zd", &sz));
ovs_assert(sz == 123);
ovs_assert(ovs_scan("0", "%zd", &sz));
ovs_assert(sz == 0);
ovs_assert(!ovs_scan("123", "%zd%zd", &sz, &sz2));
ovs_assert(ovs_scan("+123", "%zd", &sz));
ovs_assert(sz == 123);
ovs_assert(ovs_scan("-123", "%zd", &sz));
ovs_assert(sz == -123);
ovs_assert(ovs_scan("0123", "%zd", &sz));
ovs_assert(sz == 123);
ovs_assert(ovs_scan(" 123", "%zd", &sz));
ovs_assert(sz == 123);
ovs_assert(ovs_scan("0x123", "%zd", &sz));
ovs_assert(sz == 0);
ovs_assert(ovs_scan("123", "%2zd %zd", &sz, &sz2));
ovs_assert(sz == 12);
ovs_assert(sz2 == 3);
ovs_assert(ovs_scan("+123", "%2zd %zd", &sz, &sz2));
ovs_assert(sz == 1);
ovs_assert(sz2 == 23);
ovs_assert(ovs_scan("-123", "%2zd %zd", &sz, &sz2));
ovs_assert(sz == -1);
ovs_assert(sz2 == 23);
ovs_assert(ovs_scan("0123", "%2zd %zd", &sz, &sz2));
ovs_assert(sz == 1);
ovs_assert(sz2 == 23);
ovs_assert(ovs_scan("0.25", "%f", &f));
ovs_assert(f == 0.25);
ovs_assert(ovs_scan("1.0", "%f", &f));
ovs_assert(f == 1.0);
ovs_assert(ovs_scan("-5", "%f", &f));
ovs_assert(f == -5.0);
ovs_assert(ovs_scan("+6", "%f", &f));
ovs_assert(f == 6.0);
ovs_assert(ovs_scan("-1e5", "%f", &f));
ovs_assert(f == -1e5);
ovs_assert(ovs_scan("-.25", "%f", &f));
ovs_assert(f == -.25);
ovs_assert(ovs_scan("+123.e1", "%f", &f));
ovs_assert(f == 1230.0);
ovs_assert(ovs_scan("25e-2", "%f", &f));
ovs_assert(f == 0.25);
ovs_assert(ovs_scan("0.25", "%1f %f", &f, &f2));
ovs_assert(f == 0);
ovs_assert(f2 == 0.25);
ovs_assert(ovs_scan("1.0", "%2f %f", &f, &f2));
ovs_assert(f == 1.0);
ovs_assert(f2 == 0.0);
ovs_assert(!ovs_scan("-5", "%1f", &f));
ovs_assert(!ovs_scan("+6", "%1f", &f));
ovs_assert(!ovs_scan("-1e5", "%2f %*f", &f));
ovs_assert(f == -1);
ovs_assert(!ovs_scan("-.25", "%2f", &f));
ovs_assert(!ovs_scan("+123.e1", "%6f", &f));
ovs_assert(!ovs_scan("25e-2", "%4f", &f));
ovs_assert(ovs_scan("0.25", "%lf", &d));
ovs_assert(d == 0.25);
ovs_assert(ovs_scan("1.0", "%lf", &d));
ovs_assert(d == 1.0);
ovs_assert(ovs_scan("-5", "%lf", &d));
ovs_assert(d == -5.0);
ovs_assert(ovs_scan("+6", "%lf", &d));
ovs_assert(d == 6.0);
ovs_assert(ovs_scan("-1e5", "%lf", &d));
ovs_assert(d == -1e5);
ovs_assert(ovs_scan("-.25", "%lf", &d));
ovs_assert(d == -.25);
ovs_assert(ovs_scan("+123.e1", "%lf", &d));
ovs_assert(d == 1230.0);
ovs_assert(ovs_scan("25e-2", "%lf", &d));
ovs_assert(d == 0.25);
ovs_assert(ovs_scan("0.25", "%1lf %lf", &d, &d2));
ovs_assert(d == 0);
ovs_assert(d2 == 0.25);
ovs_assert(ovs_scan("1.0", "%2lf %lf", &d, &d2));
ovs_assert(d == 1.0);
ovs_assert(d2 == 0.0);
ovs_assert(!ovs_scan("-5", "%1lf", &d));
ovs_assert(!ovs_scan("+6", "%1lf", &d));
ovs_assert(!ovs_scan("-1e5", "%2lf %*f", &d));
ovs_assert(d == -1);
ovs_assert(!ovs_scan("-.25", "%2lf", &d));
ovs_assert(!ovs_scan("+123.e1", "%6lf", &d));
ovs_assert(!ovs_scan("25e-2", "%4lf", &d));
ovs_assert(ovs_scan("0.25", "%Lf", &ld));
ovs_assert(ld == 0.25);
ovs_assert(ovs_scan("1.0", "%Lf", &ld));
ovs_assert(ld == 1.0);
ovs_assert(ovs_scan("-5", "%Lf", &ld));
ovs_assert(ld == -5.0);
ovs_assert(ovs_scan("+6", "%Lf", &ld));
ovs_assert(ld == 6.0);
ovs_assert(ovs_scan("-1e5", "%Lf", &ld));
ovs_assert(ld == -1e5);
ovs_assert(ovs_scan("-.25", "%Lf", &ld));
ovs_assert(ld == -.25);
ovs_assert(ovs_scan("+123.e1", "%Lf", &ld));
ovs_assert(ld == 1230.0);
ovs_assert(ovs_scan("25e-2", "%Lf", &ld));
ovs_assert(ld == 0.25);
ovs_assert(ovs_scan("0.25", "%1Lf %Lf", &ld, &ld2));
ovs_assert(ld == 0);
ovs_assert(ld2 == 0.25);
ovs_assert(ovs_scan("1.0", "%2Lf %Lf", &ld, &ld2));
ovs_assert(ld == 1.0);
ovs_assert(ld2 == 0.0);
ovs_assert(!ovs_scan("-5", "%1Lf", &ld));
ovs_assert(!ovs_scan("+6", "%1Lf", &ld));
ovs_assert(!ovs_scan("-1e5", "%2Lf %*f", &ld));
ovs_assert(ld == -1);
ovs_assert(!ovs_scan("-.25", "%2Lf", &ld));
ovs_assert(!ovs_scan("+123.e1", "%6Lf", &ld));
ovs_assert(!ovs_scan("25e-2", "%4Lf", &ld));
ovs_assert(ovs_scan(" Hello,\tworld ", "%*s%n%*s%n", &n, &n2));
ovs_assert(n == 7);
ovs_assert(n2 == 13);
ovs_assert(!ovs_scan(" Hello,\tworld ", "%*s%*s%*s"));
ovs_assert(ovs_scan(" Hello,\tworld ", "%6s%n%5s%n", str, &n, str2, &n2));
ovs_assert(!strcmp(str, "Hello,"));
ovs_assert(n == 7);
ovs_assert(!strcmp(str2, "world"));
ovs_assert(n2 == 13);
ovs_assert(ovs_scan(" Hello,\tworld ", "%5s%5s%5s", str, str2, str3));
ovs_assert(!strcmp(str, "Hello"));
ovs_assert(!strcmp(str2, ","));
ovs_assert(!strcmp(str3, "world"));
ovs_assert(!ovs_scan(" ", "%*s"));
ovs_assert(ovs_scan(" Hello,\tworld ", "%*c%n%*c%n%c%n",
&n, &n2, &c, &n3));
ovs_assert(n == 1);
ovs_assert(n2 == 2);
ovs_assert(c == 'e');
ovs_assert(n3 == 3);
ovs_assert(ovs_scan(" Hello,\tworld ", "%*5c%5c", str));
ovs_assert(!memcmp(str, "o,\two", 5));
ovs_assert(!ovs_scan(" Hello,\tworld ", "%*15c"));
ovs_assert(ovs_scan("0x1234xyzzy", "%9[x0-9a-fA-F]%n", str, &n));
ovs_assert(!strcmp(str, "0x1234x"));
ovs_assert(n == 7);
ovs_assert(ovs_scan("foo:bar=baz", "%5[^:=]%n:%5[^:=]%n=%5[^:=]%n",
str, &n, str2, &n2, str3, &n3));
ovs_assert(!strcmp(str, "foo"));
ovs_assert(n == 3);
ovs_assert(!strcmp(str2, "bar"));
ovs_assert(n2 == 7);
ovs_assert(!strcmp(str3, "baz"));
ovs_assert(n3 == 11);
ovs_assert(!ovs_scan(" ", "%*[0-9]"));
ovs_assert(ovs_scan("0x123a]4xyzzy-", "%[]x0-9a-fA-F]", str));
ovs_assert(!strcmp(str, "0x123a]4x"));
ovs_assert(ovs_scan("abc]xyz","%[^]xyz]", str));
ovs_assert(!strcmp(str, "abc"));
ovs_assert(!ovs_scan("0x123a]4xyzzy-", "%[x0-9]a-fA-F]", str));
ovs_assert(ovs_scan("0x12-3]xyz", "%[x0-9a-f-]", str));
ovs_assert(!strcmp(str, "0x12-3"));
ovs_assert(ovs_scan("0x12-3]xyz", "%[^a-f-]", str));
ovs_assert(!strcmp(str, "0x12"));
ovs_assert(sscanf("0x12-3]xyz", "%[^-a-f]", str));
ovs_assert(!strcmp(str, "0x12"));
}
static void
test_snprintf(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
char s[16];
/* GCC 7+ and Clang 18+ warn about the following calls that truncate
* a string using snprintf(). We're testing that truncation works
* properly, so temporarily disable the warning. */
#if __GNUC__ >= 7
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
#endif
#if __clang_major__ >= 18
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-truncation"
#endif
ovs_assert(snprintf(s, 4, "abcde") == 5);
ovs_assert(!strcmp(s, "abc"));
ovs_assert(snprintf(s, 5, "abcde") == 5);
ovs_assert(!strcmp(s, "abcd"));
#if __GNUC__ >= 7
#pragma GCC diagnostic pop
#endif
#if __clang_major__ >= 18
#pragma clang diagnostic pop
#endif
ovs_assert(snprintf(s, 6, "abcde") == 5);
ovs_assert(!strcmp(s, "abcde"));
ovs_assert(snprintf(NULL, 0, "abcde") == 5);
}
static void
check_sat(long long int x, long long int y, const char *op,
long long int r_a, long long int r_b)
{
if (r_a != r_b) {
fprintf(stderr, "%lld %s %lld saturates differently: %lld vs %lld\n",
x, op, y, r_a, r_b);
abort();
}
}
static void
test_sat_math(struct ovs_cmdl_context *ctx OVS_UNUSED)
{
long long int values[] = {
LLONG_MIN, LLONG_MIN + 1, LLONG_MIN + 2, LLONG_MIN + 3,
LLONG_MIN + 4, LLONG_MIN + 5, LLONG_MIN + 6, LLONG_MIN + 7,
LLONG_MIN / 2, LLONG_MIN / 3, LLONG_MIN / 4, LLONG_MIN / 5,
-1000, -50, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 50, 1000,
LLONG_MAX / 5, LLONG_MAX / 4, LLONG_MAX / 3, LLONG_MAX / 2,
LLONG_MAX - 7, LLONG_MAX - 6, LLONG_MAX - 5, LLONG_MAX - 4,
LLONG_MAX - 3, LLONG_MAX - 2, LLONG_MAX - 1, LLONG_MAX,
};
/* Compare the behavior of our local implementation of these functions
* against the compiler implementation or its fallback. (If the fallback
* is in use then this is comparing the fallback to itself, so this test is
* only really useful if the compiler has an implementation.) */
for (long long int *x = values; x < values + ARRAY_SIZE(values); x++) {
for (long long int *y = values; y < values + ARRAY_SIZE(values); y++) {
check_sat(*x, *y, "+", llsat_add(*x, *y), llsat_add__(*x, *y));
check_sat(*x, *y, "-", llsat_sub(*x, *y), llsat_sub__(*x, *y));
check_sat(*x, *y, "*", llsat_mul(*x, *y), llsat_mul__(*x, *y));
}
}
}
#ifndef _WIN32
static void
test_file_name(struct ovs_cmdl_context *ctx)
{
int i;
for (i = 1; i < ctx->argc; i++) {
char *dir, *base;
dir = dir_name(ctx->argv[i]);
puts(dir);
free(dir);
base = base_name(ctx->argv[i]);
puts(base);
free(base);
}
}
#endif /* _WIN32 */
static const struct ovs_cmdl_command commands[] = {
{"ctz", NULL, 0, 0, test_ctz, OVS_RO},
{"clz", NULL, 0, 0, test_clz, OVS_RO},
{"round_up_pow2", NULL, 0, 0, test_round_up_pow2, OVS_RO},
{"round_down_pow2", NULL, 0, 0, test_round_down_pow2, OVS_RO},
{"count_1bits", NULL, 0, 0, test_count_1bits, OVS_RO},
{"log_2_floor", NULL, 0, 0, test_log_2_floor, OVS_RO},
{"bitwise_copy", NULL, 0, 0, test_bitwise_copy, OVS_RO},
{"bitwise_zero", NULL, 0, 0, test_bitwise_zero, OVS_RO},
{"bitwise_one", NULL, 0, 0, test_bitwise_one, OVS_RO},
{"bitwise_is_all_zeros", NULL, 0, 0, test_bitwise_is_all_zeros, OVS_RO},
{"bitwise_rscan", NULL, 0, 0, test_bitwise_rscan, OVS_RO},
{"follow-symlinks", NULL, 1, INT_MAX, test_follow_symlinks, OVS_RO},
{"assert", NULL, 0, 0, test_assert, OVS_RO},
{"ovs_scan", NULL, 0, 0, test_ovs_scan, OVS_RO},
{"snprintf", NULL, 0, 0, test_snprintf, OVS_RO},
{"sat_math", NULL, 0, 0, test_sat_math, OVS_RO},
#ifndef _WIN32
{"file_name", NULL, 1, INT_MAX, test_file_name, OVS_RO},
#endif
{NULL, NULL, 0, 0, NULL, OVS_RO},
};
static void
parse_options(int argc, char *argv[])
{
enum {
VLOG_OPTION_ENUMS
};
static const struct option long_options[] = {
VLOG_LONG_OPTIONS,
{NULL, 0, NULL, 0},
};
char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
for (;;) {
int c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
VLOG_OPTION_HANDLERS
case '?':
exit(EXIT_FAILURE);
default:
abort();
}
}
free(short_options);
}
static void
test_util_main(int argc, char *argv[])
{
struct ovs_cmdl_context ctx = { .argc = 0, };
set_program_name(argv[0]);
parse_options(argc, argv);
/* On Windows, stderr is fully buffered if connected to a pipe.
* Make it _IONBF so that an abort does not miss log contents.
* POSIX doesn't define the circumstances in which stderr is
* fully buffered either. */
setvbuf(stderr, NULL, _IONBF, 0);
ctx.argc = argc - optind;
ctx.argv = argv + optind;
ovs_cmdl_run_command(&ctx, commands);
}
OVSTEST_REGISTER("test-util", test_util_main);