source: trunk/libtransmission/utils-test.c @ 14299

Last change on this file since 14299 was 14299, checked in by jordan, 8 years ago

mike.dld's portability improvements to libtransmission, pt 1

  • Property svn:keywords set to Date Rev Author Id
File size: 10.8 KB
Line 
1/*
2 * This file Copyright (C) 2013-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: utils-test.c 14299 2014-06-23 02:38:53Z jordan $
8 */
9
10#include <limits.h> /* INT_MAX */
11#include <math.h> /* sqrt () */
12#include <string.h> /* strlen () */
13
14#include "transmission.h"
15#include "ConvertUTF.h" /* tr_utf8_validate*/
16#include "platform.h"
17#include "crypto.h"
18#include "utils.h"
19#include "web.h"
20
21#define NUM_LOOPS 1
22#define SPEED_TEST 0
23
24#if SPEED_TEST
25 #define VERBOSE
26 #undef NUM_LOOPS
27 #define NUM_LOOPS 200
28#endif
29
30#include "libtransmission-test.h"
31
32static int
33test_base64 (void)
34{
35  int len;
36  char *in, *out;
37
38  /* base64 */
39  out = tr_base64_encode ("YOYO!", -1, &len);
40  check_streq ("WU9ZTyE=", out);
41  check_int_eq (8, len);
42  in = tr_base64_decode (out, -1, &len);
43  check_streq ("YOYO!", in);
44  check_int_eq (5, len);
45  tr_free (in);
46  tr_free (out);
47  out = tr_base64_encode (NULL, 0, &len);
48  check (out == NULL);
49  check_int_eq (0, len);
50
51  return 0;
52}
53
54static int
55test_strip_positional_args (void)
56{
57  const char * in;
58  const char * out;
59  const char * expected;
60
61  in = "Hello %1$s foo %2$.*f";
62  expected = "Hello %s foo %.*f";
63  out = tr_strip_positional_args (in);
64  check_streq (expected, out);
65
66  in = "Hello %1$'d foo %2$'f";
67  expected = "Hello %d foo %f";
68  out = tr_strip_positional_args (in);
69  check_streq (expected, out);
70
71  return 0;
72}
73
74static int
75test_strstrip (void)
76{
77  char *in, *out;
78
79  /* strstrip */
80  in = tr_strdup ("   test    ");
81  out = tr_strstrip (in);
82  check (in == out);
83  check_streq ("test", out);
84  tr_free (in);
85
86  /* strstrip */
87  in = tr_strdup (" test test ");
88  out = tr_strstrip (in);
89  check (in == out);
90  check_streq ("test test", out);
91  tr_free (in);
92
93  /* strstrip */
94  in = tr_strdup ("test");
95  out = tr_strstrip (in);
96  check (in == out);
97  check_streq ("test", out);
98  tr_free (in);
99
100  return 0;
101}
102
103static int
104test_buildpath (void)
105{
106  char * out;
107
108  out = tr_buildPath ("foo", "bar", NULL);
109  check_streq ("foo" TR_PATH_DELIMITER_STR "bar", out);
110  tr_free (out);
111
112  out = tr_buildPath ("", "foo", "bar", NULL);
113  check_streq (TR_PATH_DELIMITER_STR "foo" TR_PATH_DELIMITER_STR "bar", out);
114  tr_free (out);
115
116  return 0;
117}
118
119static int
120test_utf8 (void)
121{
122  const char * in;
123  char * out;
124
125  in = "hello world";
126  out = tr_utf8clean (in, -1);
127  check_streq (in, out);
128  tr_free (out);
129
130  in = "hello world";
131  out = tr_utf8clean (in, 5);
132  check_streq ("hello", out);
133  tr_free (out);
134
135  /* this version is not utf-8 */
136  in = "Òðóäíî áûòü Áîãîì";
137  out = tr_utf8clean (in, 17);
138  check (out != NULL);
139  check ((strlen (out) == 17) || (strlen (out) == 32));
140  check (tr_utf8_validate (out, -1, NULL));
141  tr_free (out);
142
143  /* same string, but utf-8 clean */
144  in = "ÒðóÀíî áûòÌ Áîãîì";
145  out = tr_utf8clean (in, -1);
146  check (out != NULL);
147  check (tr_utf8_validate (out, -1, NULL));
148  check_streq (in, out);
149  tr_free (out);
150
151  return 0;
152}
153
154static int
155test_numbers (void)
156{
157  int i;
158  int count;
159  int * numbers;
160
161  numbers = tr_parseNumberRange ("1-10,13,16-19", -1, &count);
162  check_int_eq (15, count);
163  check_int_eq (1, numbers[0]);
164  check_int_eq (6, numbers[5]);
165  check_int_eq (10, numbers[9]);
166  check_int_eq (13, numbers[10]);
167  check_int_eq (16, numbers[11]);
168  check_int_eq (19, numbers[14]);
169  tr_free (numbers);
170
171  numbers = tr_parseNumberRange ("1-5,3-7,2-6", -1, &count);
172  check (count == 7);
173  check (numbers != NULL);
174  for (i=0; i<count; ++i)
175    check_int_eq (i+1, numbers[i]);
176  tr_free (numbers);
177
178  numbers = tr_parseNumberRange ("1-Hello", -1, &count);
179  check_int_eq (0, count);
180  check (numbers == NULL);
181
182  numbers = tr_parseNumberRange ("1-", -1, &count);
183  check_int_eq (0, count);
184  check (numbers == NULL);
185
186  numbers = tr_parseNumberRange ("Hello", -1, &count);
187  check_int_eq (0, count);
188  check (numbers == NULL);
189
190  return 0;
191}
192
193static int
194compareInts (const void * va, const void * vb)
195{
196  const int a = *(const int *)va;
197  const int b = *(const int *)vb;
198  return a - b;
199}
200
201static int
202test_lowerbound (void)
203{
204  int i;
205  const int A[] = { 1, 2, 3, 3, 3, 5, 8 };
206  const int expected_pos[] = { 0, 1, 2, 5, 5, 6, 6, 6, 7, 7 };
207  const bool expected_exact[] = { true, true, true, false, true, false, false, true, false, false };
208  const int N = sizeof (A) / sizeof (A[0]);
209
210  for (i=1; i<=10; i++)
211    {
212      bool exact;
213      const int pos = tr_lowerBound (&i, A, N, sizeof (int), compareInts, &exact);
214
215#if 0
216      fprintf (stderr, "searching for %d. ", i);
217      fprintf (stderr, "result: index = %d, ", pos);
218      if (pos != N)
219        fprintf (stderr, "A[%d] == %d\n", pos, A[pos]);
220      else
221        fprintf (stderr, "which is off the end.\n");
222#endif
223      check_int_eq (expected_pos[i-1], pos);
224      check_int_eq (expected_exact[i-1], exact);
225    }
226
227  return 0;
228}
229
230static int
231test_quickFindFirst_Iteration (const size_t k, const size_t n, int * buf, int range)
232{
233  size_t i;
234  int highest_low;
235  int lowest_high;
236
237  /* populate buf with random ints */
238  for (i=0; i<n; ++i)
239    buf[i] = tr_cryptoWeakRandInt (range);
240
241  /* find the best k */
242  tr_quickfindFirstK (buf, n, sizeof(int), compareInts, k);
243
244  /* confirm that the smallest K ints are in the first slots K slots in buf */
245
246  highest_low = INT_MIN;
247  for (i=0; i<k; ++i)
248    if (highest_low < buf[i])
249      highest_low = buf[i];
250
251  lowest_high = INT_MAX;
252  for (i=k; i<n; ++i)
253    if (lowest_high > buf[i])
254      lowest_high = buf[i];
255
256  check (highest_low <= lowest_high);
257
258  return 0;
259}
260
261static int
262test_quickfindFirst (void)
263{
264  size_t i;
265  const size_t k = 10;
266  const size_t n = 100;
267  const size_t n_trials = 1000;
268  int * buf = tr_new (int, n);
269
270  for (i=0; i<n_trials; ++i)
271    check_int_eq (0, test_quickFindFirst_Iteration (k, n, buf, 100));
272
273  tr_free (buf);
274  return 0;
275}
276
277static int
278test_memmem (void)
279{
280  char const haystack[12] = "abcabcabcabc";
281  char const needle[3] = "cab";
282
283  check (tr_memmem (haystack, sizeof haystack, haystack, sizeof haystack) == haystack);
284  check (tr_memmem (haystack, sizeof haystack, needle, sizeof needle) == haystack + 2);
285  check (tr_memmem (needle, sizeof needle, haystack, sizeof haystack) == NULL);
286
287  return 0;
288}
289
290static int
291test_hex (void)
292{
293  char hex1[41];
294  char hex2[41];
295  uint8_t sha1[20];
296
297  memcpy (hex1, "fb5ef5507427b17e04b69cef31fa3379b456735a", 41);
298  tr_hex_to_sha1 (sha1, hex1);
299  tr_sha1_to_hex (hex2, sha1);
300  check_streq (hex1, hex2);
301
302  return 0;
303}
304
305static int
306test_array (void)
307{
308  int i;
309  int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
310  int n = sizeof (array) / sizeof (array[0]);
311
312  tr_removeElementFromArray (array, 5u, sizeof (int), n--);
313  for (i=0; i<n; ++i)
314    check_int_eq ((i<5 ? i : i+1), array[i]);
315
316  tr_removeElementFromArray (array, 0u, sizeof (int), n--);
317  for (i=0; i<n; ++i)
318    check_int_eq ((i<4 ? i+1 : i+2), array[i]);
319
320  tr_removeElementFromArray (array, n-1, sizeof (int), n); n--;
321  for (i=0; i<n; ++i)
322    check_int_eq ((i<4 ? i+1 : i+2), array[i]);
323
324  return 0;
325}
326
327static int
328test_url (void)
329{
330  int port;
331  char * scheme;
332  char * host;
333  char * path;
334  char * str;
335  const char * url;
336
337  url = "http://1";
338  check (!tr_urlParse (url, -1, &scheme, &host, &port, &path));
339  check_streq ("http", scheme);
340  check_streq ("1", host);
341  check_streq ("/", path);
342  check_int_eq (80, port);
343  tr_free (scheme);
344  tr_free (path);
345  tr_free (host);
346
347  url = "http://www.some-tracker.org/some/path";
348  check (!tr_urlParse (url, -1, &scheme, &host, &port, &path));
349  check_streq ("http", scheme);
350  check_streq ("www.some-tracker.org", host);
351  check_streq ("/some/path", path);
352  check_int_eq (80, port);
353  tr_free (scheme);
354  tr_free (path);
355  tr_free (host);
356
357  url = "http://www.some-tracker.org:80/some/path";
358  check (!tr_urlParse (url, -1, &scheme, &host, &port, &path));
359  check_streq ("http", scheme);
360  check_streq ("www.some-tracker.org", host);
361  check_streq ("/some/path", path);
362  check_int_eq (80, port);
363  tr_free (scheme);
364  tr_free (path);
365  tr_free (host);
366
367  url = "http%3A%2F%2Fwww.example.com%2F~user%2F%3Ftest%3D1%26test1%3D2";
368  str = tr_http_unescape (url, strlen (url));
369  check_streq ("http://www.example.com/~user/?test=1&test1=2", str);
370  tr_free (str);
371
372  return 0;
373}
374
375static int
376test_truncd (void)
377{
378  char buf[32];
379  const double nan = sqrt (-1);
380
381  tr_snprintf (buf, sizeof (buf), "%.2f%%", 99.999);
382  check_streq ("100.00%", buf);
383
384  tr_snprintf (buf, sizeof (buf), "%.2f%%", tr_truncd (99.999, 2));
385  check_streq ("99.99%", buf);
386
387  tr_snprintf (buf, sizeof (buf), "%.4f", tr_truncd (403650.656250, 4));
388  check_streq ("403650.6562", buf);
389
390  tr_snprintf (buf, sizeof (buf), "%.2f", tr_truncd (2.15, 2));
391  check_streq ("2.15", buf);
392
393  tr_snprintf (buf, sizeof (buf), "%.2f", tr_truncd (2.05, 2));
394  check_streq ("2.05", buf);
395
396  tr_snprintf (buf, sizeof (buf), "%.2f", tr_truncd (3.3333, 2));
397  check_streq ("3.33", buf);
398
399  tr_snprintf (buf, sizeof (buf), "%.0f", tr_truncd (3.3333, 0));
400  check_streq ("3", buf);
401
402  tr_snprintf (buf, sizeof (buf), "%.2f", tr_truncd (nan, 2));
403  check (strstr (buf, "nan") != NULL);
404
405  return 0;
406}
407
408static int
409test_cryptoRand (void)
410{
411  int i;
412
413  /* test that tr_cryptoRandInt () stays in-bounds */
414  for (i = 0; i < 100000; ++i)
415    {
416      const int val = tr_cryptoRandInt (100);
417       check (val >= 0);
418       check (val < 100);
419    }
420
421  return 0;
422}
423
424static char *
425test_strdup_printf_valist (const char * fmt, ...)
426{
427  va_list args;
428  char * ret;
429
430  va_start (args, fmt);
431  ret = tr_strdup_vprintf (fmt, args);
432  va_end (args);
433
434  return ret;
435}
436
437static int
438test_strdup_printf (void)
439{
440  char * s, * s2, * s3;
441
442  s = tr_strdup_printf ("%s", "test");
443  check_streq ("test", s);
444  tr_free (s);
445
446  s = tr_strdup_printf ("%d %s %c %u", -1, "0", '1', 2);
447  check_streq ("-1 0 1 2", s);
448  tr_free (s);
449
450  s3 = tr_malloc0 (4098);
451  memset (s3, '-', 4097);
452  s3[2047] = 't';
453  s3[2048] = 'e';
454  s3[2049] = 's';
455  s3[2050] = 't';
456
457  s2 = tr_malloc0 (4096);
458  memset (s2, '-', 4095);
459  s2[2047] = '%';
460  s2[2048] = 's';
461
462  s = tr_strdup_printf (s2, "test");
463  check_streq (s3, s);
464  tr_free (s);
465
466  tr_free (s2);
467
468  s = tr_strdup_printf ("%s", s3);
469  check_streq (s3, s);
470  tr_free (s);
471
472  tr_free (s3);
473
474  s = test_strdup_printf_valist ("\n-%s-%s-%s-\n", "\r", "\t", "\b");
475  check_streq ("\n-\r-\t-\b-\n", s);
476  tr_free (s);
477
478  return 0;
479}
480
481int
482main (void)
483{
484  const testFunc tests[] = { test_array,
485                             test_base64,
486                             test_buildpath,
487                             test_cryptoRand,
488                             test_hex,
489                             test_lowerbound,
490                             test_quickfindFirst,
491                             test_memmem,
492                             test_numbers,
493                             test_strip_positional_args,
494                             test_strdup_printf,
495                             test_strstrip,
496                             test_truncd,
497                             test_url,
498                             test_utf8 };
499
500  return runTests (tests, NUM_TESTS (tests));
501}
502
Note: See TracBrowser for help on using the repository browser.