1 //==========================================================================
3 // tests/auto/autohost.inl
5 // Automated Testing by a Host Computer
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //####BSDCOPYRIGHTBEGIN####
40 // -------------------------------------------
42 // Portions of this software may have been derived from OpenBSD or other sources,
43 // and are covered by the appropriate copyright disclaimers included herein.
45 // -------------------------------------------
47 //####BSDCOPYRIGHTEND####
48 //==========================================================================
49 //#####DESCRIPTIONBEGIN####
51 // Author(s): hmt,gthomas
52 // Contributors: hmt,gthomas
54 // Purpose: Automated testing of the eCos TCP/IP Network Stack
57 // This .inl file defines routines which send /orders/ to the server
58 // running on the host machine who served us DHCP, and receive
59 // /results/ from the same machine or machines.
61 // autohost_tell() sends the order to an app "awaitorder" which feeds
62 // the order into obey.sh which obeys the order, for example, running
63 // some tftp sessions to exercise the tftp server.
65 // The /orders/ must come from a predefined list, to match the
66 // selection which obey.sh is expecting, for example "TFTP_SERV_GET"
67 // which has further parameters <target> <timeout>. Additional
68 // parameters are added/manipulated by obey.sh which then invokes a
69 // relevent script (tftpget.sh) to do the test.
71 // The test script's output is returned to us, and is collected by
72 // autohost_getresults() which runs in a high-ist prio thread. It
73 // prints the output, which is expected to match the traditional eCos
74 // PASS:<happy> FAIL:<eek!> sort of format, so that the test farm can
75 // collect these messages from the testcase output, without any direct
76 // connection to the server.
78 // autohost_init() simply starts the autohost_getresults() thread.
80 // The predefined list of orders is *not* defined here or anywhere
81 // else besides obey.sh which does a switch statement for them, to
82 // make it easier to extent; similarly the params each order takes are
83 // not centrally recorded either. It is however a convention that the
84 // word following the /order/ is our own IP address.
87 //####DESCRIPTIONEND####
89 //==========================================================================
91 #include <cyg/infra/testcase.h> // testing infrastructure
93 #include "memcheck.inl" // check on memory usage
95 externC int sprintf( char * /* str */, const char * /* format */, ... );
97 // ------------------------------------------------------------------------
99 #include <pkgconf/system.h>
100 #ifdef CYGPKG_IO_ETH_DRIVERS
101 #include <pkgconf/io_eth_drivers.h>
104 #if defined(XFAIL) || defined(XPASS)
105 // So that the test can override this automation
106 # if defined(XFAIL) && defined(XPASS)
107 # error Both XFAIL and XPASS predefined
111 # define XFAIL "XFAIL"
114 # ifdef CYGPKG_IO_ETH_DRIVERS_SIMULATED_FAILURES
115 // Then we must tell the test server to expect failures.
116 # define XFAIL "XFAIL"
118 #endif // XFAIL/XPASS not predefined
120 // ------------------------------------------------------------------------
126 CYG_TEST_FAIL_EXIT( s );
129 // ------------------------------------------------------------------------
131 #define SOURCE_PORT 9980
132 #define RESULT_PORT 9990
135 autohost_tell( struct bootp *bp, char *orders )
138 struct sockaddr_in slave, local;
140 int len = strlen( orders );
144 char complete_order[256];
147 pexit( "Orders too long" );
149 memset(&slave, 0, sizeof(slave));
150 slave.sin_family = AF_INET;
151 slave.sin_len = sizeof(slave);
152 slave.sin_port = htons(SOURCE_PORT);
153 slave.sin_addr = bp->bp_siaddr; // Talk to our DHCP server
155 s_host = socket(AF_INET, SOCK_STREAM, 0);
157 pexit("stream socket");
160 memset(&local, 0, sizeof(local));
161 local.sin_family = AF_INET;
162 local.sin_len = sizeof(local);
163 local.sin_port = INADDR_ANY;
164 local.sin_addr.s_addr = INADDR_ANY;
165 if(bind(s_host, (struct sockaddr *) &local, sizeof(local)) < 0) {
166 pexit("bind /source/ error");
168 if (setsockopt(s_host, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
169 pexit("setsockopt /source/ SO_REUSEADDR");
172 ret = connect(s_host, (struct sockaddr *)&slave, sizeof(slave));
176 "Connect failed %d err %d, s_host %d, sin_port %x, sin_addr %08x\n",
177 ret, errno, s_host, slave.sin_port, slave.sin_addr.s_addr );
178 pexit("Can't connect to target");
181 sprintf( complete_order,
188 len = 1 + strlen( complete_order ); // Send the null also
190 if ( len != write(s_host, (unsigned char *)complete_order, len ) ) {
191 pexit("Can't send orders");
193 ret = read(s_host, (unsigned char *)&ack, sizeof(ack));
195 pexit("Can't get ACK");
201 // ---------------------------------------------------------------------------
203 #define nHALTAFTERFAIL
205 static cyg_alarm ahr_fail_alarm;
206 static cyg_handle_t ahr_fail_alarm_handle = 0;
207 static cyg_alarm_t ahr_fail_alarm_function;
209 void ahr_fail_alarm_function(cyg_handle_t alarm, cyg_addrword_t data)
211 CYG_TEST_FAIL_EXIT( "Failure reported by autohost" );
215 static int result_passes = 0;
216 static int result_fails = 0;
219 autohost_getresults( cyg_addrword_t loop )
221 int s_source, e_source;
222 struct sockaddr_in e_source_addr, local;
227 s_source = socket(AF_INET, SOCK_STREAM, 6 /* TCP */ );
229 pexit("stream socket");
232 memset(&local, 0, sizeof(local));
233 local.sin_family = AF_INET;
234 local.sin_len = sizeof(local);
235 local.sin_port = ntohs(RESULT_PORT);
236 local.sin_addr.s_addr = INADDR_ANY;
237 if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) {
238 pexit("bind /source/ error");
240 if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
241 pexit("setsockopt /source/ SO_REUSEADDR");
244 if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) {
245 pexit("setsockopt /source/ SO_REUSEPORT");
249 listen(s_source, SOMAXCONN);
252 len = sizeof(e_source_addr);
253 if ((e_source = accept(s_source,
254 (struct sockaddr *)&e_source_addr, &len)) < 0) {
255 pexit("accept /source/");
258 // Wait for "source" to tell us the result
259 if ( 0 >= (len = read(e_source, result, sizeof(result)))) {
260 pexit("Can't read result");
265 while( len && ('\r' == result[len] || '\n' == result[len]) )
269 diag_printf( "%s (from %s:%d)\n", result,
270 inet_ntoa(e_source_addr.sin_addr), ntohs(e_source_addr.sin_port));
273 // Check for a pass message right now:
274 if ( 'P' == result[0] &&
281 // Check for a failure right now:
282 if ( 'F' == result[0] &&
288 // Wait a bit for the others, if any, to come in before halting
289 // the test, since the host is typically running multiple
290 // threads to torment us. Set an alarm to go FAIL_EXIT in 20S.
291 if ( ! ahr_fail_alarm_handle ) {
293 cyg_clock_to_counter(cyg_real_time_clock(), &h),
295 h, /* Attached to this ctr */
296 ahr_fail_alarm_function, /* Call-back function */
297 0, /* Call-back data */
298 &ahr_fail_alarm_handle, /* Returned alarm obj */
299 &ahr_fail_alarm /* put alarm here */
301 cyg_alarm_initialize(
302 ahr_fail_alarm_handle,
303 cyg_current_time() + (20 * 100),
305 cyg_alarm_enable( ahr_fail_alarm_handle );
316 // ---------------------------------------------------------------------------
318 static void autohost_end( int expected_passes )
321 if ( ahr_fail_alarm_handle )
322 cyg_alarm_disable( ahr_fail_alarm_handle );
325 if ( ! (result_passes >= expected_passes) )
326 CYG_TEST_INFO( "XFAIL: Not enough PASS results posted" );
327 if ( ! (0 == result_fails) )
328 CYG_TEST_INFO( "XFAIL: FAIL results posted" );
329 if ( ! (result_passes >= expected_passes && 0 == result_fails) )
330 CYG_TEST_PASS( "XFAIL: Pass anyway" );
332 CYG_TEST_CHECK( result_passes >= expected_passes,
333 "Not enough PASS results posted" );
334 CYG_TEST_CHECK( 0 == result_fails,
335 "FAIL results posted" );
337 if ( result_passes >= expected_passes && 0 == result_fails )
338 CYG_TEST_PASS( "Results from host[s] OK" );
340 // Record and check final state of net stack memory consumption
344 // ---------------------------------------------------------------------------
346 static char ahr_stack[ CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x400 ];
347 static cyg_thread ahr_thread_data;
349 static void autohost_init( void )
351 cyg_handle_t ahr_thread_handle;
352 cyg_thread_create( 5, // Priority - just a number
353 autohost_getresults, // entry
354 1, // entry parameter
355 "Autohost result monitor", // Name
356 &ahr_stack[0], // Stack
357 sizeof(ahr_stack), // Size
358 &ahr_thread_handle, // Handle
359 &ahr_thread_data // Thread data structure
361 cyg_thread_resume(ahr_thread_handle); // Start it
363 // Record initial state of net stack memory consumption