4
* Copyright Ericsson AB 1997-2009. All Rights Reserved.
6
* The contents of this file are subject to the Erlang Public License,
7
* Version 1.1, (the "License"); you may not use this file except in
8
* compliance with the License. You should have received a copy of the
9
* Erlang Public License along with this software. If not, it can be
10
* retrieved online at http://www.erlang.org/.
12
* Software distributed under the License is distributed on an "AS IS"
13
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
* the License for the specific language governing rights and limitations
22
#include <sys/types.h>
34
#define _setmode(fd, mode)
39
static char* progname; /* Name of this program (from argv[0]). */
40
static int fd_from_erl; /* File descriptor from Erlang. */
41
static int fd_to_erl; /* File descriptor to Erlang. */
43
static int packet_loop();
44
static void ensure_buf_big_enough();
46
static void reply(char* buf, unsigned size);
50
run_tests(char* argv0, TestCase test_cases[], unsigned number)
57
_setmode(0, _O_BINARY);
58
_setmode(1, _O_BINARY);
62
packet = read_packet(&n);
65
* Dispatch to the appropriate test function.
68
i = packet[0] * 256 + packet[1];
70
fprintf(stderr, "%s: bad test case number %d",
81
/***********************************************************************
83
* R e a d i n g p a c k e t s
85
************************************************************************/
88
* Reads an Erlang term.
90
* Returns: A pointer to a term (an ETERM structure) if there was
91
* at term available, or a NULL pointer if there was an 'eot' (end-of-test)
92
* packet. Aborts if anything else received.
102
encoded = read_packet(&n);
104
switch (encoded[0]) {
109
term = erl_decode(encoded+1);
112
fail("Failed to decode term");
117
fprintf(stderr, "Garbage received: ");
118
dump(encoded, n, 16);
120
fail("C program received garbage");
128
* Reads a packet from Erlang. The packet must be a standard {packet, 2}
129
* packet. This function aborts if any error is detected (including EOF).
131
* Returns: The number of bytes in the packet.
134
char *read_packet(int *len)
137
unsigned char* io_buf = NULL; /* Buffer for file i/o. */
139
unsigned char header[HEADER_SIZE];
140
unsigned packet_length; /* Length of current packet. */
144
* Read the packet header.
147
bytes_read = readn(fd_from_erl, header, HEADER_SIZE);
149
if (bytes_read == 0) {
150
fprintf(stderr, "%s: Unexpected end of file\n", progname);
153
if (bytes_read != HEADER_SIZE) {
154
fprintf(stderr, "%s: Failed to read packet header\n", progname);
159
* Get the length of this packet.
164
for (i = 0; i < HEADER_SIZE; i++)
165
packet_length = (packet_length << 8) | header[i];
167
if (len) *len=packet_length; /* report length only if caller requested it */
169
if ((io_buf = (char *) malloc(packet_length)) == NULL) {
170
fprintf(stderr, "%s: insufficient memory for i/o buffer of size %d\n",
171
progname, packet_length);
176
* Read the packet itself.
179
bytes_read = readn(fd_from_erl, io_buf, packet_length);
180
if (bytes_read != packet_length) {
181
fprintf(stderr, "%s: couldn't read packet of length %d\r\n",
182
progname, packet_length);
191
/***********************************************************************
192
* S e n d i n g r e p l i e s
194
* The functions below send various types of replies back to Erlang.
195
* Each reply start with a letter indicating the type of reply.
197
* Reply Translated to on Erlang side
198
* ----- ----------------------------
199
* [$b|Bytes] {bytes, Bytes}
201
* [$f] test_server:fail()
202
* [$f|Reason] test_server:fail(Reason)
203
* [$t|EncodedTerm] {term, Term}
205
* [$m|Message] io:format("~s", [Message]) (otherwise ignored)
207
***********************************************************************/
210
* This function reports the outcome of a test fail. It is useful if
211
* you implement a test case entirely in C code.
213
* If the ok argument is zero, a [$f] reply will be sent to the
214
* Erlang side (causing test_server:fail() to be called); otherwise,
215
* the atom 'eot' will be sent to Erlang.
217
* If you need to provide more details on a failure, use the fail() function.
221
do_report(file, line, ok)
224
int ok; /* Zero if failed; non-zero otherwise. */
230
reason = ok ? 'e' : 'f';
233
do_fail(file, line, "Generic failure");
235
/* release all unallocated blocks */
237
/* check mem usage stats */
238
erl_eterm_statistics(&ab, &fb);
239
if ((ab == 0) && (fb == 0) ) {
245
sprintf(sbuf, "still %lu terms allocated,"
246
" %lu on freelist at end of test", ab, fb);
247
do_fail(file, line, sbuf);
254
* This function causes a call to test_server:fail(Reason) on the
259
do_fail(char* file, int line, char* reason)
264
sprintf(sbuf+1, "%s, line %d: %s", file, line, reason);
265
reply(sbuf, 1+strlen(sbuf+1));
269
* This function sends a message to the Erlang side.
270
* The message will be written to the test servers log file,
271
* but will otherwise be completly ignored.
275
message(char* format, ...)
281
va_start(ap, format);
282
vsprintf(sbuf+1, format, ap);
285
reply(sbuf, 1+strlen(sbuf+1));
289
* This function sends the given term to the Erlang side,
290
* where it will be received as {term, Term}.
292
* If the given pointer is NULL (indicating an invalid term),
293
* the result on the Erlang side will be the atom 'NULL'.
295
* After sending the term, this function frees the term by
296
* calling erl_free_term().
301
ETERM* term; /* Term to be sent to Erlang side. */
303
char encoded[64*1024];
311
n = 1 + erl_encode(term, encoded+1);
319
/* Seriously broken!!! */
322
send_bin_term(x_ei_buff* x)
326
x2.buff[x2.index++] = 't';
328
reply(x2.buff, x2.index);
334
* This function sends a raw buffer of data to the
335
* Erlang side, where it will be received as {bytes, Bytes}.
339
send_buffer(buf, size)
340
char* buf; /* Buffer with bytes to send to Erlang. */
341
int size; /* Size of data to send to Erlang. */
345
send_buf = (char *) malloc(size+1);
347
memcpy(send_buf+1, buf, size);
348
reply(send_buf, size+1);
352
/***********************************************************************
354
* P r i v a t e h e l p e r s
356
***********************************************************************/
359
* Sends a packet back to Erlang.
363
reply(reply_buf, size)
364
char* reply_buf; /* Buffer with reply. */
365
unsigned size; /* Size of reply. */
367
int n; /* Temporary to hold size. */
368
int i; /* Loop counter. */
372
buf = (char *) malloc(size+HEADER_SIZE);
373
memcpy(buf+HEADER_SIZE, reply_buf, size);
376
* Fill the header starting with the least significant byte.
380
for (i = HEADER_SIZE-1; i >= 0; i--) {
381
buf[i] = (char) n; /* Store least significant byte. */
387
fprintf(stderr, "\r\nReply size: %u\r\n",
388
(unsigned)buf[0] << 8 + (unsigned)buf[1]);
390
for (i = 0; i < size; i++) {
391
fprintf(stderr,"%u %c\r\n",buf[i],buf[i]);
394
fprintf(stderr, "\r\n");
396
write(fd_to_erl, buf, size);
402
* Reads len number of bytes.
407
int fd; /* File descriptor to read from. */
408
unsigned char *buf; /* Store in this buffer. */
409
int len; /* Number of bytes to read. */
411
int n; /* Byte count in last read call. */
412
int sofar = 0; /* Bytes read so far. */
415
if ((n = read(fd, buf+sofar, len-sofar)) <= 0)
416
/* error or EOF in read */
419
} while (sofar < len);
439
for (i=0; i<imax; i++) {
442
strcpy(comma, ",...");
447
fprintf(stderr, "%u%s", (int)(buf[i]), comma);
449
if (isalpha(buf[i])) {
450
fprintf(stderr, "%c%s", buf[i], comma);
453
fprintf(stderr, "%u%s", (int)(buf[i]), comma);