129eec1da669b436f5b7793fb318dc415f4d348c
[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( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
79         if( i >= 0 ) {
80                 write( 1, "2\n", 2 );
81                 close( i );
82         }
83
84         gcounts[0] = 1;                 // build entry info -- this is hackish, but saves writing another parser
85         ecounts[0] = 2;
86         mtypes[0] = 0;
87         entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++;         // use a dns resolvable name to test that
88         entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
89
90         gcounts[1] = 2;
91         ecounts[1] = 3;
92         mtypes[1] = 1;
93         entries[enu].group = 0; entries[enu].ep_name = "localhost:4561"; enu++;
94         entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
95         entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
96
97         gcounts[2] = 0;         // 0 groups means use same rte, this is the next gropup
98         ecounts[2] = 2;
99         mtypes[2] = 1;
100         entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
101         entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
102
103         gcounts[3] = 1;         // 0 groups means use same rte, this is the next gropup
104         ecounts[3] = 2;
105         mtypes[3] = 2;
106         entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
107         entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
108
109         gcounts[4] = 1;         // 0 groups means use same rte, this is the next gropup
110         ecounts[4] = 1;
111         mtypes[4] = 3;
112         entries[enu].group = 0; entries[enu].ep_name = "localhost:4565"; enu++;
113
114
115
116         rt = uta_rt_init( );                                                                            // get us a route table
117         if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
118                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
119                 exit( 1 );
120         }
121
122         enu = 0;
123         rte = NULL;
124         for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) {                                // add entries defined above
125                 if( gcounts[i] ) {
126                         rte = uta_add_rte( rt, mtypes[i], gcounts[i] );                                 // get/create entry for message type
127                         if( (errors += fail_if_nil( rte, "route table entry" )) ) {
128                                 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
129                                 exit( 1 );
130                         }
131                 } else {
132                         if( rte == NULL ) {
133                                 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
134                                 exit( 1 );
135                         }
136                 }
137
138                 for( k = 0; k < ecounts[i]; k++ ) {
139                         ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
140                         errors += fail_if_nil( ep, "endpoint" );
141                         enu++;
142                 }
143         }
144
145         crt = uta_rt_clone( rt );
146         errors += fail_if_nil( crt, "cloned route table" );
147
148         ep = uta_get_ep( rt, "localhost:4561" );
149         errors += fail_if_nil( ep, "end point (fetch by name)" );
150         ep = uta_get_ep( rt, "bad_name:4560" );
151         errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
152
153         state = uta_epsock_byname( rt, "localhost:4561", &nn_sock );            // this should be found
154         errors += fail_if_equal( state, 0, "socket (by name)" );
155         //alt_value = uta_epsock_byname( rt, "localhost:4562" );                        // we might do a memcmp on the two structs, but for now nothing
156         //errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
157
158         alt_value = -1;
159         for( i = 0; i < 10; i++ ) {                                                                             // round robin return value should be different each time
160                 value = uta_epsock_rr( rt, 1, 0, &more, &nn_sock );                     // msg type 1, group 1
161                 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
162                 errors += fail_if_false( more, "more for mtype==1" );
163                 alt_value = value;
164         }
165
166         more = -1;
167         for( i = 0; i < 10; i++ ) {                                                     // this mtype has only one endpoint, so rr should be same each time
168                 value = uta_epsock_rr( rt, 3, 0, NULL, &nn_sock );              // also test ability to deal properly with nil more pointer
169                 if( i ) {
170                         errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
171                         errors += fail_not_equal( more, -1, "more value changed in single group instance" );
172                 }
173                 alt_value = value;
174         }
175
176         value = uta_epsock_rr( rt, 9, 0, &more, &nn_sock );                     // non-existant message type; should return false (0)
177         errors += fail_not_equal( value, 0, "socket for bad mtype was valid" );
178
179         uta_rt_clone( NULL );                                                           // verify null parms don't crash things
180         uta_rt_drop( NULL );
181         uta_epsock_rr( NULL, 1, 0, &more, &nn_sock );           // drive null case for coverage
182         uta_add_rte( NULL, 99, 1 );
183
184         fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
185         uta_add_ep( NULL, NULL, "foo", 1 );
186         uta_add_ep( rt, NULL, "foo", 1 );
187
188         buf = uta_fib( ".gitignore" );
189         errors += fail_if_nil( buf, "buffer from read file into buffer" );
190         if( buf ) {
191                 free( buf );
192         }
193         buf = uta_fib( "no-file" );
194         errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
195         if( buf ) {
196                 free( buf );
197         }
198
199         uta_rt_drop( rt );
200
201         uta_rt_drop( crt );
202
203         if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) {
204                 memset( ctx, 0, sizeof( *ctx ) );
205
206                 if( (seed_fname = getenv( "RMR_SEED_RT" )) != NULL ) {
207                         if( ! (fail_if_nil( rt, "pointer to rt for load test" )) ) {
208                                 errors++;
209                                 read_static_rt( ctx, 0 );
210                                 unsetenv( "RMR_SEED_RT" );                      // unset to test the does not exist condition
211                                 read_static_rt( ctx, 0 );
212                         } else {
213                                 fprintf( stderr, "<FAIL> cannot gen rt for load test\n" );
214                         }
215                 } else {
216                         read_static_rt( ctx, 0 );               // not defined, just drive for that one case
217                 }
218         }
219
220         uta_fib( "no-suhch-file" );                     // drive some error checking for coverage
221
222 /*
223         if( ctx ) {
224                 if( ctx->rtg_addr ) {
225                         free( ctx->rtg_addr );
226                 }
227                 free( ctx );
228         }
229 */
230
231         return !!errors;                        // 1 or 0 regardless of count
232 }