3e123434a069d7611e5198b8f33aefdd435e04f6
[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_not_equal( int a, int b, char* what ) {
190         ts_tests_driven++;
191
192         if( a != b ) {
193                 fprintf( stderr, "<FAIL> %s: values were not equal a=%d b=%d\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_if_equal( int a, int b, char* what ) {
199         ts_tests_driven++;
200
201                 fprintf( stderr, "<TESTING> %s %d\n", what, a==b );
202         if( a == b ) {
203                 fprintf( stderr, "<FAIL> %s values were equal a=%d b=%d\n", what, a, b );
204         }
205         return a != b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
206 }
207
208 static int fail_not_equalp( void* a, void* b, char* what ) {
209         ts_tests_driven++;
210
211         if( a != b ) {
212                 fprintf( stderr, "<FAIL> %s: pointers were not equal a=%p b=%p\n", what, a, b );
213         }
214         return a == b ? GOOD : BAD;                     // user may override good/bad so do NOT return a==b directly!
215 }
216
217 static int fail_if_equalp( void* a, void* b, char* what ) {
218         ts_tests_driven++;
219
220         if( a == b ) {
221                 fprintf( stderr, "<FAIL> %s pointers were equal a=%p b=%p\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
227 // for symtab and other non-message things this allows them to exclude by setting
228 #ifndef NO_DUMMY_RMR
229 /*
230         Dummy message allocator for testing without sr_static functions
231 */
232 #ifndef MSG_VER
233 #define MSG_VER 3
234 #endif
235
236 static rmr_mbuf_t* test_mk_msg( int len, int tr_len ) {
237         rmr_mbuf_t*     new_msg;
238         uta_mhdr_t* hdr;
239         size_t  alen;
240
241         alen = sizeof( *hdr ) + tr_len + len + TP_HDR_LEN;      // this does no support allocating len2 and len3 data fields
242
243         new_msg = (rmr_mbuf_t *) malloc( sizeof *new_msg );
244         memset( new_msg, 0, sizeof( *new_msg ) );
245         new_msg->tp_buf = (void *) malloc( alen );
246         memset( new_msg->tp_buf, 0, alen );
247
248         hdr = (uta_mhdr_t*) new_msg->tp_buf;
249         SET_HDR_LEN( hdr );
250         SET_HDR_TR_LEN( hdr, tr_len );
251         hdr->rmr_ver = htonl( MSG_VER );
252         strcpy( hdr->src, "dummyhost:1111" );
253         strcpy( hdr->srcip, "30.4.19.86:1111" );
254
255         new_msg->header = new_msg->tp_buf;
256         new_msg->payload =  new_msg->header + PAYLOAD_OFFSET( hdr );
257         new_msg->alloc_len = alen;
258         new_msg->len = 0;
259
260         return new_msg;
261 }
262
263 static void test_set_ver( rmr_mbuf_t* msg, int ver ) {
264         uta_mhdr_t* hdr;
265
266         hdr = (uta_mhdr_t*) msg->tp_buf;
267         hdr->rmr_ver = htonl( ver );
268         strcpy( hdr->src, "dummyhost-v2:1111" );
269         strcpy( hdr->srcip, "30.4.19.86:2222" );
270
271         return;
272 }
273
274 /*
275         These allow values to be pushed deep into the real RMR header allocated
276         at the front of the transport buffer. These are needed to simulate
277         the actions of rmr_send() which pushes the values from the message buffer
278         just before putting them on the wire.
279 */
280 static void test_set_mtype( rmr_mbuf_t* msg, int mtype ) {
281         uta_mhdr_t* hdr;
282
283         msg->mtype = mtype;
284         hdr = (uta_mhdr_t*) msg->tp_buf;
285         hdr->mtype = htonl( mtype );
286 }
287
288 static void test_set_sid( rmr_mbuf_t* msg, int sid ) {
289         uta_mhdr_t* hdr;
290
291         msg->sub_id = sid;
292         hdr = (uta_mhdr_t*) msg->tp_buf;
293         hdr->sub_id = htonl( sid );
294 }
295
296 static void test_set_plen( rmr_mbuf_t* msg, int plen ) {
297         uta_mhdr_t* hdr;
298
299         msg->len = plen;
300         hdr = (uta_mhdr_t*) msg->tp_buf;
301         hdr->plen = htonl( plen );
302 }
303
304 /*
305         Build a message and populate both the msg buffer and the tranport header
306         with mid, sid, and payload len. Tr_len causes that much space in the
307         header for trace info to be reserved.
308 */
309 static rmr_mbuf_t* mk_populated_msg( int alloc_len, int tr_len, int mtype, int sid, int plen ) {
310         uta_mhdr_t* hdr;
311         rmr_mbuf_t* mbuf;
312
313         mbuf = test_mk_msg( alloc_len, tr_len );
314         test_set_mtype( mbuf, mtype );
315         test_set_sid( mbuf, sid );
316         test_set_plen( mbuf, plen );
317
318         return mbuf;
319 }
320
321
322 // end no dummy rmr
323 #endif
324
325 #endif