More changes for scan corrections and unit test coverage
[ric-plt/lib/rmr.git] / test / rmr_si_api_static_test.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4             Copyright (c) 2019-2020 Nokia
5             Copyright (c) 2018-2020 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_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.
26
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
29                                 different).
30
31                                 The message buffer specific API tests are in a different static
32                                 module.  API functions tested here are:
33                                          rmr_close
34                                          rmr_get_rcvfd
35                                          rmr_ready
36                                          rmr_init
37                                          rmr_set_rtimeout
38                                          rmr_set_stimeout
39                                          rmr_rcv_specific
40                                          rmr_torcv_msg
41                                          rmr_rcv_msg
42                                          rmr_call
43                                          rmr_rts_msg
44                                          rmr_send_msg
45                                          rmr_mtosend_msg
46                                          rmr_free_msg
47
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
50                                 for those tests.
51
52         Author:         E. Scott Daniels
53         Date:           5 April 2019
54 */
55
56 #include <unistd.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <strings.h>
60 #include <errno.h>
61 #include <string.h>
62 #include <stdint.h>
63 #include <pthread.h>
64 #include <semaphore.h>
65
66 #include "rmr.h"
67 #include "rmr_agnostic.h"
68
69 static int rmr_api_test( ) {
70         int             errors = 0;
71         void*   rmc;                            // route manager context
72         void*   rmc2;                           // second context for non-listener init
73         rmr_mbuf_t*     msg;                    // message buffers
74         rmr_mbuf_t*     msg2;
75         int             v = 0;                                  // some value
76         char    wbuf[128];
77         int             i;
78         int             state;
79         int             max_tries;                      // prevent a sticking in any loop
80
81         v = rmr_ready( NULL );
82         errors += fail_if( v != 0, "rmr_ready returned true before initialisation "  );
83
84         em_set_long_hostname( 1 );
85         if( (rmc = rmr_init( "4560", 1024, FL_NOTHREAD )) == NULL ) {
86                 fail_if_nil( rmc, "rmr_init returned a nil pointer "  );
87                 return 1;
88         }
89
90         setenv( "RMR_SRC_ID", "somehost", 1 );                                                          // context should have this as source
91         if( (rmc2 = rmr_init( ":6789", 1024, FL_NOTHREAD )) == NULL ) {         // init without starting a thread
92                 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer for non-threaded init "  );
93         }
94
95         fprintf( stderr, "<INFO> with RMR_SRC_ID env set, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
96         v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
97         errors += fail_not_equal( v, 0, "source name not set from environment variable (see previous info)" );
98         free_ctx( rmc2 );                       // coverage
99
100         unsetenv( "RMR_SRC_ID" );                                                                                               // context should NOT have our artificial name
101         if( (rmc2 = rmr_init( NULL, 1024, FL_NOTHREAD )) == NULL ) {                    // drive default port selector code
102                 errors += fail_if_nil( rmc, "rmr_init returned a nil pointer when driving for default port "  );
103         }
104
105         fprintf( stderr, "<INFO> after unset of RMR_SRC_ID, source name in context: (%s)\n", ((uta_ctx_t *) rmc2)->my_name );
106         v = strcmp( ((uta_ctx_t *) rmc2)->my_name, "somehost:6789" );
107         errors += fail_if_equal( v, 0, "source name smells when removed from environment (see previous info)" );
108         free_ctx( rmc2 );                       // attempt to reduce leak check errors
109
110         v = rmr_ready( rmc );           // unknown return; not checking at the moment
111
112         msg = rmr_alloc_msg( NULL,  1024 );                                                                     // should return nil pointer
113         errors += fail_not_nil( msg, "rmr_alloc_msg didn't return nil when given nil context "  );
114
115
116         msg = rmr_alloc_msg( rmc, 2048 );                               // allocate larger than default size given on init
117         errors += fail_if_nil( msg, "rmr_alloc_msg returned nil msg pointer "  );
118         if( msg ) {
119                 rmr_get_srcip( msg, wbuf );
120                 errors += fail_if_equal( 0, strlen( wbuf ), "rmr_get_srcip did not did not return string with length (b) after alloc_msg" );
121                 fprintf( stderr, "<INFO> ip: %s\n", wbuf );
122         }
123
124
125         v = rmr_payload_size( NULL );
126         errors += fail_if( v >= 0, "rmr_payload_size returned valid size for nil message "  );
127         errors += fail_if( errno == 0, "rmr_payload_size did not set errno on failure "  );
128
129         v = rmr_payload_size( msg );
130         if( v >= 0 ) {
131                 errors += fail_not_equal( v, 2048, "rmr_payload_size returned invalid size (a) instead of expected size (b) "  );
132                 errors += fail_if( errno != 0, "rmr_payload_size did not clear errno on success "  );
133         } else {
134                 errors += fail_if( v < 0, "rmr_payload_size returned invalid size for good message "  );
135         }
136
137
138
139         v = rmr_get_rcvfd( NULL );
140         errors += fail_if( v >= 0, "rmr_get_rcvfd returned a valid file descriptor when given nil context "  );
141         v = rmr_get_rcvfd( rmc );
142         errors += fail_if( v < 0, "rmr_get_rcvfd did not return a valid file descriptor "  );
143
144         msg2 = rmr_send_msg( NULL, NULL );
145         errors += fail_not_nil( msg2, "send_msg returned msg pointer when given a nil message and context "  );
146
147         msg->state = 0;
148         msg = rmr_send_msg( NULL, msg );
149         errors += fail_if( msg->state == 0, "rmr_send_msg did not set msg state when msg given with nil context "  );
150
151         // --- sends will fail with a no endpoint error until a dummy route table is set, so we test fail case first.
152         msg->len = 100;
153         msg->mtype = 1;
154         msg->state = 999;
155         msg->tp_state = 999;
156         errno = 999;
157         snprintf( msg->payload, 100, "Stand up and cheer from OU to Oh yea! (1)" );
158
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_ERR_NOENDPT, "send_msg did not return no endpoints before rtable added "  );
163                 errors += fail_if( errno == 0, "send_msg did not set errno "  );
164                 errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (1)" );
165         }
166
167         gen_rt( rmc );          // --- after this point there is a dummy route table so send and rts calls should be ok
168
169         if( ! rmr_ready( rmc ) ) {
170                 fprintf( stderr, "\nPANIC!  rmr isn't showing ready after loading a rt table\n\n" );
171                 return errors;
172         }
173
174         state = init_mtcall( NULL );                                    // drive for coverage
175         errors += fail_not_equal( state, 0, "init_mtcall did not return false (a) when given a nil context pointer" );
176
177         rmr_free_msg( msg );
178         msg = rmr_alloc_msg( rmc, 2048 );                               // get a buffer with a transport header
179         msg->len = 500;
180         msg->mtype = 1;
181         msg->state = 999;
182         msg->tp_state = 999;
183         errno = 999;
184         snprintf( msg->payload, 500, "Stand up and cheer from OU to Oh yea! (5)" );
185
186         msg = rmr_send_msg( rmc, msg );
187         errors += fail_if_nil( msg, "send_msg_ did not return a message on send "  );
188         if( msg ) {
189                 errors += fail_not_equal( msg->state, RMR_OK, "send_msg returned bad status for send that should work "  );
190                 errors += fail_if( errno != 0, "send_msg set errno for send that should work "  );
191                 v = rmr_payload_size( msg );
192                 errors += fail_if( v != 2048, "send_msg did not allocate new buffer with correct size "  );
193                 errors += fail_if( msg->tp_state == 999, "send_msg did not set tp_state (2)" );
194         }
195
196         rmr_set_stimeout( NULL, 0 );            // not supported, but funciton exists, so drive away
197         rmr_set_stimeout( rmc, 20 );
198         rmr_set_stimeout( rmc, -1 );
199         rmr_set_rtimeout( NULL, 0 );
200         rmr_set_rtimeout( rmc, 20 );
201         rmr_set_rtimeout( rmc, -1 );
202
203         max_tries = 10;                                         // there shouldn't be more than 10 queued at this point
204         while( (msg2 = rmr_torcv_msg( rmc, msg2, 200 )) != NULL ) {
205                 if( msg2->state != RMR_OK || max_tries <= 0 ) {
206                         break;
207                 }
208
209                 fprintf( stderr, ">>>> len=%d state=%d (%s)\n", msg2->len, msg2->state, msg2->payload );
210                 max_tries--;
211         }
212
213         // ----- the queue load and disc cb tests should be last! -----------------------------
214         for( i = 0; i < 4000; i++ ) {                   // test ring drop
215                 if( msg == NULL ) {
216                         msg = rmr_alloc_msg( rmc, 2048 );                               // get a buffer with a transport header
217                 }
218                 msg->len = 500;
219                 msg->mtype = 1;
220                 msg->state = 999;
221                 msg->tp_state = 999;
222                 errno = 999;
223                 snprintf( msg->payload, 500, "Stand up and cheer from OU to Oh yea! msg=%d", i );
224
225                 msg = rmr_send_msg( rmc, msg );
226                 errors += fail_if_nil( msg, "send_msg_ did not return a message on send "  );
227         }
228
229         mt_disc_cb( rmc, 0 );                   // disconnect callback for coverage
230         mt_disc_cb( rmc, 100 );                 // with a fd that doesn't exist
231
232
233         // ---- trace things that are not a part of the mbuf_api functions and thus must be tested here -------
234         state = rmr_init_trace( NULL, 37 );                                             // coverage test nil context
235         errors += fail_not_equal( state, 0, "attempt to initialise trace with nil context returned non-zero state (a) "  );
236         errors += fail_if_equal( errno, 0, "attempt to initialise trace with nil context did not set errno as expected "  );
237
238         state = rmr_init_trace( rmc, 37 );
239         errors += fail_if_equal( state, 0, "attempt to set trace len in context was not successful "  );
240         errors += fail_not_equal( errno, 0, "attempt to set trace len in context did not clear errno "  );
241
242         msg = rmr_tralloc_msg( rmc, 1024, 17, "1904308620110417" );
243         errors += fail_if_nil( msg, "attempt to allocate message with trace data returned nil message "  );
244         state = rmr_get_trace( msg, wbuf, 17 );
245         errors += fail_not_equal( state, 17, "len of trace data (a) returned after msg allocation was not expected size (b) "  );
246         state = strcmp( wbuf, "1904308620110417" );
247         errors += fail_not_equal( state, 0, "trace data returned after tralloc was not correct "  );
248
249         em_send_failures = 1;
250         send_n_msgs( rmc, 30 );                 // send 30 messages with emulation failures
251         em_send_failures = 0;
252
253
254         ((uta_ctx_t *)rmc)->shutdown = 1;
255         rmr_close( NULL );                      // drive for coverage
256         rmr_close( rmc );                       // no return to check; drive for coverage
257
258
259         // --------------- nil pointer exception checks
260         rmr_rcv_specific( NULL, NULL, "foo", 0 );
261         rmr_mt_rcv( NULL, NULL, 0 );
262         mt_call( NULL, NULL, 0, 1, NULL );
263         rmr_mt_call( NULL, NULL, 0, 1 );
264         rmr_set_low_latency( NULL );
265         rmr_set_fack( NULL );
266
267
268         msg2 = rmr_alloc_msg( rmc,  1024 );
269         msg2 = rmr_rcv_msg( NULL, msg2 );
270         if( msg2 != NULL ) {
271                 errors += fail_if( msg2->state == RMR_OK, "nil context check for rcv msg returned OK" );
272         }
273         msg2 = rmr_torcv_msg( NULL, msg2, 200 );
274         if( msg2 != NULL ) {
275                 errors += fail_if( msg2->state == RMR_OK, "nil context check for torcv msg returned OK" );
276         }
277
278         //  ----- thread start coverage ---------------------------------------------------------------------------
279         setenv( "RMR_WARNINGS", "1", 1 );       // force non-default branches during these tests
280         setenv( "RMR_SRC_NAMEONLY", "1", 1 );
281
282         rmr_init( ":6789", 1024, 0 );           // threaded mode with defined/default RM target
283         setenv( "RMR_RTG_SVC", "-1", 1 );       // force into static table mode
284         rmr_init( ":6789", 1024, 0 );           // threaded mode with static table
285
286         // --------------- phew, done ------------------------------------------------------------------------------
287
288         if( ! errors ) {
289                 fprintf( stderr, "<INFO> all RMr API tests pass\n" );
290         }
291         return !!errors;
292 }