Commit e6c30818 authored by Pawel Wodkowski's avatar Pawel Wodkowski Committed by Jim Harris
Browse files

test: don't use bdev_svc application in this test



bdev_svc require system setup (like bdevs, nvme etc.) otherwise it
writes tons of  errors. Instead just start RPC server on separate thread
and connect to it.

Change-Id: I99ee58cbccbf982d70155c8ecf0fd7f860b3b6ab
Signed-off-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-on: https://review.gerrithub.io/430316


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 2f557958
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ APP = rpc_client_test

C_SRCS := rpc_client_test.c

SPDK_LIB_LIST = jsonrpc json log util
SPDK_LIB_LIST = jsonrpc json rpc log util

LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)

+1 −23
Original line number Diff line number Diff line
@@ -7,30 +7,8 @@ set -e

source $rootdir/test/common/autotest_common.sh

function rpc_client_test() {
	if [ $(uname -s) = Linux ]; then
		local conf=$rootdir/test/bdev/bdev.conf.in

		if [ ! -e $conf ]; then
			return 1
		fi

		$rootdir/test/app/bdev_svc/bdev_svc -i 0 -c ${conf} &
		svc_pid=$!
		echo "Process bdev_svc pid: $svc_pid"
		waitforlisten $svc_pid
		trap "killprocess $svc_pid" SIGINT SIGTERM EXIT

		$rootdir/test/rpc_client/rpc_client_test

		killprocess $svc_pid
	fi

	return 0
}

timing_enter rpc_client
rpc_client_test
$rootdir/test/rpc_client/rpc_client_test
timing_exit rpc_client

trap - SIGINT SIGTERM EXIT
+164 −7
Original line number Diff line number Diff line
@@ -34,8 +34,12 @@
#include "spdk/stdinc.h"
#include "spdk/event.h"
#include "spdk/jsonrpc.h"
#include "spdk/util.h"
#include "spdk/rpc.h"


#define RPC_MAX_METHODS 200
#define JOIN_TIMEOUT_S 1

