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