3 ==================================================================================
4 Copyright (c) 2020-2021 Nokia
5 Copyright (c) 2020-2021 AT&T Intellectual Property.
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 ==================================================================================
23 Abstract: This is the main driver to test the si95 core functions
24 (within rmr/src/si/src/si95).
26 Author: E. Scott Daniels
40 #include <sys/epoll.h>
41 #include <semaphore.h>
44 #include <netdb.h> // these four needed for si address tests
47 #include <netinet/in.h>
51 // specific test tools in this directory
52 #undef NNG_UNDER_TEST // NNG is NOT under test so undefine if set
53 #define NO_EMULATION 1 // no emulation of transport functions
54 #define NO_PRIVATE_HEADERS 1 // no rmr_si or rmr_nng headers
55 #define NO_DUMMY_RMR 1 // no msg things
57 #include "test_support.c" // things like fail_if()
58 #include "test_transport_em.c" // system/transport emulation (open, close, connect, etc)
60 #include <rmr_logging.h>
64 // ------------- dummy functions to force edge cases when we can ---------------------------------------
66 #define SYSTEM_UNDER_TEST 1 // for conditional code
69 These are global so they can be reset for individual tests.
71 static int good_mallocs = 0; // number of initial good malocs before failurs
72 static int bad_mallocs = 1; // number of failed mallocs (consecutive)
74 static void* test_malloc( size_t n ) {
76 fprintf( stderr, ">>>> test malloc: %d %d\n", good_mallocs, bad_mallocs );
91 // -----------------------------------------------------------------------------------------------------
93 #include <si95/siaddress.c>
94 //#include <si95/sialloc.c>
95 #include <si95/sibldpoll.c>
96 #include <si95/sicbreg.c>
97 #include <si95/sicbstat.c>
98 #include <si95/siclose.c>
99 #include <si95/siconnect.c>
100 #include <si95/siestablish.c>
101 #include <si95/sigetadd.c>
102 #include <si95/sigetname.c>
103 #include <si95/siinit.c>
104 #include <si95/silisten.c>
105 #include <si95/sinew.c>
106 #include <si95/sinewses.c>
107 #include <si95/sipoll.c>
108 //#include <si95/sircv.c>
109 #include <si95/sisend.c>
110 #include <si95/sisendt.c>
111 #include <si95/sishutdown.c>
112 #include <si95/siterm.c>
113 #include <si95/sitrash.c>
114 #define malloc test_malloc
115 #include <si95/siwait.c>
118 // ---------------------------------------------------------------------
120 void* si_ctx = NULL; // a global context might be useful
122 // ---------------------------------------------------------------------
125 Fake callback to register.
127 static int test_cb( void* data ) {
132 Returns error for coverage testing of CB calls
134 static int test_cb_err( void* data ) {
139 Memory allocation/free related tests
141 static int memory( ) {
146 // ---- SInew ----------------
147 ptr = SInew( 100 ); // invalid block type should return nil
148 errors += fail_not_nil( ptr, "memory: sinew did not return nil when given a valid struct type" );
149 SItrash( 100, NULL ); // drive trash for coverage
151 iptr = SInew( IOQ_BLK );
152 errors += fail_if_nil( iptr, "memory: sinew returned nil when given ioq request" );
153 SItrash( IOQ_BLK, iptr );
155 ptr = SInew( TP_BLK );
156 errors += fail_if_nil( ptr, "memory: sinew returned nil when given tpblk request" );
158 iptr = SInew( IOQ_BLK );
159 ((struct tp_blk *)ptr)->squeue = iptr;
160 SItrash( TP_BLK, ptr );
163 ptr = SInew( GI_BLK );
164 errors += fail_if_nil( ptr, "memory: sinew returned nil when given giblk request" );
165 SItrash( GI_BLK, ptr ); // GI block cannot be trashed, ensure this (valgind will complain about a leak)
166 free( ptr ); // we can free GI block only in tests
168 fprintf( stderr, "<INFO> memory module finished with %d errors\n", errors );
173 Test initialisation related things
178 si_ctx = SIinitialise( 0 );
179 errors += fail_if_nil( si_ctx, "init: siinit returned a nil pointer" );
181 SIclr_tflags( si_ctx, 0x00 ); // drive for coverage; no return value from these
182 SIset_tflags( si_ctx, 0x03 );
184 fprintf( stderr, "<INFO> init module finished with %d errors\n", errors );
188 static int cleanup() {
192 fprintf( stderr, "<INFO> cleanup has no context to use\n" );
196 fprintf( stderr, "<INFO> cleanup running\n" );
197 SIcbstat( si_ctx, SI_RET_UNREG, SI_CB_SECURITY );
198 SIcbstat( si_ctx, SI_RET_QUIT, SI_CB_SECURITY );
200 SItp_stats( si_ctx ); // drive for coverage only
203 SIconnect( si_ctx, "127.0.0.1:43086" ); // ensure context has a tp block to free on shutdown
207 // cleaning up the remaining global resources
208 struct ginfo_blk *gptr = (struct ginfo_blk*)si_ctx;
209 SItrash( TP_BLK, gptr->tplist );
210 free( gptr->tp_map );
215 fprintf( stderr, "<INFO> cleanup module finished with %d errors\n", errors );
220 Address related tests.
225 char buf1[4096]; // space to build buffers for xlation
226 char* hr_addr; // human readable address returned
227 void* net_addr; // a network address block of some type
230 struct sockaddr* addr;
231 addr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
233 l = SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
235 SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
238 l = SIaddress( NULL, NULL, 0 );
239 errors += fail_if_true( l != 0, "SIaddress given two null pointers didn't return 0 len" );
240 l = SIaddress( buf1, NULL, 0 );
241 errors += fail_if_true( l != 0, "SIaddress given null dest pointer didn't return 0 len" );
242 l = SIaddress( NULL, (void *) &buf1, 0 );
243 errors += fail_if_true( l != 0, "SIaddress given null src pointer didn't return 0 len" );
246 snprintf( buf1, sizeof( buf1 ), " [ff02::5:4001" ); // invalid address, drive leading space eater too
247 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR6 );
248 errors += fail_if_true( l > 0, "to addr6 with bad addr convdersion returned valid len" );
251 snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" ); // v6 might not be supported so failure is OK here; driving for coverage
252 l = SIaddress( buf1, &net_addr, AC_TOADDR6 );
254 l = SIaddress( net_addr, (void *) &hr_addr, AC_TODOT ); // convert the address back to hr string
255 errors += fail_if_true( l < 1, "v6 to dot conversion failed" );
256 errors += fail_if_nil( hr_addr, "v6 to dot conversion yields a nil pointer" );
261 snprintf( buf1, sizeof( buf1 ), "localhost:43086" );
262 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR );
263 errors += fail_if_true( l < 1, "v4 to addr conversion failed" );
265 l = SIaddress( net_addr, (void *) &hr_addr, AC_TODOT ); // convert the address back to hr string
266 errors += fail_if_true( l < 1, "to dot convdersion failed" );
267 errors += fail_if_nil( hr_addr, "v4 to dot conversion yields a nil pointer" );
271 fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
276 Prep related tests. These mostly drive cases that aren't driven by "normal"
277 connect, send, receive tests (e.g. UDP branches).
281 void* thing; // the thing that should be returned
283 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", AF_INET );
284 errors += fail_if_nil( thing, "listen prep udp returned nil block" );
285 SItrash( TP_BLK, thing );
287 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", 84306 ); // this should fail
288 errors += fail_not_nil( thing, "listen prep udp returned valid block ptr for bogus family" );
290 thing = SIconn_prep( si_ctx, UDP_DEVICE, "localhost:1234", 84306 ); // again, expect to fail; bogus family
291 errors += fail_not_nil( thing, "conn prep udp returned valid block ptr for bogus family" );
297 Polling/waiting tests. These are difficult at best because of the blocking
298 nature of things, not to mention needing to have real ports open etc.
303 struct ginfo_blk* dummy;
306 dummy = SIinitialise( 0 ); // get one to fiddle to drive edge cases
307 dummy->flags |= GIF_SHUTDOWN; // shutdown edge condition
310 free( dummy->tp_map );
312 free( dummy->cbtab );
314 memset( dummy, 0, sizeof( *dummy ) ); // force bad cookie check code to drive
319 status = SIpoll( si_ctx, 1 );
320 errors += fail_if_true( status != 0, "poll failed" );
327 Connection oriented tests.
332 int cfd = 3; // fd for close
335 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
336 errors += fail_if_true( state < 0, "connect to low port failed" );
338 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
339 errors += fail_if_true( state < 0, "connect to high port failed" );
341 tpem_set_addr_dup_state( 1 ); // force get sockket name emulation to return a duplicate address
342 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
343 errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
345 tpem_set_addr_dup_state( 0 ); // back to normal
346 tpem_set_conn_state( -1 );
347 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
348 errors += fail_if_true( state >= 0, "connect to low port successful when failure expected" );
349 tpem_set_conn_state( 3 );
351 tpem_set_sock_state( 1 ); // make scoket calls fail
352 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
353 errors += fail_if_true( state >= 0, "connect to low port successful when socket based failure expected" );
355 tpem_set_sock_state( 0 );
357 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
358 errors += fail_if_true( state < 0, "listen failed" );
360 tpem_set_bind_state( 1 );
361 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
362 errors += fail_if_true( state >= 0, "listen successful when bind error set" );
363 tpem_set_bind_state( 0 );
365 SIbldpoll( si_ctx ); // for coverage. no return value and nothing we can check
367 state = SIclose( NULL, 0 ); //coverage
368 errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
370 state = SIclose( si_ctx, cfd );
371 errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
373 state = SIclose( si_ctx, 5000 ); // out of range fd
374 errors += fail_if_true( state != SI_ERROR, "close given good context and bad fd returned success" );
376 state = SIclose( si_ctx, TCP_LISTEN_PORT ); // close listener
377 errors += fail_if_true( state == SI_ERROR, "close given good context and listener fd returned error" );
379 state = SIclose( si_ctx, UDP_PORT ); // close first open udp port (should not be there)
380 errors += fail_if_true( state != SI_ERROR, "close given good context and udp generic fd returned error" );
382 buf = SIgetname( 3 );
383 if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
386 errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
390 buf = SIgetname( -1 ); // invalid fd
391 errors += fail_not_nil( buf, "get name returned buf with non-emtpy string when given bad fd" );
393 fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
398 Misc tests that just don't fit in another bucket.
404 SIcbreg( NULL, SI_CB_SECURITY, test_cb, NULL ); // coverage only, no return value no verification
405 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
408 SIgetaddr( si_ctx, buf );
409 errors += fail_if_true( buf[0] == 0, "get address failed" );
410 fprintf( stderr, "<INFO> get address returns (%s)\n", buf );
412 fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
418 New session (accept) testing.
420 static int new_sess( ) {
423 struct tp_blk *tpptr;
426 tpptr = SInew( TP_BLK );
428 tpptr->flags |= TPF_LISTENFD;
430 tpem_set_accept_fd( -1 ); // accept will "fail" for coverage
431 status = SInewsession( si_ctx, tpptr );
432 errors += fail_if_true( status != SI_ERROR, "newsession did not fail when accept fails" );
434 tpem_set_accept_fd( 5 ); // accept will return a good fd
435 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb_err, NULL ); // register error and drive new session for error coverage
436 status = SInewsession( si_ctx, tpptr );
437 errors += fail_if_true( status >= 0, "newsession did failed when accept was good" );
439 tpem_set_accept_fd( 6 ); // accept will return a good fd
440 SIset_tflags( si_ctx, SI_TF_NODELAY | SI_TF_FASTACK ); // flip options for coverage in new sess
441 SIcbreg( si_ctx, SI_CB_CONN, test_cb, NULL ); // drive connection for coverage
442 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
443 status = SInewsession( si_ctx, tpptr );
444 errors += fail_if_true( status < 0, "newsession did failed when accept was good" );
448 fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
455 static int send_tests( ) {
461 len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
463 state = SIsendt( si_ctx, 9999, buf, len );
464 errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
466 state = SIsendt( si_ctx, -1, buf, len );
467 errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
469 SIsendt( si_ctx, 6, buf, len );
471 tpem_set_send_err( 99 );
472 SIsendt( si_ctx, 6, buf, len );
474 tpem_set_send_err( 0 );
475 tpem_set_sel_blk( 1 );
476 SIsendt( si_ctx, 6, buf, len );
478 tpem_set_sel_blk( 0 );
479 tpem_set_selef_fd( 6 ); // will cause send to fail and fd6 to close
480 SIsendt( si_ctx, 6, buf, len );
487 Wait testing. This is tricky because we don't have any sessions and thus it's difficult
488 to drive much of SIwait().
490 static int wait_tests() {
492 struct ginfo_blk* dummy;
495 dummy = SIinitialise( 0 ); // get one to fiddle to drive edge cases
496 SIwait( dummy ); // malloc should "fail"
498 dummy->flags |= GIF_SHUTDOWN;
501 free( dummy->tp_map );
503 free( dummy->cbtab );
505 memset( dummy, 0, sizeof( *dummy ) ); // force bad cookie check code to drive
511 SIwait( si_ctx ); // should drive once through the loop
516 // ----------------------------------------------------------------------------------------
524 rmr_set_vlevel( 5 ); // enable all debugging
526 fprintf( stderr, "\n<INFO> starting SI95 tests\n" );
535 errors += new_sess(); // should leave a "connected" session at fd == 6
536 errors += send_tests();
539 errors += wait_tests();
543 test_summary( errors, "SI95 tests" );
545 fprintf( stderr, "<PASS> all tests were OK\n\n" );
547 fprintf( stderr, "<FAIL> %d errors in SI95 core code\n\n", errors );