test(unit): Extend unit tests
[ric-plt/lib/rmr.git] / test / rt_static_test.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia 
5         Copyright (c) 2018-2019 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
38 #include "../src/common/include/rmr.h"
39 #include "../src/common/include/rmr_agnostic.h"
40
41 typedef struct entry_info {
42         int group;
43         char* ep_name;
44 } ei_t;
45
46
47 /*
48         This is the main route table test. It sets up a very specific table
49         for testing (not via the generic setup function for other test
50         situations).
51 */
52 static int rt_test( ) {
53         uta_ctx_t* ctx;                 // context needed to test load static rt
54         route_table_t* rt;              // route table
55         route_table_t* crt;             // cloned route table
56         rtable_ent_t*   rte;    // entry in the table
57         endpoint_t*     ep;                     // endpoint added
58         int more = 0;                   // more flag from round robin
59         int errors = 0;                 // number errors found
60         int     i;
61         int k;
62         int mtype;
63         int value;
64         int alt_value;
65         ei_t    entries[50];    // end point information
66         int             gcounts[5];             // number of groups in this set
67         int             ecounts[5];             // number of elements per group
68         int             mtypes[5];              // msg type for each group set
69         char*   tok;
70         char*   nxt_tok;
71         int             enu = 0;
72         int             state;
73         char    *buf;
74         char*   seed_fname;             // seed file
75         nng_socket nn_sock;             // this is a struct in nng, so difficult to validate
76
77         setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 );                     // allow for verbose code in rtc to be driven
78         i = open( ".rmr_verbose", O_CREAT, 0664 );
79         if( i >= 0 ) {
80                 close( i );
81         }
82
83         gcounts[0] = 1;                 // build entry info -- this is hackish, but saves writing another parser
84         ecounts[0] = 2;
85         mtypes[0] = 0;
86         entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++;         // use a dns resolvable name to test that
87         entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
88
89         gcounts[1] = 2;
90         ecounts[1] = 3;
91         mtypes[1] = 1;
92         entries[enu].group = 0; entries[enu].ep_name = "localhost:4561"; enu++;
93         entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
94         entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
95
96         gcounts[2] = 0;         // 0 groups means use same rte, this is the next gropup
97         ecounts[2] = 2;
98         mtypes[2] = 1;
99         entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
100         entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
101
102         gcounts[3] = 1;         // 0 groups means use same rte, this is the next gropup
103         ecounts[3] = 2;
104         mtypes[3] = 2;
105         entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
106         entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
107
108         gcounts[4] = 1;         // 0 groups means use same rte, this is the next gropup
109         ecounts[4] = 1;
110         mtypes[4] = 3;
111         entries[enu].group = 0; entries[enu].ep_name = "localhost:4565"; enu++;
112
113
114
115         rt = uta_rt_init( );                                                                            // get us a route table
116         if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
117                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
118                 exit( 1 );
119         }
120
121         enu = 0;
122         rte = NULL;
123         for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) {                                // add entries defined above
124                 if( gcounts[i] ) {
125                         rte = uta_add_rte( rt, mtypes[i], gcounts[i] );                                 // get/create entry for message type
126                         if( (errors += fail_if_nil( rte, "route table entry" )) ) {
127                                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
128                                 exit( 1 );
129                         }
130                 } else {
131                         if( rte == NULL ) {
132                                 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
133                                 exit( 1 );
134                         }
135                 }
136
137                 for( k = 0; k < ecounts[i]; k++ ) {
138                         ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
139                         errors += fail_if_nil( ep, "endpoint" );
140                         enu++;
141                 }
142         }
143
144         crt = uta_rt_clone( rt );
145         errors += fail_if_nil( crt, "cloned route table" );
146
147         ep = uta_get_ep( rt, "localhost:4561" );
148         errors += fail_if_nil( ep, "end point (fetch by name)" );
149         ep = uta_get_ep( rt, "bad_name:4560" );
150         errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
151
152         state = uta_epsock_byname( rt, "localhost:4561", &nn_sock );            // this should be found
153         errors += fail_if_equal( state, 0, "socket (by name)" );
154         //alt_value = uta_epsock_byname( rt, "localhost:4562" );                        // we might do a memcmp on the two structs, but for now nothing
155         //errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
156
157         alt_value = -1;
158         for( i = 0; i < 10; i++ ) {                                                                             // round robin return value should be different each time
159                 value = uta_epsock_rr( rt, 1, 0, &more, &nn_sock );                     // msg type 1, group 1
160                 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
161                 errors += fail_if_false( more, "more for mtype==1" );
162                 alt_value = value;
163         }
164
165         more = -1;
166         for( i = 0; i < 10; i++ ) {                                                     // this mtype has only one endpoint, so rr should be same each time
167                 value = uta_epsock_rr( rt, 3, 0, NULL, &nn_sock );              // also test ability to deal properly with nil more pointer
168                 if( i ) {
169                         errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
170                         errors += fail_not_equal( more, -1, "more value changed in single group instance" );
171                 }
172                 alt_value = value;
173         }
174
175         value = uta_epsock_rr( rt, 9, 0, &more, &nn_sock );                     // non-existant message type; should return false (0)
176         errors += fail_not_equal( value, 0, "socket for bad mtype was valid" );
177
178         uta_rt_clone( NULL );                                                           // verify null parms don't crash things
179         uta_rt_drop( NULL );
180         uta_epsock_rr( NULL, 1, 0, &more, &nn_sock );           // drive null case for coverage
181         uta_add_rte( NULL, 99, 1 );
182
183         fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
184         uta_add_ep( NULL, NULL, "foo", 1 );
185         uta_add_ep( rt, NULL, "foo", 1 );
186
187         buf = uta_fib( ".gitignore" );
188         errors += fail_if_nil( buf, "buffer from read file into buffer" );
189         if( buf ) {
190                 free( buf );
191         }
192         buf = uta_fib( "no-file" );
193         errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
194         if( buf ) {
195                 free( buf );
196         }
197
198         uta_rt_drop( rt );
199
200         uta_rt_drop( crt );
201
202         if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) {
203                 memset( ctx, 0, sizeof( *ctx ) );
204
205                 if( (seed_fname = getenv( "RMR_SEED_RT" )) != NULL ) {
206                         if( ! (fail_if_nil( rt, "pointer to rt for load test" )) ) {
207                                 errors++;
208                                 read_static_rt( ctx, 0 );
209                                 unsetenv( "RMR_SEED_RT" );                      // unset to test the does not exist condition
210                                 read_static_rt( ctx, 0 );
211                         } else {
212                                 fprintf( stderr, "<FAIL> cannot gen rt for load test\n" );
213                         }
214                 } else {
215                         read_static_rt( ctx, 0 );               // not defined, just drive for that one case
216                 }
217         }
218
219         uta_fib( "no-suhch-file" );                     // drive some error checking for coverage
220
221 /*
222         if( ctx ) {
223                 if( ctx->rtg_addr ) {
224                         free( ctx->rtg_addr );
225                 }
226                 free( ctx );
227         }
228 */
229
230         return !!errors;                        // 1 or 0 regardless of count
231 }