blob: 2bb1f9ca3cc7718236545e3eb8b344ea2f3bfa1c [file] [log] [blame]
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +01001/* tests for utilities of libmsomcore */
2/*
3 * (C) 2014 Holger Hans Peter Freyther
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +020023#include <osmocom/gsm/ipa.h>
Harald Welte7869baf2018-07-31 20:25:48 +020024#include <osmocom/gsm/protocol/ipaccess.h>
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +020025
26#include <osmocom/core/logging.h>
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010027#include <osmocom/core/utils.h>
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +020028#include <osmocom/core/socket.h>
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010029
30#include <stdio.h>
Harald Welte504caac2017-10-27 17:19:59 +020031#include <ctype.h>
Harald Welte15a5f8d2018-06-06 16:58:17 +020032#include <time.h>
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +020033#include <netinet/in.h>
34#include <arpa/inet.h>
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010035
36static void hexdump_test(void)
37{
38 uint8_t data[4098];
39 int i;
40
41 for (i = 0; i < ARRAY_SIZE(data); ++i)
42 data[i] = i & 0xff;
43
44 printf("Plain dump\n");
45 printf("%s\n", osmo_hexdump(data, 4));
46
47 printf("Corner case\n");
48 printf("%s\n", osmo_hexdump(data, ARRAY_SIZE(data)));
49 printf("%s\n", osmo_hexdump_nospc(data, ARRAY_SIZE(data)));
50}
51
Neels Hofmeyr7adb5672017-02-14 15:48:19 +010052static void hexparse_test(void)
53{
54 int i;
55 int rc;
56 uint8_t data[256];
57
58 printf("\nHexparse 0..255 in lower case\n");
59 memset(data, 0, sizeof(data));
60 rc = osmo_hexparse(
61 "000102030405060708090a0b0c0d0e0f"
62 "101112131415161718191a1b1c1d1e1f"
63 "202122232425262728292a2b2c2d2e2f"
64 "303132333435363738393a3b3c3d3e3f"
65 "404142434445464748494a4b4c4d4e4f"
66 "505152535455565758595a5b5c5d5e5f"
67 "606162636465666768696a6b6c6d6e6f"
68 "707172737475767778797a7b7c7d7e7f"
69 "808182838485868788898a8b8c8d8e8f"
70 "909192939495969798999a9b9c9d9e9f"
71 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
72 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
73 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
74 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
75 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
76 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
77 , data, sizeof(data));
78 printf("rc = %d\n", rc);
79 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
80 for (i = 0; i < sizeof(data); i++)
81 OSMO_ASSERT(data[i] == i);
82
83 printf("Hexparse 0..255 in upper case\n");
84 memset(data, 0, sizeof(data));
85 rc = osmo_hexparse(
86 "000102030405060708090A0B0C0D0E0F"
87 "101112131415161718191A1B1C1D1E1F"
88 "202122232425262728292A2B2C2D2E2F"
89 "303132333435363738393A3B3C3D3E3F"
90 "404142434445464748494A4B4C4D4E4F"
91 "505152535455565758595A5B5C5D5E5F"
92 "606162636465666768696A6B6C6D6E6F"
93 "707172737475767778797A7B7C7D7E7F"
94 "808182838485868788898A8B8C8D8E8F"
95 "909192939495969798999A9B9C9D9E9F"
96 "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
97 "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
98 "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
99 "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
100 "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
101 "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
102 , data, sizeof(data));
103 printf("rc = %d\n", rc);
104 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
105 for (i = 0; i < sizeof(data); i++)
106 OSMO_ASSERT(data[i] == i);
107
108 printf("Hexparse 0..255 in mixed case\n");
109 memset(data, 0, sizeof(data));
110 rc = osmo_hexparse(
111 "000102030405060708090A0B0C0D0E0F"
112 "101112131415161718191A1B1C1D1E1F"
113 "202122232425262728292A2B2C2D2E2F"
114 "303132333435363738393a3b3c3d3e3f"
115 "404142434445464748494A4B4C4D4E4F"
116 "505152535455565758595a5b5c5d5e5f"
117 "606162636465666768696A6B6C6D6E6F"
118 "707172737475767778797A7B7C7D7E7F"
119 "808182838485868788898A8B8C8D8E8F"
120 "909192939495969798999A9B9C9D9E9F"
121 "A0A1A2A3a4a5a6a7a8a9AAABACADAEAF"
122 "B0B1B2B3b4b5b6b7b8b9BABBBCBDBEBF"
123 "C0C1C2C3c4c5c6c7c8c9CACBCCCDCECF"
124 "D0D1D2D3d4d5d6d7d8d9DADBDCDDDEDF"
125 "E0E1E2E3e4e5e6e7e8e9EAEBECEDEEEF"
126 "F0F1F2F3f4f5f6f7f8f9FAFBFCFDFEFF"
127 , data, sizeof(data));
128 printf("rc = %d\n", rc);
129 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
130 for (i = 0; i < sizeof(data); i++)
131 OSMO_ASSERT(data[i] == i);
132
Neels Hofmeyr437ed4a2017-02-14 15:54:31 +0100133 printf("Hexparse 0..255 with whitespace\n");
134 memset(data, 0, sizeof(data));
135 rc = osmo_hexparse(
136 "00 01\t02\r030405060708090A0B0C0D0 E 0 F\n"
137 "10 11\t12\r131415161718191A1B1C1D1 E 1 F\n"
138 "20 21\t22\r232425262728292A2B2C2D2 E 2 F\n"
139 "30 31\t32\r333435363738393a3b3c3d3 e 3 f\n"
140 "40 41\t42\r434445464748494A4B4C4D4 E 4 F\n"
141 "50 51\t52\r535455565758595a5b5c5d5 e 5 f\n"
142 "60 61\t62\r636465666768696A6B6C6D6 E 6 F\n"
143 "70 71\t72\r737475767778797A7B7C7D7 E 7 F\n"
144 "80 81\t82\r838485868788898A8B8C8D8 E 8 F\n"
145 "90 91\t92\r939495969798999A9B9C9D9 E 9 F\n"
146 "A0 A1\tA2\rA3a4a5a6a7a8a9AAABACADA E A F\n"
147 "B0 B1\tB2\rB3b4b5b6b7b8b9BABBBCBDB E B F\n"
148 "C0 C1\tC2\rC3c4c5c6c7c8c9CACBCCCDC E C F \n"
149 "D0 D1\tD2\rD3d4d5d6d7d8d9DADBDCDDD E D F\t\n"
150 "E0 E1\tE2\rE3e4e5e6e7e8e9EAEBECEDE E E F \t\n"
151 "F0 F1\tF2\rF3f4f5f6f7f8f9FAFBFCFDF E F F \t\r\n"
152 , data, sizeof(data));
153 printf("rc = %d\n", rc);
154 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
155 for (i = 0; i < sizeof(data); i++)
156 OSMO_ASSERT(data[i] == i);
157
Neels Hofmeyr7adb5672017-02-14 15:48:19 +0100158 printf("Hexparse with buffer too short\n");
159 memset(data, 0, sizeof(data));
160 rc = osmo_hexparse("000102030405060708090a0b0c0d0e0f", data, 15);
161 printf("rc = %d\n", rc);
162
163 printf("Hexparse with uneven amount of digits\n");
164 memset(data, 0, sizeof(data));
165 rc = osmo_hexparse("000102030405060708090a0b0c0d0e0", data, 16);
166 printf("rc = %d\n", rc);
167
168 printf("Hexparse with invalid char\n");
169 memset(data, 0, sizeof(data));
170 rc = osmo_hexparse("0001020304050X0708090a0b0c0d0e0f", data, 16);
171 printf("rc = %d\n", rc);
172}
173
Harald Welte7869baf2018-07-31 20:25:48 +0200174static void test_ipa_ccm_id_resp_parsing(void)
175{
176 struct tlv_parsed tvp;
177 int rc;
178
179 static const uint8_t id_resp_data[] = {
180 0x00, 0x13, IPAC_IDTAG_MACADDR,
181 '0','0',':','0','2',':','9','5',':','0','0',':','6','2',':','9','e','\0',
182 0x00, 0x11, IPAC_IDTAG_IPADDR,
183 '1','9','2','.','1','6','8','.','1','0','0','.','1','9','0','\0',
184 0x00, 0x0a, IPAC_IDTAG_UNIT,
185 '1','2','3','4','/','0','/','0','\0',
186 0x00, 0x02, IPAC_IDTAG_LOCATION1,
187 '\0',
188 0x00, 0x0d, IPAC_IDTAG_LOCATION2,
189 'B','T','S','_','N','B','T','1','3','1','G','\0',
190 0x00, 0x0c, IPAC_IDTAG_EQUIPVERS,
191 '1','6','5','a','0','2','9','_','5','5','\0',
192 0x00, 0x14, IPAC_IDTAG_SWVERSION,
193 '1','6','8','d','4','7','2','_','v','2','0','0','b','4','1','1','d','0','\0',
194 0x00, 0x18, IPAC_IDTAG_UNITNAME,
195 'n','b','t','s','-','0','0','-','0','2','-','9','5','-','0','0','-','6','2','-','9','E','\0',
196 0x00, 0x0a, IPAC_IDTAG_SERNR,
197 '0','0','1','1','0','7','8','1','\0'
198 };
199
200 printf("\nTesting IPA CCM ID RESP parsing\n");
201
202 rc = ipa_ccm_id_resp_parse(&tvp, (uint8_t *) id_resp_data, sizeof(id_resp_data));
203 OSMO_ASSERT(rc == 0);
204
205 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_MACADDR));
206 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_MACADDR) == 0x12);
207 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_IPADDR));
208 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_IPADDR) == 0x10);
209 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNIT));
210 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNIT) == 0x09);
211 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION1));
212 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION1) == 0x01);
213 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION2));
214 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION2) == 0x0c);
215 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_EQUIPVERS));
216 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
217 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SWVERSION));
218 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
219 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SWVERSION) == 0x13);
220 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME));
221 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNITNAME) == 0x17);
222 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SERNR));
223 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SERNR) == 0x09);
224}
225
226static void test_ipa_ccm_id_get_parsing(void)
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200227{
228 struct tlv_parsed tvp;
229 int rc;
230
Harald Welte48fd0192018-07-31 20:19:49 +0200231 /* IPA CCM IDENTITY REQUEST message: 8bit length followed by respective value */
Harald Welte7869baf2018-07-31 20:25:48 +0200232 static const uint8_t id_get_data[] = {
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200233 0x01, 0x08,
234 0x01, 0x07,
235 0x01, 0x02,
236 0x01, 0x03,
237 0x01, 0x04,
238 0x01, 0x05,
239 0x01, 0x01,
240 0x01, 0x00,
241 0x11, 0x23, 0x4e, 0x6a, 0x28, 0xd2, 0xa2, 0x53, 0x3a, 0x2a, 0x82, 0xa7, 0x7a, 0xef, 0x29, 0xd4, 0x44, 0x30,
242 0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
243 };
244
Harald Welte7869baf2018-07-31 20:25:48 +0200245 printf("\nTesting IPA CCM ID GET parsing\n");
246
247 rc = ipa_ccm_id_get_parse(&tvp, id_get_data, sizeof(id_get_data));
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200248 OSMO_ASSERT(rc == 0);
249
250 OSMO_ASSERT(TLVP_PRESENT(&tvp, 8));
251 OSMO_ASSERT(TLVP_LEN(&tvp, 8) == 0);
252
253 OSMO_ASSERT(TLVP_PRESENT(&tvp, 7));
254 OSMO_ASSERT(TLVP_LEN(&tvp, 7) == 0);
255
256 OSMO_ASSERT(TLVP_PRESENT(&tvp, 2));
257 OSMO_ASSERT(TLVP_LEN(&tvp, 2) == 0);
258
259 OSMO_ASSERT(TLVP_PRESENT(&tvp, 3));
260 OSMO_ASSERT(TLVP_LEN(&tvp, 3) == 0);
261
262 OSMO_ASSERT(TLVP_PRESENT(&tvp, 4));
263 OSMO_ASSERT(TLVP_LEN(&tvp, 4) == 0);
264
265 OSMO_ASSERT(TLVP_PRESENT(&tvp, 5));
266 OSMO_ASSERT(TLVP_LEN(&tvp, 5) == 0);
267
268 OSMO_ASSERT(TLVP_PRESENT(&tvp, 1));
269 OSMO_ASSERT(TLVP_LEN(&tvp, 1) == 0);
270
271 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0));
272 OSMO_ASSERT(TLVP_LEN(&tvp, 0) == 0);
273
274 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x23));
275 OSMO_ASSERT(TLVP_LEN(&tvp, 0x23) == 16);
276
277 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x24));
278 OSMO_ASSERT(TLVP_LEN(&tvp, 0x24) == 16);
279
280 OSMO_ASSERT(!TLVP_PRESENT(&tvp, 0x25));
281}
282
Neels Hofmeyr4335bad2017-10-07 04:39:14 +0200283static struct {
284 const char *str;
285 int min_digits;
286 int max_digits;
287 bool require_even;
288 bool expect_ok;
289} test_hexstrs[] = {
290 { NULL, 0, 10, false, true },
291 { NULL, 1, 10, false, false },
292 { "", 0, 10, false, true },
293 { "", 1, 10, false, false },
294 { " ", 0, 10, false, false },
295 { "1", 0, 10, false, true },
296 { "1", 1, 10, false, true },
297 { "1", 1, 10, true, false },
298 { "1", 2, 10, false, false },
299 { "123", 1, 10, false, true },
300 { "123", 1, 10, true, false },
301 { "123", 4, 10, false, false },
302 { "1234", 4, 10, true, true },
303 { "12345", 4, 10, true, false },
304 { "123456", 4, 10, true, true },
305 { "1234567", 4, 10, true, false },
306 { "12345678", 4, 10, true, true },
307 { "123456789", 4, 10, true, false },
308 { "123456789a", 4, 10, true, true },
309 { "123456789ab", 4, 10, true, false },
310 { "123456789abc", 4, 10, true, false },
311 { "123456789ab", 4, 10, false, false },
312 { "123456789abc", 4, 10, false, false },
313 { "0123456789abcdefABCDEF", 0, 100, false, true },
314 { "0123456789 abcdef ABCDEF", 0, 100, false, false },
315 { "foobar", 0, 100, false, false },
316 { "BeadedBeeAced1EbbedDefacedFacade", 32, 32, true, true },
317 { "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 32, 32, false, true },
318 { "DeafBeddedBabeAcceededFadedDecaff", 32, 32, false, false },
319};
320
321bool test_is_hexstr()
322{
323 int i;
324 bool pass = true;
325 bool ok = true;
326 printf("\n----- %s\n", __func__);
327
328 for (i = 0; i < ARRAY_SIZE(test_hexstrs); i++) {
329 ok = osmo_is_hexstr(test_hexstrs[i].str,
330 test_hexstrs[i].min_digits,
331 test_hexstrs[i].max_digits,
332 test_hexstrs[i].require_even);
333 pass = pass && (ok == test_hexstrs[i].expect_ok);
334 printf("%2d: %s str='%s' min=%d max=%d even=%d expect=%s\n",
335 i, test_hexstrs[i].expect_ok == ok ? "pass" : "FAIL",
336 test_hexstrs[i].str,
337 test_hexstrs[i].min_digits,
338 test_hexstrs[i].max_digits,
339 test_hexstrs[i].require_even,
340 test_hexstrs[i].expect_ok ? "valid" : "invalid");
341 }
342 return pass;
343}
344
Harald Welte504caac2017-10-27 17:19:59 +0200345struct bcdcheck {
346 uint8_t bcd;
347 char ch;
348};
349
350static const struct bcdcheck bcdchecks[] = {
351 { 0, '0' },
352 { 1, '1' },
353 { 2, '2' },
354 { 3, '3' },
355 { 4, '4' },
356 { 5, '5' },
357 { 6, '6' },
358 { 7, '7' },
359 { 8, '8' },
360 { 9, '9' },
361 { 0xA, 'A' },
362 { 0xB, 'B' },
363 { 0xC, 'C' },
364 { 0xD, 'D' },
365 { 0xE, 'E' },
366 { 0xF, 'F' },
367};
368
369static void bcd_test(void)
370{
371 int i;
372
373 printf("\nTesting BCD conversion\n");
374 for (i = 0; i < ARRAY_SIZE(bcdchecks); i++) {
375 const struct bcdcheck *check = &bcdchecks[i];
376 char ch = osmo_bcd2char(check->bcd);
377 printf("\tval=0x%x, expected=%c, found=%c\n", check->bcd, check->ch, ch);
378 OSMO_ASSERT(osmo_bcd2char(check->bcd) == check->ch);
379 /* test char -> bcd back-coversion */
380 OSMO_ASSERT(osmo_char2bcd(ch) == check->bcd);
381 /* test for lowercase hex char */
382 OSMO_ASSERT(osmo_char2bcd(tolower(ch)) == check->bcd);
383 }
384}
385
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +0100386static void str_escape_test(void)
387{
388 int i;
389 int j;
390 uint8_t in_buf[32];
391 char out_buf[11];
392 const char *printable = "printable";
393 const char *res;
394
395 printf("\nTesting string escaping\n");
396 printf("- all chars from 0 to 255 in batches of 16:\n");
Pau Espin Pedrol6de34ee2018-02-01 12:49:39 +0100397 in_buf[16] = '\0';
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +0100398 for (j = 0; j < 16; j++) {
399 for (i = 0; i < 16; i++)
400 in_buf[i] = (j << 4) | i;
401 printf("\"%s\"\n", osmo_escape_str((const char*)in_buf, 16));
402 }
403
404 printf("- nul terminated:\n");
405 printf("\"%s\"\n", osmo_escape_str("termi\nated", -1));
406
407 printf("- passthru:\n");
408 res = osmo_escape_str(printable, -1);
409 if (res != printable)
410 printf("NOT passed through! \"%s\"\n", res);
411 else
412 printf("passed through unchanged \"%s\"\n", res);
413
414 printf("- zero length:\n");
415 printf("\"%s\"\n", osmo_escape_str("omitted", 0));
416
417 printf("- truncation when too long:\n");
418 memset(in_buf, 'x', sizeof(in_buf));
419 in_buf[0] = '\a';
420 in_buf[7] = 'E';
421 memset(out_buf, 0x7f, sizeof(out_buf));
422 printf("\"%s\"\n", osmo_escape_str_buf((const char *)in_buf, sizeof(in_buf), out_buf, 10));
423 OSMO_ASSERT(out_buf[10] == 0x7f);
424
425 printf("- passthrough without truncation when no escaping needed:\n");
426 memset(in_buf, 'x', sizeof(in_buf));
427 in_buf[19] = 'E';
428 in_buf[20] = '\0';
429 memset(out_buf, 0x7f, sizeof(out_buf));
430 printf("\"%s\"\n", osmo_escape_str_buf((const char *)in_buf, -1, out_buf, 10));
431 OSMO_ASSERT(out_buf[0] == 0x7f);
432}
433
Neels Hofmeyr04eb56f2018-04-09 00:41:28 +0200434static void str_quote_test(void)
435{
436 int i;
437 int j;
438 uint8_t in_buf[32];
439 char out_buf[11];
440 const char *printable = "printable";
441 const char *res;
442
443 printf("\nTesting string quoting\n");
444 printf("- all chars from 0 to 255 in batches of 16:\n");
445 in_buf[16] = '\0';
446 for (j = 0; j < 16; j++) {
447 for (i = 0; i < 16; i++)
448 in_buf[i] = (j << 4) | i;
449 printf("'%s'\n", osmo_quote_str((const char*)in_buf, 16));
450 }
451
452 printf("- nul terminated:\n");
453 printf("'%s'\n", osmo_quote_str("termi\nated", -1));
454
455 printf("- never passthru:\n");
456 res = osmo_quote_str(printable, -1);
457 if (res != printable)
458 printf("NOT passed through. '%s'\n", res);
459 else
460 printf("passed through unchanged '%s'\n", res);
461
462 printf("- zero length:\n");
463 printf("'%s'\n", osmo_quote_str("omitted", 0));
464
465 printf("- truncation when too long:\n");
466 memset(in_buf, 'x', sizeof(in_buf));
467 in_buf[0] = '\a';
468 in_buf[5] = 'E';
469 memset(out_buf, 0x7f, sizeof(out_buf));
470 printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, sizeof(in_buf), out_buf, 10));
471 OSMO_ASSERT(out_buf[10] == 0x7f);
472
473 printf("- always truncation, even when no escaping needed:\n");
474 memset(in_buf, 'x', sizeof(in_buf));
475 in_buf[6] = 'E'; /* dst has 10, less 2 quotes and nul, leaves 7, i.e. in[6] is last */
476 in_buf[20] = '\0';
477 memset(out_buf, 0x7f, sizeof(out_buf));
478 printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, -1, out_buf, 10));
479 OSMO_ASSERT(out_buf[0] == '"');
480
481 printf("- try to feed too little buf for quoting:\n");
482 printf("'%s'\n", osmo_quote_str_buf("", -1, out_buf, 2));
483
484 printf("- NULL string becomes a \"NULL\" literal:\n");
485 printf("'%s'\n", osmo_quote_str_buf(NULL, -1, out_buf, 10));
486}
487
Harald Welte15a5f8d2018-06-06 16:58:17 +0200488static void isqrt_test(void)
489{
490 int i;
491
492 printf("\nTesting integer square-root\n");
493 srand(time(NULL));
494 for (i = 0; i < 1024; i++) {
495 uint16_t x;
496 uint32_t r = rand();
497 if (RAND_MAX < UINT16_MAX)
498 x = r * (UINT16_MAX/RAND_MAX);
499 else
500 x = r;
Neels Hofmeyr6979c542018-07-19 22:05:21 +0200501 uint32_t sq = (uint32_t)x*x;
Harald Welte15a5f8d2018-06-06 16:58:17 +0200502 uint32_t y = osmo_isqrt32(sq);
503 if (y != x)
504 printf("ERROR: x=%u, sq=%u, osmo_isqrt(%u) = %u\n", x, sq, sq, y);
505 }
506}
507
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +0200508
509struct osmo_sockaddr_to_str_and_uint_test_case {
510 uint16_t port;
511 bool omit_port;
512 const char *addr;
513 unsigned int addr_len;
514 bool omit_addr;
515 unsigned int expect_rc;
516 const char *expect_returned_addr;
517};
518
519struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_test_data[] = {
520 {
521 .port = 0,
522 .addr = "0.0.0.0",
523 .addr_len = 20,
524 .expect_rc = 7,
525 },
526 {
527 .port = 65535,
528 .addr = "255.255.255.255",
529 .addr_len = 20,
530 .expect_rc = 15,
531 },
532 {
533 .port = 1234,
534 .addr = "234.23.42.123",
535 .addr_len = 20,
536 .expect_rc = 13,
537 },
538 {
539 .port = 1234,
540 .addr = "234.23.42.123",
541 .addr_len = 10,
542 .expect_rc = 13,
543 .expect_returned_addr = "234.23.42",
544 },
545 {
546 .port = 1234,
547 .omit_port = true,
548 .addr = "234.23.42.123",
549 .addr_len = 20,
550 .expect_rc = 13,
551 },
552 {
553 .port = 1234,
554 .addr = "234.23.42.123",
555 .omit_addr = true,
556 .expect_rc = 0,
557 .expect_returned_addr = "",
558 },
559 {
560 .port = 1234,
561 .addr = "234.23.42.123",
562 .addr_len = 0,
563 .expect_rc = 13,
564 .expect_returned_addr = "",
565 },
566 {
567 .port = 1234,
568 .addr = "234.23.42.123",
569 .omit_port = true,
570 .omit_addr = true,
571 .expect_rc = 0,
572 .expect_returned_addr = "",
573 },
574};
575
576static void osmo_sockaddr_to_str_and_uint_test(void)
577{
578 int i;
579 printf("\n%s\n", __func__);
580
581 for (i = 0; i < ARRAY_SIZE(osmo_sockaddr_to_str_and_uint_test_data); i++) {
582 struct osmo_sockaddr_to_str_and_uint_test_case *t =
583 &osmo_sockaddr_to_str_and_uint_test_data[i];
584
585 struct sockaddr_in sin = {
586 .sin_family = AF_INET,
587 .sin_port = htons(t->port),
588 };
589 inet_aton(t->addr, &sin.sin_addr);
590
591 char addr[20] = {};
592 uint16_t port = 0;
593 unsigned int rc;
594
595 rc = osmo_sockaddr_to_str_and_uint(
596 t->omit_addr? NULL : addr, t->addr_len,
597 t->omit_port? NULL : &port,
598 (const struct sockaddr*)&sin);
599
600 printf("[%d] %s:%u%s%s addr_len=%u --> %s:%u rc=%u\n",
601 i,
602 t->addr ? : "-",
603 t->port,
604 t->omit_addr ? " (omit addr)" : "",
605 t->omit_port ? " (omit port)" : "",
606 t->addr_len,
607 addr, port, rc);
608 if (rc != t->expect_rc)
609 printf("ERROR: Expected rc = %u\n", t->expect_rc);
610 if (!t->expect_returned_addr)
611 t->expect_returned_addr = t->addr;
612 if (strcmp(t->expect_returned_addr, addr))
613 printf("ERROR: Expected addr = '%s'\n", t->expect_returned_addr);
614 if (!t->omit_port && port != t->port)
615 printf("ERROR: Expected port = %u\n", t->port);
616 }
617}
618
Neels Hofmeyr7c749892018-09-07 03:01:38 +0200619struct osmo_str_tolowupper_test_data {
620 const char *in;
621 bool use_static_buf;
622 size_t buflen;
623 const char *expect_lower;
624 const char *expect_upper;
625 size_t expect_rc;
626 size_t expect_rc_inplace;
627};
628
629struct osmo_str_tolowupper_test_data osmo_str_tolowupper_tests[] = {
630 {
631 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
632 .use_static_buf = true,
633 .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",
634 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
635 },
636 {
637 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
638 .buflen = 99,
639 .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",
640 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
641 .expect_rc = 62,
642 .expect_rc_inplace = 62,
643 },
644 {
645 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
646 .buflen = 0,
647 .expect_lower = "Unset",
648 .expect_upper = "Unset",
649 .expect_rc = 62,
650 .expect_rc_inplace = 0,
651 },
652 {
653 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
654 .buflen = 1,
655 .expect_lower = "",
656 .expect_upper = "",
657 .expect_rc = 62,
658 .expect_rc_inplace = 0,
659 },
660 {
661 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
662 .buflen = 2,
663 .expect_lower = "a",
664 .expect_upper = "A",
665 .expect_rc = 62,
666 .expect_rc_inplace = 1,
667 },
668 {
669 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
670 .buflen = 28,
671 .expect_lower = "abcdefghijklmnopqrstuvwxyza",
672 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZA",
673 .expect_rc = 62,
674 .expect_rc_inplace = 27,
675 },
676};
677
678
679static void osmo_str_tolowupper_test()
680{
681 int i;
682 char buf[128];
683 bool ok = true;
684 printf("\n%s\n", __func__);
685
686 for (i = 0; i < ARRAY_SIZE(osmo_str_tolowupper_tests); i++) {
687 struct osmo_str_tolowupper_test_data *d = &osmo_str_tolowupper_tests[i];
688 size_t rc = 0;
689 const char *res;
690
691 /* tolower */
692 if (d->use_static_buf) {
693 res = osmo_str_tolower(d->in);
694 printf("osmo_str_tolower(%s)\n", osmo_quote_str(d->in, -1));
695 printf(" = %s\n", osmo_quote_str(res, -1));
696 } else {
697 OSMO_ASSERT(sizeof(buf) >= d->buflen);
698 osmo_strlcpy(buf, "Unset", sizeof(buf));
699 rc = osmo_str_tolower_buf(buf, d->buflen, d->in);
700 res = buf;
701 printf("osmo_str_tolower_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));
702 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
703 }
704
705 if (strcmp(res, d->expect_lower)) {
706 printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"
707 " got %s\n", i, osmo_quote_str(res, -1));
708 printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1));
709 ok = false;
710 }
711
712 if (!d->use_static_buf && d->expect_rc != rc) {
713 printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"
714 " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);
715 ok = false;
716 }
717
718 /* tolower, in-place */
719 if (!d->use_static_buf) {
720 osmo_strlcpy(buf,
721 d->buflen ? d->in : "Unset",
722 sizeof(buf));
723 rc = osmo_str_tolower_buf(buf, d->buflen, buf);
724 res = buf;
725 printf("osmo_str_tolower_buf(%zu, %s, in-place)\n",
726 d->buflen, osmo_quote_str(d->in, -1));
727 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
728
729 if (strcmp(res, d->expect_lower)) {
730 printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"
731 " got %s\n", i, osmo_quote_str(res, -1));
732 printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1));
733 ok = false;
734 }
735
736 if (d->expect_rc_inplace != rc) {
737 printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"
738 " got rc=%zu, expected rc=%zu\n",
739 i, rc, d->expect_rc_inplace);
740 ok = false;
741 }
742 }
743
744 /* toupper */
745 if (d->use_static_buf) {
746 res = osmo_str_toupper(d->in);
747 printf("osmo_str_toupper(%s)\n", osmo_quote_str(d->in, -1));
748 printf(" = %s\n", osmo_quote_str(res, -1));
749 } else {
750 OSMO_ASSERT(sizeof(buf) >= d->buflen);
751 osmo_strlcpy(buf, "Unset", sizeof(buf));
752 rc = osmo_str_toupper_buf(buf, d->buflen, d->in);
753 res = buf;
754 printf("osmo_str_toupper_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));
755 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
756 }
757
758 if (strcmp(res, d->expect_upper)) {
759 printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"
760 " got %s\n", i, osmo_quote_str(res, -1));
761 printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1));
762 ok = false;
763 }
764
765 if (!d->use_static_buf && d->expect_rc != rc) {
766 printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"
767 " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);
768 ok = false;
769 }
770
771 /* toupper, in-place */
772 if (!d->use_static_buf) {
773 osmo_strlcpy(buf,
774 d->buflen ? d->in : "Unset",
775 sizeof(buf));
776 rc = osmo_str_toupper_buf(buf, d->buflen, buf);
777 res = buf;
778 printf("osmo_str_toupper_buf(%zu, %s, in-place)\n",
779 d->buflen, osmo_quote_str(d->in, -1));
780 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
781
782 if (strcmp(res, d->expect_upper)) {
783 printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"
784 " got %s\n", i, osmo_quote_str(res, -1));
785 printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1));
786 ok = false;
787 }
788
789 if (d->expect_rc_inplace != rc) {
790 printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"
791 " got rc=%zu, expected rc=%zu\n",
792 i, rc, d->expect_rc_inplace);
793 ok = false;
794 }
795 }
796 }
797
798 OSMO_ASSERT(ok);
799}
800
801
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +0100802int main(int argc, char **argv)
803{
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200804 static const struct log_info log_info = {};
805 log_init(&log_info, NULL);
806
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +0100807 hexdump_test();
Neels Hofmeyr7adb5672017-02-14 15:48:19 +0100808 hexparse_test();
Harald Welte7869baf2018-07-31 20:25:48 +0200809 test_ipa_ccm_id_get_parsing();
810 test_ipa_ccm_id_resp_parsing();
Neels Hofmeyr4335bad2017-10-07 04:39:14 +0200811 test_is_hexstr();
Harald Welte504caac2017-10-27 17:19:59 +0200812 bcd_test();
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +0100813 str_escape_test();
Neels Hofmeyr04eb56f2018-04-09 00:41:28 +0200814 str_quote_test();
Harald Welte15a5f8d2018-06-06 16:58:17 +0200815 isqrt_test();
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +0200816 osmo_sockaddr_to_str_and_uint_test();
Neels Hofmeyr7c749892018-09-07 03:01:38 +0200817 osmo_str_tolowupper_test();
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +0100818 return 0;
819}