test(all): Add additional log messages
[ric-plt/lib/rmr.git] / test / rmr_nng_api_static_test.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4         Copyright (c) 2019 Nokia 
5         Copyright (c) 2018-2019 AT&T Intellectual Property.
6
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
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
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 ==================================================================================
19 */
20
21 /*
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.
28
29                                 The message buffer specific API tests are in a different static
30                                 module.  API functions tested here are:
31                                          rmr_close
32                                          rmr_get_rcvfd
33                                          rmr_ready
34                                          rmr_init
35                                          rmr_set_rtimeout
36                                          rmr_set_stimeout
37                                          rmr_rcv_specific
38                                          rmr_torcv_msg
39                                          rmr_rcv_msg
40                                          rmr_call
41                                          rmr_rts_msg
42                                          rmr_send_msg
43                                          rmr_mtosend_msg
44                                          rmr_free_msg
45
46         Author:         E. Scott Daniels
47         Date:           5 April 2019
48 */
49
50 #include <unistd.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <strings.h>
54 #include <errno.h>
55 #include <string.h>
56 #include <stdint.h>
57
58 #include "../src/common/include/rmr.h"
59 #include "../src/common/include/rmr_agnostic.h"
60 //#include "../src/common/src/ring_static.c"
61
62 /*
63         Send a 'burst' of messages to drive some send retry failures to increase RMr coverage
64         by handling the retry caee.
65 */
66 static void send_n_msgs( void* ctx, int n ) {
67         rmr_mbuf_t*     msg;                    // message buffers
68         int i;
69
70         msg = rmr_alloc_msg( ctx,  1024 );
71         if( ! msg ) {
72                 return;
73         }
74
75         for( i = 0; i < n; i++ ) {
76 fprintf( stderr, "mass send\n" );
77                 msg->len = 100;
78                 msg->mtype = 1;
79                 msg->state = 999;
80                 errno = 999;
81                 msg = rmr_send_msg( ctx, msg );
82         }
83 }
84
85 static int rmr_api_test( ) {
86         int             errors = 0;
87         void*   rmc;                            // route manager context
88         void*   rmc2;                           // second context for non-listener init
89         rmr_mbuf_t*     msg;                    // message buffers
90         rmr_mbuf_t*     msg2;
91         int             v = 0;                                  // some value
92         char    wbuf[128];
93         int             i;
94
95         v = rmr_ready( NULL );
96         errors += fail_if( v != 0, "rmr_ready returned true before initialisation" );
97
98         if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
99                 fail_if_nil( rmc, "rmr_init returned a nil pointer" );
100                 return 1;
101         }
102
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" );
105         }
106
107         free_ctx( rmc2 );                       // coverage
108
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" );
111         }
112
113         v = rmr_ready( rmc );           // unknown return; not checking at the moment
114
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" );
117
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" );
120
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" );
124
125         v = rmr_payload_size( msg );
126         if( v >= 0 ) {
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" );
129         } else {
130                 errors += fail_if( v < 0, "rmr_payload_size returned invalid size for good message" );
131         }
132         
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" );
137
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" );
140
141         // --- sends will fail with a no endpoint error until a dummy route table is set, so we test fail case first.
142         msg->len = 100;
143         msg->mtype = 1;
144         msg->state = 999;
145         errno = 999;
146         msg = rmr_send_msg( rmc, msg );
147         errors += fail_if_nil( msg, "send_msg_ did not return a message on send" );
148         if( msg ) {
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" );
151         }
152
153         gen_rt( rmc );          // --- after this point there is a dummy route table so send and rts calls should be ok
154
155         msg->len = 100;
156         msg->mtype = 1;
157         msg->state = 999;
158         errno = 999;
159         msg = rmr_send_msg( rmc, msg );
160         errors += fail_if_nil( msg, "send_msg_ did not return a message on send" );
161         if( msg ) {
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" );
166         }
167
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 );
174
175         msg2 = rmr_rcv_msg( NULL, NULL );
176         errors += fail_if( msg2 != NULL, "rmr_rcv_msg returned msg when given nil context and msg" );
177
178         msg2 = rmr_rcv_msg( rmc, NULL );
179         errors += fail_if( msg2 == NULL, "rmr_rcv_msg returned nil msg when given nil msg" );
180         if( msg2 ) {
181                 errors += fail_not_equal( msg2->state, RMR_OK, "receive given nil message did not return msg with good state" );
182         }
183
184         msg = rmr_rcv_msg( rmc, msg );
185         if( 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" );
188         } else {
189                 errors += fail_if_nil( msg, "rmr_rcv_msg returned a nil pointer" );
190         }
191
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" );
195
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" );
199
200
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" );
204         if( msg ) {
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" );
207         }
208
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 );
212                 if( msg ) {
213                         if( strcmp( wbuf, msg->xaction ) == 0 ) {               // found the queued message
214                                 break;
215                         }
216                         fprintf( stderr, "<INFO> msg: %s\n", msg->xaction );
217                 } else {
218                         errors += fail_if_nil( msg, "receive returnd nil msg while looking for queued message" );
219                 }
220         }
221
222         errors += fail_if( i >= 16, "did not find expected message on queue" );
223                 
224         if( ! msg ) {
225                 msg = rmr_alloc_msg( rmc, 2048 );                               // something buggered above; get a new one
226         }
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" );
229         if( msg ) {
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" );
232         }
233
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" );
237
238         rmr_free_msg( NULL );                   // drive for coverage; nothing to check
239         rmr_free_msg( msg2 );
240
241
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.
244         msg = NULL;
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" );
248                 if( msg ) {
249                         if( msg->state == RMR_ERR_TIMEOUT ) {                   // queue drained and we've seen both states from poll if we get a timeout
250                                 break;
251                         }
252                 }
253         }
254         errors += fail_if( i >= 40, "torcv_msg never returned a timeout" );
255
256         
257         em_send_failures = 1;
258         send_n_msgs( rmc, 30 );                 // send 30 messages with emulation failures
259         em_send_failures = 0;
260
261         
262         rmr_close( NULL );                      // drive for coverage
263         rmr_close( rmc );                       // no return to check; drive for coverage
264
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 ) {
267
268
269
270         if( ! errors ) {
271                 fprintf( stderr, "<INFO> all RMr API tests pass\n" );
272         }
273         return !!errors;
274 }