E. Scott Daniels | 8dd4641 | 2019-04-16 20:47:54 +0000 | [diff] [blame^] | 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 | } |