CI: Add silent cmake SonarCloud scan
[ric-plt/lib/rmr.git] / test / sr_nano_static_test.c
1 // : vi ts=4 sw=4 noet :
2 /*
3 ==================================================================================
4             Copyright (c) 2019-2021 Nokia
5             Copyright (c) 2018-2021 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:       sr_nano_static_test.c
23         Abstract:       Test the send/receive funcitons. These are meant to be included at compile
24                                 time by the test driver.
25
26         Author:         E. Scott Daniels
27         Date:           3 April 2019
28 */
29
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <pthread.h>
38 #include <semaphore.h>
39
40 #include "rmr.h"
41 #include "rmr_agnostic.h"
42
43 /*
44         Generate a simple route table (for all but direct route table testing).
45         This table contains multiple tables inasmuch as a second update set of
46         records follows the initial set.
47 */
48 static void gen_rt( uta_ctx_t* ctx ) {
49         int             fd;
50         char*   rt_stuff;               // strings for the route table
51
52         rt_stuff =
53                 "\r"                                                                            // ensure we are not screwed by broken OSes that insist on using \r
54                 "newrt|end\n"                                                           // end of table check before start of table found
55                 "# comment to drive full comment test\n"
56                 "\n"                                                                            // handle blank lines
57                 "   \n"                                                                         // handle blank lines
58             "mse|4|10|localhost:4561\n"                                 // entry before start message
59             "rte|4|localhost:4561\n"                                    // entry before start message
60                 "newrt|start\n"                                                         // false start to drive detection
61                 "xxx|badentry to drive default case"
62                 "newrt|start\n"
63             "rte|0|localhost:4560,localhost:4562,dummy-test:1111\n"                                     // these are legitimate entries for our testing
64             "rte|1|localhost:4562;localhost:4561,localhost:4569,10.7.9.86:4560\n"
65             "rte|2|localhost:4562| 10\n"                                                                // new subid at end
66             "mse|4|10|localhost:4561\n"                                                                 // new msg/subid specifier rec
67             "mse|4|localhost:4561\n"                                                                    // new mse entry with less than needed fields
68                 "   rte|   5   |localhost:4563    #garbage comment\n"           // tests white space cleanup
69             "rte|6|localhost:4562\n"
70                 "newrt|end\n";
71
72         fd = open( "utesting.rt", O_WRONLY | O_CREAT, 0600 );
73         if( fd < 0 ) {
74                 fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );
75                 return;
76         }
77
78         setenv( "RMR_SEED_RT", "utesting.rt", 1 );
79         write( fd, rt_stuff, strlen( rt_stuff ) );
80         close( fd );
81         read_static_rt( ctx, 0 );
82         unlink( "utesting.rt" );
83 }
84
85 /*
86         Generates a legitimate table but with a missing newline on the last record.
87 */
88 static void gen_mlnl_rt( uta_ctx_t* ctx ) {
89         int             fd;
90         char*   rt_stuff;               // strings for the route table
91
92         rt_stuff =
93                 "newrt|start\n"
94             "rte|0|localhost:4560,localhost:4562\n"                                     // these are legitimate entries for our testing
95             "rte|1|localhost:4562;localhost:4561,localhost:4569\n"
96             "rte|2|localhost:4562| 10\n"                                                                // new subid at end
97             "mse|4|10|localhost:4561\n"                                                                 // new msg/subid specifier rec
98             "mse|4|localhost:4561\n"                                                                    // new mse entry with less than needed fields
99                 "   rte|   5   |localhost:4563    #garbage comment\n"           // tests white space cleanup
100             "rte|6|localhost:4562\n"
101                 "newrt|end";                                                                                            // should not affect the loader
102
103         fd = open( "utesting.rt", O_WRONLY | O_CREAT, 0600 );
104         if( fd < 0 ) {
105                 fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );
106                 return;
107         }
108
109         setenv( "RMR_SEED_RT", "utesting.rt", 1 );
110         write( fd, rt_stuff, strlen( rt_stuff ) );
111         close( fd );
112         read_static_rt( ctx, 0 );
113         unlink( "utesting.rt" );
114 }
115
116 /*
117         Generate an empty route table to test edge case.
118 */
119 static void gen_empty_rt( uta_ctx_t* ctx ) {
120         int             fd;
121
122         fd = open( "utesting.rt", O_WRONLY | O_CREAT | O_TRUNC, 0600 );
123         if( fd < 0 ) {
124                 fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );
125                 return;
126         }
127
128         setenv( "RMR_SEED_RT", "utesting.rt", 1 );
129         //write( fd, "", 0 );
130         close( fd );
131         read_static_rt( ctx, 0 );
132         unlink( "utesting.rt" );
133 }
134
135 /*
136         Generate an single byte route table to drive an edge handling case.
137 */
138 static void gen_sb_rt( uta_ctx_t* ctx ) {
139         int             fd;
140
141         fd = open( "utesting.rt", O_WRONLY | O_CREAT | O_TRUNC, 0600 );
142         if( fd < 0 ) {
143                 fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );
144                 return;
145         }
146
147         setenv( "RMR_SEED_RT", "utesting.rt", 1 );
148         write( fd, " ", 1 );
149         close( fd );
150         read_static_rt( ctx, 0 );
151         unlink( "utesting.rt" );
152 }
153
154
155 /*
156         Drive the send and receive functions.  We also drive as much of the route
157         table collector as is possible without a real rtg process running somewhere.
158
159         Send and receive functions are indirectly exercised from the rmr_nano_static_test
160         module as it tests the user facing send/receive/call/rts functions. These tests
161         should exercise specific cases for the internal functions as they will not
162         specifically be driven elsewhere.
163 */
164 static int sr_nano_test() {
165         int errors = 0;                 // number errors found
166
167         uta_ctx_t* ctx;                         // context needed to test load static rt
168         uta_ctx_t*      real_ctx;       // real one to force odd situations for error testing
169         rmr_mbuf_t*     mbuf;           // mbuf to send/receive
170         rmr_mbuf_t*     mb2;            // error capturing msg buf
171         int             whid = -1;
172         int             last_whid;
173         int     state;
174         int nn_dummy_sock;                                      // dummy needed to drive send
175         int             size;
176         int             i;
177         void*   p;
178
179         //ctx = rmr_init( "tcp:4360", 2048, 0 );                                // do NOT call init -- that starts the rtc thread which isn't good here
180         ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) );              // alloc the context manually
181         memset( ctx, 0, sizeof( uta_ctx_t ) );
182
183         ctx->mring = NULL;              //uta_mk_ring( 128 );
184         ctx->max_plen = RMR_MAX_RCV_BYTES + sizeof( uta_mhdr_t );
185         ctx->max_mlen = ctx->max_plen + sizeof( uta_mhdr_t );
186         ctx->my_name = strdup( "dummy-test:1111" );
187         ctx->my_ip = strdup( "30.4.19.86:1111" );
188         uta_lookup_rtg( ctx );
189
190         ctx->rtable = NULL;
191         gen_sb_rt( ctx );                                                       // generate and read a file with a sinle byte to test edge case
192         errors += fail_not_nil( ctx->rtable, "read single byte route table produced a table" );
193
194         ctx->rtable = NULL;
195         gen_empty_rt( ctx );                                            // generate and read an empty rt file to test edge case
196         errors += fail_not_nil( ctx->rtable, "read empty route table file produced a table" );
197
198         ctx->rtable = NULL;
199         gen_mlnl_rt( ctx );                                             // ensure that a file with missing last new line does not trip us up
200         errors += fail_if_nil( ctx->rtable, "read  route table file with missing last newline did not produce a table" );
201
202         ctx->rtable = NULL;
203         gen_rt( ctx );                                                          // forces a static load with some known info since we don't start the rtc()
204         errors += fail_if_nil( ctx->rtable, "read  multi test route table file did not produce a table" );
205         gen_rt( ctx );                                                          // force a second load to test cloning
206         errors += fail_if_nil( ctx->rtable, "read  multi test route table file to test clone did not produce a table" );
207
208         p = rt_ensure_ep( NULL, "foo" );                                // drive for coverage
209         errors += fail_not_nil( p,  "rt_ensure_ep did not return nil when given nil route table" );
210
211         state = rmr_ready( NULL );
212         errors += fail_if_true( state, "reported ready when given a nil context" );
213         state = rmr_ready( ctx );
214         errors += fail_if_false( state, "reported not ready when it should be" );
215
216         mbuf = rcv_msg( ctx, NULL );
217         errors += fail_if_nil( mbuf, "no mbuf returned on receive test" );
218
219         mbuf->len = 10;
220         mbuf->mtype = 1;
221
222         mb2 = clone_msg( mbuf );
223         errors += fail_if_nil( mb2, "clone message returned nil pointer" );
224         //errors += fail_not_equal( mbuf->flags, mb2->flags, "clone did not duplicate flags" );
225         errors += fail_not_equal( mbuf->alloc_len, mb2->alloc_len, "clone did not dup alloc-len" );
226         errors += fail_not_equal( mbuf->state, mb2->state, "clone did not dup state" );
227         rmr_free_msg( mb2 );
228
229         mbuf = rmr_send_msg( NULL, mbuf );
230         errors += fail_if_nil( mbuf, "send with nil context but buffere didn't return buffer" );
231         if( mbuf ) {
232                 errors += fail_not_equal( mbuf->state, RMR_ERR_BADARG, "send with buffer but nil context didn't return right state" );
233         } else {
234                 mbuf = rmr_rcv_msg( ctx, NULL );
235         }
236
237         size = 4096;
238         state = rmr_payload_size( mbuf );
239         errors += fail_not_equal( state, size, "payload size (b) didn't return expected value (a)" );   // receive should always give 4k buffer
240
241         rmr_free_msg( mbuf );
242
243
244         // ---- direct message read into payload (no rmr header) -------------------------
245         mbuf = rcv_payload( ctx, NULL );
246         errors += fail_if_nil( mbuf, "rcv_payload did not return a message buffer when given a nil messge" );
247         if( mbuf ) {
248                 errors += fail_if_true( mbuf->len <= 0, "rcv_payload did not return a buffer with payload length set when given a nil messge" );
249                 errors += fail_not_equal( mbuf->state, 0, "rcv_payload did not return a buffer with good state when given a nil messge" );
250         }
251
252         mbuf = rcv_payload( ctx, NULL );
253         errors += fail_if_nil( mbuf, "rcv_payload did not return a message buffer" );
254         if( mbuf ) {
255                 errors += fail_if_true( mbuf->len <= 0, "rcv_payload did not return a buffer with payload length set" );
256                 errors += fail_not_equal( mbuf->state, 0, "rcv_payload did not return a buffer with good state" );
257         }
258
259         // ---- drive rtc in a 'static' (not pthreaded) mode to get some coverage; no 'results' to be verified -----
260         setenv( ENV_RTG_RAW, "1", 1 );                                                          // rtc should expect raw messages (mostly coverage here)
261         setenv( ENV_VERBOSE_FILE, ".ut_rmr_verbose", 1 );                       // allow for verbose code in rtc to be driven
262         i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0654 );
263         if( i >= 0 ) {
264                 write( i, "2\n", 2 );
265                 close( i );
266         }
267         ctx->shutdown = 1;                      // should force rtc to quit on first pass
268         rtc( NULL );                            // coverage test with nil pointer
269         rtc( ctx );
270
271         unlink( ".ut_rmr_verbose" );
272
273         return errors;
274 }