CI: Add silent cmake SonarCloud scan
[ric-plt/lib/rmr.git] / test / rt_nano_static_test.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4             Copyright (c) 2019-2021 Nokia
5             Copyright (c) 2018-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:       rt_static_test.c
23         Abstract:       Test the route table funcitons. These are meant to be included at compile
24                                 time by the test driver.
25
26         Author:         E. Scott Daniels
27         Date:           3 April 2019
28 */
29
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <pthread.h>
38 #include <semaphore.h>
39
40 #include "rmr.h"
41 #include "rmr_agnostic.h"
42
43 typedef struct entry_info {
44         int group;
45         char* ep_name;
46 } ei_t;
47
48 /*
49         Create a dummy endpoint for some direct function calls.
50 */
51 static endpoint_t* mk_ep( char* name ) {
52         endpoint_t* ep;
53
54         ep = (endpoint_t *) malloc( sizeof( struct endpoint ) );
55         ep->name = strdup( name );
56         ep->proto = strdup( "tcp" );
57         ep->addr = strdup( "address" );
58         ep->nn_sock = -1;
59         ep->open = 0;
60
61         return ep;
62 }
63
64
65 /*
66         This is the main route table test. It sets up a very specific table
67         for testing (not via the generic setup function for other test
68         situations).
69 */
70 static int rt_test( ) {
71         uta_ctx_t* ctx;                 // context needed to test load static rt
72         route_table_t* rt;              // route table
73         route_table_t*  crt;            // cloned route table
74         rtable_ent_t*   rte;    // entry in the table
75         endpoint_t*             ep;                     // endpoint added
76         int                             more = 0;                       // more flag from round robin
77         int                             errors = 0;                     // number errors found
78         int                             i;
79         int                             k;
80         int                             mtype;
81         int                             value;
82         int                             alt_value;
83         ei_t                    entries[50];    // end point information
84         int                             gcounts[5];             // number of groups in this set
85         int                             ecounts[5];             // number of elements per group
86         int                             mtypes[5];              // msg type for each group set
87         char*                   tok;
88         char*                   nxt_tok;
89         int                             enu = 0;
90         int                             state;
91         char                    *buf;
92         char*                   seed_fname;             // seed file
93         int                     nn_sock;
94
95         setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 );                     // allow for verbose code in rtc to be driven
96         i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
97         if( i >= 0 ) {
98                 write( i, "2\n", 2 );
99                 close( i );
100         }
101
102         gcounts[0] = 1;                 // build entry info -- this is hackish, but saves writing another parser
103         ecounts[0] = 2;
104         mtypes[0] = 0;
105         entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++;         // use a dns resolvable name to test that
106         entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
107
108         gcounts[1] = 2;
109         ecounts[1] = 3;
110         mtypes[1] = 1;
111         entries[enu].group = 0; entries[enu].ep_name = "localhost:4561"; enu++;
112         entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
113         entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
114
115         gcounts[2] = 0;         // 0 groups means use same rte, this is the next gropup
116         ecounts[2] = 2;
117         mtypes[2] = 1;
118         entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
119         entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
120
121         gcounts[3] = 1;         // 0 groups means use same rte, this is the next gropup
122         ecounts[3] = 2;
123         mtypes[3] = 2;
124         entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
125         entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
126
127         gcounts[4] = 1;         // 0 groups means use same rte, this is the next gropup
128         ecounts[4] = 1;
129         mtypes[4] = 3;
130         entries[enu].group = 0; entries[enu].ep_name = "localhost:4565"; enu++;
131
132
133         rt = uta_rt_init( );                                                                            // get us a route table
134         if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
135                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
136                 exit( 1 );
137         }
138
139         enu = 0;
140         rte = NULL;
141         for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) {                                // add entries defined above
142                 if( gcounts[i] ) {
143                         rte = uta_add_rte( rt, mtypes[i], gcounts[i] );                                 // get/create entry for message type
144                         if( (errors += fail_if_nil( rte, "route table entry" )) ) {
145                                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
146                                 exit( 1 );
147                         }
148                 } else {
149                         if( rte == NULL ) {
150                                 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
151                                 exit( 1 );
152                         }
153                 }
154
155                 for( k = 0; k < ecounts[i]; k++ ) {
156                         ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
157                         errors += fail_if_nil( ep, "endpoint" );
158                         enu++;
159                 }
160         }
161
162         crt = uta_rt_clone( rt );
163         errors += fail_if_nil( crt, "cloned route table" );
164
165         ep = uta_get_ep( rt, "localhost:4561" );
166         errors += fail_if_nil( ep, "end point (fetch by name)" );
167         ep = uta_get_ep( rt, "bad_name:4560" );
168         errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
169
170         state = uta_epsock_byname( rt, "localhost:4561" );              // this should be found
171         errors += fail_if_true( state < 0, "socket (by name) returned socket less than 0 when expected >= 0 socket" );
172
173         alt_value = -1;
174         for( i = 0; i < 10; i++ ) {                                                                             // round robin return value should be different each time
175                 value = uta_epsock_rr( rt, 1, 0, &more );                                       // nano returns the socket which should be different than the last call
176                 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
177                 errors += fail_if_false( more, "more for mtype==1" );
178                 alt_value = value;
179         }
180
181         more = -1;
182         for( i = 0; i < 10; i++ ) {                                                     // this mtype has only one endpoint, so rr should be same each time
183                 value = uta_epsock_rr( rt, 3, 0, NULL );                // also test ability to deal properly with nil more pointer
184                 if( i ) {
185                         errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
186                         errors += fail_not_equal( more, -1, "more value changed in single group instance" );
187                 }
188                 alt_value = value;
189         }
190
191         value = uta_epsock_rr( rt, 289486, 0, &more  );                 // non-existant message type; should return false (0)
192         errors += fail_if_true( value >= 0, "socket for bad hash key was valid" );
193
194         uta_rt_clone( NULL );                                                           // verify null parms don't crash things
195         uta_rt_drop( NULL );
196         uta_epsock_rr( NULL, 1, 0, &more );                                     // drive null case for coverage
197         uta_add_rte( NULL, 99, 1 );
198
199         fprintf( stderr, "<INFO> adding end points with nil data; warnings from RMr code are expected\n" );
200         uta_add_ep( NULL, NULL, "foo", 1 );
201         uta_add_ep( rt, NULL, "foo", 1 );
202
203         buf = uta_fib( ".gitignore" );
204         errors += fail_if_nil( buf, "buffer from read file into buffer" );
205         if( buf ) {
206                 free( buf );
207         }
208         buf = uta_fib( "no-file" );
209         errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
210         if( buf ) {
211                 free( buf );
212         }
213
214         uta_rt_drop( rt );
215
216         uta_rt_drop( crt );
217
218         if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) {
219                 memset( ctx, 0, sizeof( *ctx ) );
220
221                 if( (seed_fname = getenv( "RMR_SEED_RT" )) != NULL ) {
222                         if( ! (fail_if_nil( rt, "pointer to rt for load test" )) ) {
223                                 read_static_rt( ctx, 0 );
224                                 unsetenv( "RMR_SEED_RT" );                      // unset to test the does not exist condition
225                                 read_static_rt( ctx, 0 );
226                         } else {
227                                 fprintf( stderr, "<FAIL> cannot gen rt for load test\n" );
228                         }
229                 } else {
230                         read_static_rt( ctx, 0 );               // not defined, just drive for that one case
231                 }
232         }
233
234         buf = uta_fib( "no-suhch-file" );                       // drive some error checking for coverage
235         if( buf ) {
236                 free( buf );
237         }
238
239         rt = uta_rt_init( );                                                                            // get us a route table
240         state = uta_link2( NULL );
241         errors += fail_not_equal( state, -1, "link2 did not return (a==) -1 when given nil pointers" );
242
243         ep = mk_ep( "foo" );
244         state = rt_link2_ep( NULL );
245         errors += fail_not_equal( state, 0, "link2_ep did not return (a) bad  when given nil pointers" );
246
247         state = rt_link2_ep( ep );
248         errors += fail_not_equal( state, 1, "link2_ep did not return (a) bad  when given an ep to use to open" );
249
250         ep->open = 1;
251         state = rt_link2_ep( ep );
252         errors += fail_not_equal( state, 1, "link2_ep did not return (a) bad when given an ep which was set open" );
253
254         state = uta_epsock_rr( rt, 122, 0, NULL );
255         errors += fail_not_equal( state, -1, "uta_epsock_rr returned bad state when given nil socket pointer" );
256
257         state = uta_epsock_rr( rt, 0, -1, NULL );
258         errors += fail_not_equal( state, -1, "uta_epsock_rr returned bad state (a) when given negative group number" );
259
260         state = rt_link2_ep( NULL );
261         errors += fail_if_equal( state, -1, "call to link2_ep with nil ep returned true when false expected" );
262
263         unlink( ".ut_rmr_verbose" );
264
265         return errors;
266 }