1 // : vi ts=4 sw=4 noet :
3 ==================================================================================
4 Copyright (c) 2019 Nokia
5 Copyright (c) 2018-2019 AT&T Intellectual Property.
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
11 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
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.
26 Author: E. Scott Daniels
38 #include <semaphore.h>
41 #include "rmr_agnostic.h"
43 typedef struct entry_info {
50 Driven by symtab foreach element of one space.
51 We count using the data as a counter.
53 static void count_things( void* st, void* entry, char const* name, void* thing, void* vdata ) {
57 if( (counter = (int *) vdata) != NULL ) {
64 Returns the number of entries in the table for the given class.
66 static int count_entries( route_table_t* rt, int class ) {
76 rmr_sym_foreach_class( rt->hash, class, count_things, &counter ); // run each and update counter
82 Builds a route table key.
84 static uint64_t build_key( uint32_t mtype, uint32_t sid ) {
87 k = (uint64_t) sid << 32;
90 fprintf( stderr, "<INFO> build key: %x %x --> %llx\n", (int) mtype, (int) sid, (long long) k );
95 This is the main route table test. It sets up a very specific table
96 for testing (not via the generic setup function for other test
99 static int rt_test( ) {
100 uta_ctx_t* ctx; // context needed to test load static rt
101 uta_ctx_t* pctx; // "private" context for route manager communication tests
102 route_table_t* rt; // route table
103 route_table_t* crt; // cloned route table
104 rtable_ent_t* rte; // route table entries from table
106 endpoint_t* ep; // endpoint added
108 int more = 0; // more flag from round robin
109 int errors = 0; // number errors found
112 int c1; // general counters
117 ei_t entries[50]; // end point information
118 int gcounts[7]; // number of groups in this set
119 int ecounts[7]; // number of elements per group
120 uint64_t mtypes[7]; // mtype/sid 'key' in the modern RMR world
127 char* seed_fname; // seed file
128 SOCKET_TYPE nn_sock; // differnt in each transport (nng == struct, SI/Nano == int)
129 rmr_mbuf_t* mbuf; // message for meid route testing
130 void* p; // generic pointer
132 #ifndef NNG_UNDER_TEST
133 si_ctx_t* si_ctx = NULL;
136 setenv( "ENV_VERBOSE_FILE", ".ut_rmr_verbose", 1 ); // allow for verbose code in rtc to be driven
137 i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0644 );
139 write( i, "2\n", 2 );
145 The hacky code below calls the necessary rmr functions to create a route table
146 as though the following were read and parsed by the rmr functions. (This tests
147 the individual funcitons and avoids writing another parser, so it's not pretty.)
149 mse | 0 | 0 | yahoo.com:4561,localhost:4562
150 mse | 1 | 0 | localhost:4560,localhost:4568,localhost:4569; localhost:4561,localhost:4562
151 mse | 2 | 0 | localhost:4563,localhost:4564
152 mse | 3 | 0 | localhost:4565
153 mse | 3 | 11 | locahost:5511
154 mse | 3 | -1 | localhost:5500
156 gcounts[0] = 1; // first entry has 1 group with 2 endpoints; message type 0, sid 0
158 mtypes[0] = build_key( 0, 0 ); // mtype is now a key of mtype/sid
159 entries[enu].group = 0; entries[enu].ep_name = "yahoo.com:4561"; enu++; // use a dns resolvable name to test that
160 entries[enu].group = 0; entries[enu].ep_name = "localhost:4562"; enu++; // rest can default to some dummy ip
162 gcounts[1] = 2; // 2 groups
163 ecounts[1] = 3; // first has 3 endpoints
164 mtypes[1] = build_key( 1, 0 );
165 entries[enu].group = 0; entries[enu].ep_name = "localhost:4560"; enu++;
166 entries[enu].group = 0; entries[enu].ep_name = "localhost:4568"; enu++;
167 entries[enu].group = 0; entries[enu].ep_name = "localhost:4569"; enu++;
169 gcounts[2] = 0; // 0 means use same rte, this is the next group for the entry
170 ecounts[2] = 2; // 2 endpoints
171 mtypes[2] = 999; // ignored when appending to previous entry
172 entries[enu].group = 1; entries[enu].ep_name = "localhost:4561"; enu++;
173 entries[enu].group = 1; entries[enu].ep_name = "localhost:4562"; enu++;
175 gcounts[3] = 1; // next entry has 1 group
176 ecounts[3] = 2; // with 2 enpoints
177 mtypes[3] = build_key( 2, 0 );
178 entries[enu].group = 0; entries[enu].ep_name = "localhost:4563"; enu++;
179 entries[enu].group = 0; entries[enu].ep_name = "localhost:4564"; enu++;
181 gcounts[4] = 1; // three entries for mt==3 with different sids
183 mtypes[4] = build_key( 3, 0 );
184 entries[enu].group = 0; entries[enu].ep_name = "localhost:5500"; enu++;
188 mtypes[5] = build_key( 3, 11 );
189 entries[enu].group = 0; entries[enu].ep_name = "localhost:5511"; enu++;
193 mtypes[6] = build_key( 3, -1 );
194 entries[enu].group = 0; entries[enu].ep_name = "localhost:5512"; enu++;
197 rt = uta_rt_init( NULL );
198 errors += fail_if_false( rt == NULL, "rt_init given a nil context didn't return nil" );
200 ctx = mk_dummy_ctx(); // make a dummy with rtgate mutex
201 rt = uta_rt_init( ctx ); // get us a route table
202 if( (errors += fail_if_nil( rt, "pointer to route table" )) ) {
203 fprintf( stderr, "<FAIL> abort: cannot continue without a route table\n" );
209 for( i = 0; i < sizeof( gcounts )/sizeof( int ); i++ ) { // add entries defined above
211 rte = uta_add_rte( rt, mtypes[i], gcounts[i] ); // get/create entry for message type
212 if( (errors += fail_if_nil( rte, "route table entry" )) ) {
213 fprintf( stderr, "<FAIL> abort: cannot continue without a route table entry\n" );
218 fprintf( stderr, "<SNAFU> internal testing error -- rte was nil for gcount == 0\n" );
223 for( k = 0; k < ecounts[i]; k++ ) {
224 ep = uta_add_ep( rt, rte, entries[enu].ep_name, entries[enu].group );
225 errors += fail_if_nil( ep, "endpoint" );
230 // ----- end hacking together a route table ---------------------------------------------------
233 crt = uta_rt_clone( ctx, rt, NULL, 0 ); // create a new rt and clone only the me entries
234 errors += fail_if_nil( crt, "cloned route table" );
236 c1 = count_entries( rt, 1 );
237 c2 = count_entries( crt, 1 );
238 errors += fail_not_equal( c1, c2, "cloned (endpoints) table entries space 1 count (b) did not match original table count (a)" );
240 c2 = count_entries( crt, 0 );
241 errors += fail_not_equal( c2, 0, "cloned (endpoints) table entries space 0 count (a) was not zero as expected" );
243 errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table is not right" );
248 crt = uta_rt_clone( ctx, rt, NULL, 1 ); // clone all entries (MT and ME)
249 errors += fail_if_nil( crt, "cloned (all) route table" );
252 c1 = count_entries( rt, 0 );
253 c2 = count_entries( crt, 0 );
254 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 0 count (b) did not match original table count (a)" );
256 c1 = count_entries( rt, 1 );
257 c2 = count_entries( crt, 1 );
258 errors += fail_not_equal( c1, c2, "cloned (all) table entries space 1 count (b) did not match original table count (a)" );
260 errors += fail_if_false( crt->ephash == rt->ephash, "ephash pointer in cloned table (all) is not right" );
264 #ifdef NNG_UNDER_TEST
265 if( (ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) )) != NULL ) { // get a "context" needed for si testing
266 memset( ctx, 0, sizeof( *ctx ) );
269 fprintf( stderr, "<FAIL> cannot acllocate a context, cannot continue rtable tests\n" );
273 ctx = mk_dummy_ctx();
278 ep = uta_get_ep( rt, "localhost:4561" );
279 errors += fail_if_nil( ep, "end point (fetch by name)" );
280 ep = uta_get_ep( rt, "bad_name:4560" );
281 errors += fail_not_nil( ep, "end point (fetch by name with bad name)" );
284 #ifdef NNG_UNDER_TEST
285 state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, &ep ); // this should be found
287 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep ); // this should be found
289 errors += fail_if_equal( state, 0, "socket (by name)" );
290 errors += fail_if_nil( ep, "epsock_byname did not populate endpoint pointer when expected to" );
291 //alt_value = uta_epsock_byname( rt, "localhost:4562" ); // we might do a memcmp on the two structs, but for now nothing
292 //errors += fail_if_equal( value, alt_value, "app1/app2 sockets" );
295 state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep ); // test coverage on nil checks
297 state = uta_epsock_byname( NULL, "localhost:4561", &nn_sock, &ep );
298 errors += fail_not_equal( state, 0, "socket (by name) nil context check returned true" );
301 ctx->si_ctx = NULL; // set to drive second test
302 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, &ep );
305 errors += fail_not_equal( state, 0, "socket (by name) nil check returned true" );
307 if( ep ) { // if previous test fails, cant run this
310 state = uta_epsock_byname( rt, "localhost:4561", &nn_sock, NULL ); // test coverage on nil checks
312 state = uta_epsock_byname( ctx, "localhost:4561", &nn_sock, NULL );
314 errors += fail_if_equal( state, 0, "socket (by name) open ep check returned false" );
318 // --- test that the get_rte function finds expected keys, and retries to find 'bad' sid attempts for valid mtypes with no sid
319 rte = uta_get_rte( rt, 0, 1, TRUE ); // s=0 m=1 is defined, so this should return a pointer
320 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 true given" );
322 rte = uta_get_rte( rt, 0, 1, FALSE ); // the retry shouldn't apply, but ensure it does the righ thing
323 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=1 false given" );
325 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
326 errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 false given" );
328 rte = uta_get_rte( rt, 1000, 1, TRUE ); // this should also fail as there is no mt==1 sid==-1 defined
329 errors += fail_not_nil( rte, "get_rte returned a pointer when s=1000 m=1 true given" );
331 rte = uta_get_rte( rt, 0, 3, TRUE ); // mtype sid combo does exist; true/false should not matter
332 errors += fail_if_nil( rte, "get_rte did not return a pointer when s=0 m=3 true given" );
334 rte2 = uta_get_rte( rt, 11, 3, TRUE ); // same mtype as before, different (valid) group, rte should be different than before
335 errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=11 m=3 true given" );
336 errors += fail_if_true( rte == rte2, "get_rte for mtype==3 and different sids (0 and 11) returned the same rte pointer" );
338 rte2 = uta_get_rte( rt, 0, 3, FALSE ); // since the mtype/sid combo exists, setting false should return the same as before
339 errors += fail_if_nil( rte2, "get_rte did not return a pointer when s=0 m=3 false given" );
340 errors += fail_if_false( rte == rte2, "get_rte did not return same pointer when mtype/sid combo given with different true/false" );
342 rte = uta_get_rte( rt, 12, 3, FALSE ); // this combo does not exist and should fail when alt-key is not allowed (false)
343 errors += fail_not_nil( rte, "get_rte returned a pointer for s=12, m=3, false" );
345 rte = uta_get_rte( rt, 12, 3, TRUE ); // this should return the entry for the 3/-1 combination
346 errors += fail_if_nil( rte, "get_rte did not return a pointer for s=12, m=3, true" );
350 rte = uta_get_rte( rt, 0, 1, FALSE ); // get an rte for the next loop
352 for( i = 0; i < 10; i++ ) { // round robin return value should be different each time
353 #ifdef NNG_UNDER_TEST
354 value = uta_epsock_rr( rte, 0, &more, &nn_sock, &ep ); // msg type 1, group 1
356 value = uta_epsock_rr( ctx, rte, 0, &more, &nn_sock, &ep );
359 errors += fail_if_equal( value, alt_value, "round robiin sockets with multiple end points" );
360 errors += fail_if_false( more, "more for mtype==1" );
366 rte = uta_get_rte( rt, 0, 3, FALSE ); // get an rte for the next loop
368 for( i = 0; i < 10; i++ ) { // this mtype has only one endpoint, so rr should be same each time
369 #ifdef NNG_UNDER_TEST
370 value = uta_epsock_rr( rte, 0, NULL, &nn_sock, &ep ); // also test ability to deal properly with nil more pointer
372 value = uta_epsock_rr( ctx, rte, 0, NULL, &nn_sock, &ep );
376 errors += fail_not_equal( value, alt_value, "round robin sockets with one endpoint" );
377 errors += fail_not_equal( more, -1, "more value changed in single group instance" );
383 rte = uta_get_rte( rt, 11, 3, TRUE );
384 #ifdef NNG_UNDER_TEST
385 state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
387 state = uta_epsock_rr( ctx, rte, 22, NULL, NULL, &ep );
389 errors += fail_if_true( state, "uta_epsock_rr returned bad (non-zero) state when given nil socket pointer" );
392 uta_rt_clone( ctx, NULL, NULL, 0 ); // verify null parms don't crash things
394 #ifdef NNG_UNDER_TEST
395 uta_epsock_rr( NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
396 state = uta_epsock_rr( rte, 22, NULL, NULL, &ep );
398 state = uta_epsock_rr( NULL, NULL, 0, &more, &nn_sock, &ep ); // drive null case for coverage
399 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil ctx" );
401 state = uta_epsock_rr( ctx, NULL, 0, &more, &nn_sock, &ep );
402 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given nil rte" );
404 state = uta_epsock_rr( ctx, rte, 10000, &more, &nn_sock, &ep );
405 errors += fail_not_equal( state, 0, "uta_epsock_rr did not return false when given invalid group number" );
407 uta_add_rte( NULL, 99, 1 );
408 uta_get_rte( NULL, 0, 1000, TRUE );
410 fprintf( stderr, "[INFO] test: adding end points with nil data; warnings expected\n" );
411 uta_add_ep( NULL, NULL, "foo", 1 );
412 uta_add_ep( rt, NULL, "foo", 1 );
414 buf = uta_fib( ".gitignore" );
415 errors += fail_if_nil( buf, "buffer from read file into buffer" );
419 buf = uta_fib( "no-file" );
420 errors += fail_if_nil( buf, "buffer from read file into buffer (no file)" );
425 fprintf( stderr, "<INFO> test is overtly dropping rt table at %p\n", rt );
431 // --- force the load of a RT which has some edge case forcing issues
434 "newrt | start | dummy-seed\n"
435 "mse | 1 | -1 | localhost:84306\n"
436 "mse | 10 | -1 | localhost:84306\n"
437 "mse | 10 | 1 | localhost:84306\n"
438 "# should cause failure because there aren't 10 entries above\n"
441 "# this table has no end\n"
442 "newrt | start | dummy-seed\n"
443 "mse | 1 | -1 | localhost:84306\n"
444 "mse | 10 | -1 | localhost:84306\n"
445 "mse | 10 | 1 | localhost:84306\n"
447 "# this table should be ok\n"
448 "newrt | start | dummy-seed\n"
449 "mse | 1 | -1 | localhost:84306\n"
450 "mse | 10 | -1 | localhost:84306\n"
451 "mse | 10 | 1 | localhost:84306\n"
454 "# for an update to the existing table\n"
455 "# not in progress; drive that exception check\n"
456 "update | end | 23\n"
458 "update | start | dummy-seed\n"
459 "mse | 3 | 2 | localhost:2222\n"
460 "# short record to drive test\n"
462 "# no table end for exception handling\n"
464 "update | start | dummy-seed\n"
465 "mse | 2 | 2 | localhost:2222\n"
467 "update | end | 2\n";
469 fprintf( stderr, "<INFO> loading RT from edge case static table\n" );
470 fprintf( stderr, "<INFO> %s\n", rt_stuff );
471 gen_custom_rt( ctx, rt_stuff );
472 fprintf( stderr, "<INFO> edge case load completed\n" );
473 errors += fail_if_nil( ctx->rtable, "edge case route table didn't generate a pointer into the context" );
475 unsetenv( "RMR_SEED_RT" ); // remove for next read try
476 read_static_rt( ctx, 0 ); // drive for not there coverage
480 buf = uta_fib( "no-suhch-file" ); // drive some error checking for coverage
486 ep = (endpoint_t *) malloc( sizeof( *ep ) );
487 memset( ep, 0, sizeof( ep ) );
488 pthread_mutex_init( &ep->gate, NULL );
489 ep->name = strdup( "worm" );
492 #ifdef NNG_UNDER_TEST
493 state = uta_link2( ep );
495 state = uta_link2( ctx, ep );
497 errors += fail_if_true( state, "link2 did not return false when given a bad target name" );
499 #ifdef NNG_UNDER_TEST
500 state = uta_link2( NULL );
502 state = uta_link2( ctx, NULL );
503 errors += fail_if_true( state, "link2 did not return false when given nil ep pointer" );
505 state = uta_link2( NULL, ep );
507 errors += fail_if_true( state, "link2 did not return false when given nil pointer" );
509 ep->name = strdup( "localhost:5512" );
511 #ifdef NNG_UNDER_TEST
512 state = uta_link2( ep ); // drive for coverage
514 state = uta_link2( ctx, ep );
516 errors += fail_if_false( state, "link2 did returned false when given open ep" );
518 #ifndef NNG_UNDER_TEST
519 ep->open = 0; // context is used only if ep not open, so to check this test close the ep
521 state = rt_link2_ep( NULL, ep );
522 errors += fail_if_true( state, "rt_link2_ep returned true when given bad context" );
524 state = rt_link2_ep( ctx, NULL );
525 errors += fail_if_true( state, "rt_link2_ep returned true when given bad ep" );
528 state = rt_link2_ep( ctx, ep );
529 errors += fail_if_false( state, "rt_link2_ep returned false when given an open ep" );
532 state = rt_link2_ep( ctx, ep );
533 errors += fail_if_false( state, "rt_link2_ep returned false when given a closed ep" );
537 errors += fail_if_true( ep->open, "uta_ep_failed didn't set open flag to false" );
542 // ----------------- test the meid support for looking up an endpoint based on the meid in the message -----
545 ctx->my_name = strdup( "my_host_name" ); // set up to load a rtable
546 ctx->my_ip = strdup( "192.168.1.30" );
547 gen_rt( ctx ); // generate a route table with meid entries and hang off ctx
549 mbuf = rmr_alloc_msg( ctx, 2048 ); // buffer to play with
551 rmr_str2meid( mbuf, "meid1" ); // id that we know is in the map
553 #ifdef NNG_UNDER_TEST
554 ep = NULL; // force to nil so we see it go non-nil
555 state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
556 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
557 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
559 rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
560 state = epsock_meid( ctx->rtable, mbuf, &nn_sock, &ep );
561 // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
562 errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
564 ep = NULL; // force to nil so we see it go non-nil
565 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
566 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message" );
567 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message" );
569 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep ); // a second call to drive open == true check for coverage
570 errors += fail_if_nil( ep, "ep was nil when looking up ep with known meid in message; on open ep" );
571 errors += fail_not_equal( state, 1, "state was not true when looking up ep with known meid in message; on open ep" );
573 rmr_str2meid( mbuf, "XXXmeid1" ); // id that we know is NOT in the map
574 state = epsock_meid( ctx, ctx->rtable, mbuf, &nn_sock, &ep );
575 // it is NOT a valid check to test ep for nil -- epsock_mied doesn't guarentee ep is set/cleared when state is false
576 errors += fail_not_equal( state, 0, "state was not false when looking up ep with unknown meid in message" );
578 state = epsock_meid( NULL, ctx->rtable, mbuf, &nn_sock, &ep );
579 errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil context" );
581 state = epsock_meid( ctx, ctx->rtable, mbuf, NULL, &ep );
582 errors += fail_not_equal( state, 0, "epsock_meid returned true when given nil socket pointer" );
585 // ------------ debugging and such; coverage only calls ----------------------------------------------------------
586 ep_stats( ctx->rtable, NULL, "name", NULL, NULL ); // ensure no crash when given nil pointer
587 rt_epcounts( ctx->rtable, "testing" );
588 rt_epcounts( NULL, "testing" );
590 buf = ensure_nlterm( NULL );
591 errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given nil ptr" );
593 errors += fail_not_equal( strlen( buf ), 1, "ensure nlterm returned incorrect length string when given nil pointer" );
597 buf = ensure_nlterm( strdup( "x" ) ); // should return "x\n"
598 errors += fail_if_nil( buf, "ensure nlterm returned null pointer when given single char string" );
600 errors += fail_not_equal( strlen( buf ), 2, "ensure nlterm returned incorrect length string when given single char string" );
604 buf = strdup( "x\n" );
605 buf2 = ensure_nlterm( buf ); // buffer returned should be the same
606 if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for one char string with newline" ) ) {
612 buf = strdup( "Missing our trips to Gloria's for papossas.\n" );
613 buf2 = ensure_nlterm( buf ); // buffer returned should be the same
614 if( fail_not_pequal( buf, buf2, "ensure nlterm returned new buffer for string with newline" ) ) {
620 buf = ensure_nlterm( strdup( "Stand up and cheer!" ) ); // force addition of newline
622 errors += fail_not_equal( strcmp( buf, "Stand up and cheer!\n" ), 0, "ensure nlterm didn't add newline" );
628 // ------------- route manager request/response funcitons -------------------------------------------------------
632 smsg = rmr_alloc_msg( ctx, 1024 );
633 send_rt_ack( ctx, smsg, "123456", 0, "no reason" );
635 pctx = mk_dummy_ctx();
637 state = send_update_req( pctx, ctx );
638 errors += fail_not_equal( state, 0, "send_update_req did not return 0" );
640 ctx->rtg_whid = rmr_wh_open( ctx, "localhost:19289" );
641 state = send_update_req( pctx, ctx );
642 errors += fail_if_equal( state, 0, "send_update_req to an open whid did not return 0" );
646 // ------------- si only; fd to ep conversion functions ---------------------------------------------------------
647 #ifndef NNG_UNDER_TEST
648 ep2 = (endpoint_t *) malloc( sizeof( *ep ) );
651 fd2ep_add( ctx, 10, ep2 );
653 ep = fd2ep_get( ctx, 10 );
654 errors += fail_if_nil( ep, "fd2ep did not return pointer for known mapping" );
655 errors += fail_if_false( ep == ep2, "fd2ep did not return same pointer that was added" );
657 ep = fd2ep_get( ctx, 20 );
658 errors += fail_not_nil( ep, "fd2ep did returned a pointer for unknown mapping" );
660 ep = fd2ep_del( ctx, 10 );
661 errors += fail_if_nil( ep, "fd2ep delete did not return pointer for known mapping" );
662 errors += fail_if_false( ep == ep2, "fd2ep delete did not return same pointer that was added" );
664 ep = fd2ep_del( ctx, 20 );
665 errors += fail_not_nil( ep, "fd2ep delete returned a pointer for unknown mapping" );
668 // ---------------- misc coverage tests --------------------------------------------------------------------------
669 collect_things( NULL, NULL, NULL, NULL, NULL ); // these both return null, these test NP checks
670 collect_things( NULL, NULL, NULL, NULL, (void *) 1234 ); // the last is an invalid pointer, but check needed to force check on previous param
671 del_rte( NULL, NULL, NULL, NULL, NULL );
673 return !!errors; // 1 or 0 regardless of count