Correct bug identified in static analysis
[ric-plt/lib/rmr.git] / test / tools_static_test.c
1         if_addrs_t*     ifl;                    // interface lis2
2 // : vi ts=4 sw=4 noet :
3 /*
4 ==================================================================================
5             Copyright (c) 2019-2021 Nokia
6             Copyright (c) 2018-2021 AT&T Intellectual Property.
7
8    Licensed under the Apache License, Version 2.0 (the "License");
9    you may not use this file except in compliance with the License.
10    You may obtain a copy of the License at
11
12            http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19 ==================================================================================
20 */
21
22
23 /*
24         Mnemonic:       tools_static_test.c
25         Abstract:       Unit tests for the RMr tools module. This file is a static include
26                                 that is pulle in at compile time by the test driver.  The driver is
27                                 expected to include necessary rmr*.h and test_support files before
28                                 including this file.  In addition, a context struct, or dummy, must
29                                 be provided based on the type of testing being done.
30
31         Author:         E. Scott Daniels
32         Date:           3 April 2019
33 */
34
35 #define MAX_TOKENS 127
36
37 // -------------------- testing support internal functions ------------------------------
38 /*
39         Returns an interface name that is valid in this environment (keeps us from
40         having to know/guess a name to test with.
41 */
42 static char* get_ifname( ) {
43         struct  ifaddrs *ifs;           // pointer to head
44         struct  ifaddrs *ele;           // pointer into the list
45         char*   rstr = NULL;            // return string
46         char    octs[NI_MAXHOST+1];
47
48         getifaddrs( &ifs );
49         for( ele = ifs; ele; ele = ele->ifa_next ) {
50                 if( ele && strcmp( ele->ifa_name, "lo" ) ) {
51                         memset( octs, 0, sizeof( octs ) );
52                         getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in6 ),  octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
53                         if( *octs ) {
54                                 rstr = strdup( ele->ifa_name );
55                                 fprintf( stderr, "<INFO> found interface with address: %s\n", rstr );
56                                 break;
57                         }
58                 }
59         }
60
61         if( rstr == NULL ) {
62                 fprintf( stderr, "<ERROR> no interface with an address was found!\n" );
63         }
64         return rstr;
65 }
66
67 /*
68         Build an if-addr list from what we "see" on the current system. Keeps us from
69         having to guess about what we _might_ find in some random test setup.
70         If the inc_lo0 boolean is true, then the loop back address(es) will be
71         included.
72 */
73 static if_addrs_t* get_iflist( int inc_lo0 ) {
74         if_addrs_t* l;
75         struct  ifaddrs *ifs;           // pointer to head
76         struct  ifaddrs *ele;           // pointer into the list
77         char    octs[NI_MAXHOST+1];
78         int             max_addrs = 128;
79
80
81         if( (l = (if_addrs_t *) malloc( sizeof( if_addrs_t ) )) == NULL ) {
82                 fprintf( stderr, "<FAIL> malloc of if_addrs failed\n" );
83                 return NULL;
84         }
85         memset( l, 0, sizeof( if_addrs_t ) );
86         l->addrs = (char **) malloc( sizeof( char* ) * max_addrs );
87         if( l->addrs == NULL ) {
88                 fprintf( stderr, "<FAIL> malloc of if_addrs array failed\n" );
89                 free( l );
90                 return NULL;
91         }
92
93         getifaddrs( &ifs );
94         for( ele = ifs; ele; ele = ele->ifa_next ) {
95                 if( ele && (inc_lo0 || strcmp( ele->ifa_name, "lo" )) ) {
96                         memset( octs, 0, sizeof( octs ) );
97                         getnameinfo( ele->ifa_addr, sizeof( struct sockaddr_in6 ),  octs, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
98                         if( *octs  && l->naddrs < max_addrs ) {
99                                 l->addrs[l->naddrs] = strdup( ele->ifa_name );
100                                 l->naddrs++;
101                         }
102                 }
103         }
104
105         return l;
106 }
107
108
109
110 // ------------ internal functions to drive various categories of tests --------------------------------------
111
112 static int ztbf_test() {
113         int errors = 0;
114         char buf[128];
115         char*   sshort = "Stand up and cheer! Cheer long and loud for old Ohio.";
116         char*   slong = "Now is the time for the bobcat in the forest to make its way back to Court St for a round of pints at the Pub.";
117         int l1;
118
119         l1 = zt_buf_fill( NULL, sshort, 64 );           // drive for coverage
120         errors += fail_not_equal( l1, -1, "nil check (buf) on zt_buf_fill did not return expected value" );
121         l1 = zt_buf_fill( buf, NULL, 64 );
122         errors += fail_not_equal( l1, -1, "nil check (str) on zt_buf_fill did not return expected value" );
123
124         l1 = zt_buf_fill( buf, sshort, 64 );
125         errors += fail_not_equal( l1, strlen( sshort ), "zt_buf_fill of short buf returned unexpected len" );
126         errors += fail_not_equal( l1, strlen( buf ), "zt_buf_fill of short buf returned len did not match strlen" );
127
128         l1 = zt_buf_fill( buf, slong, 64 );
129         errors += fail_if_equal( l1, strlen( slong ), "zt_buf_fill of long buf returned unexpected len" );
130         errors += fail_not_equal( l1, strlen( buf ), "zt_buf_fill of long buf returned len did not match strlen" );
131
132         l1 = zt_buf_fill( buf, sshort, strlen( sshort ) );              // edge case of exact size
133         errors += fail_not_equal( l1, strlen( sshort )-1, "zt_buf_fill exact length edge case failed" );
134
135         l1 = zt_buf_fill( buf, sshort, 1 );                                             // unrealistic edge case
136         errors += fail_not_equal( l1, 0, "zt_buf_fill dest len == 1 test failed" );
137
138         return errors;
139 }
140
141 /*
142         various tokenising tests.
143 */
144 static int tok_tests( ) {
145         int i;
146         int j;
147         char*   dbuf;                           // duplicated buf since C marks a const string is unumtable
148         char* buf = "2,Fred,Wilma,Barney,Betty,Dino,Pebbles,Bambam,Mr. Slate,Gazoo";
149         char* tokens[MAX_TOKENS];
150         int errors = 0;
151         if_addrs_t*     ifl;                    // interface list
152         int             ntokens;
153
154         i = uta_tokenise( NULL, tokens, MAX_TOKENS, ',' );                      // nil check coverage
155         errors += fail_not_equal( i, 0, "uta_tokenise did not fail when given nil pointer" );
156
157         dbuf = strdup( buf );
158         i = uta_tokenise( dbuf, tokens, MAX_TOKENS, ',' );
159         errors += fail_not_equal( i, 10, "unexpected number of tokens returned (comma sep)" );
160         for( j = 0; j < i; j++ ) {
161                 //fprintf( stderr, ">>>> [%d] (%s)\n", j, tokens[j] );
162                 errors += fail_if_nil( tokens[j], "token from buffer" );
163         }
164         errors += fail_not_equal( strcmp( tokens[4], "Betty" ), 0, "4th token wasn't 'Betty'" );
165
166         free( dbuf );
167         dbuf = strdup( buf );
168         i = uta_tokenise( dbuf, tokens, MAX_TOKENS, '|' );
169         errors += fail_not_equal( i, 1, "unexpected number of tokens returned (bar sep)" );
170         free( dbuf );
171
172         if( (ifl = get_iflist( 1 )) == NULL ) {
173                 errors++;
174                 fprintf( stderr, "<FAIL> unable to generate an interface list for tokenising tests\n" );
175                 return errors;
176         }
177
178         dbuf = strdup( "lo0,en0,en1,wlan0,wlan1"  );            // must have a mutable string for call
179         ntokens = uta_rmip_tokenise( dbuf, ifl, tokens, MAX_TOKENS, ',' );              // should find at least lo0
180         errors += fail_if_true( ntokens < 1, "rmip tokenise didn't find an interface in the list" );
181
182         return errors;
183 }
184
185 /*
186         Tests related to finding and validating my ip address.
187 */
188 static int my_ip() {
189         int i;
190         int errors = 0;
191         char*   ip;                                     // ip address string
192         void*   if_list;
193
194         if_list = mk_ip_list( "1235" );
195         errors += fail_if_nil( if_list, "mk_ip_list returned nil pointer" );
196
197         i = has_myip( NULL, NULL, ',', 128 );           // should be false if pointers are nil
198         errors += fail_if_true( i, "has_myip returned true when given nil buffer" );
199
200         i = has_myip( "buffer contents not valid", NULL, ',', 128 );            // should be false if pointers are nil
201         errors += fail_if_true( i, "has_myip returned true when given nil list" );
202
203         i = has_myip( "buffer contents not valid", NULL, ',', 1 );                      // should be false if max < 2
204         errors += fail_if_true( i, "has_myip returned true when given small max value" );
205
206         i = has_myip( "buffer.contents.not.valid", if_list, ',', 128 );         // should be false as there is nothing valid in the list
207         errors += fail_if_true( i, "has_myip returned true when given a buffer with no valid info" );
208
209
210         setenv( "RMR_BIND_IF", "192.168.4.30", 1 );                     // drive the case where we have a hard set interface; and set known interface in list
211         if_list = mk_ip_list( "1235" );
212         errors += fail_if_nil( if_list, "mk_ip_list with env set returned nil pointer" );
213
214         i = has_myip( "192.168.1.2:1235,192.168.4.30:1235,192.168.2.19:4567", if_list, ',', 128 );              // should find our ip in middle
215         errors += fail_if_false( i, "has_myip did not find IP in middle of list" );
216
217         i = has_myip( "192.168.4.30:1235,192.168.2.19:4567,192.168.2.19:2222", if_list, ',', 128 );             // should find our ip at head
218         errors += fail_if_false( i, "has_myip did not find IP at head of list" );
219
220         i = has_myip( "192.168.23.45:4444,192.168.1.2:1235,192.168.4.30:1235", if_list, ',', 128 );             // should find our ip at end
221         errors += fail_if_false( i, "has_myip did not find IP at tail of list" );
222
223         i = has_myip( "192.168.4.30:1235", if_list, ',', 128 );                                                                                 // should find our ip when only in list
224         errors += fail_if_false( i, "has_myip did not find IP when only one in list" );
225
226         ip = get_default_ip( NULL );
227         errors += fail_not_nil( ip, "get_default_ip returned non-nil pointer when given nil information" );
228
229         ip = get_default_ip( if_list );
230         if( ip ) {
231                 free( ip );
232         } else {
233                 errors += fail_if_nil( ip, "get_defaul_ip returned nil pointer when valid pointer expected" );
234         }
235
236         ip = get_ifname();                                                      // suss out a valid interface name (not lo)
237         if( ip ) {
238                 setenv( "RMR_BIND_IF", ip, 1 );                 // drive the case where we have a hard set interface; and set known interface in list
239                 free( ip );
240                 if_list = mk_ip_list( "1235" );
241                 if( if_list ) {
242                         ip = get_default_ip( if_list );
243                         errors += fail_if_nil( ip, "get_default_ip did not return valid pointer when list created from interface name" );
244                 } else {
245                         errors += fail_if_nil( if_list, "mk_ip_list with a specific interface name returned a nil list" );
246                 }
247
248                 free( ip );
249         } else {
250                 fprintf( stderr, "<SKIP> test skipped because no interface with address could be found on system" );
251         }
252
253         return errors;
254 }
255
256 /*
257         String tools related tests.
258 */
259 static int str_tests() {
260         int j;
261         char* buf = "2,Fred,Wilma,Barney,Betty,Dino,Pebbles,Bambam,Mr. Slate,Gazoo";
262         int errors = 0;
263
264         j = uta_has_str( buf, "Mr. Slate", ',', 1 );                    // should fail (-1) because user should use strcmp in this situation
265         errors += fail_if_true( j >= 0, "test to ensure has str rejects small max" );
266
267         j = uta_has_str( buf, "Mr. Slate", ',', 27 );
268         errors += fail_if_true( j < 0, "has string did not find Mr. Slate" );
269
270         j = uta_has_str( buf, "Mrs. Slate", ',', 27 );
271         errors += fail_if_true( j >= 0, "has string not found Mrs. Slate" );
272
273         return errors;
274 }
275
276 /*
277         Tests related to host name tools.
278 */
279 static int hostname_tests() {
280         int errors = 0;
281         char*   hname;
282
283
284         hname = uta_h2ip( "192.168.1.2" );
285         errors += fail_not_equal( strcmp( hname, "192.168.1.2" ), 0, "h2ip did not return IP address when given address" );
286         errors += fail_if_nil( hname, "h2ip did not return a pointer" );
287         free( hname );
288
289         hname = uta_h2ip( "yahoo.com" );
290         errors += fail_if_nil( hname, "h2ip did not return a pointer" );
291         free( hname );
292
293         hname = uta_h2ip( "yahoo.com:1234" );                                                   // should ignore the port
294         errors += fail_if_nil( hname, "h2ip did not return a pointer" );
295         free( hname );
296
297         hname = uta_h2ip( "bugaboofoo.com:1234" );                                                      // should not be there
298         errors += fail_not_nil( hname, "h2ip lookup returned non-nil when given bogus name" );
299
300         return errors;
301 }
302
303 /*
304         Misc coverage mostly.
305 */
306 static int misc_tests() {
307         int errors = 0;
308         int v;
309         if_addrs_t*     ifl;                    // interface list
310
311         if( (ifl = get_iflist( 1 )) != NULL ) {
312                 v = is_this_myip( ifl, NULL );
313                 errors += fail_if_false( v == 0, "is this my ip didn't fail when given nil address" );
314         }
315
316         return errors;
317 }
318 // ----------------------------------------------------------------------------------------------------------------------
319
320
321 /*
322         Primary test function driven by the testing main().
323 */
324 static int tools_test( ) {
325         int errors = 0;
326
327         uta_dump_env();
328
329         errors += tok_tests();
330         errors += my_ip();
331         errors += str_tests();
332         errors += hostname_tests();
333         errors += ztbf_test();
334
335         test_summary( errors, "tools" );
336         return !!errors;                        // 1 or 0 regardless of count
337 }