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 --- lib/erl_interface/test/all_SUITE_data/runner.c | 457 +++++++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 lib/erl_interface/test/all_SUITE_data/runner.c (limited to 'lib/erl_interface/test/all_SUITE_data/runner.c') diff --git a/lib/erl_interface/test/all_SUITE_data/runner.c b/lib/erl_interface/test/all_SUITE_data/runner.c new file mode 100644 index 0000000000..24df0f5f40 --- /dev/null +++ b/lib/erl_interface/test/all_SUITE_data/runner.c @@ -0,0 +1,457 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 1997-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 +#include +#include +#include +#include +#ifndef __WIN32__ +#include +#endif +#include + +#include "runner.h" + +#ifndef __WIN32__ +#define _O_BINARY 0 +#define _setmode(fd, mode) +#endif + +#define HEADER_SIZE 4 + +static char* progname; /* Name of this program (from argv[0]). */ +static int fd_from_erl; /* File descriptor from Erlang. */ +static int fd_to_erl; /* File descriptor to Erlang. */ + +static int packet_loop(); +static void ensure_buf_big_enough(); +static int readn(); +static void reply(char* buf, unsigned size); +static void dump(); + +void +run_tests(char* argv0, TestCase test_cases[], unsigned number) +{ + int i; + int n; + char* packet; + + progname = argv0; + _setmode(0, _O_BINARY); + _setmode(1, _O_BINARY); + fd_from_erl = 0; + fd_to_erl = 1; + + packet = read_packet(&n); + + /* + * Dispatch to the appropriate test function. + */ + + i = packet[0] * 256 + packet[1]; + if (i >= number) { + fprintf(stderr, "%s: bad test case number %d", + progname, i); + free(packet); + exit(1); + } else { + (*test_cases[i])(); + free(packet); + } +} + + +/*********************************************************************** + * + * R e a d i n g p a c k e t s + * + ************************************************************************/ + +/* + * Reads an Erlang term. + * + * Returns: A pointer to a term (an ETERM structure) if there was + * at term available, or a NULL pointer if there was an 'eot' (end-of-test) + * packet. Aborts if anything else received. + */ + +ETERM* +get_term(void) +{ + char* encoded; + ETERM* term; + int n; + + encoded = read_packet(&n); + + switch (encoded[0]) { + case 'e': + free(encoded); + return NULL; + case 't': + term = erl_decode(encoded+1); + free(encoded); + if (term == NULL) { + fail("Failed to decode term"); + exit(0); + } + return term; + default: + fprintf(stderr, "Garbage received: "); + dump(encoded, n, 16); + putc('\n', stderr); + fail("C program received garbage"); + free(encoded); + exit(1); + } +} + + +/* + * Reads a packet from Erlang. The packet must be a standard {packet, 2} + * packet. This function aborts if any error is detected (including EOF). + * + * Returns: The number of bytes in the packet. + */ + +char *read_packet(int *len) +{ + + unsigned char* io_buf = NULL; /* Buffer for file i/o. */ + int i; + unsigned char header[HEADER_SIZE]; + unsigned packet_length; /* Length of current packet. */ + int bytes_read; + + /* + * Read the packet header. + */ + + bytes_read = readn(fd_from_erl, header, HEADER_SIZE); + + if (bytes_read == 0) { + fprintf(stderr, "%s: Unexpected end of file\n", progname); + exit(1); + } + if (bytes_read != HEADER_SIZE) { + fprintf(stderr, "%s: Failed to read packet header\n", progname); + exit(1); + } + + /* + * Get the length of this packet. + */ + + packet_length = 0; + + for (i = 0; i < HEADER_SIZE; i++) + packet_length = (packet_length << 8) | header[i]; + + if (len) *len=packet_length; /* report length only if caller requested it */ + + if ((io_buf = (char *) malloc(packet_length)) == NULL) { + fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n", + progname, packet_length); + exit(1); + } + + /* + * Read the packet itself. + */ + + bytes_read = readn(fd_from_erl, io_buf, packet_length); + if (bytes_read != packet_length) { + fprintf(stderr, "%s: couldn't read packet of length %d\r\n", + progname, packet_length); + free(io_buf); + exit(1); + } + + return io_buf; +} + + +/*********************************************************************** + * S e n d i n g r e p l i e s + * + * The functions below send various types of replies back to Erlang. + * Each reply start with a letter indicating the type of reply. + * + * Reply Translated to on Erlang side + * ----- ---------------------------- + * [$b|Bytes] {bytes, Bytes} + * [$e] eot + * [$f] test_server:fail() + * [$f|Reason] test_server:fail(Reason) + * [$t|EncodedTerm] {term, Term} + * [$N] 'NULL' + * [$m|Message] io:format("~s", [Message]) (otherwise ignored) + * + ***********************************************************************/ + +/* + * This function reports the outcome of a test fail. It is useful if + * you implement a test case entirely in C code. + * + * If the ok argument is zero, a [$f] reply will be sent to the + * Erlang side (causing test_server:fail() to be called); otherwise, + * the atom 'eot' will be sent to Erlang. + * + * If you need to provide more details on a failure, use the fail() function. + */ + +void +do_report(file, line, ok) + char* file; + int line; + int ok; /* Zero if failed; non-zero otherwise. */ +{ + char reason; + unsigned long ab; + unsigned long fb; + + reason = ok ? 'e' : 'f'; + + if (!ok) { + do_fail(file, line, "Generic failure"); + } else { + /* release all unallocated blocks */ + erl_eterm_release(); + /* check mem usage stats */ + erl_eterm_statistics(&ab, &fb); + if ((ab == 0) && (fb == 0) ) { + reply(&reason, 1); + } + else { + char sbuf[128]; + + sprintf(sbuf, "still %lu terms allocated," + " %lu on freelist at end of test", ab, fb); + do_fail(file, line, sbuf); + } + } +} + + +/* + * This function causes a call to test_server:fail(Reason) on the + * Erlang side. + */ + +void +do_fail(char* file, int line, char* reason) +{ + char sbuf[2048]; + + sbuf[0] = 'f'; + sprintf(sbuf+1, "%s, line %d: %s", file, line, reason); + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends a message to the Erlang side. + * The message will be written to the test servers log file, + * but will otherwise be completly ignored. + */ + +void +message(char* format, ...) +{ + va_list ap; + char sbuf[1024]; + + sbuf[0] = 'm'; + va_start(ap, format); + vsprintf(sbuf+1, format, ap); + va_end(ap); + + reply(sbuf, 1+strlen(sbuf+1)); +} + +/* + * This function sends the given term to the Erlang side, + * where it will be received as {term, Term}. + * + * If the given pointer is NULL (indicating an invalid term), + * the result on the Erlang side will be the atom 'NULL'. + * + * After sending the term, this function frees the term by + * calling erl_free_term(). + */ + +void +send_term(term) + ETERM* term; /* Term to be sent to Erlang side. */ +{ + char encoded[64*1024]; + int n; + + if (term == NULL) { + encoded[0] = 'N'; + n = 1; + } else { + encoded[0] = 't'; + n = 1 + erl_encode(term, encoded+1); + erl_free_term(term); + } + reply(encoded, n); +} + +#if 0 + +/* Seriously broken!!! */ + +void +send_bin_term(x_ei_buff* x) +{ + x_ei_buff x2; + x_ei_new(&x2); + x2.buff[x2.index++] = 't'; + x_ei_append(&x2, x); + reply(x2.buff, x2.index); + free(x2.buff); +} +#endif + +/* + * This function sends a raw buffer of data to the + * Erlang side, where it will be received as {bytes, Bytes}. + */ + +void +send_buffer(buf, size) + char* buf; /* Buffer with bytes to send to Erlang. */ + int size; /* Size of data to send to Erlang. */ +{ + char* send_buf; + + send_buf = (char *) malloc(size+1); + send_buf[0] = 'b'; + memcpy(send_buf+1, buf, size); + reply(send_buf, size+1); + free(send_buf); +} + +/*********************************************************************** + * + * P r i v a t e h e l p e r s + * + ***********************************************************************/ + +/* + * Sends a packet back to Erlang. + */ + +static void +reply(reply_buf, size) + char* reply_buf; /* Buffer with reply. */ + unsigned size; /* Size of reply. */ +{ + int n; /* Temporary to hold size. */ + int i; /* Loop counter. */ + char* buf; + + + buf = (char *) malloc(size+HEADER_SIZE); + memcpy(buf+HEADER_SIZE, reply_buf, size); + + /* + * Fill the header starting with the least significant byte. + */ + + n = size; + for (i = HEADER_SIZE-1; i >= 0; i--) { + buf[i] = (char) n; /* Store least significant byte. */ + n = n >> 8; + } + + size += HEADER_SIZE; +/* + fprintf(stderr, "\r\nReply size: %u\r\n", + (unsigned)buf[0] << 8 + (unsigned)buf[1]); + + for (i = 0; i < size; i++) { + fprintf(stderr,"%u %c\r\n",buf[i],buf[i]); + } + + fprintf(stderr, "\r\n"); +*/ + write(fd_to_erl, buf, size); + free(buf); +} + + +/* + * Reads len number of bytes. + */ + +static int +readn(fd, buf, len) + int fd; /* File descriptor to read from. */ + unsigned char *buf; /* Store in this buffer. */ + int len; /* Number of bytes to read. */ +{ + int n; /* Byte count in last read call. */ + int sofar = 0; /* Bytes read so far. */ + + do { + if ((n = read(fd, buf+sofar, len-sofar)) <= 0) + /* error or EOF in read */ + return(n); + sofar += n; + } while (sofar < len); + return sofar; +} + +void +dump(buf, sz, max) + unsigned char* buf; + int sz; + int max; +{ + int i, imax; + char comma[5] = ","; + + if (!sz) + return; + if (sz > max) + imax = max; + else + imax = sz; + + for (i=0; i max) + strcpy(comma, ",..."); + else + comma[0] = 0; + } + if (isdigit(buf[i])) + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + else { + if (isalpha(buf[i])) { + fprintf(stderr, "%c%s", buf[i], comma); + } + else + fprintf(stderr, "%u%s", (int)(buf[i]), comma); + } + } +} + -- cgit v1.2.3