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

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

(trunk) #4160: mike.dld patch: 4160-07-env.patch

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