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

Last change on this file since 14606 was 14606, checked in by jordan, 6 years ago

remove unused macro

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