From fe272a8454d2379c2ed5b0f9f04b493574316a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 15 Dec 2009 10:33:33 +0000 Subject: Include the test suites for erl_interface --- .../test/ei_accept_SUITE_data/Makefile.first | 21 ++ .../test/ei_accept_SUITE_data/Makefile.src | 45 ++++ .../test/ei_accept_SUITE_data/ei_accept_test.c | 224 ++++++++++++++++++++ .../test/ei_accept_SUITE_data/eiaccnode.c | 234 +++++++++++++++++++++ 4 files changed, 524 insertions(+) create mode 100644 lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first create mode 100644 lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src create mode 100644 lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c create mode 100644 lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c (limited to 'lib/erl_interface/test/ei_accept_SUITE_data') diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first new file mode 100644 index 0000000000..d7ec976cd0 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.first @@ -0,0 +1,21 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +ei_accept_test_decl.c: ei_accept_test.c + erl -noinput -pa ../all_SUITE_data -s init_tc run ei_accept_test -s erlang halt diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src new file mode 100644 index 0000000000..9b751d8f65 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/Makefile.src @@ -0,0 +1,45 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2001-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% +# + +include @erl_interface_mk_include@@DS@eidefs.mk + +CC0 = @CC@ +CC = ..@DS@all_SUITE_data@DS@gccifier@exe@ -CC"$(CC0)" +LD = @LD@ +LIBPATH = @erl_interface_libpath@ +LIBEI = $(LIBPATH)/@erl_interface_eilib@ +LIBFLAGS = ../all_SUITE_data/ei_runner@obj@ \ + $(LIBEI) @LIBS@ @erl_interface_sock_libs@ \ + @erl_interface_threadlib@ +CFLAGS = @EI_CFLAGS@ $(THR_DEFS) -I@erl_interface_include@ -I../all_SUITE_data +EI_ACCEPT_OBJS = ei_accept_test@obj@ ei_accept_test_decl@obj@ +EIACCNODE_OBJS = eiaccnode@obj@ + +all: ei_accept_test@exe@ eiaccnode@exe@ + +clean: + $(RM) $(EI_ACCEPT_OBJS) $(EIACCNODE_OBJS) + $(RM) ei_accept_test@exe@ eiaccnode@exe@ + +ei_accept_test@exe@: $(EI_ACCEPT_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EI_ACCEPT_OBJS) $(LIBFLAGS) + + +eiaccnode@exe@: $(EIACCNODE_OBJS) $(LIBEI) + $(LD) @CROSSLDFLAGS@ -o $@ $(EIACCNODE_OBJS) $(LIBFLAGS) diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c new file mode 100644 index 0000000000..5f898b5944 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/ei_accept_test.c @@ -0,0 +1,224 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* + * Purpose: Tests the accept function in ei_connect.c. + * Author: Jakob Cederlund (taken from erl_connect by Björn Gustavsson) + * + * See the ei_accept_SUITE.erl file for a "table of contents". + */ + +#include +#include +#ifdef VXWORKS +#include "reclaim.h" +#endif + +#ifdef __WIN32__ +#include +#include +#else +#include +#include +#include +#endif + +#include "ei_runner.h" + +static void cmd_ei_connect_init(char* buf, int len); +static void cmd_ei_accept(char* buf, int len); +static void cmd_ei_receive(char* buf, int len); +static void cmd_ei_unpublish(char* buf, int len); + +static void send_errno_result(int value); + +ei_cnode ec; + + +static struct { + char* name; + int num_args; /* Number of arguments. */ + void (*func)(char* buf, int len); +} commands[] = { + "ei_connect_init", 3, cmd_ei_connect_init, + "ei_accept", 1, cmd_ei_accept, + "ei_receive", 1, cmd_ei_receive, + "ei_unpublish", 0, cmd_ei_unpublish +}; + +/* + * Sends a list contaning all data types to the Erlang side. + */ +TESTCASE(interpret) +{ + ei_x_buff x; + int i; + ei_term term; + + ei_x_new(&x); + for (;;) { + if (get_bin_term(&x, &term)) { + report(1); + return; + } else { + char* buf = x.buff, func[MAXATOMLEN]; + int index = x.index, arity; + if (term.ei_type != ERL_SMALL_TUPLE_EXT || term.arity != 2) + fail("term should be a tuple of size 2"); + if (ei_decode_atom(buf, &index, func) < 0) + fail("function name should be an atom"); + if (ei_decode_tuple_header(buf, &index, &arity) != 0) + fail("function arguments should be a tuple"); + for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) { + if (strcmp(func, commands[i].name) == 0) { + if (arity != commands[i].num_args) + fail("wrong number of arguments"); + commands[i].func(buf + index, x.buffsz - index); + break; + } + } + if (i >= sizeof(commands)/sizeof(commands[0])) { + message("\"%d\" \n", func); + fail("bad command"); + } + } + } +} + +static void cmd_ei_connect_init(char* buf, int len) +{ + int index = 0, r = 0; + int type, size; + long l; + char b[100]; + char cookie[MAXATOMLEN], * cp = cookie; + ei_x_buff res; + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int"); + sprintf(b, "c%d", l); + /* FIXME don't use internal and maybe use skip?! */ + ei_get_type_internal(buf, &index, &type, &size); + if (ei_decode_atom(buf, &index, cookie) < 0) + fail("expected atom (cookie)"); + if (cookie[0] == '\0') + cp = NULL; + r = ei_connect_init(&ec, b, cp, 0); + ei_x_new_with_version(&res); + ei_x_encode_long(&res, r); + send_bin_term(&res); + ei_x_free(&res); +} + +static int my_listen(int port) +{ + int listen_fd; + struct sockaddr_in addr; + const char *on = "1"; + + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)); + + memset((void*) &addr, 0, (size_t) sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + return -1; + + listen(listen_fd, 5); + return listen_fd; +} + +static void cmd_ei_accept(char* buf, int len) +{ + int index = 0; + int listen, r; + ErlConnect conn; + long port; + ei_x_buff x; + int i; + + /* get port */ + if (ei_decode_long(buf, &index, &port) < 0) + fail("expected int (port)"); + /* Make a listen socket */ + if ((listen = my_listen(port)) <= 0) + fail("listen"); + + if ((i = ei_publish(&ec, port)) == -1) + fail("ei_publish"); +#ifdef VXWORKS + save_fd(i); +#endif + r = ei_accept(&ec, listen, &conn); +#ifdef VXWORKS + save_fd(r); +#endif + /* send result, errno and nodename */ + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 3); + ei_x_encode_long(&x, r); + ei_x_encode_long(&x, erl_errno); + ei_x_encode_atom(&x, conn.nodename); /* or rather string? */ + send_bin_term(&x); + ei_x_free(&x); +} + +static void cmd_ei_receive(char* buf, int len) +{ + ei_x_buff x; + erlang_msg msg; + long l; + int fd, index = 0; + + if (ei_decode_long(buf, &index, &l) < 0) + fail("expected int (fd)"); + fd = l; + ei_x_new(&x); + for (;;) { + int got = ei_xreceive_msg(fd, &msg, &x); + if (got == ERL_TICK) + continue; + if (got == ERL_ERROR) + fail("ei_xreceive_msg"); + break; + } + index = 1; + send_bin_term(&x); + ei_x_free(&x); +} + +static void cmd_ei_unpublish(char* buf, int len) +{ + send_errno_result(ei_unpublish(&ec)); +} + +static void send_errno_result(int value) +{ + ei_x_buff x; + ei_x_new_with_version(&x); + ei_x_encode_tuple_header(&x, 2); + ei_x_encode_long(&x, value); + ei_x_encode_long(&x, erl_errno); + send_bin_term(&x); + ei_x_free(&x); +} diff --git a/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c new file mode 100644 index 0000000000..af58f75963 --- /dev/null +++ b/lib/erl_interface/test/ei_accept_SUITE_data/eiaccnode.c @@ -0,0 +1,234 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 2001-2009. All Rights Reserved. + * + * The contents of this file are subject to the Erlang Public License, + * Version 1.1, (the "License"); you may not use this file except in + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +/* to test multiple threads in ei */ + +#include +#include + +#ifdef __WIN32__ +#include +#include +#include +#else +#ifndef VXWORKS +#include +#endif +#include +#include +#include +#endif + +#include "ei.h" + +#ifdef VXWORKS +#include +#include +#include +#define MAIN cnode +#else +#define MAIN main +#endif + +static int my_listen(int port); + +/* + A small einode. + To be called from the test case ei_accept_SUITE:multi_thread + usage: eiaccnode + + - start threads 0..n-1 + - in each thread + - listen on "ei0" .. "ei" + - wait for connection + - receive a pid + - send {i, } back + - shutdown gracefully +*/ + +static const char* cookie, * desthost; +static int port; /* actually base port */ + +#ifndef SD_SEND +#ifdef SHUTWR +#define SD_SEND SHUT_WR +#else +#define SD_SEND 1 +#endif +#endif + +#ifndef __WIN32__ +#define closesocket(fd) close(fd) +#endif + +#ifdef __WIN32__ +static DWORD WINAPI +#else +static void* +#endif + einode_thread(void* num) +{ + int n = (int)num; + ei_cnode ec; + char myname[100], destname[100]; + int r, fd, listen; + ErlConnect conn; + erlang_msg msg; +/* FILE* f;*/ + + sprintf(myname, "eiacc%d", n); + printf("thread %d (%s) listening\n", n, myname, destname); + r = ei_connect_init(&ec, myname, cookie, 0); + if ((listen = my_listen(port+n)) <= 0) { + printf("listen err\n"); + exit(7); + } + if (ei_publish(&ec, port + n) == -1) { + printf("ei_publish port %d\n", port+n); + exit(8); + } + fd = ei_accept(&ec, listen, &conn); + printf("ei_accept %d\n", fd); + if (fd >= 0) { + ei_x_buff x, xs; + int index, version; + erlang_pid pid; + + ei_x_new(&x); + for (;;) { + int got = ei_xreceive_msg(fd, &msg, &x); + if (got == ERL_TICK) + continue; + if (got == ERL_ERROR) { + printf("receive error %d\n", n); + return 0; + } + printf("received %d\n", got); + break; + } + index = 0; + if (ei_decode_version(x.buff, &index, &version) != 0) { + printf("ei_decode_version %d\n", n); + return 0; + } + if (ei_decode_pid(x.buff, &index, &pid) != 0) { + printf("ei_decode_pid %d\n", n); + return 0; + } +/* fprintf(f, "got pid from %s \n", pid.node);*/ + ei_x_new_with_version(&xs); + ei_x_encode_tuple_header(&xs, 2); + ei_x_encode_long(&xs, n); + ei_x_encode_pid(&xs, &pid); + r = ei_send(fd, &pid, xs.buff, xs.index); +/* fprintf(f, "sent %d bytes %d\n", xs.index, r);*/ + shutdown(fd, SD_SEND); + closesocket(fd); + ei_x_free(&x); + ei_x_free(&xs); + } else { + printf("coudn't connect fd %d r %d\n", fd, r); + } + printf("done thread %d\n", n); +/* fclose(f);*/ + return 0; +} + +MAIN(int argc, char *argv[]) +{ + int i, n, no_threads; +#ifndef VXWORKS +#ifdef __WIN32__ + HANDLE threads[100]; +#else + pthread_t threads[100]; +#endif +#endif + + if (argc < 3) + exit(1); + + cookie = argv[1]; + n = atoi(argv[2]); + if (n > 100) + exit(2); + desthost = argv[3]; + port = atoi(argv[4]); +#ifndef VXWORKS + no_threads = argv[5] != NULL && strcmp(argv[5], "nothreads") == 0; +#else + no_threads = 1; +#endif + for (i = 0; i < n; ++i) { + if (!no_threads) { +#ifndef VXWORKS +#ifdef __WIN32__ + unsigned tid; + threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread, + (void*)i, 0, &tid); +#else + pthread_create(&threads[i], NULL, einode_thread, (void*)i); +#endif +#else + ; +#endif + } else + einode_thread((void*)i); + } + + if (!no_threads) +#ifndef VXWORKS + for (i = 0; i < n; ++i) { +#ifdef __WIN32__ + if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0) +#else + if (pthread_join(threads[i], NULL) != 0) +#endif + printf("bad wait thread %d\n", i); + } +#else + ; +#endif + printf("ok\n"); + return 0; +} + +static int my_listen(int port) +{ + int listen_fd; + struct sockaddr_in addr; + const char *on = "1"; + + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + + setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, on, sizeof(on)); + + memset((void*) &addr, 0, (size_t) sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(listen_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + return -1; + + listen(listen_fd, 5); + return listen_fd; +} + -- cgit v1.2.3