blob: 972b767046d74636d3b67ad58d48f33ddf71efdf [file] [log] [blame]
E. Scott Daniels8dd46412019-04-16 20:47:54 +00001// : vi ts=4 sw=4 noet :
2/*
3==================================================================================
E. Scott Daniels5efb1e62019-05-02 17:09:35 +00004 Copyright (c) 2019 Nokia
E. Scott Daniels8790bf02019-04-23 12:59:28 +00005 Copyright (c) 2018-2019 AT&T Intellectual Property.
E. Scott Daniels8dd46412019-04-16 20:47:54 +00006
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
E. Scott Daniels8790bf02019-04-23 12:59:28 +000011 http://www.apache.org/licenses/LICENSE-2.0
E. Scott Daniels8dd46412019-04-16 20:47:54 +000012
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
E. Scott Daniels5efb1e62019-05-02 17:09:35 +000024 time by the test driver.
E. Scott Daniels8dd46412019-04-16 20:47:54 +000025
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
41typedef struct entry_info {
42 int group;
43 char* ep_name;
44} ei_t;
45
46
47/*
E. Scott Daniels3376a212019-05-14 14:14:20 +000048 Driven by symtab foreach element of one space.
49 We count using the data as a counter.
50*/
51static void count_things( void* st, void* entry, char const* name, void* thing, void* vdata ) {
52 int* counter;
53
54 if( thing ) {
55 if( (counter = (int *) vdata) != NULL ) {
56 *counter++;
57 }
58 }
59}
60
61/*
62 Returns the number of entries in the table for the given class.
63*/
64static int count_entries( route_table_t* rt, int class ) {
65 int counter = 0;
66
67 if( ! rt ) {
68 return 0;
69 }
70 if( !rt->hash ) {
71 return 0;
72 }
73
74 rmr_sym_foreach_class( rt->hash, class, count_things, &counter ); // run each and update counter
75
76 return counter;
77}
78
79/*
E. Scott Daniels8dd46412019-04-16 20:47:54 +000080 This is the main route table test. It sets up a very specific table
81 for testing (not via the generic setup function for other test
82 situations).
83*/
84static int rt_test( ) {
85 uta_ctx_t* ctx; // context needed to test load static rt
86 route_table_t* rt; // route table
87 route_table_t* crt; // cloned route table
88 rtable_ent_t* rte; // entry in the table
89 endpoint_t* ep; // endpoint added
90 int more = 0; // more flag from round robin
91 int errors = 0; // number errors found
92 int i;
93 int k;
E. Scott Daniels3376a212019-05-14 14:14:20 +000094 int c1; // general counters
95 int c2;
E. Scott Daniels8dd46412019-04-16 20:47:54 +000096 int mtype;
97 int value;
98 int alt_value;
99 ei_t entries[50]; // end point information
100 int gcounts[5]; // number of groups in this set
101 int ecounts[5]; // number of elements per group
102 int mtypes[5]; // msg type for each group set
103 char* tok;
104 char* nxt_tok;
105 int enu = 0;
106 int state;
107 char *buf;
108 char* seed_fname; // seed file
109 nng_socket nn_sock; // this is a struct in nng, so difficult to validate
110
111 setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 ); // allow for verbose code in rtc to be driven
E. Scott Danielsd7109572019-04-18 14:01:16 +0000112 i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000113 if( i >= 0 ) {
E. Scott Danielsd7109572019-04-18 14:01:16 +0000114 write( 1, "2\n", 2 );
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000115 close( i );
116 }
117
118 gcounts[0] = 1; // build entry info -- this is hackish, but saves writing another parser
119 ecounts[0] = 2;
120 mtypes[0] = 0;
121 entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++; // use a dns resolvable name to test that
122 entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
123
124 gcounts[1] = 2;
125 ecounts[1] = 3;
126 mtypes[1] = 1;
127 entries[enu].group = 0; entries[enu].ep_name = "localhost:4561"; enu++;
128 entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
129 entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
130
131 gcounts[2] = 0; // 0 groups means use same rte, this is the next gropup
132 ecounts[2] = 2;
133 mtypes[2] = 1;
134 entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
135 entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
136
137 gcounts[3] = 1; // 0 groups means use same rte, this is the next gropup
138 ecounts[3] = 2;
139 mtypes[3] = 2;
140 entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
141 entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
142
143 gcounts[4] = 1; // 0 groups means use same rte, this is the next gropup
144 ecounts[4] = 1;
145 mtypes[4] = 3;
146 entries[enu].group = 0; entries[enu].ep_name = "localhost:4565"; enu++;
147
148
149
150 rt = uta_rt_init( ); // get us a route table
151 if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
152 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
153 exit( 1 );
154 }
155
156 enu = 0;
157 rte = NULL;
158 for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) { // add entries defined above
159 if( gcounts[i] ) {
160 rte = uta_add_rte( rt, mtypes[i], gcounts[i] ); // get/create entry for message type
161 if( (errors += fail_if_nil( rte, "route table entry" )) ) {
162 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
163 exit( 1 );
164 }
165 } else {
166 if( rte == NULL ) {
167 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
168 exit( 1 );
169 }
170 }
171
172 for( k = 0; k < ecounts[i]; k++ ) {
173 ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
174 errors += fail_if_nil( ep, "endpoint" );
175 enu++;
176 }
177 }
178
E. Scott Daniels3376a212019-05-14 14:14:20 +0000179 crt = uta_rt_clone( rt ); // clone only the endpoint entries
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000180 errors += fail_if_nil( crt, "cloned route table" );
E. Scott Daniels3376a212019-05-14 14:14:20 +0000181 if( crt ) {
182 c1 = count_entries( rt, 1 );
183 c2 = count_entries( crt, 1 );
184 errors += fail_not_equal( c1, c2, "cloned (endpoints) table entries space 1 count (b) did not match original table count (a)" );
185
186 c2 = count_entries( crt, 0 );
187 errors += fail_not_equal( c2, 0, "cloned (endpoints) table entries space 0 count (a) was not zero as expected" );
188 uta_rt_drop( crt );
189 }
190
191
192 crt = uta_rt_clone_all( rt ); // clone all entries
193 errors += fail_if_nil( crt, "cloned all route table" );
194
195 if( crt ) {
196 c1 = count_entries( rt, 0 );
197 c2 = count_entries( crt, 0 );
198 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 0 count (b) did not match original table count (a)" );
199
200 c1 = count_entries( rt, 1 );
201 c2 = count_entries( crt, 1 );
202 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 1 count (b) did not match original table count (a)" );
203 uta_rt_drop( crt );
204 }
205
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000206
207 ep = uta_get_ep( rt, "localhost:4561" );
208 errors += fail_if_nil( ep, "end point (fetch by name)" );
209 ep = uta_get_ep( rt, "bad_name:4560" );
210 errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
211
212 state = uta_epsock_byname( rt, "localhost:4561", &nn_sock ); // this should be found
213 errors += fail_if_equal( state, 0, "socket (by name)" );
214 //alt_value = uta_epsock_byname( rt, "localhost:4562" ); // we might do a memcmp on the two structs, but for now nothing
215 //errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
216
217 alt_value = -1;
218 for( i = 0; i < 10; i++ ) { // round robin return value should be different each time
219 value = uta_epsock_rr( rt, 1, 0, &more, &nn_sock ); // msg type 1, group 1
220 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
221 errors += fail_if_false( more, "more for mtype==1" );
222 alt_value = value;
223 }
224
225 more = -1;
226 for( i = 0; i < 10; i++ ) { // this mtype has only one endpoint, so rr should be same each time
227 value = uta_epsock_rr( rt, 3, 0, NULL, &nn_sock ); // also test ability to deal properly with nil more pointer
228 if( i ) {
229 errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
230 errors += fail_not_equal( more, -1, "more value changed in single group instance" );
231 }
232 alt_value = value;
233 }
234
235 value = uta_epsock_rr( rt, 9, 0, &more, &nn_sock ); // non-existant message type; should return false (0)
236 errors += fail_not_equal( value, 0, "socket for bad mtype was valid" );
237
238 uta_rt_clone( NULL ); // verify null parms don't crash things
239 uta_rt_drop( NULL );
240 uta_epsock_rr( NULL, 1, 0, &more, &nn_sock ); // drive null case for coverage
241 uta_add_rte( NULL, 99, 1 );
242
243 fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
244 uta_add_ep( NULL, NULL, "foo", 1 );
245 uta_add_ep( rt, NULL, "foo", 1 );
246
247 buf = uta_fib( ".gitignore" );
248 errors += fail_if_nil( buf, "buffer from read file into buffer" );
249 if( buf ) {
250 free( buf );
251 }
252 buf = uta_fib( "no-file" );
253 errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
254 if( buf ) {
255 free( buf );
256 }
257
258 uta_rt_drop( rt );
259
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000260 if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) {
261 memset( ctx, 0, sizeof( *ctx ) );
262
263 if( (seed_fname = getenv( "RMR_SEED_RT" )) != NULL ) {
264 if( ! (fail_if_nil( rt, "pointer to rt for load test" )) ) {
265 errors++;
266 read_static_rt( ctx, 0 );
267 unsetenv( "RMR_SEED_RT" ); // unset to test the does not exist condition
268 read_static_rt( ctx, 0 );
269 } else {
270 fprintf( stderr, "<FAIL> cannot gen rt for load test\n" );
271 }
272 } else {
273 read_static_rt( ctx, 0 ); // not defined, just drive for that one case
274 }
275 }
276
277 uta_fib( "no-suhch-file" ); // drive some error checking for coverage
278
279/*
280 if( ctx ) {
281 if( ctx->rtg_addr ) {
282 free( ctx->rtg_addr );
283 }
284 free( ctx );
285 }
286*/
287
E. Scott Danielsa41c6f52019-04-23 18:24:25 +0000288 state = uta_link2( "worm", NULL, NULL );
289 errors += fail_if_true( state, "link2 did not return false when given nil pointers" );
E. Scott Daniels5efb1e62019-05-02 17:09:35 +0000290
E. Scott Danielsa41c6f52019-04-23 18:24:25 +0000291 state = uta_epsock_rr( rt, 122, 0, NULL, NULL );
292 errors += fail_if_true( state, "uta_epsock_rr returned bad state when given nil socket pointer" );
293
294 rt = uta_rt_init( ); // get us a route table
295 state = uta_epsock_rr( rt, 0, -1, NULL, &nn_sock );
296 errors += fail_if_true( state, "uta_epsock_rr returned bad state (true) when given negative group number" );
297
E. Scott Daniels8dd46412019-04-16 20:47:54 +0000298 return !!errors; // 1 or 0 regardless of count
299}