blob: d592fe042e9a24c0ef588ed243b0e6ec097bd92c [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>
Neels Hofmeyr7079e692018-12-05 21:02:36 +010035#include <errno.h>
Neels Hofmeyr2cbe25f2019-02-11 20:32:06 +010036#include <limits.h>
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010037
38static void hexdump_test(void)
39{
40 uint8_t data[4098];
Neels Hofmeyr0423b612019-01-14 23:32:53 +010041 char buf[256];
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010042 int i;
43
44 for (i = 0; i < ARRAY_SIZE(data); ++i)
45 data[i] = i & 0xff;
46
47 printf("Plain dump\n");
48 printf("%s\n", osmo_hexdump(data, 4));
Neels Hofmeyr0423b612019-01-14 23:32:53 +010049 printf("%s\n", osmo_hexdump_nospc(data, 4));
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010050
51 printf("Corner case\n");
52 printf("%s\n", osmo_hexdump(data, ARRAY_SIZE(data)));
53 printf("%s\n", osmo_hexdump_nospc(data, ARRAY_SIZE(data)));
Neels Hofmeyr0423b612019-01-14 23:32:53 +010054
55#define _HEXDUMP_BUF_TEST(SIZE, DELIM, DELIM_AFTER) \
56 buf[0] = '!'; \
57 buf[1] = '\0'; \
58 printf("osmo_hexdump_buf(buf, " #SIZE ", data, 4, %s, " #DELIM_AFTER ")\n = \"%s\"\n", \
59 DELIM ? #DELIM : "NULL", \
60 osmo_hexdump_buf(buf, SIZE, data, 4, DELIM, DELIM_AFTER))
61#define HEXDUMP_BUF_TEST(DELIM) \
62 _HEXDUMP_BUF_TEST(sizeof(buf), DELIM, false); \
63 _HEXDUMP_BUF_TEST(sizeof(buf), DELIM, true); \
64 _HEXDUMP_BUF_TEST(6, DELIM, false); \
65 _HEXDUMP_BUF_TEST(7, DELIM, false); \
66 _HEXDUMP_BUF_TEST(8, DELIM, false); \
67 _HEXDUMP_BUF_TEST(6, DELIM, true); \
68 _HEXDUMP_BUF_TEST(7, DELIM, true); \
69 _HEXDUMP_BUF_TEST(8, DELIM, true)
70
71 HEXDUMP_BUF_TEST("[delim]");
72 HEXDUMP_BUF_TEST(" ");
73 HEXDUMP_BUF_TEST(":");
74 HEXDUMP_BUF_TEST("::");
75 HEXDUMP_BUF_TEST("");
76 HEXDUMP_BUF_TEST(NULL);
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +010077}
78
Neels Hofmeyr7adb5672017-02-14 15:48:19 +010079static void hexparse_test(void)
80{
81 int i;
82 int rc;
83 uint8_t data[256];
84
85 printf("\nHexparse 0..255 in lower case\n");
86 memset(data, 0, sizeof(data));
87 rc = osmo_hexparse(
88 "000102030405060708090a0b0c0d0e0f"
89 "101112131415161718191a1b1c1d1e1f"
90 "202122232425262728292a2b2c2d2e2f"
91 "303132333435363738393a3b3c3d3e3f"
92 "404142434445464748494a4b4c4d4e4f"
93 "505152535455565758595a5b5c5d5e5f"
94 "606162636465666768696a6b6c6d6e6f"
95 "707172737475767778797a7b7c7d7e7f"
96 "808182838485868788898a8b8c8d8e8f"
97 "909192939495969798999a9b9c9d9e9f"
98 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
99 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
100 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
101 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
102 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
103 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
104 , data, sizeof(data));
105 printf("rc = %d\n", rc);
106 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
107 for (i = 0; i < sizeof(data); i++)
108 OSMO_ASSERT(data[i] == i);
109
110 printf("Hexparse 0..255 in upper case\n");
111 memset(data, 0, sizeof(data));
112 rc = osmo_hexparse(
113 "000102030405060708090A0B0C0D0E0F"
114 "101112131415161718191A1B1C1D1E1F"
115 "202122232425262728292A2B2C2D2E2F"
116 "303132333435363738393A3B3C3D3E3F"
117 "404142434445464748494A4B4C4D4E4F"
118 "505152535455565758595A5B5C5D5E5F"
119 "606162636465666768696A6B6C6D6E6F"
120 "707172737475767778797A7B7C7D7E7F"
121 "808182838485868788898A8B8C8D8E8F"
122 "909192939495969798999A9B9C9D9E9F"
123 "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
124 "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
125 "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
126 "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
127 "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
128 "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
129 , data, sizeof(data));
130 printf("rc = %d\n", rc);
131 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
132 for (i = 0; i < sizeof(data); i++)
133 OSMO_ASSERT(data[i] == i);
134
135 printf("Hexparse 0..255 in mixed case\n");
136 memset(data, 0, sizeof(data));
137 rc = osmo_hexparse(
138 "000102030405060708090A0B0C0D0E0F"
139 "101112131415161718191A1B1C1D1E1F"
140 "202122232425262728292A2B2C2D2E2F"
141 "303132333435363738393a3b3c3d3e3f"
142 "404142434445464748494A4B4C4D4E4F"
143 "505152535455565758595a5b5c5d5e5f"
144 "606162636465666768696A6B6C6D6E6F"
145 "707172737475767778797A7B7C7D7E7F"
146 "808182838485868788898A8B8C8D8E8F"
147 "909192939495969798999A9B9C9D9E9F"
148 "A0A1A2A3a4a5a6a7a8a9AAABACADAEAF"
149 "B0B1B2B3b4b5b6b7b8b9BABBBCBDBEBF"
150 "C0C1C2C3c4c5c6c7c8c9CACBCCCDCECF"
151 "D0D1D2D3d4d5d6d7d8d9DADBDCDDDEDF"
152 "E0E1E2E3e4e5e6e7e8e9EAEBECEDEEEF"
153 "F0F1F2F3f4f5f6f7f8f9FAFBFCFDFEFF"
154 , data, sizeof(data));
155 printf("rc = %d\n", rc);
156 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
157 for (i = 0; i < sizeof(data); i++)
158 OSMO_ASSERT(data[i] == i);
159
Neels Hofmeyr437ed4a2017-02-14 15:54:31 +0100160 printf("Hexparse 0..255 with whitespace\n");
161 memset(data, 0, sizeof(data));
162 rc = osmo_hexparse(
163 "00 01\t02\r030405060708090A0B0C0D0 E 0 F\n"
164 "10 11\t12\r131415161718191A1B1C1D1 E 1 F\n"
165 "20 21\t22\r232425262728292A2B2C2D2 E 2 F\n"
166 "30 31\t32\r333435363738393a3b3c3d3 e 3 f\n"
167 "40 41\t42\r434445464748494A4B4C4D4 E 4 F\n"
168 "50 51\t52\r535455565758595a5b5c5d5 e 5 f\n"
169 "60 61\t62\r636465666768696A6B6C6D6 E 6 F\n"
170 "70 71\t72\r737475767778797A7B7C7D7 E 7 F\n"
171 "80 81\t82\r838485868788898A8B8C8D8 E 8 F\n"
172 "90 91\t92\r939495969798999A9B9C9D9 E 9 F\n"
173 "A0 A1\tA2\rA3a4a5a6a7a8a9AAABACADA E A F\n"
174 "B0 B1\tB2\rB3b4b5b6b7b8b9BABBBCBDB E B F\n"
175 "C0 C1\tC2\rC3c4c5c6c7c8c9CACBCCCDC E C F \n"
176 "D0 D1\tD2\rD3d4d5d6d7d8d9DADBDCDDD E D F\t\n"
177 "E0 E1\tE2\rE3e4e5e6e7e8e9EAEBECEDE E E F \t\n"
178 "F0 F1\tF2\rF3f4f5f6f7f8f9FAFBFCFDF E F F \t\r\n"
179 , data, sizeof(data));
180 printf("rc = %d\n", rc);
181 printf("--> %s\n\n", osmo_hexdump(data, sizeof(data)));
182 for (i = 0; i < sizeof(data); i++)
183 OSMO_ASSERT(data[i] == i);
184
Neels Hofmeyr7adb5672017-02-14 15:48:19 +0100185 printf("Hexparse with buffer too short\n");
186 memset(data, 0, sizeof(data));
187 rc = osmo_hexparse("000102030405060708090a0b0c0d0e0f", data, 15);
188 printf("rc = %d\n", rc);
189
190 printf("Hexparse with uneven amount of digits\n");
191 memset(data, 0, sizeof(data));
192 rc = osmo_hexparse("000102030405060708090a0b0c0d0e0", data, 16);
193 printf("rc = %d\n", rc);
194
195 printf("Hexparse with invalid char\n");
196 memset(data, 0, sizeof(data));
197 rc = osmo_hexparse("0001020304050X0708090a0b0c0d0e0f", data, 16);
198 printf("rc = %d\n", rc);
199}
200
Harald Welte7869baf2018-07-31 20:25:48 +0200201static void test_ipa_ccm_id_resp_parsing(void)
202{
203 struct tlv_parsed tvp;
204 int rc;
205
206 static const uint8_t id_resp_data[] = {
207 0x00, 0x13, IPAC_IDTAG_MACADDR,
208 '0','0',':','0','2',':','9','5',':','0','0',':','6','2',':','9','e','\0',
209 0x00, 0x11, IPAC_IDTAG_IPADDR,
210 '1','9','2','.','1','6','8','.','1','0','0','.','1','9','0','\0',
211 0x00, 0x0a, IPAC_IDTAG_UNIT,
212 '1','2','3','4','/','0','/','0','\0',
213 0x00, 0x02, IPAC_IDTAG_LOCATION1,
214 '\0',
215 0x00, 0x0d, IPAC_IDTAG_LOCATION2,
216 'B','T','S','_','N','B','T','1','3','1','G','\0',
217 0x00, 0x0c, IPAC_IDTAG_EQUIPVERS,
218 '1','6','5','a','0','2','9','_','5','5','\0',
219 0x00, 0x14, IPAC_IDTAG_SWVERSION,
220 '1','6','8','d','4','7','2','_','v','2','0','0','b','4','1','1','d','0','\0',
221 0x00, 0x18, IPAC_IDTAG_UNITNAME,
222 'n','b','t','s','-','0','0','-','0','2','-','9','5','-','0','0','-','6','2','-','9','E','\0',
223 0x00, 0x0a, IPAC_IDTAG_SERNR,
224 '0','0','1','1','0','7','8','1','\0'
225 };
226
227 printf("\nTesting IPA CCM ID RESP parsing\n");
228
229 rc = ipa_ccm_id_resp_parse(&tvp, (uint8_t *) id_resp_data, sizeof(id_resp_data));
230 OSMO_ASSERT(rc == 0);
231
232 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_MACADDR));
233 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_MACADDR) == 0x12);
234 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_IPADDR));
235 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_IPADDR) == 0x10);
236 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNIT));
237 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNIT) == 0x09);
238 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION1));
239 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION1) == 0x01);
240 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION2));
241 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION2) == 0x0c);
242 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_EQUIPVERS));
243 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
244 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SWVERSION));
245 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
246 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SWVERSION) == 0x13);
247 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME));
248 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNITNAME) == 0x17);
249 OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SERNR));
250 OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SERNR) == 0x09);
251}
252
253static void test_ipa_ccm_id_get_parsing(void)
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200254{
255 struct tlv_parsed tvp;
256 int rc;
257
Harald Welte48fd0192018-07-31 20:19:49 +0200258 /* IPA CCM IDENTITY REQUEST message: 8bit length followed by respective value */
Harald Welte7869baf2018-07-31 20:25:48 +0200259 static const uint8_t id_get_data[] = {
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200260 0x01, 0x08,
261 0x01, 0x07,
262 0x01, 0x02,
263 0x01, 0x03,
264 0x01, 0x04,
265 0x01, 0x05,
266 0x01, 0x01,
267 0x01, 0x00,
268 0x11, 0x23, 0x4e, 0x6a, 0x28, 0xd2, 0xa2, 0x53, 0x3a, 0x2a, 0x82, 0xa7, 0x7a, 0xef, 0x29, 0xd4, 0x44, 0x30,
269 0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
270 };
271
Harald Welte7869baf2018-07-31 20:25:48 +0200272 printf("\nTesting IPA CCM ID GET parsing\n");
273
274 rc = ipa_ccm_id_get_parse(&tvp, id_get_data, sizeof(id_get_data));
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +0200275 OSMO_ASSERT(rc == 0);
276
277 OSMO_ASSERT(TLVP_PRESENT(&tvp, 8));
278 OSMO_ASSERT(TLVP_LEN(&tvp, 8) == 0);
279
280 OSMO_ASSERT(TLVP_PRESENT(&tvp, 7));
281 OSMO_ASSERT(TLVP_LEN(&tvp, 7) == 0);
282
283 OSMO_ASSERT(TLVP_PRESENT(&tvp, 2));
284 OSMO_ASSERT(TLVP_LEN(&tvp, 2) == 0);
285
286 OSMO_ASSERT(TLVP_PRESENT(&tvp, 3));
287 OSMO_ASSERT(TLVP_LEN(&tvp, 3) == 0);
288
289 OSMO_ASSERT(TLVP_PRESENT(&tvp, 4));
290 OSMO_ASSERT(TLVP_LEN(&tvp, 4) == 0);
291
292 OSMO_ASSERT(TLVP_PRESENT(&tvp, 5));
293 OSMO_ASSERT(TLVP_LEN(&tvp, 5) == 0);
294
295 OSMO_ASSERT(TLVP_PRESENT(&tvp, 1));
296 OSMO_ASSERT(TLVP_LEN(&tvp, 1) == 0);
297
298 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0));
299 OSMO_ASSERT(TLVP_LEN(&tvp, 0) == 0);
300
301 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x23));
302 OSMO_ASSERT(TLVP_LEN(&tvp, 0x23) == 16);
303
304 OSMO_ASSERT(TLVP_PRESENT(&tvp, 0x24));
305 OSMO_ASSERT(TLVP_LEN(&tvp, 0x24) == 16);
306
307 OSMO_ASSERT(!TLVP_PRESENT(&tvp, 0x25));
308}
309
Neels Hofmeyr4335bad2017-10-07 04:39:14 +0200310static struct {
311 const char *str;
312 int min_digits;
313 int max_digits;
314 bool require_even;
315 bool expect_ok;
316} test_hexstrs[] = {
317 { NULL, 0, 10, false, true },
318 { NULL, 1, 10, false, false },
319 { "", 0, 10, false, true },
320 { "", 1, 10, false, false },
321 { " ", 0, 10, false, false },
322 { "1", 0, 10, false, true },
323 { "1", 1, 10, false, true },
324 { "1", 1, 10, true, false },
325 { "1", 2, 10, false, false },
326 { "123", 1, 10, false, true },
327 { "123", 1, 10, true, false },
328 { "123", 4, 10, false, false },
329 { "1234", 4, 10, true, true },
330 { "12345", 4, 10, true, false },
331 { "123456", 4, 10, true, true },
332 { "1234567", 4, 10, true, false },
333 { "12345678", 4, 10, true, true },
334 { "123456789", 4, 10, true, false },
335 { "123456789a", 4, 10, true, true },
336 { "123456789ab", 4, 10, true, false },
337 { "123456789abc", 4, 10, true, false },
338 { "123456789ab", 4, 10, false, false },
339 { "123456789abc", 4, 10, false, false },
340 { "0123456789abcdefABCDEF", 0, 100, false, true },
341 { "0123456789 abcdef ABCDEF", 0, 100, false, false },
342 { "foobar", 0, 100, false, false },
343 { "BeadedBeeAced1EbbedDefacedFacade", 32, 32, true, true },
344 { "C01ffedC1cadaeAc1d1f1edAcac1aB0a", 32, 32, false, true },
345 { "DeafBeddedBabeAcceededFadedDecaff", 32, 32, false, false },
346};
347
348bool test_is_hexstr()
349{
350 int i;
351 bool pass = true;
352 bool ok = true;
353 printf("\n----- %s\n", __func__);
354
355 for (i = 0; i < ARRAY_SIZE(test_hexstrs); i++) {
356 ok = osmo_is_hexstr(test_hexstrs[i].str,
357 test_hexstrs[i].min_digits,
358 test_hexstrs[i].max_digits,
359 test_hexstrs[i].require_even);
360 pass = pass && (ok == test_hexstrs[i].expect_ok);
361 printf("%2d: %s str='%s' min=%d max=%d even=%d expect=%s\n",
362 i, test_hexstrs[i].expect_ok == ok ? "pass" : "FAIL",
363 test_hexstrs[i].str,
364 test_hexstrs[i].min_digits,
365 test_hexstrs[i].max_digits,
366 test_hexstrs[i].require_even,
367 test_hexstrs[i].expect_ok ? "valid" : "invalid");
368 }
369 return pass;
370}
371
Harald Welte504caac2017-10-27 17:19:59 +0200372struct bcdcheck {
373 uint8_t bcd;
374 char ch;
375};
376
377static const struct bcdcheck bcdchecks[] = {
378 { 0, '0' },
379 { 1, '1' },
380 { 2, '2' },
381 { 3, '3' },
382 { 4, '4' },
383 { 5, '5' },
384 { 6, '6' },
385 { 7, '7' },
386 { 8, '8' },
387 { 9, '9' },
388 { 0xA, 'A' },
389 { 0xB, 'B' },
390 { 0xC, 'C' },
391 { 0xD, 'D' },
392 { 0xE, 'E' },
393 { 0xF, 'F' },
394};
395
396static void bcd_test(void)
397{
398 int i;
399
400 printf("\nTesting BCD conversion\n");
401 for (i = 0; i < ARRAY_SIZE(bcdchecks); i++) {
402 const struct bcdcheck *check = &bcdchecks[i];
403 char ch = osmo_bcd2char(check->bcd);
404 printf("\tval=0x%x, expected=%c, found=%c\n", check->bcd, check->ch, ch);
405 OSMO_ASSERT(osmo_bcd2char(check->bcd) == check->ch);
406 /* test char -> bcd back-coversion */
407 OSMO_ASSERT(osmo_char2bcd(ch) == check->bcd);
408 /* test for lowercase hex char */
409 OSMO_ASSERT(osmo_char2bcd(tolower(ch)) == check->bcd);
410 }
411}
412
Neels Hofmeyr7079e692018-12-05 21:02:36 +0100413struct bcd2str_test {
414 const char *bcd_hex;
415 int start_nibble;
416 int end_nibble;
417 bool allow_hex;
418 size_t str_size;
419 const char *expect_str;
420 int expect_rc;
421};
422
423static const struct bcd2str_test bcd2str_tests[] = {
424 {
425 .bcd_hex = "1a 32 54 76 98 f0",
426 .start_nibble = 1,
427 .end_nibble = 11,
428 .expect_str = "1234567890",
429 .expect_rc = 10,
430 },
431 {
432 .bcd_hex = "1a 32 a4 cb 9d f0",
433 .start_nibble = 1,
434 .end_nibble = 11,
435 .expect_str = "1234ABCD90",
436 .expect_rc = -EINVAL,
437 },
438 {
439 .bcd_hex = "1a 32 a4 cb 9d f0",
440 .start_nibble = 1,
441 .end_nibble = 11,
442 .allow_hex = true,
443 .expect_str = "1234ABCD90",
444 .expect_rc = 10,
445 },
446 {
447 .bcd_hex = "1a 32 54 76 98 f0",
448 .start_nibble = 1,
449 .end_nibble = 12,
450 .expect_str = "1234567890F",
451 .expect_rc = -EINVAL,
452 },
453 {
454 .bcd_hex = "1a 32 54 76 98 f0",
455 .start_nibble = 1,
456 .end_nibble = 12,
457 .allow_hex = true,
458 .expect_str = "1234567890F",
459 .expect_rc = 11,
460 },
461 {
462 .bcd_hex = "1a 32 54 76 98 f0",
463 .start_nibble = 0,
464 .end_nibble = 12,
465 .allow_hex = true,
466 .expect_str = "A1234567890F",
467 .expect_rc = 12,
468 },
469 {
470 .bcd_hex = "1a 32 54 76 98 f0",
471 .start_nibble = 1,
472 .end_nibble = 12,
473 .str_size = 5,
474 .expect_str = "1234",
475 .expect_rc = 11,
476 },
477 {
478 .bcd_hex = "",
479 .start_nibble = 1,
480 .end_nibble = 1,
481 .expect_str = "",
482 .expect_rc = 0,
483 },
484};
485
486static void bcd2str_test(void)
487{
488 int i;
489 uint8_t bcd[64];
490 int rc;
491
492 printf("\nTesting bcd to string conversion\n");
493
494 for (i = 0; i < ARRAY_SIZE(bcd2str_tests); i++) {
495 const struct bcd2str_test *t = &bcd2str_tests[i];
496 char str[64] = {};
497 size_t str_size = t->str_size ? : sizeof(str);
498
499 osmo_hexparse(t->bcd_hex, bcd, sizeof(bcd));
500
501 printf("- BCD-input='%s' nibbles=[%d..%d[ str_size=%zu\n", t->bcd_hex,
502 t->start_nibble, t->end_nibble, str_size);
503 rc = osmo_bcd2str(str, str_size, bcd, t->start_nibble, t->end_nibble, t->allow_hex);
504
505 printf(" rc=%d\n", rc);
506
507 OSMO_ASSERT(str[str_size-1] == '\0');
508 printf(" -> %s\n", osmo_quote_str(str, -1));
509
510 if (rc != t->expect_rc)
511 printf(" ERROR: expected rc=%d\n", t->expect_rc);
512 if (strcmp(str, t->expect_str))
513 printf(" ERROR: expected result %s\n", osmo_quote_str(t->expect_str, -1));
514 }
515
516 printf("- zero output buffer\n");
517 rc = osmo_bcd2str(NULL, 100, bcd, 1, 2, false);
518 printf(" bcd2str(NULL, ...) -> %d\n", rc);
519 OSMO_ASSERT(rc < 0);
520 rc = osmo_bcd2str((char*)23, 0, bcd, 1, 2, false);
521 printf(" bcd2str(dst, 0, ...) -> %d\n", rc);
522 OSMO_ASSERT(rc < 0);
523}
524
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +0100525static void str_escape_test(void)
526{
527 int i;
528 int j;
529 uint8_t in_buf[32];
530 char out_buf[11];
531 const char *printable = "printable";
532 const char *res;
533
534 printf("\nTesting string escaping\n");
535 printf("- all chars from 0 to 255 in batches of 16:\n");
Pau Espin Pedrol6de34ee2018-02-01 12:49:39 +0100536 in_buf[16] = '\0';
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +0100537 for (j = 0; j < 16; j++) {
538 for (i = 0; i < 16; i++)
539 in_buf[i] = (j << 4) | i;
540 printf("\"%s\"\n", osmo_escape_str((const char*)in_buf, 16));
541 }
542
543 printf("- nul terminated:\n");
544 printf("\"%s\"\n", osmo_escape_str("termi\nated", -1));
545
546 printf("- passthru:\n");
547 res = osmo_escape_str(printable, -1);
548 if (res != printable)
549 printf("NOT passed through! \"%s\"\n", res);
550 else
551 printf("passed through unchanged \"%s\"\n", res);
552
553 printf("- zero length:\n");
554 printf("\"%s\"\n", osmo_escape_str("omitted", 0));
555
556 printf("- truncation when too long:\n");
557 memset(in_buf, 'x', sizeof(in_buf));
558 in_buf[0] = '\a';
559 in_buf[7] = 'E';
560 memset(out_buf, 0x7f, sizeof(out_buf));
561 printf("\"%s\"\n", osmo_escape_str_buf((const char *)in_buf, sizeof(in_buf), out_buf, 10));
562 OSMO_ASSERT(out_buf[10] == 0x7f);
563
564 printf("- passthrough without truncation when no escaping needed:\n");
565 memset(in_buf, 'x', sizeof(in_buf));
566 in_buf[19] = 'E';
567 in_buf[20] = '\0';
568 memset(out_buf, 0x7f, sizeof(out_buf));
569 printf("\"%s\"\n", osmo_escape_str_buf((const char *)in_buf, -1, out_buf, 10));
570 OSMO_ASSERT(out_buf[0] == 0x7f);
571}
572
Neels Hofmeyr04eb56f2018-04-09 00:41:28 +0200573static void str_quote_test(void)
574{
575 int i;
576 int j;
577 uint8_t in_buf[32];
578 char out_buf[11];
579 const char *printable = "printable";
580 const char *res;
581
582 printf("\nTesting string quoting\n");
583 printf("- all chars from 0 to 255 in batches of 16:\n");
584 in_buf[16] = '\0';
585 for (j = 0; j < 16; j++) {
586 for (i = 0; i < 16; i++)
587 in_buf[i] = (j << 4) | i;
588 printf("'%s'\n", osmo_quote_str((const char*)in_buf, 16));
589 }
590
591 printf("- nul terminated:\n");
592 printf("'%s'\n", osmo_quote_str("termi\nated", -1));
593
594 printf("- never passthru:\n");
595 res = osmo_quote_str(printable, -1);
596 if (res != printable)
597 printf("NOT passed through. '%s'\n", res);
598 else
599 printf("passed through unchanged '%s'\n", res);
600
601 printf("- zero length:\n");
602 printf("'%s'\n", osmo_quote_str("omitted", 0));
603
604 printf("- truncation when too long:\n");
605 memset(in_buf, 'x', sizeof(in_buf));
606 in_buf[0] = '\a';
607 in_buf[5] = 'E';
608 memset(out_buf, 0x7f, sizeof(out_buf));
609 printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, sizeof(in_buf), out_buf, 10));
610 OSMO_ASSERT(out_buf[10] == 0x7f);
611
612 printf("- always truncation, even when no escaping needed:\n");
613 memset(in_buf, 'x', sizeof(in_buf));
614 in_buf[6] = 'E'; /* dst has 10, less 2 quotes and nul, leaves 7, i.e. in[6] is last */
615 in_buf[20] = '\0';
616 memset(out_buf, 0x7f, sizeof(out_buf));
617 printf("'%s'\n", osmo_quote_str_buf((const char *)in_buf, -1, out_buf, 10));
618 OSMO_ASSERT(out_buf[0] == '"');
619
620 printf("- try to feed too little buf for quoting:\n");
621 printf("'%s'\n", osmo_quote_str_buf("", -1, out_buf, 2));
622
623 printf("- NULL string becomes a \"NULL\" literal:\n");
624 printf("'%s'\n", osmo_quote_str_buf(NULL, -1, out_buf, 10));
625}
626
Harald Welte15a5f8d2018-06-06 16:58:17 +0200627static void isqrt_test(void)
628{
629 int i;
630
631 printf("\nTesting integer square-root\n");
632 srand(time(NULL));
633 for (i = 0; i < 1024; i++) {
634 uint16_t x;
635 uint32_t r = rand();
636 if (RAND_MAX < UINT16_MAX)
637 x = r * (UINT16_MAX/RAND_MAX);
638 else
639 x = r;
Neels Hofmeyr6979c542018-07-19 22:05:21 +0200640 uint32_t sq = (uint32_t)x*x;
Harald Welte15a5f8d2018-06-06 16:58:17 +0200641 uint32_t y = osmo_isqrt32(sq);
642 if (y != x)
643 printf("ERROR: x=%u, sq=%u, osmo_isqrt(%u) = %u\n", x, sq, sq, y);
644 }
645}
646
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +0200647
648struct osmo_sockaddr_to_str_and_uint_test_case {
649 uint16_t port;
650 bool omit_port;
651 const char *addr;
652 unsigned int addr_len;
653 bool omit_addr;
654 unsigned int expect_rc;
655 const char *expect_returned_addr;
656};
657
658struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_test_data[] = {
659 {
660 .port = 0,
661 .addr = "0.0.0.0",
662 .addr_len = 20,
663 .expect_rc = 7,
664 },
665 {
666 .port = 65535,
667 .addr = "255.255.255.255",
668 .addr_len = 20,
669 .expect_rc = 15,
670 },
671 {
672 .port = 1234,
673 .addr = "234.23.42.123",
674 .addr_len = 20,
675 .expect_rc = 13,
676 },
677 {
678 .port = 1234,
679 .addr = "234.23.42.123",
680 .addr_len = 10,
681 .expect_rc = 13,
682 .expect_returned_addr = "234.23.42",
683 },
684 {
685 .port = 1234,
686 .omit_port = true,
687 .addr = "234.23.42.123",
688 .addr_len = 20,
689 .expect_rc = 13,
690 },
691 {
692 .port = 1234,
693 .addr = "234.23.42.123",
694 .omit_addr = true,
695 .expect_rc = 0,
696 .expect_returned_addr = "",
697 },
698 {
699 .port = 1234,
700 .addr = "234.23.42.123",
701 .addr_len = 0,
702 .expect_rc = 13,
703 .expect_returned_addr = "",
704 },
705 {
706 .port = 1234,
707 .addr = "234.23.42.123",
708 .omit_port = true,
709 .omit_addr = true,
710 .expect_rc = 0,
711 .expect_returned_addr = "",
712 },
713};
714
715static void osmo_sockaddr_to_str_and_uint_test(void)
716{
717 int i;
718 printf("\n%s\n", __func__);
719
720 for (i = 0; i < ARRAY_SIZE(osmo_sockaddr_to_str_and_uint_test_data); i++) {
721 struct osmo_sockaddr_to_str_and_uint_test_case *t =
722 &osmo_sockaddr_to_str_and_uint_test_data[i];
723
724 struct sockaddr_in sin = {
725 .sin_family = AF_INET,
726 .sin_port = htons(t->port),
727 };
728 inet_aton(t->addr, &sin.sin_addr);
729
730 char addr[20] = {};
731 uint16_t port = 0;
732 unsigned int rc;
733
734 rc = osmo_sockaddr_to_str_and_uint(
735 t->omit_addr? NULL : addr, t->addr_len,
736 t->omit_port? NULL : &port,
737 (const struct sockaddr*)&sin);
738
739 printf("[%d] %s:%u%s%s addr_len=%u --> %s:%u rc=%u\n",
740 i,
741 t->addr ? : "-",
742 t->port,
743 t->omit_addr ? " (omit addr)" : "",
744 t->omit_port ? " (omit port)" : "",
745 t->addr_len,
746 addr, port, rc);
747 if (rc != t->expect_rc)
748 printf("ERROR: Expected rc = %u\n", t->expect_rc);
749 if (!t->expect_returned_addr)
750 t->expect_returned_addr = t->addr;
751 if (strcmp(t->expect_returned_addr, addr))
752 printf("ERROR: Expected addr = '%s'\n", t->expect_returned_addr);
753 if (!t->omit_port && port != t->port)
754 printf("ERROR: Expected port = %u\n", t->port);
755 }
756}
757
Neels Hofmeyr7c749892018-09-07 03:01:38 +0200758struct osmo_str_tolowupper_test_data {
759 const char *in;
760 bool use_static_buf;
761 size_t buflen;
762 const char *expect_lower;
763 const char *expect_upper;
764 size_t expect_rc;
765 size_t expect_rc_inplace;
766};
767
768struct osmo_str_tolowupper_test_data osmo_str_tolowupper_tests[] = {
769 {
770 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
771 .use_static_buf = true,
772 .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",
773 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
774 },
775 {
776 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
777 .buflen = 99,
778 .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()",
779 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
780 .expect_rc = 62,
781 .expect_rc_inplace = 62,
782 },
783 {
784 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
785 .buflen = 0,
786 .expect_lower = "Unset",
787 .expect_upper = "Unset",
788 .expect_rc = 62,
789 .expect_rc_inplace = 0,
790 },
791 {
792 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
793 .buflen = 1,
794 .expect_lower = "",
795 .expect_upper = "",
796 .expect_rc = 62,
797 .expect_rc_inplace = 0,
798 },
799 {
800 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
801 .buflen = 2,
802 .expect_lower = "a",
803 .expect_upper = "A",
804 .expect_rc = 62,
805 .expect_rc_inplace = 1,
806 },
807 {
808 .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()",
809 .buflen = 28,
810 .expect_lower = "abcdefghijklmnopqrstuvwxyza",
811 .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZA",
812 .expect_rc = 62,
813 .expect_rc_inplace = 27,
814 },
815};
816
817
818static void osmo_str_tolowupper_test()
819{
820 int i;
821 char buf[128];
822 bool ok = true;
823 printf("\n%s\n", __func__);
824
825 for (i = 0; i < ARRAY_SIZE(osmo_str_tolowupper_tests); i++) {
826 struct osmo_str_tolowupper_test_data *d = &osmo_str_tolowupper_tests[i];
827 size_t rc = 0;
828 const char *res;
829
830 /* tolower */
831 if (d->use_static_buf) {
832 res = osmo_str_tolower(d->in);
833 printf("osmo_str_tolower(%s)\n", osmo_quote_str(d->in, -1));
834 printf(" = %s\n", osmo_quote_str(res, -1));
835 } else {
836 OSMO_ASSERT(sizeof(buf) >= d->buflen);
837 osmo_strlcpy(buf, "Unset", sizeof(buf));
838 rc = osmo_str_tolower_buf(buf, d->buflen, d->in);
839 res = buf;
840 printf("osmo_str_tolower_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));
841 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
842 }
843
844 if (strcmp(res, d->expect_lower)) {
845 printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"
846 " got %s\n", i, osmo_quote_str(res, -1));
847 printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1));
848 ok = false;
849 }
850
851 if (!d->use_static_buf && d->expect_rc != rc) {
852 printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n"
853 " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);
854 ok = false;
855 }
856
857 /* tolower, in-place */
858 if (!d->use_static_buf) {
859 osmo_strlcpy(buf,
860 d->buflen ? d->in : "Unset",
861 sizeof(buf));
862 rc = osmo_str_tolower_buf(buf, d->buflen, buf);
863 res = buf;
864 printf("osmo_str_tolower_buf(%zu, %s, in-place)\n",
865 d->buflen, osmo_quote_str(d->in, -1));
866 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
867
868 if (strcmp(res, d->expect_lower)) {
869 printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"
870 " got %s\n", i, osmo_quote_str(res, -1));
871 printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1));
872 ok = false;
873 }
874
875 if (d->expect_rc_inplace != rc) {
876 printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n"
877 " got rc=%zu, expected rc=%zu\n",
878 i, rc, d->expect_rc_inplace);
879 ok = false;
880 }
881 }
882
883 /* toupper */
884 if (d->use_static_buf) {
885 res = osmo_str_toupper(d->in);
886 printf("osmo_str_toupper(%s)\n", osmo_quote_str(d->in, -1));
887 printf(" = %s\n", osmo_quote_str(res, -1));
888 } else {
889 OSMO_ASSERT(sizeof(buf) >= d->buflen);
890 osmo_strlcpy(buf, "Unset", sizeof(buf));
891 rc = osmo_str_toupper_buf(buf, d->buflen, d->in);
892 res = buf;
893 printf("osmo_str_toupper_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1));
894 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
895 }
896
897 if (strcmp(res, d->expect_upper)) {
898 printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"
899 " got %s\n", i, osmo_quote_str(res, -1));
900 printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1));
901 ok = false;
902 }
903
904 if (!d->use_static_buf && d->expect_rc != rc) {
905 printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n"
906 " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc);
907 ok = false;
908 }
909
910 /* toupper, in-place */
911 if (!d->use_static_buf) {
912 osmo_strlcpy(buf,
913 d->buflen ? d->in : "Unset",
914 sizeof(buf));
915 rc = osmo_str_toupper_buf(buf, d->buflen, buf);
916 res = buf;
917 printf("osmo_str_toupper_buf(%zu, %s, in-place)\n",
918 d->buflen, osmo_quote_str(d->in, -1));
919 printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1));
920
921 if (strcmp(res, d->expect_upper)) {
922 printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"
923 " got %s\n", i, osmo_quote_str(res, -1));
924 printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1));
925 ok = false;
926 }
927
928 if (d->expect_rc_inplace != rc) {
929 printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n"
930 " got rc=%zu, expected rc=%zu\n",
931 i, rc, d->expect_rc_inplace);
932 ok = false;
933 }
934 }
935 }
936
937 OSMO_ASSERT(ok);
938}
939
Neels Hofmeyr2cbe25f2019-02-11 20:32:06 +0100940/* Copy of the examples from OSMO_STRBUF_APPEND() */
941int print_spaces(char *dst, size_t dst_len, int argument)
942{
943 int i;
944 if (argument < 0)
945 return -EINVAL;
946 for (i = 0; i < argument && i < dst_len; i++)
947 dst[i] = ' ';
948 if (dst_len)
949 dst[OSMO_MIN(dst_len - 1, argument)] = '\0';
950 return argument;
951}
952
953void strbuf_example(char *buf, size_t buflen)
954{
955 struct osmo_strbuf sb = { .buf = buf, .len = buflen };
956
957 OSMO_STRBUF_APPEND(sb, print_spaces, 5);
958 OSMO_STRBUF_APPEND(sb, snprintf, "The answer is %d but what is the question?", 42);
959 OSMO_STRBUF_APPEND(sb, print_spaces, 423423);
960
961 printf("%s\n", buf);
962 printf("would have needed %zu bytes\n", sb.chars_needed);
963}
964
965/* Copy of the examples from OSMO_STRBUF_PRINTF() */
966int strbuf_example2(char *buf, size_t buflen)
967{
968 int i;
969 struct osmo_strbuf sb = { .buf = buf, .len = buflen };
970
971 OSMO_STRBUF_PRINTF(sb, "T minus");
972 for (i = 10; i; i--)
973 OSMO_STRBUF_PRINTF(sb, " %d", i);
974 OSMO_STRBUF_PRINTF(sb, " ... Lift off!");
975
976 return sb.chars_needed;
977}
978
979int strbuf_cascade(char *buf, size_t buflen)
980{
981 struct osmo_strbuf sb = { .buf = buf, .len = buflen };
982
983 OSMO_STRBUF_APPEND(sb, strbuf_example2);
984 OSMO_STRBUF_PRINTF(sb, " -- ");
985 OSMO_STRBUF_APPEND(sb, strbuf_example2);
986 OSMO_STRBUF_PRINTF(sb, " -- ");
987 OSMO_STRBUF_APPEND(sb, strbuf_example2);
988
989 return sb.chars_needed;
990}
991
992void strbuf_test()
993{
994 char buf[256];
995 int rc;
996 printf("\n%s\n", __func__);
997
998 printf("OSMO_STRBUF_APPEND():\n");
999 strbuf_example(buf, 23);
1000
1001 printf("\nOSMO_STRBUF_PRINTF():\n");
1002 rc = strbuf_example2(buf, 23);
1003 printf("1: (need %d chars, had size=23) %s\n", rc, buf);
1004
1005 rc = strbuf_example2(buf, rc);
1006 printf("2: (need %d chars, had size=%d) %s\n", rc, rc, buf);
1007
1008 rc = strbuf_example2(buf, rc + 1);
1009 printf("3: (need %d chars, had size=%d+1) %s\n", rc, rc, buf);
1010
1011 rc = strbuf_example2(buf, 0);
1012 snprintf(buf, sizeof(buf), "0x2b 0x2b 0x2b...");
1013 printf("4: (need %d chars, had size=0) %s\n", rc, buf);
1014
1015 rc = strbuf_example2(NULL, 99);
1016 printf("5: (need %d chars, had NULL buffer)\n", rc);
1017
1018 printf("\ncascade:\n");
1019 rc = strbuf_cascade(buf, sizeof(buf));
1020 printf("(need %d chars)\n%s\n", rc, buf);
1021 rc = strbuf_cascade(buf, 63);
1022 printf("(need %d chars, had size=63) %s\n", rc, buf);
1023}
Neels Hofmeyr7c749892018-09-07 03:01:38 +02001024
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +01001025int main(int argc, char **argv)
1026{
Holger Hans Peter Freytherf558ed42015-06-02 15:52:06 +02001027 static const struct log_info log_info = {};
1028 log_init(&log_info, NULL);
1029
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +01001030 hexdump_test();
Neels Hofmeyr7adb5672017-02-14 15:48:19 +01001031 hexparse_test();
Harald Welte7869baf2018-07-31 20:25:48 +02001032 test_ipa_ccm_id_get_parsing();
1033 test_ipa_ccm_id_resp_parsing();
Neels Hofmeyr4335bad2017-10-07 04:39:14 +02001034 test_is_hexstr();
Harald Welte504caac2017-10-27 17:19:59 +02001035 bcd_test();
Neels Hofmeyr7079e692018-12-05 21:02:36 +01001036 bcd2str_test();
Neels Hofmeyr9910bbc2017-12-16 00:54:52 +01001037 str_escape_test();
Neels Hofmeyr04eb56f2018-04-09 00:41:28 +02001038 str_quote_test();
Harald Welte15a5f8d2018-06-06 16:58:17 +02001039 isqrt_test();
Neels Hofmeyr59f4caf2018-07-19 22:13:19 +02001040 osmo_sockaddr_to_str_and_uint_test();
Neels Hofmeyr7c749892018-09-07 03:01:38 +02001041 osmo_str_tolowupper_test();
Neels Hofmeyr2cbe25f2019-02-11 20:32:06 +01001042 strbuf_test();
Holger Hans Peter Freytherb79a1482014-01-02 13:55:00 +01001043 return 0;
1044}