Add summary data to unit test output
[ric-plt/lib/rmr.git] / test / si95_test.c
1 // :vi sw=4 ts=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2020 Nokia
5         Copyright (c) 2020 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
39 #include <netdb.h>              // these four needed for si address tests
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <netinet/in.h>
43
44
45
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <strings.h>
50 #include <errno.h>
51 #include <string.h>
52 #include <stdint.h>
53 #include <ctype.h>
54 #include <sys/epoll.h>
55 #include <pthread.h>
56 #include <semaphore.h>
57
58 #define DEBUG 1
59
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
65
66 #include "test_support.c"                                       // things like fail_if()
67 #include "test_transport_em.c"                          // system/transport emulation (open, close, connect, etc)
68
69 /*
70 #include "rmr.h"                                        // things the users see
71 #include "rmr_symtab.h"
72 #include "rmr_agnostic.h"                       // transport agnostic header
73 */
74 #include <rmr_logging.h>
75 #include <logging.c>
76
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>
99
100 // ---------------------------------------------------------------------
101
102 void*   si_ctx = NULL;                  // a global context might be useful
103
104 // ---------------------------------------------------------------------
105
106 /*
107         Fake callback to register.
108 */
109 static int test_cb( void* data ) {
110         return 0;
111 }
112
113 /*
114         Returns error for coverage testing of CB calls
115 */
116 static int test_cb_err( void* data ) {
117         return -1;
118 }
119
120 /*
121         Memory allocation/free related tests
122 */
123 static int memory( ) {
124         int             errors = 0;
125         void*   ptr;
126         void*   iptr;
127
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
132
133         iptr = SInew( IOQ_BLK );
134         errors += fail_if_nil( iptr, "memory: sinew returned nil when given ioq request" );
135         SItrash(  IOQ_BLK, iptr );
136
137         ptr = SInew( TP_BLK );
138         errors += fail_if_nil( ptr, "memory: sinew returned nil when given tpblk request" );
139         if( ptr ) {
140                 iptr = SInew( IOQ_BLK );
141                 ((struct tp_blk *)ptr)->squeue = iptr;
142                 SItrash(  TP_BLK, ptr );
143         }
144
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)
148
149         fprintf( stderr, "<INFO> memory module finished with %d errors\n", errors );
150         return errors;
151 }
152
153 /*
154         Test initialisation related things
155 */
156 static int init() {
157         int             errors = 0;
158
159         si_ctx = SIinitialise( 0 );
160         errors += fail_if_nil( si_ctx, "init: siinit returned a nil pointer" );
161
162         SIclr_tflags( si_ctx, 0x00 );           // drive for coverage; no return value from these
163         SIset_tflags( si_ctx, 0x03 );
164
165         fprintf( stderr, "<INFO> init  module finished with %d errors\n", errors );
166         return errors;
167 }
168
169 static int cleanup() {
170         int errors = 0;
171
172         if( ! si_ctx ) {
173                 fprintf( stderr, "<INFO> cleanup has no context to use\n" );
174                 return 0;
175         }
176
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 );
180
181         SItp_stats( si_ctx );           // drive for coverage only
182         SItp_stats( NULL );
183
184         SIconnect( si_ctx, "localhost:43086" ); // ensure context has a tp block to free on shutdown
185         SIshutdown( NULL );
186         SIabort( si_ctx );
187
188
189         fprintf( stderr, "<INFO> cleanup  module finished with %d errors\n", errors );
190         return errors;
191 }
192
193 /*
194         Address related tests.
195 */
196 static int addr() {
197         int errors = 0;
198         int l;
199         struct sockaddr* addr;
200         char buf1[4096];
201         char buf2[4096];
202         char* dest;
203
204         addr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
205 /*
206         l = SIgenaddr( "    [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
207
208         SIgenaddr( "    [ff02::4]:4567", PF_INET6, IPPROTO_TCP, SOCK_STREAM, &addr );
209 */
210
211         dest = NULL;
212         snprintf( buf1, sizeof( buf1 ), "   [ff02::5:4001" );           // invalid address, drive leading space eater too
213         l = SIaddress( buf1, (void **)  &dest, AC_TOADDR6 );
214         errors += fail_if_true( l > 0, "to addr6 with bad addr convdersion returned valid len" );
215
216         snprintf( buf1, sizeof( buf1 ), "[ff02::5]:4002" );             // v6 might not be supported so failure is OK here; driving for coverage
217         l=SIaddress( buf1, (void **) &dest, AC_TOADDR6 );
218
219         snprintf( buf1, sizeof( buf1 ), "localhost:43086" );
220         l = SIaddress( buf1, (void **) &dest, AC_TOADDR );
221         errors += fail_if_true( l < 1, "to addr convdersion failed" );
222
223         snprintf( buf1, sizeof( buf1 ), "localhost:4004" );
224         l = SIaddress( buf1, (void **) &dest, AC_TODOT );
225         errors += fail_if_true( l < 1, "to dot convdersion failed" );
226
227         fprintf( stderr, "<INFO> addr module finished with %d errors\n", errors );
228         return errors;
229 }
230
231
232 /*
233         Connection oriented tests.
234 */
235 static int conn( ) {
236         int errors = 0;
237         int state;
238         int cfd = 3;                                    // fd for close
239         char*   buf;
240
241         state = SIconnect( si_ctx, "localhost:4567" );          // driver regular connect
242         errors += fail_if_true( state < 0, "connect to low port failed" );
243
244         state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
245         errors += fail_if_true( state < 0, "connect to high port failed" );
246
247         tpem_set_addr_dup_state( 1 );                                           // force get sockket name emulation to return a duplicate address
248         state = SIconnect( si_ctx, "localhost:43086" );         // drive save connect with good return code
249         errors += fail_if_true( state >= 0, "forced dup connect did not return error" );
250
251         tpem_set_addr_dup_state( 0 );                                           // back to normal
252         tpem_set_conn_state( -1 );
253         state = SIconnect( si_ctx, "localhost:4567" );          // driver regular connect
254         errors += fail_if_true( state >= 0, "connect to low port successful when failure expected" );
255         tpem_set_conn_state( 3 );
256
257         tpem_set_sock_state( 1 );                                                       // make scoket calls fail
258         state = SIconnect( si_ctx, "localhost:4567" );          // driver regular connect
259         errors += fail_if_true( state >= 0, "connect to low port successful when socket based failure expected" );
260
261         tpem_set_sock_state( 0 );
262
263         state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
264         errors += fail_if_true( state < 0, "listen failed" );
265
266         tpem_set_bind_state( 1 );
267         state = SIlistener( si_ctx, TCP_DEVICE, "0.0.0.0:4567" );
268         errors += fail_if_true( state >= 0, "listen successful when bind error set" );
269         tpem_set_bind_state( 0 );
270
271         SIbldpoll( si_ctx );            // for coverage. no return value and nothing we can check
272
273         state = SIclose( NULL, 0 );                     //coverage
274         errors += fail_if_true( state != SI_ERROR, "close given nil context returned success" );
275
276         state = SIclose( si_ctx, cfd );
277         errors += fail_if_true( state == SI_ERROR, "close given good context and good fd returned error" );
278
279         state = SIclose( si_ctx, 5000 );                                                // out of range fd
280         errors += fail_if_true( state != SI_ERROR, "close given good context and bad fd returned success" );
281
282         state = SIclose( si_ctx, TCP_LISTEN_PORT );                             // close listener
283         errors += fail_if_true( state == SI_ERROR, "close given good context and listener fd returned error" );
284
285         state = SIclose( si_ctx, UDP_PORT );                                    // close first open udp port (should not be there)
286         errors += fail_if_true( state != SI_ERROR, "close given good context and udp generic fd returned error" );
287
288         buf = SIgetname( 3 );
289         if( fail_if_true( buf == NULL, "get name failed to return a buffer" ) ) {
290                 errors++;
291         } else {
292                 errors += fail_if_true( buf[0] == 0, "get name returned buf with emtpy string" );
293         }
294
295         fprintf( stderr, "<INFO> conn module finished with %d errors\n", errors );
296         return errors;
297 }
298
299 /*
300         Misc tests that just don't fit in another bucket.
301 */
302 static int misc( ) {
303         int errors = 0;
304         char    buf[1024];
305
306         SIcbreg( NULL, SI_CB_SECURITY, test_cb, NULL );         // coverage only, no return value no verification
307         SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
308
309         buf[0] = 0;
310         SIgetaddr( si_ctx, buf );
311         errors += fail_if_true( buf[0] == 0, "get address failed" );
312         fprintf( stderr, "<INFO> get address returns (%s)\n", buf );
313
314         fprintf( stderr, "<INFO> misc module finished with %d errors\n", errors );
315         return errors;
316 }
317
318
319 /*
320         New session (accept) testing.
321 */
322 static int new_sess( ) {
323         int errors = 0;
324         char    buf[1024];
325         struct tp_blk *tpptr;
326         int             status;
327
328         tpptr = SInew( TP_BLK );
329         tpptr->fd = 3;
330         tpptr->flags |= TPF_LISTENFD;
331
332         tpem_set_accept_fd( -1 );                                                                       // accept will "fail" for coverage
333         status = SInewsession( si_ctx, tpptr );
334         errors += fail_if_true( status != SI_ERROR, "newsession did not fail when accept fails" );
335
336         tpem_set_accept_fd( 5 );                                                                        // accept will return a good fd
337         SIcbreg( si_ctx, SI_CB_SECURITY, test_cb_err, NULL );           // register error and drive new session for error coverage
338         status = SInewsession( si_ctx, tpptr );
339         errors += fail_if_true( status >= 0, "newsession did failed when accept was good" );
340
341         tpem_set_accept_fd( 6 );                                                                        // accept will return a good fd
342         SIset_tflags( si_ctx, SI_TF_NODELAY | SI_TF_FASTACK );          // flip options for coverage in new sess
343         SIcbreg( si_ctx, SI_CB_CONN, test_cb, NULL );                           // drive connection for coverage
344         SIcbreg( si_ctx, SI_CB_SECURITY, test_cb, NULL );
345         status = SInewsession( si_ctx, tpptr );
346         errors += fail_if_true( status < 0, "newsession did failed when accept was good" );
347
348         fprintf( stderr, "<INFO> new_sess module finished with %d errors\n", errors );
349         return errors;
350 }
351
352 /*
353         Send tests
354 */
355 static int send_tests( ) {
356         int             errors = 0;
357         char    buf[1024];
358         int             len;
359         int             state;
360
361         len = snprintf( buf, 100, "Heaven knows I'm miserable now!" );
362
363         state = SIsendt( si_ctx, 9999, buf, len );
364         errors += fail_if_true( state >= 0, "send given fd out of range did not fail" );
365
366         state = SIsendt( si_ctx, -1, buf, len );
367         errors += fail_if_true( state >= 0, "send given neg fd did not fail" );
368
369         SIsendt( si_ctx, 6, buf, len );
370
371         tpem_set_send_err( 99 );
372         SIsendt( si_ctx, 6, buf, len );
373
374         tpem_set_send_err( 0 );
375         tpem_set_sel_blk( 1 );
376         SIsendt( si_ctx, 6, buf, len );
377
378         tpem_set_sel_blk( 0 );
379         tpem_set_selef_fd( 6 );                                         // will cause send to fail and fd6 to close
380         SIsendt( si_ctx, 6, buf, len );
381
382         return errors;
383 }
384
385
386 // ----------------------------------------------------------------------------------------
387
388 /*
389         Drive tests...
390 */
391 int main() {
392         int errors = 0;
393
394         rmr_set_vlevel( 5 );                    // enable all debugging
395
396         fprintf( stderr, "\n<INFO> starting SI95 tests\n" );
397
398         errors += init();
399         errors += memory();
400         errors += addr();
401         errors += conn();
402         errors += misc();
403
404         errors += new_sess();           // should leave a "connected" session at fd == 6
405         errors += send_tests();
406
407         errors += cleanup();
408
409         test_summary( errors, "SI95 tests" );
410         if( errors == 0 ) {
411                 fprintf( stderr, "<PASS> all tests were OK\n\n" );
412         } else {
413                 fprintf( stderr, "<FAIL> %d errors in SI95 core code\n\n", errors );
414         }
415
416         return !!errors;
417 }