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: rmr_api_static_test.c
23 Abstract: Specific tests related to the API functions in rmr_nng.c/rmr.c.
24 This should be included by a driver, but only the main RMr
25 driver and there will likely not be a specific stand alone driver
26 for just this small set of tests because of the depth of the
27 library needed to test at this level.
29 This can be used for both the nng and nanomsg outward facing
32 The message buffer specific API tests are in a different static
33 module. API functions tested here are:
49 Author: E. Scott Daniels
61 #include "../src/common/include/rmr.h"
62 #include "../src/common/include/rmr_agnostic.h"
65 Send a 'burst' of messages to drive some send retry failures to increase RMr coverage
66 by handling the retry caee.
68 static void send_n_msgs( void* ctx, int n ) {
69 rmr_mbuf_t* msg; // message buffers
72 msg = rmr_alloc_msg( ctx, 1024 );
77 for( i = 0; i < n; i++ ) {
78 //fprintf( stderr, "mass send\n" );
83 msg = rmr_send_msg( ctx, msg );
87 static int rmr_api_test( ) {
89 void* rmc; // route manager context
90 void* rmc2; // second context for non-listener init
91 rmr_mbuf_t* msg; // message buffers
93 int v = 0; // some value
98 v = rmr_ready( NULL );
99 errors += fail_if( v != 0, "rmr_ready returned true before initialisation " );
101 if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
102 fail_if_nil( rmc, "rmr_init returned a nil pointer " );
106 if( (rmc2 = rmr_init( ":6789", 1024, FL_NOTHREAD )) == NULL ) { // init without starting a thread
107 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer for non-threaded init " );
110 free_ctx( rmc2 ); // coverage
112 if( (rmc2 = rmr_init( NULL, 1024, FL_NOTHREAD )) == NULL ) { // drive default port selector code
113 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for default port " );
116 v = rmr_ready( rmc ); // unknown return; not checking at the moment
118 msg = rmr_alloc_msg( NULL, 1024 ); // should return nil pointer
119 errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context " );
121 msg = rmr_alloc_msg( rmc, 2048 ); // allocate larger than default size given on init
122 errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer " );
124 v = rmr_payload_size( NULL );
125 errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message " );
126 errors += fail_if( errno == 0, "rmr_payload_size did not set errno on failure " );
128 v = rmr_payload_size( msg );
130 errors += fail_not_equal( v, 2048, "rmr_payload_size returned invalid size (a) instead of expected size (b) " );
131 errors += fail_if( errno != 0, "rmr_payload_size did not clear errno on success " );
133 errors += fail_if( v < 0, "rmr_payload_size returned invalid size for good message " );
137 // this is only supported in nng, so behavour is different depending on the underlying library being tested
138 v = rmr_get_rcvfd( NULL );
139 errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor when given nil context " );
140 v = rmr_get_rcvfd( rmc );
141 errors += fail_if( v < 0, "rmr_get_rcvfd did not return a valid file descriptor " );
143 v = rmr_get_rcvfd( NULL );
144 errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor when given nil context " );
145 v = rmr_get_rcvfd( rmc );
146 errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor (not supported in nanomsg)" );
149 msg2 = rmr_send_msg( NULL, NULL ); // drive for coverage
150 errors += fail_not_nil( msg2, "send_msg returned msg pointer when given a nil message and context " );
153 msg = rmr_send_msg( NULL, msg );
154 errors += fail_if( msg->state == 0, "rmr_send_msg did not set msg state when msg given with nil context " );
156 // --- sends will fail with a no endpoint error until a dummy route table is set, so we test fail case first.
161 msg = rmr_send_msg( rmc, msg );
162 errors += fail_if_nil( msg, "send_msg_ did not return a message on send " );
164 errors += fail_not_equal( msg->state, RMR_ERR_NOENDPT, "send_msg did not return no endpoints before rtable added " );
165 errors += fail_if( errno == 0, "send_msg did not set errno " );
168 gen_rt( rmc ); // --- after this point there is a dummy route table so send and rts calls should be ok
174 msg = rmr_send_msg( rmc, msg );
175 errors += fail_if_nil( msg, "send_msg_ did not return a message on send " );
177 errors += fail_not_equal( msg->state, RMR_OK, "send_msg returned bad status for send that should work " );
178 errors += fail_if( errno != 0, "send_msg set errno for send that should work " );
179 v = rmr_payload_size( msg );
180 errors += fail_if( v != 2048, "send_msg did not allocate new buffer with correct size " );
183 rmr_set_stimeout( NULL, 0 );
184 rmr_set_stimeout( rmc, 20 );
185 rmr_set_stimeout( rmc, -1 );
186 rmr_set_rtimeout( NULL, 0 );
187 rmr_set_rtimeout( rmc, 20 );
188 rmr_set_rtimeout( rmc, -1 );
190 msg2 = rmr_rcv_msg( NULL, NULL );
191 errors += fail_if( msg2 != NULL, "rmr_rcv_msg returned msg when given nil context and msg " );
193 msg2 = rmr_rcv_msg( rmc, NULL );
194 errors += fail_if( msg2 == NULL, "rmr_rcv_msg returned nil msg when given nil msg " );
196 if( msg2->state != RMR_ERR_EMPTY ) {
197 errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state (not empty) " );
199 //errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state " );
203 msg = rmr_rcv_msg( rmc, msg );
205 errors += fail_not_equal( msg->state, RMR_OK, "rmr_rcv_msg did not return an ok state " );
206 errors += fail_not_equal( msg->len, 220, "rmr_rcv_msg returned message with invalid len " );
208 errors += fail_if_nil( msg, "rmr_rcv_msg returned a nil pointer " );
211 rmr_rts_msg( NULL, NULL ); // drive for coverage
212 rmr_rts_msg( rmc, NULL );
213 errors += fail_if( errno == 0, "rmr_rts_msg did not set errno when given a nil message " );
216 msg = rmr_rts_msg( NULL, msg ); // should set state in msg
217 errors += fail_if_equal( msg->state, 0, "rmr_rts_msg did not set state when given valid message but no context " );
220 msg = rmr_rts_msg( rmc, msg ); // return the buffer to the sender
221 errors += fail_if_nil( msg, "rmr_rts_msg did not return a message pointer " );
222 errors += fail_if( errno != 0, "rmr_rts_msg did not reset errno " );
227 msg = rmr_call( NULL, msg );
228 errors += fail_if( msg->state == 0, "rmr_call did not set message state when given message with nil context " );
230 snprintf( msg->xaction, 17, "%015d", 16 ); // dummy transaction id (emulation generates, this should arrive after a few calls to recv)
233 msg = rmr_call( rmc, msg ); // dummy nng/nano function will sequentually add xactions and should match or '16'
234 errors += fail_if_nil( msg, "rmr_call returned a nil message on call expected to succeed " );
236 errors += fail_not_equal( msg->state, RMR_OK, "rmr_call did not properly set state on successful return " );
237 errors += fail_not_equal( errno, 0, "rmr_call did not properly set errno (a) on successful return " );
240 snprintf( wbuf, 17, "%015d", 14 ); // while waiting, the queued messages should have #14, so issue a few receives looking for it
241 for( i = 0; i < 16; i++ ) { // it should be in the first 15
242 msg = rmr_rcv_msg( rmc, msg );
244 if( strcmp( wbuf, msg->xaction ) == 0 ) { // found the queued message
247 fprintf( stderr, "<INFO> msg: %s\n", msg->xaction );
249 errors += fail_if_nil( msg, "receive returnd nil msg while looking for queued message " );
253 errors += fail_if( i >= 16, "did not find expected message on queue " );
256 msg = rmr_alloc_msg( rmc, 2048 ); // something buggered above; get a new one
260 msg = rmr_call( rmc, msg ); // make a call that we never expect a response on (nil pointer back)
261 errors += fail_not_nil( msg, "rmr_call returned a nil message on call expected not to receive a response " );
262 errors += fail_if( errno == 0, "rmr_call did not set errno on failure " );
264 rmr_free_msg( NULL ); // drive for coverage; nothing to check
265 rmr_free_msg( msg2 );
268 msg2 = rmr_torcv_msg( NULL, NULL, 10 );
269 errors += fail_not_nil( msg2, "rmr_torcv_msg returned a pointer when given nil information " );
270 msg2 = rmr_torcv_msg( rmc, NULL, 10 );
271 errors += fail_if_nil( msg2, "rmr_torcv_msg did not return a message pointer when given a nil old msg " );
273 // --- test timeout receive; our dummy epoll function will return 1 ready on first call and 0 ready (timeout emulation) on second
274 // however we must drain the swamp (queue) first, so run until we get a timeout error, or 20 and report error if we get to 20.
276 for( i = 0; i < 40; i++ ) {
277 msg = rmr_torcv_msg( rmc, msg, 10 );
278 errors += fail_if_nil( msg, "torcv_msg returned nil msg when message expected " );
280 if( msg->state == RMR_ERR_TIMEOUT || msg->state == RMR_ERR_EMPTY ) { // queue drained and we've seen both states from poll if we get a timeout
285 errors += fail_if( i >= 40, "torcv_msg never returned a timeout " );
288 // ---- trace things that are not a part of the mbuf_api functions and thus must be tested here
289 state = rmr_init_trace( NULL, 37 ); // coverage test nil context
290 errors += fail_not_equal( state, 0, "attempt to initialise trace with nil context returned non-zero state (a) " );
291 errors += fail_if_equal( errno, 0, "attempt to initialise trace with nil context did not set errno as expected " );
293 state = rmr_init_trace( rmc, 37 );
294 errors += fail_if_equal( state, 0, "attempt to set trace len in context was not successful " );
295 errors += fail_not_equal( errno, 0, "attempt to set trace len in context did not clear errno " );
297 msg = rmr_tralloc_msg( rmc, 1024, 17, "1904308620110417" );
298 errors += fail_if_nil( msg, "attempt to allocate message with trace data returned nil message " );
299 state = rmr_get_trace( msg, wbuf, 17 );
300 errors += fail_not_equal( state, 17, "len of trace data (a) returned after msg allocation was not expected size (b) " );
301 state = strcmp( wbuf, "1904308620110417" );
302 errors += fail_not_equal( state, 0, "trace data returned after tralloc was not correct " );
304 em_send_failures = 1;
305 send_n_msgs( rmc, 30 ); // send 30 messages with emulation failures
306 em_send_failures = 0;
309 rmr_close( NULL ); // drive for coverage
310 rmr_close( rmc ); // no return to check; drive for coverage
314 fprintf( stderr, "<INFO> all RMr API tests pass\n" );