Commit df7e0e0d authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by David S. Miller
Browse files

VSOCK: extract utility functions from vsock_diag_test.c



Move useful functions into a separate file in preparation for more
vsock test programs.

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ce1c7f84
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
all: test
test: vsock_diag_test
vsock_diag_test: vsock_diag_test.o timeout.o control.o
vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o

CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE
.PHONY: all test clean
+66 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * vsock test utilities
 *
 * Copyright (C) 2017 Red Hat, Inc.
 *
 * Author: Stefan Hajnoczi <stefanha@redhat.com>
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include "timeout.h"
#include "util.h"

/* Install signal handlers */
void init_signals(void)
{
	struct sigaction act = {
		.sa_handler = sigalrm,
	};

	sigaction(SIGALRM, &act, NULL);
	signal(SIGPIPE, SIG_IGN);
}

/* Parse a CID in string representation */
unsigned int parse_cid(const char *str)
{
	char *endptr = NULL;
	unsigned long n;

	errno = 0;
	n = strtoul(str, &endptr, 10);
	if (errno || *endptr != '\0') {
		fprintf(stderr, "malformed CID \"%s\"\n", str);
		exit(EXIT_FAILURE);
	}
	return n;
}

/* Run test cases.  The program terminates if a failure occurs. */
void run_tests(const struct test_case *test_cases,
	       const struct test_opts *opts)
{
	int i;

	for (i = 0; test_cases[i].name; i++) {
		void (*run)(const struct test_opts *opts);

		printf("%s...", test_cases[i].name);
		fflush(stdout);

		if (opts->mode == TEST_MODE_CLIENT)
			run = test_cases[i].run_client;
		else
			run = test_cases[i].run_server;

		if (run)
			run(opts);

		printf("ok\n");
	}
}
+36 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef UTIL_H
#define UTIL_H

/* Tests can either run as the client or the server */
enum test_mode {
	TEST_MODE_UNSET,
	TEST_MODE_CLIENT,
	TEST_MODE_SERVER
};

/* Test runner options */
struct test_opts {
	enum test_mode mode;
	unsigned int peer_cid;
};

/* A test case definition.  Test functions must print failures to stderr and
 * terminate with exit(EXIT_FAILURE).
 */
struct test_case {
	const char *name; /* human-readable name */

	/* Called when test mode is TEST_MODE_CLIENT */
	void (*run_client)(const struct test_opts *opts);

	/* Called when test mode is TEST_MODE_SERVER */
	void (*run_server)(const struct test_opts *opts);
};

void init_signals(void);
unsigned int parse_cid(const char *str);
void run_tests(const struct test_case *test_cases,
	       const struct test_opts *opts);

#endif /* UTIL_H */
+22 −70
Original line number Diff line number Diff line
@@ -9,12 +9,10 @@

#include <getopt.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -28,12 +26,7 @@

#include "timeout.h"
#include "control.h"

enum test_mode {
	TEST_MODE_UNSET,
	TEST_MODE_CLIENT,
	TEST_MODE_SERVER
};
#include "util.h"

/* Per-socket status */
struct vsock_stat {
@@ -334,7 +327,7 @@ static void free_sock_stat(struct list_head *sockets)
		free(st);
}

static void test_no_sockets(unsigned int peer_cid)
static void test_no_sockets(const struct test_opts *opts)
{
	LIST_HEAD(sockets);

@@ -345,7 +338,7 @@ static void test_no_sockets(unsigned int peer_cid)
	free_sock_stat(&sockets);
}

