1 // : vi ts=4 sw=4 noet :
3 ==================================================================================
4 Copyright (c) 2019-2021 Nokia
5 Copyright (c) 2018-2021 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: rmr_si_api_static_test.c
23 Abstract: Specific tests related to the API functions in rmr_si.c.
24 This should be included by a driver which invokes the 'main'
25 test function here: rmr_api_test.
27 This test set applies only to the outward facting API functions
28 in the rmr_si.c module (mostly because the context for SI is
31 The message buffer specific API tests are in a different static
32 module. API functions tested here are:
48 Not all message/call functions can be tested here because of the
49 callback nature of SI. There is a specific rcv test static module
52 Author: E. Scott Daniels
64 #include <semaphore.h>
67 #include "rmr_agnostic.h"
70 Driving ep counts is tricky when trying to do it as a part of the rts function, so
71 we drive that code on it's own.
73 static int test_ep_counts() {
75 struct endpoint ep; // need a dummy endpoint
77 memset( &ep, 0, sizeof( ep ) );
79 incr_ep_counts( RMR_OK, &ep );
80 errors += fail_if_false( ep.scounts[EPSC_GOOD] == 1, "ep inc good counter had bad value" );
82 incr_ep_counts( RMR_ERR_RETRY, &ep );
83 errors += fail_if_false( ep.scounts[EPSC_TRANS] == 1, "ep inc trans counter had bad value" );
85 incr_ep_counts( 99, &ep ); // any non-retry/ok value
86 errors += fail_if_false( ep.scounts[EPSC_FAIL] == 1, "ep inc fail counter had bad value" );
88 incr_ep_counts( RMR_OK, NULL ); // ensure nil pointer doesn't crash us
93 static int rmr_api_test( ) {
95 void* rmc; // route manager context
96 void* rmc2; // second context for non-listener init
97 rmr_mbuf_t* msg; // message buffers
99 int v = 0; // some value
102 void* p; // generic pointer to test return value
104 int max_tries; // prevent a sticking in any loop
107 v = rmr_ready( NULL );
108 errors += fail_if( v != 0, "rmr_ready returned true before initialisation " );
110 em_set_long_hostname( 1 );
111 if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
112 fail_if_nil( rmc, "rmr_init returned a nil pointer " );
116 setenv( "RMR_SRC_ID", "somehost", 1 ); // context should have this as source
117 if( (rmc2 = rmr_init( ":6789", 1024, FL_NOTHREAD )) == NULL ) { // init without starting a thread
118 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer for non-threaded init " );
121 fprintf( stderr, "<INFO> with RMR_SRC_ID env set, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
122 v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
123 errors += fail_not_equal( v, 0, "source name not set from environment variable (see previous info)" );
124 free_ctx( rmc2 ); // coverage
126 unsetenv( "RMR_SRC_ID" ); // context should NOT have our artificial name
127 if( (rmc2 = rmr_init( NULL, 1024, FL_NOTHREAD )) == NULL ) { // drive default port selector code
128 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for default port " );
131 fprintf( stderr, "<INFO> after unset of RMR_SRC_ID, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
132 v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
133 errors += fail_if_equal( v, 0, "source name smells when removed from environment (see previous info)" );
134 free_ctx( rmc2 ); // attempt to reduce leak check errors
136 v = rmr_ready( rmc ); // unknown return; not checking at the moment
138 msg = rmr_alloc_msg( NULL, 1024 ); // should return nil pointer
139 errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context " );
142 msg = rmr_alloc_msg( rmc, 2048 ); // allocate larger than default size given on init
143 errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer " );
145 rmr_get_srcip( msg, wbuf );
146 errors += fail_if_equal( 0, strlen( wbuf ), "rmr_get_srcip did not did not return string with length (b) after alloc_msg" );
147 fprintf( stderr, "<INFO> ip: %s\n", wbuf );
151 v = rmr_payload_size( NULL );
152 errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message " );
153 errors += fail_if( errno == 0, "rmr_payload_size did not set errno on failure " );
155 v = rmr_payload_size( msg );
157 errors += fail_not_equal( v, 2048, "rmr_payload_size returned invalid size (a) instead of expected size (b) " );
158 errors += fail_if( errno != 0, "rmr_payload_size did not clear errno on success " );
160 errors += fail_if( v < 0, "rmr_payload_size returned invalid size for good message " );
165 v = rmr_get_rcvfd( NULL );
166 errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor when given nil context " );
167 v = rmr_get_rcvfd( rmc );
168 errors += fail_if( v < 0, "rmr_get_rcvfd did not return a valid file descriptor " );
170 msg2 = rmr_send_msg( NULL, NULL );
171 errors += fail_not_nil( msg2, "send_msg returned msg pointer when given a nil message and context " );
174 msg = rmr_send_msg( NULL, msg );
175 errors += fail_if( msg->state == 0, "rmr_send_msg did not set msg state when msg given with nil context " );
177 // --- sends will fail with a no endpoint error until a dummy route table is set, so we test fail case first.
183 snprintf( msg->payload, 100, "Stand up and cheer from OU to Oh yea! (1)" );
185 msg = rmr_send_msg( rmc, msg );
186 errors += fail_if_nil( msg, "send_msg_ did not return a message on send " );
188 errors += fail_not_equal( msg->state, RMR_ERR_NOENDPT, "send_msg did not return no endpoints before rtable added " );
189 errors += fail_if( errno == 0, "send_msg did not set errno " );
190 errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (1)" );
193 gen_rt( rmc ); // --- after this point there is a dummy route table so send and rts calls should be ok
195 if( ! rmr_ready( rmc ) ) {
196 fprintf( stderr, "\nPANIC! rmr isn't showing ready after loading a rt table\n\n" );
200 state = init_mtcall( NULL ); // drive for coverage
201 errors += fail_not_equal( state, 0, "init_mtcall did not return false (a) when given a nil context pointer" );
204 msg = rmr_alloc_msg( rmc, 2048 ); // get a buffer with a transport header
210 snprintf( msg->payload, 500, "Stand up and cheer from OU to Oh yea! (5)" );
212 msg = rmr_send_msg( rmc, msg );
213 errors += fail_if_nil( msg, "send_msg_ did not return a message on send " );
215 errors += fail_not_equal( msg->state, RMR_OK, "send_msg returned bad status for send that should work " );
216 errors += fail_if( errno != 0, "send_msg set errno for send that should work " );
217 v = rmr_payload_size( msg );
218 errors += fail_if( v != 2048, "send_msg did not allocate new buffer with correct size " );
219 errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (2)" );
222 rmr_set_stimeout( NULL, 0 ); // not supported, but funciton exists, so drive away
223 rmr_set_stimeout( rmc, 20 );
224 rmr_set_stimeout( rmc, -1 );
225 rmr_set_rtimeout( NULL, 0 );
226 rmr_set_rtimeout( rmc, 20 );
227 rmr_set_rtimeout( rmc, -1 );
229 max_tries = 10; // there shouldn't be more than 10 queued at this point
230 while( (msg2 = rmr_torcv_msg( rmc, msg2, 200 )) != NULL ) {
231 if( msg2->state != RMR_OK || max_tries <= 0 ) {
235 fprintf( stderr, ">>>> len=%d state=%d (%s)\n", msg2->len, msg2->state, msg2->payload );
239 // ----- the queue load and disc cb tests should be last! -----------------------------
240 for( i = 0; i < 4000; i++ ) { // test ring drop
242 msg = rmr_alloc_msg( rmc, 2048 ); // get a buffer with a transport header
249 snprintf( msg->payload, 500, "Stand up and cheer from OU to Oh yea! msg=%d", i );
251 msg = rmr_send_msg( rmc, msg );
252 errors += fail_if_nil( msg, "send_msg_ did not return a message on send " );
255 mt_disc_cb( rmc, 0 ); // disconnect callback for coverage
256 mt_disc_cb( rmc, 100 ); // with a fd that doesn't exist
259 // ---- trace things that are not a part of the mbuf_api functions and thus must be tested here -------
260 state = rmr_init_trace( NULL, 37 ); // coverage test nil context
261 errors += fail_not_equal( state, 0, "attempt to initialise trace with nil context returned non-zero state (a) " );
262 errors += fail_if_equal( errno, 0, "attempt to initialise trace with nil context did not set errno as expected " );
264 state = rmr_init_trace( rmc, 37 );
265 errors += fail_if_equal( state, 0, "attempt to set trace len in context was not successful " );
266 errors += fail_not_equal( errno, 0, "attempt to set trace len in context did not clear errno " );
268 msg = rmr_tralloc_msg( rmc, 1024, 17, "1904308620110417" );
269 errors += fail_if_nil( msg, "attempt to allocate message with trace data returned nil message " );
270 state = rmr_get_trace( msg, wbuf, 17 );
271 errors += fail_not_equal( state, 17, "len of trace data (a) returned after msg allocation was not expected size (b) " );
272 state = strcmp( wbuf, "1904308620110417" );
273 errors += fail_not_equal( state, 0, "trace data returned after tralloc was not correct " );
275 em_send_failures = 1;
276 send_n_msgs( rmc, 30 ); // send 30 messages with emulation failures
277 em_send_failures = 0;
280 ((uta_ctx_t *)rmc)->shutdown = 1;
281 rmr_close( NULL ); // drive for coverage
282 rmr_close( rmc ); // no return to check; drive for coverage
285 // ----- mt_rcv edge cases -------------------------------------------------------------------------------------
286 ctx = mk_dummy_ctx();
287 p = rmr_mt_rcv( NULL, msg, 0 ); // give a valid message to cover additional lines
288 errors += fail_if_nil( p, "rmr_rt_rcv did not pointer when given a message with a nil context" );
290 errors += fail_if_equal( msg->state, RMR_OK, "rmr_mt_rcv returned OK state when given nil context" );
293 p = rmr_mt_rcv( ctx, msg, 0 ); // one shot receive "poll" case
294 errors += fail_if_nil( p, "mt_rcv with one shot time length did not return a pointer" );
297 // --------------- nil pointer exception checks ----------------------------------------------------------------
298 rmr_rcv_specific( NULL, NULL, "foo", 0 );
299 mt_call( NULL, NULL, 0, 1, NULL );
300 rmr_mt_call( NULL, NULL, 0, 1 );
301 rmr_set_low_latency( NULL );
302 rmr_set_fack( NULL );
305 msg2 = rmr_alloc_msg( rmc, 1024 );
306 msg2 = rmr_rcv_msg( NULL, msg2 );
308 errors += fail_if( msg2->state == RMR_OK, "nil context check for rcv msg returned OK" );
310 msg2 = rmr_torcv_msg( NULL, msg2, 200 );
312 errors += fail_if( msg2->state == RMR_OK, "nil context check for torcv msg returned OK" );
315 // ----- thread start coverage ---------------------------------------------------------------------------
316 setenv( "RMR_WARNINGS", "1", 1 ); // force non-default branches during these tests
317 setenv( "RMR_SRC_NAMEONLY", "1", 1 );
319 rmr_init( ":6789", 1024, 0 ); // threaded mode with defined/default RM target
320 setenv( "RMR_RTG_SVC", "-1", 1 ); // force into static table mode
321 rmr_init( ":6789", 1024, 0 ); // threaded mode with static table
324 // ---- some things must be pushed specifically for edge cases and such ------------------------------------
325 errors += test_ep_counts();
326 init_err( "test error message", rmc, rmc2, ENOMEM ); // drive for coverage
328 ctx = mk_dummy_ctx();
329 ctx->river_hash = rmr_sym_alloc( 129 );
331 buf2mbuf( NULL, NULL, 0, 0 ); // things in mt_call_si_static
333 state = mt_data_cb( NULL, 0, "123", 3 );
334 errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
336 state = mt_data_cb( ctx, -1, "123", 3 );
337 errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
340 state = mt_data_cb( ctx, 23, "123", 3 ); // force add river to hash reference
341 errors += fail_not_equal( state, 0, "mt_data_cb didn't respond correctly when ctx is nil" );
343 mt_disc_cb( NULL, 0 );
344 mt_disc_cb( ctx, 128 ); // for a FD we know isn't there
347 p = mt_receive( NULL );
348 errors += fail_not_nil( p, "mt_receive returned non-nil pointer when given nil context" );
350 // --------------- phew, done ------------------------------------------------------------------------------
353 fprintf( stderr, "<INFO> all RMr API tests pass\n" );