3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 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
39 #include <netdb.h> // these four needed for si address tests
42 #include <netinet/in.h>
54 #include <sys/epoll.h>
56 #include <semaphore.h>
60 // specific test tools in this directory
61 #undef NNG_UNDER_TEST // NNG is NOT under test so undefine if set
62 #define NO_EMULATION 1 // no emulation of transport functions
63 #define NO_PRIVATE_HEADERS 1 // no rmr_si or rmr_nng headers
64 #define NO_DUMMY_RMR 1 // no msg things
66 #include "test_support.c" // things like fail_if()
67 #include "test_transport_em.c" // system/transport emulation (open, close, connect, etc)
70 #include "rmr.h" // things the users see
71 #include "rmr_symtab.h"
72 #include "rmr_agnostic.h" // transport agnostic header
74 #include <rmr_logging.h>
77 #include <si95/siaddress.c>
78 //#include <si95/sialloc.c>
79 #include <si95/sibldpoll.c>
80 #include <si95/sicbreg.c>
81 #include <si95/sicbstat.c>
82 #include <si95/siclose.c>
83 #include <si95/siconnect.c>
84 #include <si95/siestablish.c>
85 #include <si95/sigetadd.c>
86 #include <si95/sigetname.c>
87 #include <si95/siinit.c>
88 #include <si95/silisten.c>
89 #include <si95/sinew.c>
90 #include <si95/sinewses.c>
91 #include <si95/sipoll.c>
92 //#include <si95/sircv.c>
93 #include <si95/sisend.c>
94 #include <si95/sisendt.c>
95 #include <si95/sishutdown.c>
96 #include <si95/siterm.c>
97 #include <si95/sitrash.c>
98 //#include <si95/siwait.c>
100 // ---------------------------------------------------------------------
102 void* si_ctx = NULL; // a global context might be useful
104 // ---------------------------------------------------------------------
107 Fake callback to register.
109 static int test_cb( void* data ) {
114 Returns error for coverage testing of CB calls
116 static int test_cb_err( void* data ) {
121 Memory allocation/free related tests
123 static int memory( ) {
128 // ---- SInew ----------------
129 ptr = SInew( 100 ); // invalid block type should return nil
130 errors += fail_not_nil( ptr, "memory: sinew did not return nil when given a valid struct type" );
131 SItrash( 100, NULL ); // drive trash for coverage
133 iptr = SInew( IOQ_BLK );
134 errors += fail_if_nil( iptr, "memory: sinew returned nil when given ioq request" );
135 SItrash( IOQ_BLK, iptr );
137 ptr = SInew( TP_BLK );
138 errors += fail_if_nil( ptr, "memory: sinew returned nil when given tpblk request" );
140 iptr = SInew( IOQ_BLK );
141 ((struct tp_blk *)ptr)->squeue = iptr;
142 SItrash( TP_BLK, ptr );
145 ptr = SInew( GI_BLK );
146 errors += fail_if_nil( ptr, "memory: sinew returned nil when given giblk request" );
147 SItrash( GI_BLK, ptr ); // GI block cannot be trashed, ensure this (valgind will complain about a leak)
149 fprintf( stderr, "<INFO> memory module finished with %d errors\n", errors );
154 Test initialisation related things
159 si_ctx = SIinitialise( 0 );
160 errors += fail_if_nil( si_ctx, "init: siinit returned a nil pointer" );
162 SIclr_tflags( si_ctx, 0x00 ); // drive for coverage; no return value from these
163 SIset_tflags( si_ctx, 0x03 );
165 fprintf( stderr, "<INFO> init module finished with %d errors\n", errors );
169 static int cleanup() {
173 fprintf( stderr, "<INFO> cleanup has no context to use\n" );
177 fprintf( stderr, "<INFO> cleanup running\n" );
178 SIcbstat( si_ctx, SI_RET_UNREG, SI_CB_SECURITY );
179 SIcbstat( si_ctx, SI_RET_QUIT, SI_CB_SECURITY );
181 SItp_stats( si_ctx ); // drive for coverage only
184 SIconnect( si_ctx, "localhost:43086" ); // ensure context has a tp block to free on shutdown
189 fprintf( stderr, "<INFO> cleanup module finished with %d errors\n", errors );
194 Address related tests.
199 struct sockaddr* addr;
200 char buf1[4096]; // space to build buffers for xlation
201 char* hr_addr; // human readable address returned
202 void* net_addr; // a network address block of some type
204 addr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
206 l = SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
208 SIgenaddr( " [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
211 l = SIaddress( NULL, NULL, 0 );
212 errors += fail_if_true( l != 0, "SIaddress given two null pointers didn't return 0 len" );
213 l = SIaddress( buf1, NULL, 0 );
214 errors += fail_if_true( l != 0, "SIaddress given null dest pointer didn't return 0 len" );
215 l = SIaddress( NULL, buf1, 0 );
216 errors += fail_if_true( l != 0, "SIaddress given null src pointer didn't return 0 len" );
219 snprintf( buf1, sizeof( buf1 ), " [ff02::5:4001" ); // invalid address, drive leading space eater too
220 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR6 );
221 errors += fail_if_true( l > 0, "to addr6 with bad addr convdersion returned valid len" );
224 snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" ); // v6 might not be supported so failure is OK here; driving for coverage
225 l = SIaddress( buf1, &net_addr, AC_TOADDR6 );
227 l = SIaddress( net_addr, &hr_addr, AC_TODOT ); // convert the address back to hr string
228 errors += fail_if_true( l < 1, "v6 to dot conversion failed" );
229 errors += fail_if_nil( hr_addr, "v6 to dot conversion yields a nil pointer" );
233 snprintf( buf1, sizeof( buf1 ), "localhost:43086" );
234 l = SIaddress( buf1, (void **) &net_addr, AC_TOADDR );
235 errors += fail_if_true( l < 1, "v4 to addr conversion failed" );
237 l = SIaddress( net_addr, &hr_addr, AC_TODOT ); // convert the address back to hr string
238 errors += fail_if_true( l < 1, "to dot convdersion failed" );
239 errors += fail_if_nil( hr_addr, "v4 to dot conversion yields a nil pointer" );
242 fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
247 Prep related tests. These mostly drive cases that aren't driven by "normal"
248 connect, send, receive tests (e.g. UDP branches).
252 void* thing; // the thing that should be returned
254 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", AF_INET );
255 errors += fail_if_nil( thing, "listen prep udp returned nil block" );
257 thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", 84306 ); // this should fail
258 errors += fail_not_nil( thing, "listen prep udp returned valid block ptr for bogus family" );
260 thing = SIconn_prep( si_ctx, UDP_DEVICE, "localhost:1234", 84306 ); // again, expect to fail; bogus family
261 errors += fail_not_nil( thing, "conn prep udp returned valid block ptr for bogus family" );
267 Polling/waiting tests. These are difficult at best because of the blocking
268 nature of things, not to mention needing to have real ports open etc.
274 status = SIpoll( si_ctx, 1 );
275 errors += fail_if_true( status != 0, "poll failed" );
282 Connection oriented tests.
287 int cfd = 3; // fd for close
290 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
291 errors += fail_if_true( state < 0, "connect to low port failed" );
293 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
294 errors += fail_if_true( state < 0, "connect to high port failed" );
296 tpem_set_addr_dup_state( 1 ); // force get sockket name emulation to return a duplicate address
297 state = SIconnect( si_ctx, "localhost:43086" ); // drive save connect with good return code
298 errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
300 tpem_set_addr_dup_state( 0 ); // back to normal
301 tpem_set_conn_state( -1 );
302 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
303 errors += fail_if_true( state >= 0, "connect to low port successful when failure expected" );
304 tpem_set_conn_state( 3 );
306 tpem_set_sock_state( 1 ); // make scoket calls fail
307 state = SIconnect( si_ctx, "localhost:4567" ); // driver regular connect
308 errors += fail_if_true( state >= 0, "connect to low port successful when socket based failure expected" );
310 tpem_set_sock_state( 0 );
312 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
313 errors += fail_if_true( state < 0, "listen failed" );
315 tpem_set_bind_state( 1 );
316 state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
317 errors += fail_if_true( state >= 0, "listen successful when bind error set" );
318 tpem_set_bind_state( 0 );
320 SIbldpoll( si_ctx ); // for coverage. no return value and nothing we can check
322 state = SIclose( NULL, 0 ); //coverage
323 errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
325 state = SIclose( si_ctx, cfd );
326 errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
328 state = SIclose( si_ctx, 5000 ); // out of range fd
329 errors += fail_if_true( state != SI_ERROR, "close given good context and bad fd returned success" );
331 state = SIclose( si_ctx, TCP_LISTEN_PORT ); // close listener
332 errors += fail_if_true( state == SI_ERROR, "close given good context and listener fd returned error" );
334 state = SIclose( si_ctx, UDP_PORT ); // close first open udp port (should not be there)
335 errors += fail_if_true( state != SI_ERROR, "close given good context and udp generic fd returned error" );
337 buf = SIgetname( 3 );
338 if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
341 errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
345 buf = SIgetname( -1 ); // invalid fd
346 errors += fail_not_nil( buf, "get name returned buf with non-emtpy string when given bad fd" );
348 fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
353 Misc tests that just don't fit in another bucket.
359 SIcbreg( NULL, SI_CB_SECURITY, test_cb, NULL ); // coverage only, no return value no verification
360 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
363 SIgetaddr( si_ctx, buf );
364 errors += fail_if_true( buf[0] == 0, "get address failed" );
365 fprintf( stderr, "<INFO> get address returns (%s)\n", buf );
367 fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
373 New session (accept) testing.
375 static int new_sess( ) {
378 struct tp_blk *tpptr;
381 tpptr = SInew( TP_BLK );
383 tpptr->flags |= TPF_LISTENFD;
385 tpem_set_accept_fd( -1 ); // accept will "fail" for coverage
386 status = SInewsession( si_ctx, tpptr );
387 errors += fail_if_true( status != SI_ERROR, "newsession did not fail when accept fails" );
389 tpem_set_accept_fd( 5 ); // accept will return a good fd
390 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb_err, NULL ); // register error and drive new session for error coverage
391 status = SInewsession( si_ctx, tpptr );
392 errors += fail_if_true( status >= 0, "newsession did failed when accept was good" );
394 tpem_set_accept_fd( 6 ); // accept will return a good fd
395 SIset_tflags( si_ctx, SI_TF_NODELAY | SI_TF_FASTACK ); // flip options for coverage in new sess
396 SIcbreg( si_ctx, SI_CB_CONN, test_cb, NULL ); // drive connection for coverage
397 SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
398 status = SInewsession( si_ctx, tpptr );
399 errors += fail_if_true( status < 0, "newsession did failed when accept was good" );
401 fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
408 static int send_tests( ) {
414 len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
416 state = SIsendt( si_ctx, 9999, buf, len );
417 errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
419 state = SIsendt( si_ctx, -1, buf, len );
420 errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
422 SIsendt( si_ctx, 6, buf, len );
424 tpem_set_send_err( 99 );
425 SIsendt( si_ctx, 6, buf, len );
427 tpem_set_send_err( 0 );
428 tpem_set_sel_blk( 1 );
429 SIsendt( si_ctx, 6, buf, len );
431 tpem_set_sel_blk( 0 );
432 tpem_set_selef_fd( 6 ); // will cause send to fail and fd6 to close
433 SIsendt( si_ctx, 6, buf, len );
439 // ----------------------------------------------------------------------------------------
447 rmr_set_vlevel( 5 ); // enable all debugging
449 fprintf( stderr, "\n<INFO> starting SI95 tests\n" );
458 errors += new_sess(); // should leave a "connected" session at fd == 6
459 errors += send_tests();
465 test_summary( errors, "SI95 tests" );
467 fprintf( stderr, "<PASS> all tests were OK\n\n" );
469 fprintf( stderr, "<FAIL> %d errors in SI95 core code\n\n", errors );