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
41 #include <sys/epoll.h>
42 #include <semaphore.h>
45 #include <netdb.h> // these four needed for si address tests
48 #include <netinet/in.h>
52 // specific test tools in this directory
53 #undef NNG_UNDER_TEST // NNG is NOT under test so undefine if set
54 #define NO_EMULATION 1 // no emulation of transport functions
55 #define NO_PRIVATE_HEADERS 1 // no rmr_si or rmr_nng headers
56 #define NO_DUMMY_RMR 1 // no msg things
58 #include "test_support.c" // things like fail_if()
59 #include "test_transport_em.c" // system/transport emulation (open, close, connect, etc)
61 #include <rmr_logging.h>
65 // ------------- dummy functions to force edge cases when we can ---------------------------------------
67 #define SYSTEM_UNDER_TEST 1 // for conditional code
70 These are global so they can be reset for individual tests.
72 static int good_mallocs = 0; // number of initial good malocs before failurs
73 static int bad_mallocs = 1; // number of failed mallocs (consecutive)
75 static void* test_malloc( size_t n ) {
77 fprintf( stderr, ">>>> test malloc: %d %d\n", good_mallocs, bad_mallocs );
92 // -----------------------------------------------------------------------------------------------------
94 #include <si95/siaddress.c>
95 //#include <si95/sialloc.c>
96 #include <si95/sibldpoll.c>
97 #include <si95/sicbreg.c>
98 #include <si95/sicbstat.c>
99 #include <si95/siclose.c>
100 #include <si95/siconnect.c>
101 #include <si95/siestablish.c>
102 #include <si95/sigetadd.c>
103 #include <si95/sigetname.c>
104 #include <si95/siinit.c>
105 #include <si95/silisten.c>
106 #include <si95/sinew.c>
107 #include <si95/sinewses.c>
108 #include <si95/sipoll.c>
109 //#include <si95/sircv.c>
110 #include <si95/sisend.c>
111 #include <si95/sisendt.c>
112 #include <si95/sishutdown.c>
113 #include <si95/siterm.c>
114 #include <si95/sitrash.c>
115 #define malloc test_malloc
116 #include <si95/siwait.c>
119 // ---------------------------------------------------------------------
121 void* si_ctx = NULL; // a global context might be useful
123 // ---------------------------------------------------------------------
126 Fake callback to register.
128 static int test_cb( void* data ) {
133 Returns error for coverage testing of CB calls
135 static int test_cb_err( void* data ) {
140 Memory allocation/free related tests
142 static int memory( ) {
147 // ---- SInew ----------------
148 ptr = SInew( 100 ); // invalid block type should return nil
149 errors += fail_not_nil( ptr, "memory: sinew did not return nil when given a valid struct type" );
150 SItrash( 100, NULL ); // drive trash for coverage
152 iptr = SInew( IOQ_BLK );
153 errors += fail_if_nil( iptr, "memory: sinew returned nil when given ioq request" );
154 SItrash( IOQ_BLK, iptr );
156 ptr = SInew( TP_BLK );
157 errors += fail_if_nil( ptr, "memory: sinew returned nil when given tpblk request" );
159 iptr = SInew( IOQ_BLK );
160 ((struct tp_blk *)ptr)->squeue = iptr;
161 SItrash( TP_BLK, ptr );
164 ptr = SInew( GI_BLK );
165 errors += fail_if_nil( ptr, "memory: sinew returned nil when given giblk request" );
166 SItrash( GI_BLK, ptr ); // GI block cannot be trashed, ensure this (valgind will complain about a leak)
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
208 fprintf( stderr, "<INFO> cleanup module finished with %d errors\n", errors );
213 Address related tests.
218 struct sockaddr* addr;
219 char buf1[4096]; // space to build buffers for xlation
220 char* hr_addr; // human readable address returned
221 void* net_addr; // a network address block of some type
223 addr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
225 l = SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
227 SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
230 l = SIaddress( NULL, NULL, 0 );
231 errors += fail_if_true( l != 0, "SIaddress given two null pointers didn't return 0 len" );
232 l = SIaddress( buf1, NULL, 0 );
233 errors += fail_if_true( l != 0, "SIaddress given null dest pointer didn't return 0 len" );
234 l = SIaddress( NULL, (void *) &buf1, 0 );
235 errors += fail_if_true( l != 0, "SIaddress given null src pointer didn't return 0 len" );
238 snprintf( buf1, sizeof( buf1 ), " [ff02::5:4001" ); // invalid address, drive leading space eater too
239 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR6 );
240 errors += fail_if_true( l > 0, "to addr6 with bad addr convdersion returned valid len" );
243 snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" ); // v6 might not be supported so failure is OK here; driving for coverage
244 l = SIaddress( buf1, &net_addr, AC_TOADDR6 );
246 l = SIaddress( net_addr, (void *) &hr_addr, AC_TODOT ); // convert the address back to hr string
247 errors += fail_if_true( l < 1, "v6 to dot conversion failed" );
248 errors += fail_if_nil( hr_addr, "v6 to dot conversion yields a nil pointer" );
252 snprintf( buf1, sizeof( buf1 ), "localhost:43086" );
253 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR );
254 errors += fail_if_true( l < 1, "v4 to addr conversion failed" );
256 l = SIaddress( net_addr, (void *) &hr_addr, AC_TODOT ); // convert the address back to hr string
257 errors += fail_if_true( l < 1, "to dot convdersion failed" );
258 errors += fail_if_nil( hr_addr, "v4 to dot conversion yields a nil pointer" );
261 fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
266 Prep related tests. These mostly drive cases that aren't driven by "normal"
267 connect, send, receive tests (e.g. UDP branches).
271 void* thing; // the thing that should be returned
273 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", AF_INET );
274 errors += fail_if_nil( thing, "listen prep udp returned nil block" );
276 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", 84306 ); // this should fail
277 errors += fail_not_nil( thing, "listen prep udp returned valid block ptr for bogus family" );
279 thing = SIconn_prep( si_ctx, UDP_DEVICE, "localhost:1234", 84306 ); // again, expect to fail; bogus family
280 errors += fail_not_nil( thing, "conn prep udp returned valid block ptr for bogus family" );
286 Polling/waiting tests. These are difficult at best because of the blocking
287 nature of things, not to mention needing to have real ports open etc.
292 struct ginfo_blk* dummy;
295 dummy = SIinitialise( 0 ); // get one to fiddle to drive edge cases
296 dummy->flags |= GIF_SHUTDOWN; // shutdown edge condition
299 memset( dummy, 0, sizeof( *dummy ) ); // force bad cookie check code to drive
302 status = SIpoll( si_ctx, 1 );
303 errors += fail_if_true( status != 0, "poll failed" );
310 Connection oriented tests.
315 int cfd = 3; // fd for close
318 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
319 errors += fail_if_true( state < 0, "connect to low port failed" );
321 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
322 errors += fail_if_true( state < 0, "connect to high port failed" );
324 tpem_set_addr_dup_state( 1 ); // force get sockket name emulation to return a duplicate address
325 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
326 errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
328 tpem_set_addr_dup_state( 0 ); // back to normal
329 tpem_set_conn_state( -1 );
330 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
331 errors += fail_if_true( state >= 0, "connect to low port successful when failure expected" );
332 tpem_set_conn_state( 3 );
334 tpem_set_sock_state( 1 ); // make scoket calls fail
335 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
336 errors += fail_if_true( state >= 0, "connect to low port successful when socket based failure expected" );
338 tpem_set_sock_state( 0 );
340 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
341 errors += fail_if_true( state < 0, "listen failed" );
343 tpem_set_bind_state( 1 );
344 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
345 errors += fail_if_true( state >= 0, "listen successful when bind error set" );
346 tpem_set_bind_state( 0 );
348 SIbldpoll( si_ctx ); // for coverage. no return value and nothing we can check
350 state = SIclose( NULL, 0 ); //coverage
351 errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
353 state = SIclose( si_ctx, cfd );
354 errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
356 state = SIclose( si_ctx, 5000 ); // out of range fd
357 errors += fail_if_true( state != SI_ERROR, "close given good context and bad fd returned success" );
359 state = SIclose( si_ctx, TCP_LISTEN_PORT ); // close listener
360 errors += fail_if_true( state == SI_ERROR, "close given good context and listener fd returned error" );
362 state = SIclose( si_ctx, UDP_PORT ); // close first open udp port (should not be there)
363 errors += fail_if_true( state != SI_ERROR, "close given good context and udp generic fd returned error" );
365 buf = SIgetname( 3 );
366 if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
369 errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
373 buf = SIgetname( -1 ); // invalid fd
374 errors += fail_not_nil( buf, "get name returned buf with non-emtpy string when given bad fd" );
376 fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
381 Misc tests that just don't fit in another bucket.
387 SIcbreg( NULL, SI_CB_SECURITY, test_cb, NULL ); // coverage only, no return value no verification
388 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
391 SIgetaddr( si_ctx, buf );
392 errors += fail_if_true( buf[0] == 0, "get address failed" );
393 fprintf( stderr, "<INFO> get address returns (%s)\n", buf );
395 fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
401 New session (accept) testing.
403 static int new_sess( ) {
406 struct tp_blk *tpptr;
409 tpptr = SInew( TP_BLK );
411 tpptr->flags |= TPF_LISTENFD;
413 tpem_set_accept_fd( -1 ); // accept will "fail" for coverage
414 status = SInewsession( si_ctx, tpptr );
415 errors += fail_if_true( status != SI_ERROR, "newsession did not fail when accept fails" );
417 tpem_set_accept_fd( 5 ); // accept will return a good fd
418 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb_err, NULL ); // register error and drive new session for error coverage
419 status = SInewsession( si_ctx, tpptr );
420 errors += fail_if_true( status >= 0, "newsession did failed when accept was good" );
422 tpem_set_accept_fd( 6 ); // accept will return a good fd
423 SIset_tflags( si_ctx, SI_TF_NODELAY | SI_TF_FASTACK ); // flip options for coverage in new sess
424 SIcbreg( si_ctx, SI_CB_CONN, test_cb, NULL ); // drive connection for coverage
425 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
426 status = SInewsession( si_ctx, tpptr );
427 errors += fail_if_true( status < 0, "newsession did failed when accept was good" );
429 fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
436 static int send_tests( ) {
442 len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
444 state = SIsendt( si_ctx, 9999, buf, len );
445 errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
447 state = SIsendt( si_ctx, -1, buf, len );
448 errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
450 SIsendt( si_ctx, 6, buf, len );
452 tpem_set_send_err( 99 );
453 SIsendt( si_ctx, 6, buf, len );
455 tpem_set_send_err( 0 );
456 tpem_set_sel_blk( 1 );
457 SIsendt( si_ctx, 6, buf, len );
459 tpem_set_sel_blk( 0 );
460 tpem_set_selef_fd( 6 ); // will cause send to fail and fd6 to close
461 SIsendt( si_ctx, 6, buf, len );
468 Wait testing. This is tricky because we don't have any sessions and thus it's difficult
469 to drive much of SIwait().
471 static int wait_tests() {
473 struct ginfo_blk* dummy;
476 dummy = SIinitialise( 0 ); // get one to fiddle to drive edge cases
477 SIwait( dummy ); // malloc should "fail"
479 dummy->flags |= GIF_SHUTDOWN;
482 memset( dummy, 0, sizeof( *dummy ) ); // force bad cookie check code to drive
485 SIwait( si_ctx ); // should drive once through the loop
490 // ----------------------------------------------------------------------------------------
498 rmr_set_vlevel( 5 ); // enable all debugging
500 fprintf( stderr, "\n<INFO> starting SI95 tests\n" );
509 errors += new_sess(); // should leave a "connected" session at fd == 6
510 errors += send_tests();
513 errors += wait_tests();
517 test_summary( errors, "SI95 tests" );
519 fprintf( stderr, "<PASS> all tests were OK\n\n" );
521 fprintf( stderr, "<FAIL> %d errors in SI95 core code\n\n", errors );