static const char *g_rpcsock_addr = SPDK_DEFAULT_RPC_ADDR;
static int g_addr_family = AF_UNIX;
@@ -73,13 +77,17 @@ spdk_jsonrpc_client_check_rpc_method(struct spdk_jsonrpc_client *client, char *m
	spdk_jsonrpc_end_request(request, w);
	spdk_jsonrpc_client_send_request(client, request);

	do {
		rc = spdk_jsonrpc_client_recv_response(client);
	if (rc) {
	} while (rc == -EAGAIN || rc == -ENOTCONN);

	if (rc != 0) {
		goto out;
	}

	json_resp = spdk_jsonrpc_client_get_response(client);
	if (json_resp == NULL) {
		SPDK_ERRLOG("spdk_jsonrpc_client_get_response() failed\n");
		rc = -errno;
		goto out;

@@ -87,6 +95,7 @@ spdk_jsonrpc_client_check_rpc_method(struct spdk_jsonrpc_client *client, char *m

	/* Check for error response */
	if (json_resp->error != NULL) {
		SPDK_ERRLOG("Unexpected error response\n");
		rc = -1;
		goto out;
	}
@@ -95,6 +104,7 @@ spdk_jsonrpc_client_check_rpc_method(struct spdk_jsonrpc_client *client, char *m

	rc = get_jsonrpc_method_json_parser(&resp, json_resp->result);
	if (rc) {
		SPDK_ERRLOG("get_jsonrpc_method_json_parser() failed\n");
		goto out;
	}

@@ -106,6 +116,7 @@ spdk_jsonrpc_client_check_rpc_method(struct spdk_jsonrpc_client *client, char *m
	}

	rc = -1;
	SPDK_ERRLOG("Method '%s' not found in response\n", method_name);

out:
	for (i = 0; i < (int)resp.method_num; i++) {
@@ -117,20 +128,166 @@ out:
	return rc;
}

int main(int argc, char **argv)
static void
rpc_test_method_startup(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
{
	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
					 "rpc_test_method_startup(): Method body not implemented");
}
SPDK_RPC_REGISTER("test_method_startup", rpc_test_method_startup, SPDK_RPC_STARTUP)

static void
rpc_test_method_runtime(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
{
	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
					 "rpc_test_method_runtime(): Method body not implemented");
}
SPDK_RPC_REGISTER("test_method_runtime", rpc_test_method_runtime, SPDK_RPC_RUNTIME)

/* Helper function */
static int
_sem_timedwait(sem_t *sem, __time_t sec)
{
	struct timespec timeout;

	clock_gettime(CLOCK_REALTIME, &timeout);
	timeout.tv_sec += sec;

	return sem_timedwait(sem, &timeout);
}

volatile int g_rpc_server_th_stop;
static sem_t g_rpc_server_th_listening;
static sem_t g_rpc_server_th_done;

static void *
rpc_server_th(void *arg)
{
	struct spdk_jsonrpc_client *client;
	int rc;

	rc = spdk_rpc_listen(g_rpcsock_addr);
	if (rc) {
		fprintf(stderr, "spdk_rpc_listen() failed: %d\n", rc);
		goto out;
	}

	sem_post(&g_rpc_server_th_listening);

	while (!g_rpc_server_th_stop) {
		spdk_rpc_accept();
		usleep(50);
	}

	spdk_rpc_close();
out:
	sem_post(&g_rpc_server_th_done);

	return (void *)(intptr_t)rc;
}

static sem_t g_rpc_client_th_done;

static void *
rpc_client_th(void *arg)
{
	struct spdk_jsonrpc_client *client = NULL;
	char *method_name = "get_rpc_methods";
	int rc;


	rc = _sem_timedwait(&g_rpc_server_th_listening, 2);
	if (rc == -1) {
		fprintf(stderr, "Timeout waiting for server thread to start listening: %d\n", errno);
		goto out;
	}

	client = spdk_jsonrpc_client_connect(g_rpcsock_addr, g_addr_family);
	if (!client) {
		return EXIT_FAILURE;
		fprintf(stderr, "spdk_jsonrpc_client_connect() failed: %d\n", errno);
		rc = -1;
		goto out;
	}

	rc = spdk_jsonrpc_client_check_rpc_method(client, method_name);
	if (rc) {
		fprintf(stderr, "spdk_jsonrpc_client_check_rpc_method() failed: %d\n", errno);
		goto out;
	}

out:
	if (client) {
		spdk_jsonrpc_client_close(client);
	}

	sem_post(&g_rpc_client_th_done);
	return (void *)(intptr_t)rc;
}

int main(int argc, char **argv)
{
	pthread_t srv_tid, client_tid;
	int srv_tid_valid;
	int client_tid_valid = -1;
	int th_rc = INT_MIN;
	int rc = 0, err_cnt = 0;

	sem_init(&g_rpc_server_th_listening, 0, 0);
	sem_init(&g_rpc_server_th_done, 0, 0);
	sem_init(&g_rpc_client_th_done, 0, 0);

	srv_tid_valid = pthread_create(&srv_tid, NULL, rpc_server_th, NULL);
	if (srv_tid_valid != 0) {
		fprintf(stderr, "pthread_create() failed to create server thread: %d\n", srv_tid_valid);
		goto out;
	}

	client_tid_valid = pthread_create(&client_tid, NULL, rpc_client_th, NULL);
	if (client_tid_valid != 0) {
		fprintf(stderr, "pthread_create(): failed to create client thread: %d\n", client_tid_valid);
		goto out;
	}

out:
	if (client_tid_valid == 0) {
		rc = _sem_timedwait(&g_rpc_client_th_done, JOIN_TIMEOUT_S);
		if (rc) {
			fprintf(stderr, "failed to join client thread (rc: %d)\n", rc);
			err_cnt++;
		}

		rc = pthread_join(client_tid, (void **)&th_rc);
		if (rc) {
			fprintf(stderr, "pthread_join() on cliennt thread failed (rc: %d)\n", rc);
			err_cnt++;
		} else if (th_rc) {
			fprintf(stderr, "cliennt thread failed reported failure(thread rc: %d)\n", th_rc);
			err_cnt++;
		}
	}

	g_rpc_server_th_stop = 1;

	if (srv_tid_valid == 0) {
		rc = _sem_timedwait(&g_rpc_server_th_done, JOIN_TIMEOUT_S);
		if (rc) {
			fprintf(stderr, "server thread failed to exit in %d sec: (rc: %d)\n", JOIN_TIMEOUT_S, rc);
			err_cnt++;
		}

		rc = pthread_join(srv_tid, (void **)&th_rc);
		if (rc) {
			fprintf(stderr, "pthread_join() on cliennt thread failed (rc: %d)\n", rc);
			err_cnt++;
		} else if (th_rc) {
			fprintf(stderr, "cliennt thread failed reported failure(thread rc: %d)\n", th_rc);
			err_cnt++;
		}
	}

	sem_destroy(&g_rpc_server_th_listening);
	sem_destroy(&g_rpc_server_th_done);
	sem_destroy(&g_rpc_client_th_done);

	return rc ? EXIT_FAILURE : 0;
	fprintf(stderr, "%s\n", err_cnt == 0 ? "OK" : "FAILED");
	return err_cnt ? EXIT_FAILURE : 0;
}