]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/io/fileio/v2_0/tests/select.c
Initial revision
[karo-tx-redboot.git] / packages / io / fileio / v2_0 / tests / select.c
1 //==========================================================================
2 //
3 //      select.c
4 //
5 //      Test select implementation
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):           nickg
44 // Contributors:        nickg
45 // Date:                2000-05-25
46 // Purpose:             Test select implementation
47 // Description:         
48 //                      
49 //                      
50 //                      
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <pkgconf/system.h>
57 #include <pkgconf/isoinfra.h>
58
59 #ifndef CYGINT_ISO_PTHREAD_IMPL
60 # define NA_MSG "POSIX threads needed to run test"
61 #endif
62
63 #include <cyg/infra/testcase.h>
64
65 #ifndef NA_MSG
66
67 #include <pkgconf/hal.h>
68 #include <pkgconf/kernel.h>
69 #include <pkgconf/io_fileio.h>
70
71 #ifdef CYGPKG_IO_SERIAL
72 #include <pkgconf/io_serial.h>
73 #endif
74
75 #define __ECOS 1                        // dont like this at all
76
77 #include <cyg/kernel/ktypes.h>         // base kernel types
78 #include <cyg/infra/cyg_trac.h>        // tracing macros
79 #include <cyg/infra/cyg_ass.h>         // assertion macros
80
81 #include <unistd.h>
82 #include <fcntl.h>
83 #include <sys/stat.h>
84 #include <sys/select.h>
85 #include <errno.h>
86 #include <string.h>
87
88 #ifdef CYGPKG_NET
89 #include <network.h>
90 #include <arpa/inet.h>
91 #define TEST_NET
92 #endif
93
94 #ifdef CYGPKG_IO_SERIAL_LOOP
95 #define TEST_DEV
96 #endif
97
98 #include <pthread.h>
99 #include <signal.h>
100
101
102 #include <cyg/infra/diag.h>            // HAL polled output
103
104 //--------------------------------------------------------------------------
105
106 #define SHOW_RESULT( _fn, _res ) \
107 diag_printf("INFO: " #_fn "() returned %ld %s\n", (long)_res, _res<0?strerror(errno):"");
108
109 //--------------------------------------------------------------------------
110 // Thread stack.
111
112 char thread1_stack[PTHREAD_STACK_MIN*2];
113 char thread2_stack[PTHREAD_STACK_MIN*2];
114
115 //--------------------------------------------------------------------------
116 // Local variables
117
118 // Thread IDs
119 pthread_t thread1;
120 pthread_t thread2;
121
122 #ifdef TEST_NET        
123 struct sockaddr_in sa;
124 #endif
125
126 //--------------------------------------------------------------------------
127 // Test buffers
128 // The buffer size here must be less that the size of the serial device
129 // buffers since the serial devices do not currently implement flow
130 // control.
131
132 #define TEST_BUFSIZE 100
133
134 #ifdef TEST_NET        
135 static char buf1[TEST_BUFSIZE];
136 static char buf2[TEST_BUFSIZE];
137 static char buf3[TEST_BUFSIZE];
138 #endif
139 #ifdef TEST_DEV
140 static char sbuf1[TEST_BUFSIZE];
141 static char sbuf2[TEST_BUFSIZE];
142 static char sbuf3[TEST_BUFSIZE];
143 #endif
144
145
146 //--------------------------------------------------------------------------
147
148 void show_fdsets( char *s, int nfd, fd_set *rd, fd_set *wr, fd_set *ex )
149 {
150     int i;
151     diag_printf("INFO:<%s nfd %d ",s,nfd);
152
153     if( rd )
154     {
155         diag_printf("rd: [");
156         for( i = 0; i < nfd ; i++ )
157             if( FD_ISSET( i, rd ) ) diag_printf("%d ",i);
158         diag_printf("] ");        
159     }    
160     if( wr )
161     {
162         diag_printf("wr: [");                
163         for( i = 0; i < nfd ; i++ )
164             if( FD_ISSET( i, wr ) ) diag_printf("%d ",i);
165         diag_printf("] ");        
166     }
167     if( ex )
168     {
169         diag_printf("ex: [");                
170         for( i = 0; i < nfd ; i++ )
171             if( FD_ISSET( i, ex ) ) diag_printf("%d ",i);
172         diag_printf("] ");                
173     }
174
175     diag_printf(">\n");
176 }
177
178
179 //--------------------------------------------------------------------------
180
181 void *pthread_entry1( void *arg)
182 {
183 #ifdef TEST_NET        
184     int fd = 0, fd2 = -1;
185     struct sockaddr_in accsa;
186     socklen_t accsa_len = sizeof(accsa);
187     int netstate = 0;
188 #endif    
189 #ifdef TEST_DEV    
190     int ser0;
191     int serstate = 0;
192 #endif
193 #if defined(TEST_DEV) || defined(TEST_NET)
194     int i;
195     ssize_t done;
196 #endif    
197     int netdone = 0;
198     int serdone = 0;
199     int err;
200     fd_set rd, wr;
201     
202     CYG_TEST_INFO( "Thread 1 running" );
203
204     FD_ZERO( &rd );
205     FD_ZERO( &wr );
206     
207 #ifdef TEST_DEV
208
209     CYG_TEST_INFO( "Thread1: calling open()");
210     ser0 = open("/dev/ser0", O_RDWR );
211     if( ser0 < 0 ) SHOW_RESULT( open, ser0 );
212     CYG_TEST_CHECK( ser0 >= 0, "open(/dev/ser0) returned error");
213
214     FD_SET( ser0, &rd );
215 #else
216     serdone = 1;
217 #endif
218
219 #ifdef TEST_NET
220
221     for( i = 0; i < TEST_BUFSIZE; i++ ) buf1[i] = i;
222     
223     CYG_TEST_INFO( "Thread1: calling socket()");        
224     fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
225     if( fd < 0 ) SHOW_RESULT( socket, fd );
226     CYG_TEST_CHECK( fd >= 0, "socket() returned error");
227
228     CYG_TEST_INFO( "Thread1: calling bind()");
229     err = bind( fd, (struct sockaddr *)&sa, sizeof(sa));
230     if( err < 0 ) SHOW_RESULT( bind, err );    
231     CYG_TEST_CHECK( err == 0, "bind() returned error");
232
233     CYG_TEST_INFO( "Thread1: calling listen()");
234     err = listen( fd, 3);
235     if( err < 0 ) SHOW_RESULT( listen, err );    
236     CYG_TEST_CHECK( err == 0, "listen() returned error");
237
238     FD_SET( fd, &rd );
239     
240 #else
241     netdone = 1;
242 #endif
243
244     while(!(netdone && serdone))
245     {
246         fd_set rd_res = rd;
247         fd_set wr_res = wr;
248         
249         CYG_TEST_INFO( "Thread1: calling select()");
250         show_fdsets( "Thread1 request: ", 8, &rd_res, &wr_res, NULL );
251         err = select( 8, &rd_res, &wr_res, NULL, NULL );
252         if( err < 0 ) SHOW_RESULT( select, err );    
253         CYG_TEST_CHECK( err >= 0, "select() returned error");
254         show_fdsets( "Thread1 result: ", 8, &rd_res, &wr_res, NULL );        
255         
256 #ifdef TEST_NET
257         switch( netstate )
258         {
259         case 0:
260             CYG_TEST_INFO( "Thread1: netstate 0");
261             if( FD_ISSET( fd, &rd_res ) )
262             {
263                 CYG_TEST_INFO( "Thread1: calling accept(fd)");
264                 fd2 = accept( fd, (struct sockaddr *)&accsa, &accsa_len );
265                 if( fd2 < 0 ) SHOW_RESULT( accept, fd2 );    
266                 CYG_TEST_CHECK( fd2 >= 0, "accept() returned error");
267
268                 FD_CLR( fd, &rd );
269                 FD_SET( fd2, &wr );
270
271                 netstate++;                
272             }
273             break;
274
275
276         case 1:
277             CYG_TEST_INFO( "Thread1: netstate 1");
278             if( FD_ISSET( fd2, &wr_res ) )
279             {
280                 
281                 CYG_TEST_INFO( "Thread1: calling write(fd2)");
282                 done = write( fd2, buf1, TEST_BUFSIZE);
283                 if( done != TEST_BUFSIZE ) SHOW_RESULT( write, done );
284                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "write() returned bad size");
285
286                 FD_CLR( fd2, &wr );
287                 FD_SET( fd2, &rd );
288
289                 netstate++;
290             }
291             break;
292
293         case 2:
294             CYG_TEST_INFO( "Thread1: netstate 2");
295             if( FD_ISSET( fd2, &rd_res ) )
296             {
297                 CYG_TEST_INFO( "Thread1: calling read(fd2)");
298                 done = read( fd2, buf3, TEST_BUFSIZE);
299                 if( done != TEST_BUFSIZE ) SHOW_RESULT( read, done );
300                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "read() returned bad size");    
301
302                 for( i = 0; i < TEST_BUFSIZE; i++ )
303                     if( buf1[i] != buf3[i] )
304                         diag_printf("buf1[%d](%02x) != buf3[%d](%02x)\n",i,buf1[i],i,buf3[i]);
305
306                 FD_CLR( fd2, &rd );
307
308                 netstate++;
309                 netdone = 1;
310                 CYG_TEST_INFO( "Thread1: netdone");
311             }
312             break;
313             
314         }
315 #endif        
316
317 #ifdef TEST_DEV
318         switch( serstate )
319         {
320         case 0:
321             CYG_TEST_INFO( "Thread1: serstate 0");
322             if( FD_ISSET( ser0, &rd_res ) )
323             {
324                 CYG_TEST_INFO( "Thread1: calling read(ser0)");
325                 done = read( ser0, sbuf2, TEST_BUFSIZE);
326                 if( done != TEST_BUFSIZE ) SHOW_RESULT( read, done );
327                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "read() returned bad size");    
328
329                 for( i = 0; i < TEST_BUFSIZE; i++ )
330                     if( sbuf1[i] != sbuf2[i] )
331                         diag_printf("buf1[%d](%02x) != buf2[%d](%02x)\n",i,sbuf1[i],i,sbuf2[i]);
332
333                 FD_CLR( ser0, &rd );
334                 FD_SET( ser0, &wr );
335                 serstate++;
336                 
337             }
338             break;
339             
340         case 1:
341             CYG_TEST_INFO( "Thread1: serstate 1");
342             if( FD_ISSET( ser0, &wr_res ) )
343             {
344                 CYG_TEST_INFO( "Thread1: calling write(ser0)");
345                 done = write( ser0, sbuf2, TEST_BUFSIZE);
346                 if( done != TEST_BUFSIZE ) SHOW_RESULT( write, done );
347                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "write() returned bad size");
348
349                 FD_CLR( ser0, &wr );
350                 
351                 serstate++;
352                 serdone = 1;
353                 CYG_TEST_INFO( "Thread1: serdone");
354             }
355             else FD_SET( ser0, &wr );
356             break;
357         }
358 #endif        
359     }
360
361 #ifdef TEST_NET    
362     CYG_TEST_INFO( "Thread1: calling close(fd)");
363     err = close(fd);
364     if( err < 0 ) SHOW_RESULT( close, err );    
365     CYG_TEST_CHECK( err == 0, "close() returned error");    
366
367     if( fd2 >= 0 )
368     {
369         CYG_TEST_INFO( "Thread1: calling close(fd2)");
370         err = close(fd2);
371         if( err < 0 ) SHOW_RESULT( close, err );    
372         CYG_TEST_CHECK( err == 0, "close() returned error");
373     }
374 #endif
375 #ifdef TEST_DEV
376     CYG_TEST_INFO( "Thread1: calling close(ser0)");
377     err = close(ser0);
378     if( err < 0 ) SHOW_RESULT( close, err );    
379     CYG_TEST_CHECK( err == 0, "close() returned error");    
380 #endif
381     
382     CYG_TEST_INFO( "Thread1: calling pthread_exit()");    
383     pthread_exit( arg );
384 }
385
386 //--------------------------------------------------------------------------
387
388 void *pthread_entry2( void *arg)
389 {
390 #ifdef TEST_NET        
391     int fd;
392     int netstate = 0;
393 #endif    
394 #ifdef TEST_DEV    
395     int ser1;
396     int serstate = 0;
397 #endif    
398 #if defined(TEST_DEV) || defined(TEST_NET)
399     int i;
400     ssize_t done;
401 #endif    
402     int netdone = 0;
403     int serdone = 0;
404     int err;
405     fd_set rd, wr;
406     
407     CYG_TEST_INFO( "Thread 2 running" );
408
409     FD_ZERO( &rd );
410     FD_ZERO( &wr );
411
412 #ifdef TEST_NET            
413     CYG_TEST_INFO( "Thread2: calling socket()");
414     fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
415     if( fd < 0 ) SHOW_RESULT( socket, fd );
416     CYG_TEST_CHECK( fd >= 0, "socket() returned error");
417
418     CYG_TEST_INFO( "Thread2: calling connect()");
419     err = connect( fd, (struct sockaddr *)&sa, sizeof(sa));
420     if( err < 0 ) SHOW_RESULT( connect, err );    
421     CYG_TEST_CHECK( err == 0, "connect() returned error");
422
423     FD_SET( fd, &rd );
424 #else
425     netdone = 1;
426 #endif
427
428 #ifdef TEST_DEV
429     for( i = 0; i < TEST_BUFSIZE; i++ ) sbuf1[i] = i;
430     
431     CYG_TEST_INFO( "Thread2: calling open(/dev/ser1)");
432     ser1 = open("/dev/ser1", O_RDWR );
433     if( ser1 < 0 ) SHOW_RESULT( open, ser1 );
434     CYG_TEST_CHECK( ser1 >= 0, "open(/dev/ser1) returned error");
435
436     CYG_TEST_INFO( "Thread2: calling write(ser1)");
437     done = write( ser1, sbuf1, TEST_BUFSIZE);
438     if( done != TEST_BUFSIZE ) SHOW_RESULT( write, done );
439     CYG_TEST_CHECK( done == TEST_BUFSIZE, "write() returned bad size");
440     
441     FD_SET( ser1, &wr );
442     
443 #else
444     serdone = 1;
445 #endif    
446     
447     while(!(netdone && serdone))
448     {
449         fd_set rd_res = rd;
450         fd_set wr_res = wr;
451         
452         CYG_TEST_INFO( "Thread2: calling select()");
453         show_fdsets( "Thread2 request: ", 8, &rd_res, &wr_res, NULL );
454         err = select( 8, &rd_res, &wr_res, NULL, NULL );
455         if( err < 0 ) SHOW_RESULT( select, err );    
456         CYG_TEST_CHECK( err >= 0, "select() returned error");    
457         show_fdsets( "Thread2 result: ", 8, &rd_res, &wr_res, NULL );
458                 
459 #ifdef TEST_NET
460         switch( netstate )
461         {
462         case 0:
463             CYG_TEST_INFO( "Thread2: netstate 0");
464             if( FD_ISSET( fd, &rd_res ) )
465             {
466                 CYG_TEST_INFO( "Thread2: calling read()");
467                 done = read( fd, buf2, TEST_BUFSIZE);
468                 if( done != TEST_BUFSIZE ) SHOW_RESULT( read, done );
469                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "read() returned bad size");    
470
471                 for( i = 0; i < TEST_BUFSIZE; i++ )
472                     if( buf1[i] != buf2[i] )
473                         diag_printf("buf1[%d](%02x) != buf2[%d](%02x)\n",i,buf1[i],i,buf2[i]);
474
475                 netstate++;
476
477                 FD_CLR( fd, &rd );
478                 FD_SET( fd, &wr );
479             }
480             break;
481
482         case 1:
483             CYG_TEST_INFO( "Thread2: netstate 1");
484             if( FD_ISSET( fd, &wr_res ) )
485             {
486
487                 CYG_TEST_INFO( "Thread2: calling write()");
488                 done = write( fd, buf2, TEST_BUFSIZE);
489                 if( done != TEST_BUFSIZE ) SHOW_RESULT( write, done );
490                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "write() returned bad size");
491
492                 FD_CLR( fd, &wr );
493                 
494                 netstate++;
495                 netdone = 1;
496                 CYG_TEST_INFO( "Thread2: netdone");
497             }
498             break;
499             
500         }
501 #endif
502
503 #ifdef TEST_DEV
504         switch( serstate )
505         {
506         case 0:
507             CYG_TEST_INFO( "Thread2: serstate 0");
508             if( FD_ISSET( ser1, &wr_res ) )
509             {
510                 FD_CLR( ser1, &wr );
511                 FD_SET( ser1, &rd );
512                 serstate++;
513             }
514             break;
515
516         case 1:
517             CYG_TEST_INFO( "Thread2: serstate 1");            
518             if( FD_ISSET( ser1, &rd_res ) )
519             {
520                 CYG_TEST_INFO( "Thread2: calling read(ser1)");
521                 done = read( ser1, sbuf3, TEST_BUFSIZE);
522                 if( done != TEST_BUFSIZE ) SHOW_RESULT( read, done );
523                 CYG_TEST_CHECK( done == TEST_BUFSIZE, "read() returned bad size");    
524
525                 for( i = 0; i < TEST_BUFSIZE; i++ )
526                     if( sbuf1[i] != sbuf3[i] )
527                         diag_printf("sbuf1[%d](%02x) != sbuf3[%d](%02x)\n",i,sbuf1[i],i,sbuf3[i]);
528
529                 FD_CLR( ser1, &rd );
530
531                 serstate++;
532                 serdone = 1;
533                 CYG_TEST_INFO( "Thread2: serdone");
534             }
535             break;
536         }
537 #endif        
538     }
539
540 #ifdef TEST_NET    
541     CYG_TEST_INFO( "Thread2: calling close(fd)");
542     err = close(fd);
543     if( err < 0 ) SHOW_RESULT( close, err );    
544     CYG_TEST_CHECK( err == 0, "close() returned error");    
545 #endif
546 #ifdef TEST_DEV
547     CYG_TEST_INFO( "Thread2: calling close(ser1)");
548     err = close(ser1);
549     if( err < 0 ) SHOW_RESULT( close, err );    
550     CYG_TEST_CHECK( err == 0, "close(ser1) returned error");    
551 #endif
552     
553     
554     CYG_TEST_INFO( "Thread2: calling pthread_exit()");    
555     pthread_exit( arg );
556 }
557
558 //==========================================================================
559 // main
560
561 int main( int argc, char **argv )
562 {
563     void *retval;
564     pthread_attr_t attr;
565     struct sched_param schedparam;
566
567     CYG_TEST_INIT();
568
569 #ifdef TEST_NET
570     sa.sin_family = AF_INET;
571     sa.sin_len = sizeof(sa);
572     inet_aton("127.0.0.1", &sa.sin_addr);
573     sa.sin_port = htons(1234);
574     init_all_network_interfaces();
575 #endif
576     
577     // Create test threads
578
579     {
580         pthread_attr_init( &attr );
581
582         schedparam.sched_priority = 10;
583         pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
584         pthread_attr_setschedpolicy( &attr, SCHED_RR );
585         pthread_attr_setschedparam( &attr, &schedparam );
586         pthread_attr_setstackaddr( &attr, (void *)&thread1_stack[sizeof(thread1_stack)] );
587         pthread_attr_setstacksize( &attr, sizeof(thread1_stack) );
588
589         pthread_create( &thread1,
590                         &attr,
591                         pthread_entry1,
592                         (void *)0x12345671);
593     }
594
595     {
596         pthread_attr_init( &attr );
597
598         schedparam.sched_priority = 5;
599         pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
600         pthread_attr_setschedpolicy( &attr, SCHED_RR );
601         pthread_attr_setschedparam( &attr, &schedparam );
602         pthread_attr_setstackaddr( &attr, (void *)&thread2_stack[sizeof(thread2_stack)] );
603         pthread_attr_setstacksize( &attr, sizeof(thread2_stack) );
604
605         pthread_create( &thread2,
606                         &attr,
607                         pthread_entry2,
608                         (void *)0x12345672);
609     }
610     
611     // Now join with thread1
612     CYG_TEST_INFO( "Main: calling pthread_join(thread1)");
613     pthread_join( thread1, &retval );
614
615     // And thread 2
616     CYG_TEST_INFO( "Main: calling pthread_join(thread2)");
617     pthread_join( thread2, &retval );
618
619     CYG_TEST_PASS_FINISH("select");
620 }
621
622 #else
623
624 //==========================================================================
625 // main
626
627 void cyg_start(void)
628 {
629     CYG_TEST_INIT();
630
631     CYG_TEST_NA(NA_MSG);
632 }
633
634 #endif
635
636
637 // -------------------------------------------------------------------------
638 // EOF socket.c