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 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 The message buffer specific API tests are in a different static
30 module. API functions tested here are:
46 Author: E. Scott Daniels
58 #include "../src/common/include/rmr.h"
59 #include "../src/common/include/rmr_agnostic.h"
60 //#include "../src/common/src/ring_static.c"
63 Send a 'burst' of messages to drive some send retry failures to increase RMr coverage
64 by handling the retry caee.
66 static void send_n_msgs( void* ctx, int n ) {
67 rmr_mbuf_t* msg; // message buffers
70 msg = rmr_alloc_msg( ctx, 1024 );
75 for( i = 0; i < n; i++ ) {
76 fprintf( stderr, "mass send\n" );
81 msg = rmr_send_msg( ctx, msg );
85 static int rmr_api_test( ) {
87 void* rmc; // route manager context
88 void* rmc2; // second context for non-listener init
89 rmr_mbuf_t* msg; // message buffers
91 int v = 0; // some value
95 v = rmr_ready( NULL );
96 errors += fail_if( v != 0, "rmr_ready returned true before initialisation" );
98 if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
99 fail_if_nil( rmc, "rmr_init returned a nil pointer" );
103 if( (rmc2 = rmr_init( ":6789", 1024, FL_NOTHREAD )) == NULL ) { // init without starting a thread
104 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer for non-threaded init" );
107 free_ctx( rmc2 ); // coverage
109 if( (rmc2 = rmr_init( NULL, 1024, FL_NOTHREAD )) == NULL ) { // drive default port selector code
110 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for default port" );
113 v = rmr_ready( rmc ); // unknown return; not checking at the moment
115 msg = rmr_alloc_msg( NULL, 1024 ); // should return nil pointer
116 errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context" );
118 msg = rmr_alloc_msg( rmc, 2048 ); // allocate larger than default size given on init
119 errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer" );
121 v = rmr_payload_size( NULL );
122 errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message" );
123 errors += fail_if( errno == 0, "rmr_payload_size did not set errno on failure" );
125 v = rmr_payload_size( msg );
127 errors += fail_not_equal( v, 2048, "rmr_payload_size returned invalid size (a) instead of expected size (b)" );
128 errors += fail_if( errno != 0, "rmr_payload_size did not clear errno on success" );
130 errors += fail_if( v < 0, "rmr_payload_size returned invalid size for good message" );
133 v = rmr_get_rcvfd( NULL );
134 errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor when given nil context" );
135 v = rmr_get_rcvfd( rmc );
136 errors += fail_if( v < 0, "rmr_get_rcvfd did not return a valid file descriptor" );
138 msg2 = rmr_send_msg( NULL, NULL ); // drive for coverage
139 errors += fail_not_nil( msg2, "send_msg returned msg pointer when given a nil message and context" );
141 // --- sends will fail with a no endpoint error until a dummy route table is set, so we test fail case first.
146 msg = rmr_send_msg( rmc, msg );
147 errors += fail_if_nil( msg, "send_msg_ did not return a message on send" );
149 errors += fail_not_equal( msg->state, RMR_ERR_NOENDPT, "send_msg did not return no endpoints before rtable added" );
150 errors += fail_if( errno == 0, "send_msg did not set errno" );
153 gen_rt( rmc ); // --- after this point there is a dummy route table so send and rts calls should be ok
159 msg = rmr_send_msg( rmc, msg );
160 errors += fail_if_nil( msg, "send_msg_ did not return a message on send" );
162 errors += fail_not_equal( msg->state, RMR_OK, "send_msg returned bad status for send that should work" );
163 errors += fail_if( errno != 0, "send_msg set errno for send that should work" );
164 v = rmr_payload_size( msg );
165 errors += fail_if( v != 2048, "send_msg did not allocate new buffer with correct size" );
168 rmr_set_stimeout( NULL, 0 );
169 rmr_set_stimeout( rmc, 20 );
170 rmr_set_stimeout( rmc, -1 );
171 rmr_set_rtimeout( NULL, 0 );
172 rmr_set_rtimeout( rmc, 20 );
173 rmr_set_rtimeout( rmc, -1 );
175 msg2 = rmr_rcv_msg( NULL, NULL );
176 errors += fail_if( msg2 != NULL, "rmr_rcv_msg returned msg when given nil context and msg" );
178 msg2 = rmr_rcv_msg( rmc, NULL );
179 errors += fail_if( msg2 == NULL, "rmr_rcv_msg returned nil msg when given nil msg" );
181 errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state" );
184 msg = rmr_rcv_msg( rmc, msg );
186 errors += fail_if( msg->state != RMR_OK, "rmr_rcv_msg did not return an ok state" );
187 errors += fail_not_equal( msg->len, 129, "rmr_rcv_msg returned message with invalid len" );
189 errors += fail_if_nil( msg, "rmr_rcv_msg returned a nil pointer" );
192 rmr_rts_msg( NULL, NULL ); // drive for coverage
193 rmr_rts_msg( rmc, NULL );
194 errors += fail_if( errno == 0, "rmr_rts_msg did not set errno when given a nil message" );
196 msg = rmr_rts_msg( rmc, msg ); // return the buffer to the sender
197 errors += fail_if_nil( msg, "rmr_rts_msg did not return a message pointer" );
198 errors += fail_if( errno != 0, "rmr_rts_msg did not reset errno" );
201 snprintf( msg->xaction, 17, "%015d", 16 ); // dummy transaction id (emulation generates, this should arrive after a few calls to recv)
202 msg = rmr_call( rmc, msg ); // this call should return a message as we can anticipate a dummy message in
203 errors += fail_if_nil( msg, "rmr_call returned a nil message on call expected to succeed" );
205 errors += fail_not_equal( msg->state, RMR_OK, "rmr_call did not properly set state on successful return" );
206 errors += fail_if( errno != 0, "rmr_call did not properly set errno on successful return" );
209 snprintf( wbuf, 17, "%015d", 14 ); // if we call receive we should find this in the first 15 tries
210 for( i = 0; i < 16; i++ ) {
211 msg = rmr_rcv_msg( rmc, msg );
213 if( strcmp( wbuf, msg->xaction ) == 0 ) { // found the queued message
216 fprintf( stderr, "<INFO> msg: %s\n", msg->xaction );
218 errors += fail_if_nil( msg, "receive returnd nil msg while looking for queued message" );
222 errors += fail_if( i >= 16, "did not find expected message on queue" );
225 msg = rmr_alloc_msg( rmc, 2048 ); // something buggered above; get a new one
227 msg = rmr_call( rmc, msg ); // make a call that we never expect a response on
228 errors += fail_not_nil( msg, "rmr_call returned a non-nil message on call expected not to receive a response" );
230 errors += fail_not_equal( msg->state, RMR_OK, "rmr_call did not properly set state on queued message receive" );
231 errors += fail_if( errno != 0, "rmr_call did not properly set errno on queued message receivesuccessful" );
234 msg = rmr_call( rmc, msg ); // this should "timeout" because the message xaction id won't ever appear again
235 errors += fail_not_nil( msg, "rmr_call returned a non-nil message on call expected to fail" );
236 errors += fail_if( errno == 0, "rmr_call did not set errno on failure" );
238 rmr_free_msg( NULL ); // drive for coverage; nothing to check
239 rmr_free_msg( msg2 );
242 // --- test timeout receive; our dummy epoll function will return 1 ready on first call and 0 ready (timeout emulation) on second
243 // 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.
245 for( i = 0; i < 40; i++ ) {
246 msg = rmr_torcv_msg( rmc, msg, 10 );
247 errors += fail_if_nil( msg, "torcv_msg returned nil msg when message expected" );
249 if( msg->state == RMR_ERR_TIMEOUT ) { // queue drained and we've seen both states from poll if we get a timeout
254 errors += fail_if( i >= 40, "torcv_msg never returned a timeout" );
257 em_send_failures = 1;
258 send_n_msgs( rmc, 30 ); // send 30 messages with emulation failures
259 em_send_failures = 0;
262 rmr_close( NULL ); // drive for coverage
263 rmr_close( rmc ); // no return to check; drive for coverage
265 //extern rmr_mbuf_t* rmr_mtosend_msg( void* vctx, rmr_mbuf_t* msg, int max_to ) {
266 //extern rmr_mbuf_t* rmr_torcv_msg( void* vctx, rmr_mbuf_t* old_msg, int ms_to ) {
271 fprintf( stderr, "<INFO> all RMr API tests pass\n" );