2 // : vi ts=4 sw=4 noet :
4 ==================================================================================
5 Copyright (c) 2019-2021 Nokia
6 Copyright (c) 2018-2021 AT&T Intellectual Property.
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 ==================================================================================
23 Mmemonic: rt_static_test.c
24 Abstract: Test the route table funcitons. These are meant to be included at compile
25 time by the test driver.
27 Author: E. Scott Daniels
39 #include <semaphore.h>
42 #include "rmr_agnostic.h"
44 typedef struct entry_info {
51 Driven by symtab foreach element of one space.
52 We count using the data as a counter.
54 static void count_things( void* st, void* entry, char const* name, void* thing, void* vdata ) {
58 if( (counter = (int *) vdata) != NULL ) {
65 Returns the number of entries in the table for the given class.
67 static int count_entries( route_table_t* rt, int class ) {
77 rmr_sym_foreach_class( rt->hash, class, count_things, &counter ); // run each and update counter
83 Builds a route table key.
85 static uint64_t build_key( uint32_t mtype, uint32_t sid ) {
88 k = (uint64_t) sid << 32;
91 fprintf( stderr, "<INFO> build key: %x %x --> %llx\n", (int) mtype, (int) sid, (long long) k );
96 Create a very large set of things to clone and ensure that the colleciton
97 buffers are properly resized without errors.
99 static int lg_clone_test( ) {
105 old_env = getenv( "RMR_SEED_RT" );
106 setenv( "RMR_SEED_RT", "./large_meid.rt", 1 );
108 ctx = mk_dummy_ctx();
110 read_static_rt( ctx, 0 );
111 p = uta_rt_clone( ctx, ctx->rtable, NULL, 1 ); // clone to force the copy from the existing table
112 errors += fail_if_nil( p, "clone of large table returned nil" );
114 errors += fail_not_equal( p->error, 0, "clone of large table had error" );
117 setenv( "RMR_SEED_RT", old_env, 1 );
123 This is the main route table test. It sets up a very specific table
124 for testing (not via the generic setup function for other test
127 static int rt_test( ) {
128 uta_ctx_t* ctx; // context needed to test load static rt
129 uta_ctx_t* pctx; // "private" context for route manager communication tests
130 route_table_t* rt; // route table
131 route_table_t* crt; // cloned route table
132 rtable_ent_t* rte; // route table entries from table
134 endpoint_t* ep; // endpoint added
136 int more = 0; // more flag from round robin
137 int errors = 0; // number errors found
140 int c1; // general counters
145 ei_t entries[50]; // end point information
146 int gcounts[7]; // number of groups in this set
147 int ecounts[7]; // number of elements per group
148 uint64_t mtypes[7]; // mtype/sid 'key' in the modern RMR world
155 char* seed_fname; // seed file
156 SOCKET_TYPE nn_sock; // differnt in each transport (nng == struct, SI/Nano == int)
157 rmr_mbuf_t* mbuf; // message for meid route testing
158 void* p; // generic pointer
160 #ifndef NNG_UNDER_TEST
161 si_ctx_t* si_ctx = NULL;
164 setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 ); // allow for verbose code in rtc to be driven
165 i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
167 write( i, "2\n", 2 );
173 The hacky code below calls the necessary rmr functions to create a route table
174 as though the following were read and parsed by the rmr functions. (This tests
175 the individual funcitons and avoids writing another parser, so it's not pretty.)
177 mse | 0 | 0 | yahoo.com:4561,localhost:4562
178 mse | 1 | 0 | localhost:4560,localhost:4568,localhost:4569; localhost:4561,localhost:4562
179 mse | 2 | 0 | localhost:4563,localhost:4564
180 mse | 3 | 0 | localhost:4565
181 mse | 3 | 11 | locahost:5511
182 mse | 3 | -1 | localhost:5500
184 gcounts[0] = 1; // first entry has 1 group with 2 endpoints; message type 0, sid 0
186 mtypes[0] = build_key( 0, 0 ); // mtype is now a key of mtype/sid
187 entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++; // use a dns resolvable name to test that
188 entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
190 gcounts[1] = 2; // 2 groups
191 ecounts[1] = 3; // first has 3 endpoints
192 mtypes[1] = build_key( 1, 0 );
193 entries[enu].group = 0; entries[enu].ep_name = "localhost:4560"; enu++;
194 entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
195 entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
197 gcounts[2] = 0; // 0 means use same rte, this is the next group for the entry
198 ecounts[2] = 2; // 2 endpoints
199 mtypes[2] = 999; // ignored when appending to previous entry
200 entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
201 entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
203 gcounts[3] = 1; // next entry has 1 group
204 ecounts[3] = 2; // with 2 enpoints
205 mtypes[3] = build_key( 2, 0 );
206 entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
207 entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
209 gcounts[4] = 1; // three entries for mt==3 with different sids
211 mtypes[4] = build_key( 3, 0 );
212 entries[enu].group = 0; entries[enu].ep_name = "localhost:5500"; enu++;
216 mtypes[5] = build_key( 3, 11 );
217 entries[enu].group = 0; entries[enu].ep_name = "localhost:5511"; enu++;
221 mtypes[6] = build_key( 3, -1 );
222 entries[enu].group = 0; entries[enu].ep_name = "localhost:5512"; enu++;
225 rt = uta_rt_init( NULL );
226 errors += fail_if_false( rt == NULL, "rt_init given a nil context didn't return nil" );
228 ctx = mk_dummy_ctx(); // make a dummy with rtgate mutex
229 rt = uta_rt_init( ctx ); // get us a route table
230 if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
231 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
237 for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) { // add entries defined above
239 rte = uta_add_rte( rt, mtypes[i], gcounts[i] ); // get/create entry for message type
240 if( (errors += fail_if_nil( rte, "route table entry" )) ) {
241 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
246 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
251 for( k = 0; k < ecounts[i]; k++ ) {
252 ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
253 errors += fail_if_nil( ep, "endpoint" );
258 // ----- end hacking together a route table ---------------------------------------------------
261 crt = uta_rt_clone( ctx, rt, NULL, 0 ); // create a new rt and clone only the me entries
262 errors += fail_if_nil( crt, "cloned route table" );
264 c1 = count_entries( rt, 1 );
265 c2 = count_entries( crt, 1 );
266 errors += fail_not_equal( c1, c2, "cloned (endpoints) table entries space 1 count (b) did not match original table count (a)" );
268 c2 = count_entries( crt, 0 );
269 errors += fail_not_equal( c2, 0, "cloned (endpoints) table entries space 0 count (a) was not zero as expected" );
271 errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table is not right" );
276 crt = uta_rt_clone( ctx, rt, NULL, 1 ); // clone all entries (MT and ME)
277 errors += fail_if_nil( crt, "cloned (all) route table" );
280 c1 = count_entries( rt, 0 );
281 c2 = count_entries( crt, 0 );
282 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 0 count (b) did not match original table count (a)" );
284 c1 = count_entries( rt, 1 );
285 c2 = count_entries( crt, 1 );
286 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 1 count (b) did not match original table count (a)" );
288 errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table (all) is not right" );
292 #ifdef NNG_UNDER_TEST
293 if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) { // get a "context" needed for si testing
294 memset( ctx, 0, sizeof( *ctx ) );
297 fprintf( stderr, "<FAIL> cannot acllocate a context, cannot continue rtable tests\n" );
301 ctx = mk_dummy_ctx();
306 ep = uta_get_ep( rt, "localhost:4561" );
307 errors += fail_if_nil( ep, "end point (fetch by name)" );
308 ep = uta_get_ep( rt, "bad_name:4560" );
309 errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
312 #ifdef NNG_UNDER_TEST
313 state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, &ep ); // this should be found
315 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep ); // this should be found
317 errors += fail_if_equal( state, 0, "socket (by name)" );
318 errors += fail_if_nil( ep, "epsock_byname did not populate endpoint pointer when expected to" );
319 //alt_value = uta_epsock_byname( rt, "localhost:4562" ); // we might do a memcmp on the two structs, but for now nothing
320 //errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
323 state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep ); // test coverage on nil checks
325 state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep );
326 errors += fail_not_equal( state, 0, "socket (by name) nil context check returned true" );
329 ctx->si_ctx = NULL; // set to drive second test
330 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep );
333 errors += fail_not_equal( state, 0, "socket (by name) nil check returned true" );
335 if( ep ) { // if previous test fails, cant run this
338 state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, NULL ); // test coverage on nil checks
340 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, NULL );
342 errors += fail_if_equal( state, 0, "socket (by name) open ep check returned false" );
346 // --- test that the get_rte function finds expected keys, and retries to find 'bad' sid attempts for valid mtypes with no sid
347 rte = uta_get_rte( rt, 0, 1, TRUE ); // s=0 m=1 is defined, so this should return a pointer
348 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 true given" );
350 rte = uta_get_rte( rt, 0, 1, FALSE ); // the retry shouldn't apply, but ensure it does the righ thing
351 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 false given" );
353 rte = uta_get_rte( rt, 1000, 1, FALSE ); // s=1000 does not exist for any msg type; should return nil as not allowed to drop sid
354 errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 false given" );
356 rte = uta_get_rte( rt, 1000, 1, TRUE ); // this should also fail as there is no mt==1 sid==-1 defined
357 errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 true given" );
359 rte = uta_get_rte( rt, 0, 3, TRUE ); // mtype sid combo does exist; true/false should not matter
360 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=3 true given" );
362 rte2 = uta_get_rte( rt, 11, 3, TRUE ); // same mtype as before, different (valid) group, rte should be different than before
363 errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=11 m=3 true given" );
364 errors += fail_if_true( rte == rte2, "get_rte for mtype==3 and different sids (0 and 11) returned the same rte pointer" );
366 rte2 = uta_get_rte( rt, 0, 3, FALSE ); // since the mtype/sid combo exists, setting false should return the same as before
367 errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=0 m=3 false given" );
368 errors += fail_if_false( rte == rte2, "get_rte did not return same pointer when mtype/sid combo given with different true/false" );
370 rte = uta_get_rte( rt, 12, 3, FALSE ); // this combo does not exist and should fail when alt-key is not allowed (false)
371 errors += fail_not_nil( rte, "get_rte returned a pointer for s=12, m=3, false" );
373 rte = uta_get_rte( rt, 12, 3, TRUE ); // this should return the entry for the 3/-1 combination
374 errors += fail_if_nil( rte, "get_rte did not return a pointer for s=12, m=3, true" );
378 rte = uta_get_rte( rt, 0, 1, FALSE ); // get an rte for the next loop
380 for( i = 0; i < 10; i++ ) { // round robin return value should be different each time
381 #ifdef NNG_UNDER_TEST
382 value = uta_epsock_rr( rte, 0, &more, &nn_sock, &ep ); // msg type 1, group 1
384 value = uta_epsock_rr( ctx, rte, 0, &more, &nn_sock, &ep );
387 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
388 errors += fail_if_false( more, "more for mtype==1" );
394 rte = uta_get_rte( rt, 0, 3, FALSE ); // get an rte for the next loop
396 for( i = 0; i < 10; i++ ) { // this mtype has only one endpoint, so rr should be same each time
397 #ifdef NNG_UNDER_TEST
398 value = uta_epsock_rr( rte, 0, NULL, &nn_sock, &ep ); // also test ability to deal properly with nil more pointer
400 value = uta_epsock_rr( ctx, rte, 0, NULL, &nn_sock, &ep );
404 errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
405 errors += fail_not_equal( more, -1, "more value changed in single group instance" );
411 rte = uta_get_rte( rt, 11, 3, TRUE );
412 #ifdef NNG_UNDER_TEST
413 state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
415 state = uta_epsock_rr( ctx, rte, 22, NULL, NULL, &ep );
417 errors += fail_if_true( state, "uta_epsock_rr returned bad (non-zero) state when given nil socket pointer" );
420 uta_rt_clone( ctx, NULL, NULL, 0 ); // verify null parms don't crash things
422 #ifdef NNG_UNDER_TEST
423 uta_epsock_rr( NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
424 state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
426 state = uta_epsock_rr( NULL, NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
427 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil ctx" );
429 state = uta_epsock_rr( ctx, NULL, 0, &more, &nn_sock, &ep );
430 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil rte" );
432 state = uta_epsock_rr( ctx, rte, 10000, &more, &nn_sock, &ep );
433 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given invalid group number" );
435 uta_add_rte( NULL, 99, 1 );
436 uta_get_rte( NULL, 0, 1000, TRUE );
438 fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
439 uta_add_ep( NULL, NULL, "foo", 1 );
440 uta_add_ep( rt, NULL, "foo", 1 );
442 buf = uta_fib( ".gitignore" );
443 errors += fail_if_nil( buf, "buffer from read file into buffer" );
447 buf = uta_fib( "no-file" );
448 errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
453 fprintf( stderr, "<INFO> test is overtly dropping rt table at %p\n", rt );
459 // --- force the load of a RT which has some edge case forcing issues
462 "newrt | start | dummy-seed\n"
463 "mse | 1 | -1 | localhost:84306\n"
464 "mse | 10 | -1 | localhost:84306\n"
465 "mse | 10 | 1 | localhost:84306\n"
466 "# should cause failure because there aren't 10 entries above\n"
469 "# this table has no end\n"
470 "newrt | start | dummy-seed\n"
471 "mse | 1 | -1 | localhost:84306\n"
472 "mse | 10 | -1 | localhost:84306\n"
473 "mse | 10 | 1 | localhost:84306\n"
475 "# this table should be ok\n"
476 "newrt | start | dummy-seed\n"
477 "mse | 1 | -1 | localhost:84306\n"
478 "mse | 10 | -1 | localhost:84306\n"
479 "mse | 10 | 1 | localhost:84306\n"
482 "# for an update to the existing table\n"
483 "# not in progress; drive that exception check\n"
484 "update | end | 23\n"
486 "update | start | dummy-seed\n"
487 "mse | 3 | 2 | localhost:2222\n"
488 "# short record to drive test\n"
490 "# no table end for exception handling\n"
492 "update | start | dummy-seed\n"
493 "mse | 2 | 2 | localhost:2222\n"
495 "update | end | 2\n";
497 fprintf( stderr, "<INFO> loading RT from edge case static table\n" );
498 fprintf( stderr, "<INFO> %s\n", rt_stuff );
499 gen_custom_rt( ctx, rt_stuff );
500 fprintf( stderr, "<INFO> edge case load completed\n" );
501 errors += fail_if_nil( ctx->rtable, "edge case route table didn't generate a pointer into the context" );
503 unsetenv( "RMR_SEED_RT" ); // remove for next read try
504 if( ctx && ctx->seed_rt_fname != NULL ) {
505 free( ctx->seed_rt_fname );
506 ctx->seed_rt_fname = NULL;
508 read_static_rt( ctx, 0 ); // drive for not there coverage
512 buf = uta_fib( "no-suhch-file" ); // drive some error checking for coverage
518 ep = (endpoint_t *) malloc( sizeof( *ep ) );
519 memset( ep, 0, sizeof( ep ) );
520 pthread_mutex_init( &ep->gate, NULL );
521 ep->name = strdup( "worm" );
524 #ifdef NNG_UNDER_TEST
525 state = uta_link2( ep );
527 state = uta_link2( ctx, ep );
529 errors += fail_if_true( state, "link2 did not return false when given a bad target name" );
531 #ifdef NNG_UNDER_TEST
532 state = uta_link2( NULL );
534 state = uta_link2( ctx, NULL );
535 errors += fail_if_true( state, "link2 did not return false when given nil ep pointer" );
537 state = uta_link2( NULL, ep );
539 errors += fail_if_true( state, "link2 did not return false when given nil pointer" );
541 ep->name = strdup( "localhost:5512" );
543 #ifdef NNG_UNDER_TEST
544 state = uta_link2( ep ); // drive for coverage
546 state = uta_link2( ctx, ep );
548 errors += fail_if_false( state, "link2 did returned false when given open ep" );
550 #ifndef NNG_UNDER_TEST
551 ep->open = 0; // context is used only if ep not open, so to check this test close the ep
553 state = rt_link2_ep( NULL, ep );
554 errors += fail_if_true( state, "rt_link2_ep returned true when given bad context" );
556 state = rt_link2_ep( ctx, NULL );
557 errors += fail_if_true( state, "rt_link2_ep returned true when given bad ep" );
560 state = rt_link2_ep( ctx, ep );
561 errors += fail_if_false( state, "rt_link2_ep returned false when given an open ep" );
564 state = rt_link2_ep( ctx, ep );
565 errors += fail_if_false( state, "rt_link2_ep returned false when given a closed ep" );
569 errors += fail_if_true( ep->open, "uta_ep_failed didn't set open flag to false" );
574 // ----------------- test the meid support for looking up an endpoint based on the meid in the message -----
577 ctx->my_name = strdup( "my_host_name" ); // set up to load a rtable
578 ctx->my_ip = strdup( "192.168.1.30" );
579 if( ctx && ctx->seed_rt_fname != NULL ) {
580 free( ctx->seed_rt_fname );
581 ctx->seed_rt_fname = NULL;
583 gen_rt( ctx ); // generate a route table with meid entries and hang off ctx
585 mbuf = rmr_alloc_msg( ctx, 2048 ); // buffer to play with
587 rmr_str2meid( mbuf, "meid1" ); // id that we know is in the map
589 #ifdef NNG_UNDER_TEST
590 ep = NULL; // force to nil so we see it go non-nil
591 state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
592 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
593 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
595 rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
596 state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
597 // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
598 errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
600 ep = NULL; // force to nil so we see it go non-nil
601 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
602 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
603 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
605 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep ); // a second call to drive open == true check for coverage
606 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message; on open ep" );
607 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message; on open ep" );
609 rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
610 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
611 // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
612 errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
614 state = epsock_meid( NULL, ctx->rtable, mbuf, &nn_sock, &ep );
615 errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil context" );
617 state = epsock_meid( ctx, ctx->rtable, mbuf, NULL, &ep );
618 errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil socket pointer" );
621 // ------------ debugging and such; coverage only calls ----------------------------------------------------------
622 ep_stats( ctx->rtable, NULL, "name", NULL, NULL ); // ensure no crash when given nil pointer
623 rt_epcounts( ctx->rtable, "testing" );
624 rt_epcounts( NULL, "testing" );
626 buf = ensure_nlterm( NULL );
627 errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given nil ptr" );
629 errors += fail_not_equal( strlen( buf ), 1, "ensure nlterm returned incorrect length string when given nil pointer" );
633 buf = ensure_nlterm( strdup( "x" ) ); // should return "x\n"
634 errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given single char string" );
636 errors += fail_not_equal( strlen( buf ), 2, "ensure nlterm returned incorrect length string when given single char string" );
640 buf = strdup( "x\n" );
641 buf2 = ensure_nlterm( buf ); // buffer returned should be the same
642 if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for one char string with newline" ) ) {
648 buf = strdup( "Missing our trips to Gloria's for papossas.\n" );
649 buf2 = ensure_nlterm( buf ); // buffer returned should be the same
650 if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for string with newline" ) ) {
656 buf = ensure_nlterm( strdup( "Stand up and cheer!" ) ); // force addition of newline
658 errors += fail_not_equal( strcmp( buf, "Stand up and cheer!\n" ), 0, "ensure nlterm didn't add newline" );
664 // ------------- route manager request/response funcitons -------------------------------------------------------
668 smsg = rmr_alloc_msg( ctx, 1024 );
669 send_rt_ack( ctx, smsg, "123456", 0, "no reason" );
671 pctx = mk_dummy_ctx();
673 state = send_update_req( pctx, ctx );
674 errors += fail_not_equal( state, 0, "send_update_req did not return 0" );
676 ctx->rtg_whid = rmr_wh_open( ctx, "localhost:19289" );
677 state = send_update_req( pctx, ctx );
678 errors += fail_if_equal( state, 0, "send_update_req to an open whid did not return 0" );
682 // ------------- si only; fd to ep conversion functions ---------------------------------------------------------
683 #ifndef NNG_UNDER_TEST
684 ep2 = (endpoint_t *) malloc( sizeof( *ep ) );
687 fd2ep_add( ctx, 10, ep2 );
689 ep = fd2ep_get( ctx, 10 );
690 errors += fail_if_nil( ep, "fd2ep did not return pointer for known mapping" );
691 errors += fail_if_false( ep == ep2, "fd2ep did not return same pointer that was added" );
693 ep = fd2ep_get( ctx, 20 );
694 errors += fail_not_nil( ep, "fd2ep did returned a pointer for unknown mapping" );
696 ep = fd2ep_del( ctx, 10 );
697 errors += fail_if_nil( ep, "fd2ep delete did not return pointer for known mapping" );
698 errors += fail_if_false( ep == ep2, "fd2ep delete did not return same pointer that was added" );
700 ep = fd2ep_del( ctx, 20 );
701 errors += fail_not_nil( ep, "fd2ep delete returned a pointer for unknown mapping" );
704 // ---------------- misc coverage tests --------------------------------------------------------------------------
705 collect_things( NULL, NULL, NULL, NULL, NULL ); // these both return null, these test NP checks
706 collect_things( NULL, NULL, NULL, NULL, (void *) 1234 ); // the last is an invalid pointer, but check needed to force check on previous param
707 del_rte( NULL, NULL, NULL, NULL, NULL );
709 ctx = mk_dummy_ctx();
710 roll_tables( ctx ); // drive nil rt check
714 // ------ specific edge case tests -------------------------------------------------------------------------------
715 errors += lg_clone_test( );
717 unlink( ".ut_rmr_verbose" );
719 return errors; // 1 or 0 regardless of count