static void test_listen_socket_server(unsigned int peer_cid)
static void test_listen_socket_server(const struct test_opts *opts)
{
	union {
		struct sockaddr sa;
@@ -383,7 +376,7 @@ static void test_listen_socket_server(unsigned int peer_cid)
	free_sock_stat(&sockets);
}

static void test_connect_client(unsigned int peer_cid)
static void test_connect_client(const struct test_opts *opts)
{
	union {
		struct sockaddr sa;
@@ -392,7 +385,7 @@ static void test_connect_client(unsigned int peer_cid)
		.svm = {
			.svm_family = AF_VSOCK,
			.svm_port = 1234,
			.svm_cid = peer_cid,
			.svm_cid = opts->peer_cid,
		},
	};
	int fd;
@@ -429,7 +422,7 @@ static void test_connect_client(unsigned int peer_cid)
	free_sock_stat(&sockets);
}

static void test_connect_server(unsigned int peer_cid)
static void test_connect_server(const struct test_opts *opts)
{
	union {
		struct sockaddr sa;
@@ -481,9 +474,9 @@ static void test_connect_server(unsigned int peer_cid)
			clientaddr.sa.sa_family);
		exit(EXIT_FAILURE);
	}
	if (clientaddr.svm.svm_cid != peer_cid) {
	if (clientaddr.svm.svm_cid != opts->peer_cid) {
		fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
			peer_cid, clientaddr.svm.svm_cid);
			opts->peer_cid, clientaddr.svm.svm_cid);
		exit(EXIT_FAILURE);
	}

@@ -502,11 +495,7 @@ static void test_connect_server(unsigned int peer_cid)
	free_sock_stat(&sockets);
}

static struct {
	const char *name;
	void (*run_client)(unsigned int peer_cid);
	void (*run_server)(unsigned int peer_cid);
} test_cases[] = {
static struct test_case test_cases[] = {
	{
		.name = "No sockets",
		.run_server = test_no_sockets,
@@ -523,30 +512,6 @@ static struct {
	{},
};

static void init_signals(void)
{
	struct sigaction act = {
		.sa_handler = sigalrm,
	};

	sigaction(SIGALRM, &act, NULL);
	signal(SIGPIPE, SIG_IGN);
}

static unsigned int parse_cid(const char *str)
{
	char *endptr = NULL;
	unsigned long int n;

	errno = 0;
	n = strtoul(str, &endptr, 10);
	if (errno || *endptr != '\0') {
		fprintf(stderr, "malformed CID \"%s\"\n", str);
		exit(EXIT_FAILURE);
	}
	return n;
}

static const char optstring[] = "";
static const struct option longopts[] = {
	{
@@ -601,9 +566,10 @@ int main(int argc, char **argv)
{
	const char *control_host = NULL;
	const char *control_port = NULL;
	int mode = TEST_MODE_UNSET;
	unsigned int peer_cid = VMADDR_CID_ANY;
	int i;
	struct test_opts opts = {
		.mode = TEST_MODE_UNSET,
		.peer_cid = VMADDR_CID_ANY,
	};

	init_signals();

@@ -619,16 +585,16 @@ int main(int argc, char **argv)
			break;
		case 'm':
			if (strcmp(optarg, "client") == 0)
				mode = TEST_MODE_CLIENT;
				opts.mode = TEST_MODE_CLIENT;
			else if (strcmp(optarg, "server") == 0)
				mode = TEST_MODE_SERVER;
				opts.mode = TEST_MODE_SERVER;
			else {
				fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
				return EXIT_FAILURE;
			}
			break;
		case 'p':
			peer_cid = parse_cid(optarg);
			opts.peer_cid = parse_cid(optarg);
			break;
		case 'P':
			control_port = optarg;
@@ -641,35 +607,21 @@ int main(int argc, char **argv)

	if (!control_port)
		usage();
	if (mode == TEST_MODE_UNSET)
	if (opts.mode == TEST_MODE_UNSET)
		usage();
	if (peer_cid == VMADDR_CID_ANY)
	if (opts.peer_cid == VMADDR_CID_ANY)
		usage();

	if (!control_host) {
		if (mode != TEST_MODE_SERVER)
		if (opts.mode != TEST_MODE_SERVER)
			usage();
		control_host = "0.0.0.0";
	}

	control_init(control_host, control_port, mode == TEST_MODE_SERVER);

	for (i = 0; test_cases[i].name; i++) {
		void (*run)(unsigned int peer_cid);
	control_init(control_host, control_port,
		     opts.mode == TEST_MODE_SERVER);

		printf("%s...", test_cases[i].name);
		fflush(stdout);

		if (mode == TEST_MODE_CLIENT)
			run = test_cases[i].run_client;
		else
			run = test_cases[i].run_server;

		if (run)
			run(peer_cid);

		printf("ok\n");
	}
	run_tests(test_cases, &opts);

	control_cleanup();
	return EXIT_SUCCESS;