Correct inability to extend payload for rts msg
[ric-plt/lib/rmr.git] / test / sr_nng_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:       sr_nng_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 // ----------- local test support ----------------------------------------------------------
44 #define CLONE   1                       // convenience constants for payload realloc tests
45 #define NO_CLONE 0
46 #define COPY 1
47 #define NO_COPY 0
48
49 /*
50         Generate a simple route table (for all but direct route table testing).
51         This gets tricky inasmuch as we generate two in one; first a whole table 
52         and then two update tables. The first is a table with a bad counter in the
53         last record to test that we don't load that table and error. The second
54         is a good update.
55 */
56 static void gen_rt( uta_ctx_t* ctx ) {
57         int             fd;
58         char*   rt_stuff;               // strings for the route table
59
60         rt_stuff =
61                 "newrt|end\n"                                                           // end of table check before start of table found
62                 "# comment to drive full comment test\n"
63                 "\n"                                                                            // handle blank lines
64                 "   \n"                                                                         // handle blank lines
65             "mse|4|10|localhost:4561\n"                                 // entry before start message
66             "rte|4|localhost:4561\n"                                    // entry before start message
67                 "newrt|start\n"                                                         // false start to drive detection
68                 "xxx|badentry to drive default case"
69                 "newrt|start\n"
70             "rte|0|localhost:4560,localhost:4562\n"                                     // these are legitimate entries for our testing
71             "rte|1|localhost:4562;localhost:4561,localhost:4569\n"
72             "rte|2|localhost:4562| 10\n"                                                                // new subid at end
73             "mse|4|10|localhost:4561\n"                                                                 // new msg/subid specifier rec
74             "mse|4|localhost:4561\n"                                                                    // new mse entry with less than needed fields
75                 "   rte|   5   |localhost:4563    #garbage comment\n"           // tests white space cleanup
76             "rte|6|localhost:4562\n"
77                 "newrt|end\n";
78
79         fd = open( "utesting.rt", O_WRONLY | O_CREAT, 0600 );
80         if( fd < 0 ) {
81                 fprintf( stderr, "<BUGGERED> unable to open file for testing route table gen\n" );
82                 return;
83         }
84
85         setenv( "RMR_SEED_RT", "utesting.rt", 1 );
86         write( fd, rt_stuff, strlen( rt_stuff ) );              // write in the whole table
87
88         rt_stuff =
89                 "updatert|start\n"                                                                      // this is an update to the table
90             "mse|4|99|fooapp:9999,barapp:9999;logger:9999\n"    // update just one entry
91                 "updatert|end | 3\n";                                                           // bad count; this update should be rejected
92         write( fd, rt_stuff, strlen( rt_stuff ) );
93
94         rt_stuff =
95                 "updatert|start\n"                                                                      // this is an update to the table
96             "mse|4|10|fooapp:4561,barapp:4561;logger:9999\n"    // update just one entry
97                 "del|2|-1\n"                                                                            // delete an entry; not there so no action
98                 "del|2|10\n"                                                                            // delete an entry
99                 "updatert|end | 3\n";                                                           // end table; updates have a count as last field
100         write( fd, rt_stuff, strlen( rt_stuff ) );
101         
102         close( fd );
103         read_static_rt( ctx, 1 );                                                               // force in verbose mode to see stats on tty if failure
104         unlink( "utesting.rt" );
105 }
106
107
108 /*
109         Drive the send and receive functions.  We also drive as much of the route
110         table collector as is possible without a real rtg process running somewhere.
111
112         Send and receive functions are indirectly exercised from the rmr_nng_static_test
113         module as it tests the user facing send/receive/call/rts functions. These tests
114         should exercise specific cases for the internal functions as they will not
115         specifically be driven elsewhere.
116 */
117 static int sr_nng_test() {
118         uta_ctx_t* ctx;                         // context needed to test load static rt
119         uta_ctx_t*      real_ctx;       // real one to force odd situations for error testing
120         int errors = 0;                 // number errors found
121         rmr_mbuf_t*     mbuf;           // mbuf to send/receive
122         rmr_mbuf_t*     mb2;            // second mbuf when needed
123         int             whid = -1;
124         int             last_whid;
125         int     state;
126         nng_socket nn_dummy_sock;                                       // dummy needed to drive send
127         int             size;
128         int             i;
129         void*   p;
130         char*   payload_str;
131
132         //ctx = rmr_init( "tcp:4360", 2048, 0 );                                // do NOT call init -- that starts the rtc thread which isn't good here
133         ctx = (uta_ctx_t *) malloc( sizeof( uta_ctx_t ) );              // alloc the context manually
134         memset( ctx, 0, sizeof( uta_ctx_t ) );
135
136         ctx->mring = NULL;              //uta_mk_ring( 128 );
137         ctx->max_plen = RMR_MAX_RCV_BYTES + sizeof( uta_mhdr_t );
138         ctx->max_mlen = ctx->max_plen + sizeof( uta_mhdr_t );
139         ctx->my_name = strdup( "dummy-test" );
140         ctx->my_ip = strdup( "30.4.19.86:1111" );
141         uta_lookup_rtg( ctx );
142
143         gen_rt( ctx );                                                          // forces a static load with some known info since we don't start the rtc()
144         gen_rt( ctx );                                                          // force a second load to test cloning
145
146         p = rt_ensure_ep( NULL, "foo" );                                // drive for coverage
147         errors += fail_not_nil( p,  "rt_ensure_ep did not return nil when given nil route table" );
148
149         state = rmr_ready( NULL );
150         errors += fail_if_true( state, "reported ready when given a nil context" );
151         state = rmr_ready( ctx );
152         errors += fail_if_false( state, "reported not ready when it should be" );
153
154         mbuf = rcv_msg( ctx, NULL );
155         errors += fail_if_nil( mbuf, "no mbuf returned on receive test" );
156
157         mbuf->len = 10;
158         mbuf->mtype = 1;
159
160         mb2 = clone_msg( mbuf );
161         errors += fail_if_nil( mb2, "clone message returned nil pointer" );
162         errors += fail_not_equal( mbuf->flags, mb2->flags, "clone did not duplicate flags" );
163         errors += fail_not_equal( mbuf->alloc_len, mb2->alloc_len, "clone did not dup alloc-len" );
164         errors += fail_not_equal( mbuf->state, mb2->state, "clone did not dup state" );
165         rmr_free_msg( mb2 );
166
167         mbuf = rmr_send_msg( NULL, mbuf );
168         errors += fail_if_nil( mbuf, "send with nil context but buffere didn't return buffer" );
169         if( mbuf ) {
170                 errors += fail_not_equal( mbuf->state, RMR_ERR_BADARG, "send with buffer but nil context didn't return right state" );
171         } else {
172                 mbuf = rmr_rcv_msg( ctx, NULL );
173         }
174
175         size = 2048 - em_hdr_size();            // emulated nng receive allocates 2K buffers -- subtract off header size
176         state = rmr_payload_size( mbuf );
177         errors += fail_not_equal( state, size, "payload size didn't return expected value" );   // receive should always give 4k buffer
178
179         rmr_free_msg( mbuf );
180
181
182         state = xlate_nng_state( NNG_EAGAIN, 99 );
183         errors += fail_if( state == 99, "xlate_nng_state returned default for nng_eagain" );
184         errors += fail_if( errno != EAGAIN, "xlate_nng_state did not set errno to eagain for nng_eagain" );
185
186         state = xlate_nng_state( NNG_ETIMEDOUT, 99 );
187         errors += fail_if( state == 99, "xlate_nng_state returned default for nng_timeout" );
188         errors += fail_if( errno != EAGAIN, "xlate_nng_state did not set errno to eagain for nng_timeout" );
189
190         state = xlate_nng_state( NNG_ENOTSUP, 99 );
191         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_notsup" );
192
193         state = xlate_nng_state( NNG_ENOTSUP, 99 );
194         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_notsup" );
195         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (1)" );
196
197         state = xlate_nng_state( NNG_EINVAL, 99 );
198         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_inval" );
199         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (2)" );
200
201         state = xlate_nng_state( NNG_ENOMEM, 99 );
202         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_nomem" );
203         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (3)" );
204
205         state = xlate_nng_state( NNG_ESTATE, 99 );
206         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_state" );
207         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (4)" );
208
209         state = xlate_nng_state( NNG_ECLOSED, 99 );
210         errors += fail_if( state != 99, "xlate_nng_state did not return  default for nng_closed" );
211         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (5)" );
212
213         state = xlate_nng_state( 999, 99 );
214         errors += fail_if( state != 99, "xlate_nng_state did not return  default for unknown error" );
215         errors += fail_if( errno == 0, "xlate_nng_state did not set errno (6)" );
216
217         // ---- drive rtc in a 'static' (not pthreaded) mode to get some coverage; no 'results' to be verified -----
218         setenv( ENV_RTG_RAW, "1", 1 );                                                          // rtc should expect raw messages (mostly coverage here)
219         setenv( ENV_VERBOSE_FILE, ".ut_rmr_verbose", 1 );                       // allow for verbose code in rtc to be driven
220         i = open( ".ut_rmr_verbose", O_RDWR | O_CREAT, 0654 );
221         if( i >= 0 ) {
222                 write( i, "2\n", 2 );
223                 close( i );
224         }
225         ctx->shutdown = 1;                      // should force rtc to quit on first pass
226         rtc( NULL );                            // coverage test with nil pointer
227         rtc( ctx );
228
229         setenv( "RMR_RTG_SVC", "4567", 1 );             // drive for edge case coverage to ensure no nil pointer etc
230         rtc( ctx );
231         setenv( "RMR_RTG_SVC", "tcp:4567", 1 );
232         rtc( ctx );
233         setenv( "RMR_RTG_SVC", "tcp:4567:error", 1 );
234         rtc( ctx );
235
236         // ------------- reallocation tests ------------------------------------------------------------
237         // we use mk_populated_msg() to create a message with mid/sid/plen pushed into the transport
238         // header to simulate a message having been sent and received which is what causes this data
239         // to push into the wire packet.
240
241         payload_str = "Stand Up and Cheer; OU78-82";
242
243
244         mbuf = mk_populated_msg( 1024, 0, 99, 100, strlen( payload_str ) );
245         memcpy( mbuf->payload, payload_str, mbuf->len );
246         mb2 = realloc_payload( mbuf, 512, NO_COPY, NO_CLONE );
247         errors += fail_if_nil( mb2, "realloc_payload (no copy) returned a nil pointer when reallocating with smaller size" );
248         errors += fail_if_false( mbuf == mb2, "non-clone realloc payload (no copy) of smaller size did not return the same buffer" );
249
250         mb2 = realloc_payload( NULL, 512, NO_COPY, NO_CLONE );
251         errors += fail_not_nil( mb2, "realloc payload did not return nil pointer when passed nil mbuf" );
252
253         mb2 = realloc_payload( mbuf, 0, NO_COPY, NO_CLONE );
254         errors += fail_not_nil( mb2, "realloc payload did not return nil pointer when passed bad len" );
255
256         fprintf( stderr, "<TEST> no copy/no clone test starts\n" );
257         mb2 = realloc_payload( mbuf, 2048, NO_COPY, NO_CLONE );
258         errors += fail_if_false( mbuf == mb2, "realloc payload (no copy) of larger size did not return the same msg buffer(1)" );
259         errors += fail_not_equal( mb2->mtype, -1, "realloc payload (no copy) did not reset mtype(a) to expected(b) value" );
260         errors += fail_not_equal( mb2->sub_id, -1, "realloc payload (no copy) did not reset sub-id(a) to expected(b) value" );
261         errors += fail_if_nil( mb2, "realloc payload returned (no copy) a nil pointer when increasing payload len" );
262         errors += fail_not_equal( mb2->len, 0, "realloc payload payload len(a) not expected(b):" );
263         errors += fail_not_equal( rmr_payload_size( mb2), 2048, "realloc payload alloc len(a) not expected(b)" );
264
265         fprintf( stderr, "<TEST> copy/no clone test starts\n" );
266         mbuf = mk_populated_msg( 1024, 0, 99, 100, strlen( payload_str ) );
267         memcpy( mbuf->payload, payload_str, mbuf->len );
268         mb2 = realloc_payload( mbuf, 2048, COPY, NO_CLONE );
269         errors += fail_if_false( mbuf == mb2, "non-clone realloc payload (copy) of larger size did not return the same msg buffer(2)" );
270         errors += fail_if_nil( mb2, "realloc payload (copy) returned a nil pointer when increasing payload len)" );
271         errors += fail_not_equal( mb2->mtype, 99, "realloc payload (copy) did not reset mtype(a) to expected(b) value" );
272         errors += fail_not_equal( mb2->sub_id, 100, "realloc payload (copy) did not reset sub-id(a) to expected(b) value" );
273         errors += fail_if_equal( mb2->len, 0, "realloc payload (copy) msg len(a) not expected(b)" );
274         errors += fail_not_equal( rmr_payload_size( mb2), 2048, "realloc payload (copy) alloc len(a) not expected(b)" );
275         errors += fail_not_equal( strncmp( payload_str, mb2->payload, strlen( payload_str )), 0, "realloc payload(copy) didn't copy payload" );
276
277         fprintf( stderr, "<TEST> copy/clone test starts requested buffer smaller than original\n" );
278         mbuf = mk_populated_msg( 1024, 0, 99, 100, strlen( payload_str ) );
279         memcpy( mbuf->payload, payload_str, mbuf->len );
280         mb2 = realloc_payload( mbuf, 512, COPY, CLONE );
281         errors += fail_if_true( mbuf == mb2, "realloc payload (clone+copy) of larger size did not return different message buffers" );
282         errors += fail_if_nil( mb2, "realloc payload (clone+copy) returned a nil pointer when increasing payload len)" );
283         errors += fail_not_equal( mb2->mtype, 99, "realloc payload (clone+copy) did not reset mtype(a) to expected(b) value" );
284         errors += fail_not_equal( mb2->sub_id, 100, "realloc payload (clone+copy) did not reset sub-id(a) to expected(b) value" );
285         errors += fail_not_equal( mb2->len, strlen( payload_str ), "realloc payload (clone+copy) msg len(a) not expected(b)" );
286         errors += fail_not_equal( rmr_payload_size( mb2), 1024, "realloc payload (clone+copy) alloc len(a) not expected(b)" );
287         errors += fail_not_equal( strncmp( payload_str, mb2->payload, strlen( payload_str )), 0, "realloc payload(clone+copy) didn't copy payload" );
288
289         // with a clone, we must verify that original message looks sane too
290         errors += fail_not_equal( mbuf->mtype, 99, "realloc payload (clone+copy) validation of unchanged mbuf->mtype fails" );
291         errors += fail_not_equal( mbuf->sub_id, 100, "realloc payload (clone+copy) validation of unchanged mbuf->subid fails" );
292         errors += fail_not_equal( mbuf->len, strlen( payload_str ), "realloc payload (clone+copy) validation of unchanged payload len fails" );
293         errors += fail_not_equal( rmr_payload_size( mbuf ), 1024, "realloc payload (clone+copy) validation of unchanged alloc length fails" );
294         errors += fail_not_equal( strncmp( payload_str, mbuf->payload, strlen( payload_str )), 0, "realloc payload(clone+copy) validation of unchanged payload fails" );
295
296
297         fprintf( stderr, "<TEST> copy/clone test starts requested buf is larger than original\n" );
298         mbuf = mk_populated_msg( 1024, 0, 99, 100, strlen( payload_str ) );
299         memcpy( mbuf->payload, payload_str, mbuf->len );
300         mb2 = realloc_payload( mbuf, 2048, COPY, CLONE );
301         errors += fail_if_true( mbuf == mb2, "realloc payload(clone+copy/lg) of larger size did not return different message buffers" );
302         errors += fail_if_nil( mb2, "realloc payload (clone+copy/lg) returned a nil pointer when increasing payload len)" );
303         errors += fail_not_equal( mb2->mtype, 99, "realloc payload (clone+copy/lg) did not reset mtype(a) to expected(b) value" );
304         errors += fail_not_equal( mb2->sub_id, 100, "realloc payload (clone+copy/lg) did not reset sub-id(a) to expected(b) value" );
305         errors += fail_not_equal( mb2->len, strlen( payload_str ), "realloc payload (clone+copy/lg) msg len(a) not expected(b)" );
306         errors += fail_not_equal( rmr_payload_size( mb2), 2048, "realloc payload (clone+copy/lg) alloc len(a) not expected(b)" );
307         errors += fail_not_equal( strncmp( payload_str, mb2->payload, strlen( payload_str )), 0, "realloc payload(clone+copy/lg) didn't copy payload" );
308
309         // with a clone, we must verify that original message looks sane too
310         errors += fail_not_equal( mbuf->mtype, 99, "realloc payload (clone+copy/lg) validation of unchanged mbuf->mtype fails" );
311         errors += fail_not_equal( mbuf->sub_id, 100, "realloc payload (clone+copy/lg) validation of unchanged mbuf->subid fails" );
312         errors += fail_not_equal( mbuf->len, strlen( payload_str ), "realloc payload (clone+copy/lg) validation of unchanged payload len fails" );
313         errors += fail_not_equal( rmr_payload_size( mbuf ), 1024, "realloc payload (clone+copy/lg) validation of unchanged alloc length fails" );
314         errors += fail_not_equal( strncmp( payload_str, mbuf->payload, strlen( payload_str )), 0, "realloc payload(clone+copy/lg) validation of unchanged payload fails" );
315
316         // original message should be unharmed, and new message should have no type/sid or payload len; total alloc len should be requested enlargement
317         fprintf( stderr, "<TEST> no copy/clone test starts requested buf is larger than original\n" );
318         mbuf = mk_populated_msg( 1024, 0, 99, 100, strlen( payload_str ) );
319         memcpy( mbuf->payload, payload_str, mbuf->len );
320         mb2 = realloc_payload( mbuf, 2048, NO_COPY, CLONE );
321         errors += fail_if_true( mbuf == mb2, "realloc payload (clone+nocopy) of larger size did not return different message buffers" );
322         errors += fail_if_nil( mb2, "realloc payload (clone+nocopy) returned a nil pointer when increasing payload len)" );
323         errors += fail_not_equal( mb2->mtype, -1, "realloc payload (clone+nocopy) did not reset mtype(a) to expected(b) value" );
324         errors += fail_not_equal( mb2->sub_id, -1, "realloc payload (clone+nocopy) did not reset sub-id(a) to expected(b) value" );
325         errors += fail_not_equal( mb2->len, 0, "realloc payload (clone+nocopy) msg len(a) not expected(b)" );
326         errors += fail_not_equal( rmr_payload_size( mb2 ), 2048, "realloc payload (clone+nocopy) alloc len(a) not expected(b)" );
327         errors += fail_if_equal( strncmp( payload_str, mb2->payload, strlen( payload_str )), 0, "realloc payload(clone+nocopy) copied payload when not supposed to" );
328
329         // with a clone, we must verify that original message looks sane too
330         errors += fail_not_equal( mbuf->mtype, 99, "realloc payload (clone+nocopy) validation of unchanged mbuf->mtype fails" );
331         errors += fail_not_equal( mbuf->sub_id, 100, "realloc payload (clone+nocopy) validation of unchanged mbuf->subid fails" );
332         errors += fail_not_equal( mbuf->len, strlen( payload_str ), "realloc payload (clone+nocopy) validation of unchanged payload len fails" );
333         errors += fail_not_equal( rmr_payload_size( mbuf ), 1024, "realloc payload (clone+nocopy) validation of unchanged alloc length fails" );
334         errors += fail_not_equal( strncmp( payload_str, mbuf->payload, strlen( payload_str )), 0, "realloc payload (clone+nocopy) validation of unchanged payload fails" );
335
336
337         return !!errors;
338 }