More changes for scan corrections and unit test coverage
[ric-plt/lib/rmr.git] / test / test_support.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         Mnemonic:       test_tools.c
23         Abstract:       Functions for test applications to make their life a bit easier.
24                                 This file is probably compiled to a .o, and then included on
25                                 the cc command for the test.
26         Author:         E. Scott Daniels
27         Date:           6 January 2019
28 */
29
30 #ifndef _test_support_c
31 #define _test_support_c
32
33 #include <signal.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39
40 /*
41         This is ugly, but needed to allow for component testing.
42
43         The test code (e.g. foo_test.c and not foo_static_test.c) can include these
44         constants to turn off the import of test support files:
45                 NO_EMULATION            -- the transport emulation will not be included
46                 NO_PRIVATE_HEADERS      -- the private headers for the transport component of RMR
47                                                                 (e.g. si) will not be included.
48 */
49 #ifndef NO_EMULATION                            // assume emulation unless specifically put off (love double negatives)
50         #ifdef NNG_UNDER_TEST
51                 #define TP_HDR_LEN 0                            // needed for support functions but nonexistant in nng world
52                 #include "test_nng_em.c"                        // nano/ngg emulation functions
53         #else
54                 #include "test_si95_em.c"                       // si emulation functions
55         #endif
56 #endif
57
58 #ifndef NO_PRIVATE_HEADERS                                      // include transport headers unless specifically turned off
59         #ifdef NNG_UNDER_TEST
60                 #include <rmr_nng_private.h>            // context things are type sensitive
61         #else
62                 #include "si95/socket_if.h"                     // need to have the si context more than anything else
63                 #include <rmr_si_private.h>
64         #endif
65 #endif
66
67 #ifndef BAD
68 #define BAD 1                   // these are exit codes unless user overrides
69 #define GOOD 0
70 #endif
71
72 // -----------  a couple of globals make it easier ---------------------------------------
73 static int      ts_tests_driven = 0;                    // number of fail_if calls made == numer of tests driven
74
75 // ---------------------------------------------------------------------------------------
76
77 /*
78         Support test counting, reset and summary.
79 */
80 static int test_get_attempted() {
81         return ts_tests_driven;
82 }
83
84 static void test_reset_attempted() {
85         ts_tests_driven = 0;
86 }
87
88 static void test_summary( int ecount, char* tag ) {
89         fprintf( stderr, "<SUMMARY> %s completed;  %d total tests, %d passed, %d failed\n",
90                 tag, ts_tests_driven, ts_tests_driven - ecount, ecount );
91 }
92
93 /*
94         Snag the optional positional parameter at pp, return defval if not there.
95 */
96 static char* snag_pp( int pp, int argc, char** argv, char* defval ) {
97
98         if( pp < argc ) {
99                 return argv[pp];
100         }
101
102         return defval;
103 }
104
105 /*
106         Signal handler -- inside of the tests we will exit cleanly for hup/temp/intr
107         signals so that the coverage stuff will generate the needed data files. If
108         we inter/term the process they don't drive.
109 */
110
111 void sig_clean_exit( int sign ) {
112         fprintf( stderr, "signal trapped for clean exit: %d\n", sign );
113         exit( 0 );
114 }
115
116 /*
117         Setup all of the signal handling for signals that we want to force a clean exit:
118         term, intr, hup, quit, usr1/2 alarm, etc.  All others we'll let default.
119 */
120 static void set_signals( void ) {
121         struct sigaction sa;
122         int     sig_list[] = { SIGINT, SIGQUIT, SIGILL, SIGALRM, SIGTERM, SIGUSR1 , SIGUSR2 };
123         int i;
124         int nele;               // number of elements in the list
125
126         nele = (int) ( sizeof( sig_list )/sizeof( int ) );              // convert raw size to the number of elements
127         for( i = 0; i < nele; i ++ ) {
128                 memset( &sa, 0, sizeof( sa ) );
129                 sa.sa_handler = sig_clean_exit;
130                 sigaction( sig_list[i], &sa, NULL );
131         }
132 }
133
134
135 /*
136         Assert like logic except these just record the test and return state so that we
137         can attempt all tests and not abort on the first failure as an assert would do.
138 */
139 static int fail_if_nil( void* p, char* what ) {
140         ts_tests_driven++;
141
142         if( !p ) {
143                 fprintf( stderr, "<FAIL> %s: pointer was nil\n", what );
144         }
145         return p ? GOOD : BAD;
146 }
147
148 static int fail_not_nil( void* p, char* what ) {
149         ts_tests_driven++;
150
151         if( p ) {
152                 fprintf( stderr, "<FAIL> %s: pointer was not nil\n", what );
153         }
154         return !p ? GOOD : BAD;
155 }
156
157 static int fail_if_false( int bv, char* what ) {
158         ts_tests_driven++;
159
160         if( !bv ) {
161                 fprintf( stderr, "<FAIL> %s: expected true, boolean test was false (%d)\n", what, bv );
162         }
163
164         return bv ? GOOD : BAD;
165 }
166
167 static int fail_if_true( int bv, char* what ) {
168         ts_tests_driven++;
169
170         if( bv ) {
171                 fprintf( stderr, "<FAIL> %s: expected false, boolean test was true (%d)\n", what, bv );
172         }
173         return bv ? BAD : GOOD;
174 }
175
176 /*
177         Same as fail_if_true(), but reads easier in the test code.
178 */
179 static int fail_if( int bv, char* what ) {
180         ts_tests_driven++;
181
182
183         if( bv ) {
184                 fprintf( stderr, "<FAIL> %s: expected false, boolean test was true (%d)\n", what, bv );
185         }
186         return bv ? BAD : GOOD;
187 }
188
189 static int fail_pequal( void* a, void* b, char* what ) {
190         ts_tests_driven++;
191
192         if( a == b ) {
193                 fprintf( stderr, "<FAIL> %s: pointers were not equal a=%p b=%p\n", what, a, b );
194         }
195         return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
196 }
197
198 static int fail_not_pequal( void* a, void* b, char* what ) {
199         ts_tests_driven++;
200
201         if( a != b ) {
202                 fprintf( stderr, "<FAIL> %s: pointers were not equal a=%p b=%p\n", what, a, b );
203         }
204         return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
205 }
206
207 static int fail_not_equal( int a, int b, char* what ) {
208         ts_tests_driven++;
209
210         if( a != b ) {
211                 fprintf( stderr, "<FAIL> %s: values were not equal a=%d b=%d\n", what, a, b );
212         }
213         return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
214 }
215
216 static int fail_if_equal( int a, int b, char* what ) {
217         ts_tests_driven++;
218
219                 fprintf( stderr, "<TESTING> %s %d\n", what, a==b );
220         if( a == b ) {
221                 fprintf( stderr, "<FAIL> %s values were equal a=%d b=%d\n", what, a, b );
222         }
223         return a != b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
224 }
225
226 static int fail_not_equalp( void* a, void* b, char* what ) {
227         ts_tests_driven++;
228
229         if( a != b ) {
230                 fprintf( stderr, "<FAIL> %s: pointers were not equal a=%p b=%p\n", what, a, b );
231         }
232         return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
233 }
234
235 static int fail_if_equalp( void* a, void* b, char* what ) {
236         ts_tests_driven++;
237
238         if( a == b ) {
239                 fprintf( stderr, "<FAIL> %s pointers were equal a=%p b=%p\n", what, a, b );
240         }
241         return a != b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
242 }
243
244
245 // for symtab and other non-message things this allows them to exclude by setting
246 #ifndef NO_DUMMY_RMR
247 /*
248         Dummy message allocator for testing without sr_static functions
249 */
250 #ifndef MSG_VER
251 #define MSG_VER 3
252 #endif
253
254 static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
255         rmr_mbuf_t*     new_msg;
256         uta_mhdr_t* hdr;
257         size_t  alen;
258
259         alen = sizeof( *hdr ) + tr_len + len + TP_HDR_LEN;      // this does no support allocating len2 and len3 data fields
260
261         new_msg = (rmr_mbuf_t *) malloc( sizeof *new_msg );
262         memset( new_msg, 0, sizeof( *new_msg ) );
263         new_msg->tp_buf = (void *) malloc( alen );
264         memset( new_msg->tp_buf, 0, alen );
265
266         hdr = (uta_mhdr_t*) new_msg->tp_buf;
267         SET_HDR_LEN( hdr );
268         SET_HDR_TR_LEN( hdr, tr_len );
269         hdr->rmr_ver = htonl( MSG_VER );
270         strcpy( hdr->src, "dummyhost:1111" );
271         strcpy( hdr->srcip, "30.4.19.86:1111" );
272
273         new_msg->header = new_msg->tp_buf;
274         new_msg->payload =  new_msg->header + PAYLOAD_OFFSET( hdr );
275         new_msg->alloc_len = alen;
276         new_msg->len = 0;
277
278         return new_msg;
279 }
280
281 static void test_set_ver( rmr_mbuf_t* msg, int ver ) {
282         uta_mhdr_t* hdr;
283
284         hdr = (uta_mhdr_t*) msg->tp_buf;
285         hdr->rmr_ver = htonl( ver );
286         strcpy( hdr->src, "dummyhost-v2:1111" );
287         strcpy( hdr->srcip, "30.4.19.86:2222" );
288
289         return;
290 }
291
292 /*
293         These allow values to be pushed deep into the real RMR header allocated
294         at the front of the transport buffer. These are needed to simulate
295         the actions of rmr_send() which pushes the values from the message buffer
296         just before putting them on the wire.
297 */
298 static void test_set_mtype( rmr_mbuf_t* msg, int mtype ) {
299         uta_mhdr_t* hdr;
300
301         msg->mtype = mtype;
302         hdr = (uta_mhdr_t*) msg->tp_buf;
303         hdr->mtype = htonl( mtype );
304 }
305
306 static void test_set_sid( rmr_mbuf_t* msg, int sid ) {
307         uta_mhdr_t* hdr;
308
309         msg->sub_id = sid;
310         hdr = (uta_mhdr_t*) msg->tp_buf;
311         hdr->sub_id = htonl( sid );
312 }
313
314 static void test_set_plen( rmr_mbuf_t* msg, int plen ) {
315         uta_mhdr_t* hdr;
316
317         msg->len = plen;
318         hdr = (uta_mhdr_t*) msg->tp_buf;
319         hdr->plen = htonl( plen );
320 }
321
322 /*
323         Build a message and populate both the msg buffer and the tranport header
324         with mid, sid, and payload len. Tr_len causes that much space in the
325         header for trace info to be reserved.
326 */
327 static rmr_mbuf_t* mk_populated_msg( int alloc_len, int tr_len, int mtype, int sid, int plen ) {
328         uta_mhdr_t* hdr;
329         rmr_mbuf_t* mbuf;
330
331         mbuf = test_mk_msg( alloc_len, tr_len );
332         test_set_mtype( mbuf, mtype );
333         test_set_sid( mbuf, sid );
334         test_set_plen( mbuf, plen );
335
336         return mbuf;
337 }
338
339
340 // end no dummy rmr
341 #endif
342
343 #endif