From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- .../emulator/test/obsolete_SUITE_data/Makefile.src | 33 +++ .../test/obsolete_SUITE_data/erl_threads.c | 302 +++++++++++++++++++++ .../test/obsolete_SUITE_data/testcase_driver.c | 262 ++++++++++++++++++ .../test/obsolete_SUITE_data/testcase_driver.h | 57 ++++ 4 files changed, 654 insertions(+) create mode 100644 erts/emulator/test/obsolete_SUITE_data/Makefile.src create mode 100644 erts/emulator/test/obsolete_SUITE_data/erl_threads.c create mode 100644 erts/emulator/test/obsolete_SUITE_data/testcase_driver.c create mode 100644 erts/emulator/test/obsolete_SUITE_data/testcase_driver.h (limited to 'erts/emulator/test/obsolete_SUITE_data') diff --git a/erts/emulator/test/obsolete_SUITE_data/Makefile.src b/erts/emulator/test/obsolete_SUITE_data/Makefile.src new file mode 100644 index 0000000000..d8e2b861c0 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/Makefile.src @@ -0,0 +1,33 @@ +# ``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 via the world wide web 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. +# +# The Initial Developer of the Original Code is Ericsson Utvecklings AB. +# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings +# AB. All Rights Reserved.'' +# +# $Id$ +# + +TEST_DRVS = erl_threads@dll@ +CC = @CC@ +LD = @LD@ +CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@ +SHLIB_EXTRA_LDLIBS = testcase_driver@obj@ + +all: $(TEST_DRVS) + +@SHLIB_RULES@ + +testcase_driver@obj@: testcase_driver.c testcase_driver.h +$(TEST_DRVS): testcase_driver@obj@ + + + diff --git a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c new file mode 100644 index 0000000000..27a5163121 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c @@ -0,0 +1,302 @@ +/* ``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 via the world wide web 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. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" + +#ifndef __WIN32__ + +#define NO_OF_THREADS 2 + +#include +#include + +static int die; +static int cw_passed; +static int res_tf0; +static int res_tf1; +static erl_mutex_t mtx; +static erl_cond_t cnd; +static erl_thread_t tid[NO_OF_THREADS]; +static int need_join[NO_OF_THREADS]; + +typedef struct { + int n; +} thr_arg_t; + + +static void *tf0(void *vta) +{ + int r; + + if (((thr_arg_t *) vta)->n != 0) + goto fail; + + r = erts_mutex_lock(mtx); + if (r != 0) { + erts_mutex_unlock(mtx); + goto fail; + } + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_mutex_unlock(mtx); + if (r != 0) + goto fail; + + res_tf0 = 0; + + return (void *) &res_tf0; + + fail: + return NULL; +} + + +static void *tf1(void *vta) +{ + int r; + + if (((thr_arg_t *) vta)->n != 1) + goto fail; + + r = erts_mutex_lock(mtx); + if (r != 0) { + erts_mutex_unlock(mtx); + goto fail; + } + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_cond_wait(cnd, mtx); + if (r != 0 || die) { + erts_mutex_unlock(mtx); + goto fail; + } + + cw_passed++; + + r = erts_mutex_unlock(mtx); + if (r != 0) + goto fail; + + res_tf1 = 1; + + erts_thread_exit((void *) &res_tf1); + + res_tf1 = 4711; + + fail: + return NULL; +} + +#endif /* #ifndef __WIN32__ */ + +void +testcase_run(TestCaseState_t *tcs) +{ +#ifdef __WIN32__ + testcase_skipped(tcs, "Nothing to test; not supported on windows."); +#else + int i, r; + void *tres[NO_OF_THREADS]; + thr_arg_t ta[NO_OF_THREADS]; + erl_thread_t t1; + + die = 0; + cw_passed = 0; + + for (i = 0; i < NO_OF_THREADS; i++) + need_join[i] = 0; + + res_tf0 = 17; + res_tf1 = 17; + + cnd = mtx = NULL; + + /* Create mutex and cond */ + mtx = erts_mutex_create(); + ASSERT(tcs, mtx); + cnd = erts_cond_create(); + ASSERT(tcs, cnd); + + /* Create the threads */ + ta[0].n = 0; + r = erts_thread_create(&tid[0], tf0, (void *) &ta[0], 0); + ASSERT(tcs, r == 0); + need_join[0] = 1; + + ta[1].n = 1; + r = erts_thread_create(&tid[1], tf1, (void *) &ta[1], 0); + ASSERT(tcs, r == 0); + need_join[1] = 1; + + /* Make sure the threads waits on cond wait */ + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 0, (void) erts_mutex_unlock(mtx)); + + + /* Let one thread pass one cond wait */ + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 1, (void) erts_mutex_unlock(mtx)); + + + /* Let both threads pass one cond wait */ + r = erts_cond_broadcast(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 3, (void) erts_mutex_unlock(mtx)); + + + /* Let the thread that only have passed one cond wait pass the other one */ + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + sleep(1); + + r = erts_mutex_lock(mtx); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + ASSERT_CLNUP(tcs, cw_passed == 4, (void) erts_mutex_unlock(mtx)); + + /* Both threads should have passed both cond waits and exited; + join them and check returned values */ + + r = erts_thread_join(tid[0], &tres[0]); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + need_join[0] = 0; + + ASSERT_CLNUP(tcs, tres[0] == &res_tf0, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf0 == 0, (void) erts_mutex_unlock(mtx)); + + r = erts_thread_join(tid[1], &tres[1]); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + need_join[1] = 0; + + ASSERT_CLNUP(tcs, tres[1] == &res_tf1, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, res_tf1 == 1, (void) erts_mutex_unlock(mtx)); + + /* Test signaling when noone waits */ + + r = erts_cond_signal(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + /* Test broadcasting when noone waits */ + + r = erts_cond_broadcast(cnd); + ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); + + /* erts_cond_timedwait() not supported anymore */ + r = erts_cond_timedwait(cnd, mtx, 1000); + ASSERT_CLNUP(tcs, r != 0, (void) erts_mutex_unlock(mtx)); + ASSERT_CLNUP(tcs, + strcmp(erl_errno_id(r), "enotsup") == 0, + (void) erts_mutex_unlock(mtx)); + + r = erts_mutex_unlock(mtx); + ASSERT(tcs, r == 0); + + r = erts_mutex_destroy(mtx); + ASSERT(tcs, r == 0); + mtx = NULL; + + r = erts_cond_destroy(cnd); + ASSERT(tcs, r == 0); + cnd = NULL; + + /* ... */ + t1 = erts_thread_self(); + + if (cw_passed == 4711) { + /* We don't want to execute this just check that the + symbol/symbols is/are defined */ + erts_thread_kill(t1); + } + +#endif /* #ifndef __WIN32__ */ +} + +char * +testcase_name(void) +{ + return "erl_threads"; +} + +void +testcase_cleanup(TestCaseState_t *tcs) +{ + int i; + for (i = 0; i < NO_OF_THREADS; i++) { + if (need_join[i]) { + erts_mutex_lock(mtx); + die = 1; + erts_cond_broadcast(cnd); + erts_mutex_unlock(mtx); + erts_thread_join(tid[1], NULL); + } + } + if (mtx) + erts_mutex_destroy(mtx); + if (cnd) + erts_cond_destroy(cnd); +} + diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c new file mode 100644 index 0000000000..99d5adb041 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c @@ -0,0 +1,262 @@ +/* ``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 via the world wide web 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. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#include "testcase_driver.h" +#include +#include +#include +#include +#include + +#ifdef __WIN32__ +#undef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 1 +#define vsnprintf _vsnprintf +#endif + +#ifndef HAVE_VSNPRINTF +#define HAVE_VSNPRINTF 0 +#endif + +#define COMMENT_BUF_SZ 4096 + +#define TESTCASE_FAILED 0 +#define TESTCASE_SKIPPED 1 +#define TESTCASE_SUCCEEDED 2 + +typedef struct { + TestCaseState_t visible; + int port; + int result; + jmp_buf done_jmp_buf; + char *comment; + char comment_buf[COMMENT_BUF_SZ]; +} InternalTestCaseState_t; + +long testcase_drv_start(int port, char *command); +int testcase_drv_stop(long drv_data); +int testcase_drv_run(long drv_data, char *buf, int len); + +static DriverEntry testcase_drv_entry = { + NULL, + testcase_drv_start, + testcase_drv_stop, + testcase_drv_run +}; + + +int DRIVER_INIT(testcase_drv)(void *arg) +{ + testcase_drv_entry.driver_name = testcase_name(); + return (int) &testcase_drv_entry; +} + +long +testcase_drv_start(int port, char *command) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) + driver_alloc(sizeof(InternalTestCaseState_t)); + if (!itcs) { + return -1; + } + + itcs->visible.testcase_name = testcase_name(); + itcs->visible.extra = NULL; + itcs->port = port; + itcs->result = TESTCASE_FAILED; + itcs->comment = ""; + + return (long) itcs; +} + +int +testcase_drv_stop(long drv_data) +{ + testcase_cleanup((TestCaseState_t *) drv_data); + driver_free((void *) drv_data); + return 0; +} + +int +testcase_drv_run(long drv_data, char *buf, int len) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; + DriverTermData result_atom; + DriverTermData msg[12]; + + itcs->visible.command = buf; + itcs->visible.command_len = len; + + if (setjmp(itcs->done_jmp_buf) == 0) { + testcase_run((TestCaseState_t *) itcs); + itcs->result = TESTCASE_SUCCEEDED; + } + + switch (itcs->result) { + case TESTCASE_SUCCEEDED: + result_atom = driver_mk_atom("succeeded"); + break; + case TESTCASE_SKIPPED: + result_atom = driver_mk_atom("skipped"); + break; + case TESTCASE_FAILED: + default: + result_atom = driver_mk_atom("failed"); + break; + } + + msg[0] = ERL_DRV_ATOM; + msg[1] = (DriverTermData) result_atom; + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (DriverTermData) itcs->comment; + msg[8] = (DriverTermData) strlen(itcs->comment); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (DriverTermData) 4; + + driver_output_term(itcs->port, msg, 11); + return 0; +} + +int +testcase_assertion_failed(TestCaseState_t *tcs, + char *file, int line, char *assertion) +{ + testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"", + file, line, assertion); + return 0; +} + +void +testcase_printf(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + DriverTermData msg[12]; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + msg[0] = ERL_DRV_ATOM; + msg[1] = (DriverTermData) driver_mk_atom("print"); + + msg[2] = ERL_DRV_PORT; + msg[3] = driver_mk_port(itcs->port); + + msg[4] = ERL_DRV_ATOM; + msg[5] = driver_mk_atom(itcs->visible.testcase_name); + + msg[6] = ERL_DRV_STRING; + msg[7] = (DriverTermData) itcs->comment_buf; + msg[8] = (DriverTermData) strlen(itcs->comment_buf); + + msg[9] = ERL_DRV_TUPLE; + msg[10] = (DriverTermData) 4; + + driver_output_term(itcs->port, msg, 11); +} + + +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SUCCEEDED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_SKIPPED; + itcs->comment = itcs->comment_buf; + + longjmp(itcs->done_jmp_buf, 1); +} + +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...) +{ + InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; + char buf[10]; + size_t bufsz = sizeof(buf); + va_list va; + va_start(va, frmt); +#if HAVE_VSNPRINTF + vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va); +#else + vsprintf(itcs->comment_buf, frmt, va); +#endif + va_end(va); + + itcs->result = TESTCASE_FAILED; + itcs->comment = itcs->comment_buf; + + if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0 + && strcmp("true", buf) == 0) { + fprintf(stderr, "Testcase \"%s\" failed: %s\n", + itcs->visible.testcase_name, itcs->comment); + abort(); + } + + longjmp(itcs->done_jmp_buf, 1); +} + +void *testcase_alloc(size_t size) +{ + return driver_alloc(size); +} + +void *testcase_realloc(void *ptr, size_t size) +{ + return driver_realloc(ptr, size); +} + +void testcase_free(void *ptr) +{ + driver_free(ptr); +} diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h new file mode 100644 index 0000000000..3d85ca6df0 --- /dev/null +++ b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h @@ -0,0 +1,57 @@ +/* ``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 via the world wide web 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. + * + * The Initial Developer of the Original Code is Ericsson Utvecklings AB. + * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings + * AB. All Rights Reserved.'' + * + * $Id$ + */ + +#ifndef TESTCASE_DRIVER_H__ +#define TESTCASE_DRIVER_H__ + +#include "obsolete/driver.h" +#include + +typedef struct { + char *testcase_name; + char *command; + int command_len; + void *extra; +} TestCaseState_t; + +#define ASSERT_CLNUP(TCS, B, CLN) \ +do { \ + if (!(B)) { \ + CLN; \ + testcase_assertion_failed((TCS), __FILE__, __LINE__, #B); \ + } \ +} while (0) + +#define ASSERT(TCS, B) ASSERT_CLNUP(TCS, B, (void) 0) + +void testcase_printf(TestCaseState_t *tcs, char *frmt, ...); +void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...); +void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...); +void testcase_failed(TestCaseState_t *tcs, char *frmt, ...); +int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line, + char *assertion); +void *testcase_alloc(size_t size); +void *testcase_realloc(void *ptr, size_t size); +void testcase_free(void *ptr); + + +char *testcase_name(void); +void testcase_run(TestCaseState_t *tcs); +void testcase_cleanup(TestCaseState_t *tcs); + +#endif -- cgit v1.2.3