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