mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
tests: Add test rx/simple
This adds a new test, rx/simple, which runs a simple rx client against a server process. It does not make use of rxgen-generated RPCs, but instead runs as a single stream of data on an rx call. The client creates a new connection to this service and sends a string. The server performs a simple transformation (rot13) and returns the new string back to the client. This commit adds the simple-client and simple-server programs, as well as the "simple-t" script test driver. These programs serve as a very simple example of using Rx, as well as a basic functionality test. Co-developed-by: Andrew Deason <adeason@sinenomine.net> Change-Id: I78862ecb75a9bb3ccbfef049d11a95182c5e0278 Reviewed-on: https://gerrit.openafs.org/15780 Reviewed-by: Cheyenne Wills <cwills@sinenomine.net> Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Andrew Deason <adeason@sinenomine.net>
This commit is contained in:
parent
6c1676c515
commit
266ee3a1fe
@ -21,6 +21,7 @@ ptserver/pts-man
|
|||||||
rx/atomic
|
rx/atomic
|
||||||
rx/event
|
rx/event
|
||||||
rx/perf
|
rx/perf
|
||||||
|
rx/simple
|
||||||
volser/vos-man
|
volser/vos-man
|
||||||
volser/vos
|
volser/vos
|
||||||
bucoord/backup-man
|
bucoord/backup-man
|
||||||
|
2
tests/rx/.gitignore
vendored
2
tests/rx/.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
/atomic-t
|
/atomic-t
|
||||||
/event-t
|
/event-t
|
||||||
|
/simple-client
|
||||||
|
/simple-server
|
||||||
|
@ -10,7 +10,10 @@ MODULE_CFLAGS = -I$(TOP_OBJDIR)
|
|||||||
LIBS = $(abs_top_builddir)/tests/common/libafstest_common.la \
|
LIBS = $(abs_top_builddir)/tests/common/libafstest_common.la \
|
||||||
$(abs_top_builddir)/src/rx/liboafs_rx.la
|
$(abs_top_builddir)/src/rx/liboafs_rx.la
|
||||||
|
|
||||||
BINS = atomic-t event-t
|
SIMPLE_LIBS = $(TOP_LIBDIR)/libafsrpc.a \
|
||||||
|
$(TOP_LIBDIR)/libafsutil.a
|
||||||
|
|
||||||
|
BINS = atomic-t event-t simple-client simple-server
|
||||||
|
|
||||||
all: $(BINS)
|
all: $(BINS)
|
||||||
|
|
||||||
@ -19,6 +22,13 @@ atomic-t: atomic-t.o $(LIBS)
|
|||||||
|
|
||||||
event-t: event-t.o $(LIBS)
|
event-t: event-t.o $(LIBS)
|
||||||
$(LT_LDRULE_static) event-t.o $(LIBS) $(LIB_roken) $(XLIBS)
|
$(LT_LDRULE_static) event-t.o $(LIBS) $(LIB_roken) $(XLIBS)
|
||||||
|
|
||||||
|
simple-client: simple-client.o $(SIMPLE_LIBS)
|
||||||
|
$(LT_LDRULE_static) simple-client.o $(SIMPLE_LIBS) ${LIB_hcrypto} $(LIB_roken) $(XLIBS)
|
||||||
|
|
||||||
|
simple-server: simple-server.o $(SIMPLE_LIBS)
|
||||||
|
$(LT_LDRULE_static) simple-server.o $(SIMPLE_LIBS) ${LIB_hcrypto} $(LIB_roken) $(XLIBS)
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
||||||
clean distclean:
|
clean distclean:
|
||||||
|
133
tests/rx/simple-client.c
Normal file
133
tests/rx/simple-client.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Sahil Siddiq <sahilcdq@proton.me>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <afsconfig.h>
|
||||||
|
#include <afs/param.h>
|
||||||
|
|
||||||
|
#include <roken.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
#include <rx/rx.h>
|
||||||
|
#include <afs/afsutil.h>
|
||||||
|
|
||||||
|
static afs_uint32
|
||||||
|
str2addr(char *str)
|
||||||
|
{
|
||||||
|
afs_int32 addr = 0;
|
||||||
|
struct hostent *th = hostutil_GetHostByName(str);
|
||||||
|
if (th == NULL) {
|
||||||
|
errx(1, "Could not resolve host '%s'", str);
|
||||||
|
}
|
||||||
|
memcpy(&addr, th->h_addr, sizeof(addr));
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static afs_uint32
|
||||||
|
str2int(const char *str)
|
||||||
|
{
|
||||||
|
return strtoul(str, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
run_call(struct rx_connection *conn, char *message)
|
||||||
|
{
|
||||||
|
struct rx_call *call;
|
||||||
|
afs_int32 nbytes = strlen(message);
|
||||||
|
afs_int32 nbytes_n;
|
||||||
|
char *recvbuf;
|
||||||
|
afs_int32 code = RX_PROTOCOL_ERROR;
|
||||||
|
|
||||||
|
recvbuf = calloc(nbytes + 1, 1);
|
||||||
|
opr_Assert(recvbuf != NULL);
|
||||||
|
|
||||||
|
call = rx_NewCall(conn);
|
||||||
|
opr_Assert(call != NULL);
|
||||||
|
|
||||||
|
nbytes_n = htonl(nbytes);
|
||||||
|
if (rx_Write32(call, &nbytes_n) != sizeof(nbytes_n)) {
|
||||||
|
warnx("rx_Write32 failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_Write(call, message, nbytes) != nbytes) {
|
||||||
|
warnx("rx_Write failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_Read(call, recvbuf, nbytes) != nbytes) {
|
||||||
|
warnx("rx_Read failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n", recvbuf);
|
||||||
|
|
||||||
|
code = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
code = rx_EndCall(call, code);
|
||||||
|
if (code != 0) {
|
||||||
|
warnx("call aborted with code %d", code);
|
||||||
|
}
|
||||||
|
free(recvbuf);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
afs_uint32 host;
|
||||||
|
afs_uint16 port;
|
||||||
|
afs_uint16 service_id;
|
||||||
|
char *message;
|
||||||
|
int code;
|
||||||
|
struct rx_connection *conn;
|
||||||
|
|
||||||
|
setprogname(argv[0]);
|
||||||
|
|
||||||
|
if (argc != 5) {
|
||||||
|
errx(1, "Usage: %s <host> <port> <service_id> <message>", getprogname());
|
||||||
|
}
|
||||||
|
|
||||||
|
host = str2addr(argv[1]);
|
||||||
|
port = str2int(argv[2]);
|
||||||
|
service_id = str2int(argv[3]);
|
||||||
|
message = argv[4];
|
||||||
|
|
||||||
|
code = rx_Init(0);
|
||||||
|
if (code != 0) {
|
||||||
|
errx(1, "rx_Init failed with %d", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = rx_NewConnection(host, htons(port), service_id,
|
||||||
|
rxnull_NewClientSecurityObject(), 0);
|
||||||
|
opr_Assert(conn != NULL);
|
||||||
|
|
||||||
|
code = run_call(conn, message);
|
||||||
|
|
||||||
|
rx_DestroyConnection(conn);
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
141
tests/rx/simple-server.c
Normal file
141
tests/rx/simple-server.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Sahil Siddiq <sahilcdq@proton.me>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <afsconfig.h>
|
||||||
|
#include <afs/param.h>
|
||||||
|
|
||||||
|
#include <roken.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
|
#include <rx/rx.h>
|
||||||
|
|
||||||
|
#define MAX_SIZE 16
|
||||||
|
|
||||||
|
/* Arbitrary error code constants. */
|
||||||
|
#define ERROR_TOOBIG 201
|
||||||
|
|
||||||
|
static afs_uint32
|
||||||
|
str2int(const char *str)
|
||||||
|
{
|
||||||
|
return strtoul(str, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rot13(char *buf, afs_int32 nbytes)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nbytes; i++) {
|
||||||
|
if ((buf[i] >= 'n' && buf[i] <= 'z') ||
|
||||||
|
(buf[i] >= 'N' && buf[i] <= 'Z'))
|
||||||
|
{
|
||||||
|
buf[i] -= 13;
|
||||||
|
} else if ((buf[i] >= 'a' && buf[i] <= 'm') ||
|
||||||
|
(buf[i] >= 'A' && buf[i] <= 'M'))
|
||||||
|
{
|
||||||
|
buf[i] += 13;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static afs_int32
|
||||||
|
rxsimple_ExecuteRequest(struct rx_call *call)
|
||||||
|
{
|
||||||
|
afs_int32 nbytes;
|
||||||
|
afs_int32 nbytes_n;
|
||||||
|
afs_int32 code = RX_PROTOCOL_ERROR;
|
||||||
|
char buf[MAX_SIZE];
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
if (rx_Read32(call, &nbytes_n) != sizeof(nbytes_n)) {
|
||||||
|
warnx("rx_Read32 failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
nbytes = ntohl(nbytes_n);
|
||||||
|
|
||||||
|
if (nbytes > sizeof(buf)) {
|
||||||
|
warnx("nbytes too large: %d > %d", nbytes, (int)sizeof(buf));
|
||||||
|
code = ERROR_TOOBIG;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_Read(call, buf, nbytes) != nbytes) {
|
||||||
|
warnx("rx_Read failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rot13(buf, nbytes);
|
||||||
|
|
||||||
|
if (rx_Write(call, buf, nbytes) != nbytes) {
|
||||||
|
warnx("rx_Write failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
afs_uint16 port;
|
||||||
|
afs_uint16 service_id;
|
||||||
|
afs_int32 code;
|
||||||
|
struct rx_service *service;
|
||||||
|
struct rx_securityClass *secobj;
|
||||||
|
|
||||||
|
setprogname(argv[0]);
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
errx(1, "Usage: %s <port> <service_id>", getprogname());
|
||||||
|
}
|
||||||
|
|
||||||
|
port = str2int(argv[1]);
|
||||||
|
service_id = str2int(argv[2]);
|
||||||
|
|
||||||
|
code = rx_Init(htons(port));
|
||||||
|
if (code != 0) {
|
||||||
|
errx(1, "rx_Init failed with %d", code);
|
||||||
|
}
|
||||||
|
|
||||||
|
secobj = rxnull_NewClientSecurityObject();
|
||||||
|
service = rx_NewService(0, service_id, "rxsimple", &secobj, 1,
|
||||||
|
rxsimple_ExecuteRequest);
|
||||||
|
opr_Assert(service != NULL);
|
||||||
|
|
||||||
|
rx_StartServer(0);
|
||||||
|
|
||||||
|
printf("%s: Ready to receive calls\n", getprogname());
|
||||||
|
|
||||||
|
/* Close stdout to indicate that the server is ready to receive calls. */
|
||||||
|
fclose(stdout);
|
||||||
|
|
||||||
|
rx_ServerProc(NULL);
|
||||||
|
abort();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
76
tests/rx/simple-t
Executable file
76
tests/rx/simple-t
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Sahil Siddiq <sahilcdq@proton.me>.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||||
|
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use lib $ENV{C_TAP_SOURCE} . "/tests-lib/perl5";
|
||||||
|
|
||||||
|
use afstest qw(obj_path);
|
||||||
|
use Test::More tests=>4;
|
||||||
|
use POSIX qw(:sys_wait_h :signal_h);
|
||||||
|
|
||||||
|
my $port = 4000;
|
||||||
|
my $service = 1234;
|
||||||
|
my $server = obj_path("tests/rx/simple-server");
|
||||||
|
my $client = obj_path("tests/rx/simple-client");
|
||||||
|
my $server_pid;
|
||||||
|
|
||||||
|
# Start up the server
|
||||||
|
$server_pid = open(my $server_fh, '-|', $server, $port, $service);
|
||||||
|
if (!defined($server_pid)) {
|
||||||
|
die("Failed to run $server: $!");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for the server to finish starting
|
||||||
|
while (my $line = <$server_fh>) {
|
||||||
|
chomp($line);
|
||||||
|
diag($line);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Server is now ready to receive calls
|
||||||
|
|
||||||
|
pass("Started server");
|
||||||
|
|
||||||
|
# Start up a client, and run a test
|
||||||
|
my $message = 'Hello OpenAFS';
|
||||||
|
my $expected = 'Uryyb BcraNSF';
|
||||||
|
my $got = qx($client localhost $port $service "$message");
|
||||||
|
chomp($got);
|
||||||
|
|
||||||
|
is(0, $?, "Client ran successfully");
|
||||||
|
is($expected, $got, "Rot13 performed successfully");
|
||||||
|
|
||||||
|
# Kill the server process
|
||||||
|
kill("TERM", $server_pid);
|
||||||
|
|
||||||
|
close($server_fh);
|
||||||
|
my $ecode = ${^CHILD_ERROR_NATIVE};
|
||||||
|
if (WIFSIGNALED($ecode) && WTERMSIG($ecode) == SIGTERM) {
|
||||||
|
pass("Server died with SIGTERM");
|
||||||
|
} elsif (WIFSIGNALED($ecode)) {
|
||||||
|
fail("Server died with signal ".WTERMSIG($ecode));
|
||||||
|
} else {
|
||||||
|
fail("Server exited with code". WEXITSTATUS($ecode));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user