Release RMR version 4.8.0
[ric-plt/lib/rmr.git] / test / si95_test_fixme.c
1 // :vi sw=4 ts=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2020-2021 Nokia
5         Copyright (c) 2020-2021 AT&T Intellectual Property.
6
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
10
11            http://www.apache.org/licenses/LICENSE-2.0
12
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 ==================================================================================
19 */
20
21 /*
22         Mmemonic:       si95_test.c
23         Abstract:       This is the main driver to test the si95 core functions
24                                 (within rmr/src/si/src/si95).
25
26         Author:         E. Scott Daniels
27         Date:           6 March 2018
28 */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <netdb.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <pthread.h>
37 #include <ctype.h>
38 #include <unistd.h>
39 #include <strings.h>
40 #include <stdint.h>
41 #include <sys/epoll.h>
42 #include <semaphore.h>
43
44
45 #include <netdb.h>              // these four needed for si address tests
46 #include <stdio.h>
47 #include <ctype.h>
48 #include <netinet/in.h>
49
50 #define DEBUG 1
51
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
57
58 #include "test_support.c"                                       // things like fail_if()
59 #include "test_transport_em.c"                          // system/transport emulation (open, close, connect, etc)
60
61 #include <rmr_logging.h>
62 #include <logging.c>
63
64
65 // ------------- dummy functions to force edge cases when we can ---------------------------------------
66
67 #define SYSTEM_UNDER_TEST       1                               // for conditional code
68
69 /*
70         These are global so they can be reset for individual tests.
71 */
72 static int good_mallocs = 0;            // number of initial good malocs before failurs
73 static int bad_mallocs = 1;                     // number of failed mallocs (consecutive)
74
75 static void* test_malloc( size_t n ) {
76
77 fprintf( stderr, ">>>> test malloc: %d %d\n", good_mallocs, bad_mallocs );
78         if( good_mallocs ) {
79                 good_mallocs--;
80                 return malloc( n );
81         }
82
83         if( bad_mallocs ) {
84                 bad_mallocs--;
85                 errno = ENOMEM;
86                 return NULL;
87         }
88
89         return malloc( n );
90 }
91
92 // -----------------------------------------------------------------------------------------------------
93
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>
117 #undef malloc
118
119 // ---------------------------------------------------------------------
120
121 void*   si_ctx = NULL;                  // a global context might be useful
122
123 // ---------------------------------------------------------------------
124
125 /*
126         Fake callback to register.
127 */
128 static int test_cb( void* data ) {
129         return 0;
130 }
131
132 /*
133         Returns error for coverage testing of CB calls
134 */
135 static int test_cb_err( void* data ) {
136         return -1;
137 }
138
139 /*
140         Memory allocation/free related tests
141 */
142 static int memory( ) {
143         int             errors = 0;
144         void*   ptr;
145         void*   iptr;
146
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
151
152         iptr = SInew( IOQ_BLK );
153         errors += fail_if_nil( iptr, "memory: sinew returned nil when given ioq request" );
154         SItrash(  IOQ_BLK, iptr );
155
156         ptr = SInew( TP_BLK );
157         errors += fail_if_nil( ptr, "memory: sinew returned nil when given tpblk request" );
158         if( ptr ) {
159                 iptr = SInew( IOQ_BLK );
160                 ((struct tp_blk *)ptr)->squeue = iptr;
161                 SItrash(  TP_BLK, ptr );
162         }
163
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)
167
168         fprintf( stderr, "<INFO> memory module finished with %d errors\n", errors );
169         return errors;
170 }
171
172 /*
173         Test initialisation related things
174 */
175 static int init() {
176         int             errors = 0;
177
178         si_ctx = SIinitialise( 0 );
179         errors += fail_if_nil( si_ctx, "init: siinit returned a nil pointer" );
180
181         SIclr_tflags( si_ctx, 0x00 );           // drive for coverage; no return value from these
182         SIset_tflags( si_ctx, 0x03 );
183
184         fprintf( stderr, "<INFO> init  module finished with %d errors\n", errors );
185         return errors;
186 }
187
188 static int cleanup() {
189         int errors = 0;
190
191         if( ! si_ctx ) {
192                 fprintf( stderr, "<INFO> cleanup has no context to use\n" );
193                 return 0;
194         }
195
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 );
199
200         SItp_stats( si_ctx );           // drive for coverage only
201         SItp_stats( NULL );
202
203         SIconnect( si_ctx, "127.0.0.1:43086" ); // ensure context has a tp block to free on shutdown
204         SIshutdown( NULL );
205         SIabort( si_ctx );
206
207
208         fprintf( stderr, "<INFO> cleanup  module finished with %d errors\n", errors );
209         return errors;
210 }
211
212 /*
213         Address related tests.
214 */
215 static int addr() {
216         int errors = 0;
217         int l;
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
222
223         addr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
224 /*
225         l = SIgenaddr( "    [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
226
227         SIgenaddr( "    [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
228 */
229
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" );
236
237         net_addr = NULL;
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" );
241         free( net_addr );
242
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 );
245         if( l > 0 ) {
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" );
249                 free( net_addr );
250         }
251
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" );
255
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" );
259         free( net_addr );
260
261         fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
262         return errors;
263 }
264
265 /*
266         Prep related tests. These mostly drive cases that aren't driven by "normal"
267         connect, send, receive tests (e.g. UDP branches).
268 */
269 static int prep() {
270         int             errors = 0;
271         void*   thing;                                  // the thing that should be returned
272
273         thing = SIlisten_prep( UDP_DEVICE, "localhost:1234", AF_INET );
274         errors += fail_if_nil( thing, "listen prep udp returned nil block" );
275
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" );
278
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" );
281
282         return errors;
283 }
284
285 /*
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.
288 */
289 static int poll() {
290         int errors  = 0;
291         int status;
292         struct ginfo_blk* dummy;
293
294
295         dummy = SIinitialise( 0 );                              // get one to fiddle to drive edge cases
296         dummy->flags |= GIF_SHUTDOWN;                   // shutdown edge condition
297         SIpoll( dummy, 1 );
298
299         memset( dummy, 0, sizeof( *dummy ) );   // force bad cookie check code to drive
300         SIpoll( dummy, 1 );
301
302         status = SIpoll( si_ctx, 1 );
303         errors += fail_if_true( status != 0, "poll failed" );
304
305         return errors;
306 }
307
308
309 /*
310         Connection oriented tests.
311 */
312 static int conn( ) {
313         int errors = 0;
314         int state;
315         int cfd = 3;                                    // fd for close
316         char*   buf;
317
318         state = SIconnect( si_ctx, "localhost:4567" );          // driver regular connect
319         errors += fail_if_true( state < 0, "connect to low port failed" );
320
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" );
323
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" );
327
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 );
333
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" );
337
338         tpem_set_sock_state( 0 );
339
340         state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
341         errors += fail_if_true( state < 0, "listen failed" );
342
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 );
347
348         SIbldpoll( si_ctx );            // for coverage. no return value and nothing we can check
349
350         state = SIclose( NULL, 0 );                     //coverage
351         errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
352
353         state = SIclose( si_ctx, cfd );
354         errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
355
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" );
358
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" );
361
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" );
364
365         buf = SIgetname( 3 );
366         if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
367                 errors++;
368         } else {
369                 errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
370                 free( buf );
371         }
372
373         buf = SIgetname( -1 );                  // invalid fd
374         errors += fail_not_nil( buf, "get name returned buf with non-emtpy string when given bad fd" );
375
376         fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
377         return errors;
378 }
379
380 /*
381         Misc tests that just don't fit in another bucket.
382 */
383 static int misc( ) {
384         int errors = 0;
385         char    buf[1024];
386
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 );
389
390         buf[0] = 0;
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 );
394
395         fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
396         return errors;
397 }
398
399
400 /*
401         New session (accept) testing.
402 */
403 static int new_sess( ) {
404         int errors = 0;
405         char    buf[1024];
406         struct tp_blk *tpptr;
407         int             status;
408
409         tpptr = SInew( TP_BLK );
410         tpptr->fd = 3;
411         tpptr->flags |= TPF_LISTENFD;
412
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" );
416
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" );
421
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" );
428
429         fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
430         return errors;
431 }
432
433 /*
434         Send tests
435 */
436 static int send_tests( ) {
437         int             errors = 0;
438         char    buf[1024];
439         int             len;
440         int             state;
441
442         len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
443
444         state = SIsendt( si_ctx, 9999, buf, len );
445         errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
446
447         state = SIsendt( si_ctx, -1, buf, len );
448         errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
449
450         SIsendt( si_ctx, 6, buf, len );
451
452         tpem_set_send_err( 99 );
453         SIsendt( si_ctx, 6, buf, len );
454
455         tpem_set_send_err( 0 );
456         tpem_set_sel_blk( 1 );
457         SIsendt( si_ctx, 6, buf, len );
458
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 );
462
463         return errors;
464 }
465
466
467 /*
468         Wait testing.  This is tricky because we don't have any sessions and thus it's difficult
469         to drive much of SIwait().
470 */
471 static int wait_tests() {
472         int errors = 0;
473         struct ginfo_blk* dummy;
474
475
476         dummy = SIinitialise( 0 );                              // get one to fiddle to drive edge cases
477         SIwait( dummy );                                                // malloc should "fail"
478
479         dummy->flags |= GIF_SHUTDOWN;
480         SIwait( dummy );
481
482         memset( dummy, 0, sizeof( *dummy ) );   // force bad cookie check code to drive
483         SIwait( dummy );
484
485         SIwait( si_ctx );                                               // should drive once through the loop
486
487         return errors;
488 }
489
490 // ----------------------------------------------------------------------------------------
491
492 /*
493         Drive tests...
494 */
495 int main() {
496         int errors = 0;
497
498         rmr_set_vlevel( 5 );                    // enable all debugging
499
500         fprintf( stderr, "\n<INFO> starting SI95 tests\n" );
501
502         errors += init();
503         errors += memory();
504         errors += addr();
505         errors += prep();
506         errors += conn();
507         errors += misc();
508
509         errors += new_sess();           // should leave a "connected" session at fd == 6
510         errors += send_tests();
511
512         errors += poll();
513         errors += wait_tests();
514
515         errors += cleanup();
516
517         test_summary( errors, "SI95 tests" );
518         if( errors == 0 ) {
519                 fprintf( stderr, "<PASS> all tests were OK\n\n" );
520         } else {
521                 fprintf( stderr, "<FAIL> %d errors in SI95 core code\n\n", errors );
522         }
523
524         return !!errors;
525 }