source: trunk/libtransmission/variant-test.c @ 14241

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

Copyedit the license's revised text: (1) remove unnecessary repitition use of the word 'license' from the top of the header and source files (2) add the standard 'we hope it's useful, but no warranty' clause to COPYING (3) make explicit that linking OpenSSL is allowed (see https://people.gnome.org/~markmc/openssl-and-the-gpl.html for background) (4) sync the Qt and GTK+ clients' license popups with COPYING's revised text

  • Property svn:keywords set to Date Rev Author Id
File size: 14.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: variant-test.c 14241 2014-01-21 03:10:30Z jordan $
8 */
9
10#include <ctype.h> /* isspace () */
11#include <errno.h> /* EILSEQ */
12#include <string.h> /* strlen (), strncmp () */
13
14#include <event2/buffer.h>
15
16#define __LIBTRANSMISSION_VARIANT_MODULE___
17#include "transmission.h"
18#include "utils.h" /* tr_free */
19#include "variant.h"
20#include "variant-common.h"
21
22#include "libtransmission-test.h"
23
24#ifndef WIN32
25#define STACK_SMASH_DEPTH (1 * 1000 * 1000)
26#else
27#define STACK_SMASH_DEPTH ( 100 * 1000)
28#endif
29
30static int
31testInt (void)
32{
33  uint8_t buf[128];
34  int64_t val;
35  int err;
36  const uint8_t * end;
37
38  /* good int string */
39  tr_snprintf ((char*)buf, sizeof (buf), "i64e");
40  err = tr_bencParseInt (buf, buf + 4, &end, &val);
41  check_int_eq (0, err);
42  check_int_eq (64, val);
43  check ((buf + 4) ==  end);
44
45  /* missing 'e' */
46  end = NULL;
47  val = 888;
48  err = tr_bencParseInt (buf, buf + 3, &end, &val);
49  check_int_eq (EILSEQ, err);
50  check_int_eq (888, val);
51  check (end == NULL);
52
53  /* empty buffer */
54  err = tr_bencParseInt (buf, buf + 0, &end, &val);
55  check_int_eq (EILSEQ, err);
56  check_int_eq (888, val);
57  check (end == NULL);
58
59  /* bad number */
60  tr_snprintf ((char*)buf, sizeof (buf), "i6z4e");
61  err = tr_bencParseInt (buf, buf + 5, &end, &val);
62  check_int_eq (EILSEQ, err);
63  check_int_eq (888, val);
64  check (end == NULL);
65
66  /* negative number */
67  tr_snprintf ((char*)buf, sizeof (buf), "i-3e");
68  err = tr_bencParseInt (buf, buf + 4, &end, &val);
69  check_int_eq (0, err);
70  check_int_eq (-3, val);
71  check ((buf + 4) == end);
72
73  /* zero */
74  tr_snprintf ((char*)buf, sizeof (buf), "i0e");
75  err = tr_bencParseInt (buf, buf + 4, &end, &val);
76  check_int_eq (0, err);
77  check_int_eq (0, val);
78  check ((buf + 3) == end);
79
80  /* no leading zeroes allowed */
81  val = 0;
82  end = NULL;
83  tr_snprintf ((char*)buf, sizeof (buf), "i04e");
84  err = tr_bencParseInt (buf, buf + 4, &end, &val);
85  check_int_eq (EILSEQ, err);
86  check_int_eq (0, val);
87  check (NULL == end);
88
89  return 0;
90}
91
92static int
93testStr (void)
94{
95  uint8_t buf[128];
96  int err;
97  const uint8_t * end;
98  const uint8_t * str;
99  size_t len;
100
101  /* good string */
102  tr_snprintf ((char*)buf, sizeof (buf), "4:boat");
103  err = tr_bencParseStr (buf, buf + 6, &end, &str, &len);
104  check_int_eq (0, err);
105  check_int_eq (4, len);
106  check (!strncmp ((char*)str, "boat", len));
107  check (end == buf + 6);
108  str = NULL;
109  end = NULL;
110  len = 0;
111
112  /* string goes past end of buffer */
113  err = tr_bencParseStr (buf, buf + 5, &end, &str, &len);
114  check_int_eq (EILSEQ, err);
115  check_int_eq (0, len);
116  check (str == NULL);
117  check (end == NULL);
118  check (!len);
119
120  /* empty string */
121  tr_snprintf ((char*)buf, sizeof (buf), "0:");
122  err = tr_bencParseStr (buf, buf + 2, &end, &str, &len);
123  check_int_eq (0, err);
124  check_int_eq (0, len);
125  check (!*str);
126  check (end == buf + 2);
127  str = NULL;
128  end = NULL;
129  len = 0;
130
131  /* short string */
132  tr_snprintf ((char*)buf, sizeof (buf), "3:boat");
133  err = tr_bencParseStr (buf, buf + 6, &end, &str, &len);
134  check_int_eq (0, err);
135  check_int_eq (3, len);
136  check (!strncmp ((char*)str, "boa", len));
137  check (end == buf + 5);
138  str = NULL;
139  end = NULL;
140  len = 0;
141
142  return 0;
143}
144
145static int
146testString (const char * str, bool isGood)
147{
148  tr_variant val;
149  const char * end = NULL;
150  char * saved;
151  const size_t    len = strlen (str);
152  int savedLen;
153  int err;
154
155  err = tr_variantFromBencFull (&val, str, len, NULL, &end);
156
157  if (!isGood)
158    {
159      check (err);
160    }
161  else
162    {
163      check (!err);
164#if 0
165      fprintf (stderr, "in: [%s]\n", str);
166      fprintf (stderr, "out:\n%s", tr_variantToStr (&val, TR_VARIANT_FMT_JSON, NULL));
167#endif
168      check (end == str + len);
169      saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &savedLen);
170      check_streq (str, saved);
171      check_int_eq (savedLen, len);
172      tr_free (saved);
173      tr_variantFree (&val);
174    }
175
176  return 0;
177}
178
179static int
180testParse (void)
181{
182  tr_variant val;
183  tr_variant * child;
184  tr_variant * child2;
185  char buf[512];
186  const char * end;
187  int err;
188  int len;
189  int64_t i;
190  char * saved;
191
192  tr_snprintf ((char*)buf, sizeof (buf), "i64e");
193  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
194  check (!err);
195  check (tr_variantGetInt (&val, &i));
196  check_int_eq (64, i);
197  check (end == buf + 4);
198  tr_variantFree (&val);
199
200  tr_snprintf ((char*)buf, sizeof (buf), "li64ei32ei16ee");
201  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
202  check (!err);
203  check (end == buf + strlen ((char*)buf));
204  check (val.val.l.count == 3);
205  check (tr_variantGetInt (&val.val.l.vals[0], &i));
206  check_int_eq (64, i);
207  check (tr_variantGetInt (&val.val.l.vals[1], &i));
208  check_int_eq (32, i);
209  check (tr_variantGetInt (&val.val.l.vals[2], &i));
210  check_int_eq (16, i);
211  saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &len);
212  check_streq ((char*)buf, saved);
213  tr_free (saved);
214  tr_variantFree (&val);
215
216  end = NULL;
217  tr_snprintf ((char*)buf, sizeof (buf), "lllee");
218  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
219  check (err);
220  check (end == NULL);
221
222  end = NULL;
223  tr_snprintf ((char*)buf, sizeof (buf), "le");
224  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
225  check (!err);
226  check (end == buf + 2);
227  saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &len);
228  check_streq ("le", saved);
229  tr_free (saved);
230  tr_variantFree (&val);
231
232  if ((err = testString ("llleee", true)))
233    return err;
234  if ((err = testString ("d3:cow3:moo4:spam4:eggse", true)))
235    return err;
236  if ((err = testString ("d4:spaml1:a1:bee", true)))
237    return err;
238  if ((err = testString ("d5:greenli1ei2ei3ee4:spamd1:ai123e3:keyi214eee", true)))
239    return err;
240  if ((err = testString ("d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee", true)))
241    return err;
242  if ((err = testString ("d8:completei1e8:intervali1800e12:min intervali1800e5:peers0:e", true)))
243    return err;
244  if ((err = testString ("d1:ai0e1:be", false))) /* odd number of children */
245    return err;
246  if ((err = testString ("", false)))
247    return err;
248  if ((err = testString (" ", false)))
249    return err;
250
251  /* nested containers
252   * parse an unsorted dict
253   * save as a sorted dict */
254  end = NULL;
255  tr_snprintf ((char*)buf, sizeof (buf), "lld1:bi32e1:ai64eeee");
256  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
257  check (!err);
258  check (end == buf + strlen ((const char*)buf));
259  check ((child = tr_variantListChild (&val, 0)));
260  check ((child2 = tr_variantListChild (child, 0)));
261  saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &len);
262  check_streq ("lld1:ai64e1:bi32eeee", saved);
263  tr_free (saved);
264  tr_variantFree (&val);
265
266  /* too many endings */
267  end = NULL;
268  tr_snprintf ((char*)buf, sizeof (buf), "leee");
269  err = tr_variantFromBencFull (&val, buf, sizeof(buf), NULL, &end);
270  check (!err);
271  check (end == buf + 2);
272  saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &len);
273  check_streq ("le", saved);
274  tr_free (saved);
275  tr_variantFree (&val);
276
277  /* no ending */
278  end = NULL;
279  tr_snprintf ((char*)buf, sizeof (buf), "l1:a1:b1:c");
280  err = tr_variantFromBencFull (&val, buf, strlen(buf), NULL, &end);
281  check (err);
282
283  /* incomplete string */
284  end = NULL;
285  tr_snprintf ((char*)buf, sizeof (buf), "1:");
286  err = tr_variantFromBencFull (&val, buf, strlen(buf), NULL, &end);
287  check (err);
288
289  return 0;
290}
291
292static void
293stripWhitespace (char * in)
294{
295  char * out;
296
297  for (out=in; in && *in; ++in)
298    if (!isspace (*in))
299      *out++ = *in;
300
301  *out = '\0';
302}
303
304static int
305testJSONSnippet (const char * benc_str,
306                 const char * expected)
307{
308  tr_variant top;
309  char * serialized;
310  struct evbuffer * buf;
311
312  tr_variantFromBenc (&top, benc_str, strlen(benc_str));
313  buf = tr_variantToBuf (&top, TR_VARIANT_FMT_JSON);
314  serialized = (char*) evbuffer_pullup (buf, -1);
315  stripWhitespace (serialized);
316#if 0
317  fprintf (stderr, "benc: %s\n", benc_str);
318  fprintf (stderr, "json: %s\n", serialized);
319  fprintf (stderr, "want: %s\n", expected);
320#endif
321  check_streq (expected, serialized);
322  tr_variantFree (&top);
323  evbuffer_free (buf);
324  return 0;
325}
326
327static int
328testJSON (void)
329{
330  int val;
331  const char * benc_str;
332  const char * expected;
333
334  benc_str = "i6e";
335  expected = "6";
336  if ((val = testJSONSnippet (benc_str, expected)))
337    return val;
338
339  benc_str = "d5:helloi1e5:worldi2ee";
340  expected = "{\"hello\":1,\"world\":2}";
341  if ((val = testJSONSnippet (benc_str, expected)))
342    return val;
343
344  benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3eee";
345  expected = "{\"foo\":[1,2,3],\"hello\":1,\"world\":2}";
346  if ((val = testJSONSnippet (benc_str, expected)))
347    return val;
348
349  benc_str = "d5:helloi1e5:worldi2e3:fooli1ei2ei3ed1:ai0eeee";
350  expected = "{\"foo\":[1,2,3,{\"a\":0}],\"hello\":1,\"world\":2}";
351  if ((val = testJSONSnippet (benc_str, expected)))
352    return val;
353
354  benc_str = "d4:argsd6:statusle7:status2lee6:result7:successe";
355  expected = "{\"args\":{\"status\":[],\"status2\":[]},\"result\":\"success\"}";
356  if ((val = testJSONSnippet (benc_str, expected)))
357    return val;
358
359  return 0;
360}
361
362static int
363testMerge (void)
364{
365  size_t len;
366  tr_variant dest, src;
367  int64_t i;
368  const char * s;
369  const tr_quark i1 = tr_quark_new ("i1", 2);
370  const tr_quark i2 = tr_quark_new ("i2", 2);
371  const tr_quark i3 = tr_quark_new ("i3", 2);
372  const tr_quark i4 = tr_quark_new ("i4", 2);
373  const tr_quark s5 = tr_quark_new ("s5", 2);
374  const tr_quark s6 = tr_quark_new ("s6", 2);
375  const tr_quark s7 = tr_quark_new ("s7", 2);
376  const tr_quark s8 = tr_quark_new ("s8", 2);
377
378  /* initial dictionary (default values)  */
379  tr_variantInitDict (&dest, 10);
380  tr_variantDictAddInt (&dest, i1, 1);
381  tr_variantDictAddInt (&dest, i2, 2);
382  tr_variantDictAddInt (&dest, i4, -35); /* remains untouched */
383  tr_variantDictAddStr (&dest, s5, "abc");
384  tr_variantDictAddStr (&dest, s6, "def");
385  tr_variantDictAddStr (&dest, s7, "127.0.0.1"); /* remains untouched */
386
387  /* new dictionary, will overwrite items in dest  */
388  tr_variantInitDict (&src, 10);
389  tr_variantDictAddInt (&src, i1, 1);     /* same value */
390  tr_variantDictAddInt (&src, i2, 4);     /* new value */
391  tr_variantDictAddInt (&src, i3, 3);     /* new key:value */
392  tr_variantDictAddStr (&src, s5, "abc"); /* same value */
393  tr_variantDictAddStr (&src, s6, "xyz"); /* new value */
394  tr_variantDictAddStr (&src, s8, "ghi"); /* new key:value */
395
396  tr_variantMergeDicts (&dest, /*const*/ &src);
397
398  check (tr_variantDictFindInt (&dest, i1, &i));
399  check_int_eq (1, i);
400  check (tr_variantDictFindInt (&dest, i2, &i));
401  check_int_eq (4, i);
402  check (tr_variantDictFindInt (&dest, i3, &i));
403  check_int_eq (3, i);
404  check (tr_variantDictFindInt (&dest, i4, &i));
405  check_int_eq (-35, i);
406  check (tr_variantDictFindStr (&dest, s5, &s, &len));
407  check_int_eq (3, len);
408  check_streq ("abc", s);
409  check (tr_variantDictFindStr (&dest, s6, &s, &len));
410  check_int_eq (3, len);
411  check_streq ("xyz", s);
412  check (tr_variantDictFindStr (&dest, s7, &s,  &len));
413  check_int_eq (9, len);
414  check_streq ("127.0.0.1", s);
415  check (tr_variantDictFindStr (&dest, s8, &s, &len));
416  check_int_eq (3, len);
417  check_streq ("ghi", s);
418
419  tr_variantFree (&dest);
420  tr_variantFree (&src);
421  return 0;
422}
423
424static int
425testStackSmash (void)
426{
427  int i;
428  int len;
429  int err;
430  char * in;
431  const char * end;
432  tr_variant val;
433  char * saved;
434  const int depth = STACK_SMASH_DEPTH;
435
436  in = tr_new (char, depth * 2 + 1);
437  for (i = 0; i < depth; ++i)
438    {
439      in[i] = 'l';
440      in[depth + i] = 'e';
441    }
442  in[depth * 2] = '\0';
443  err = tr_variantFromBencFull (&val, in, depth*2, NULL, &end);
444  check_int_eq (0, err);
445  check (end == in + (depth * 2));
446  saved = tr_variantToStr (&val, TR_VARIANT_FMT_BENC, &len);
447  check_streq ((char*)in, saved);
448  tr_free (in);
449  tr_free (saved);
450  tr_variantFree (&val);
451
452  return 0;
453}
454
455static int
456testBool (void)
457{
458  tr_variant top;
459  int64_t intVal;
460  bool boolVal;
461  const tr_quark key1 = tr_quark_new ("key1", 4);
462  const tr_quark key2 = tr_quark_new ("key2", 4);
463  const tr_quark key3 = tr_quark_new ("key3", 4);
464  const tr_quark key4 = tr_quark_new ("key4", 4);
465
466  tr_variantInitDict (&top, 0);
467
468  tr_variantDictAddBool (&top, key1, false);
469  tr_variantDictAddBool (&top, key2, 0);
470  tr_variantDictAddInt  (&top, key3, true);
471  tr_variantDictAddInt  (&top, key4, 1);
472  check (tr_variantDictFindBool (&top, key1, &boolVal));
473  check (!boolVal);
474  check (tr_variantDictFindBool (&top, key2, &boolVal));
475  check (!boolVal);
476  check (tr_variantDictFindBool (&top, key3, &boolVal));
477  check (boolVal);
478  check (tr_variantDictFindBool (&top, key4, &boolVal));
479  check (boolVal);
480  check (tr_variantDictFindInt (&top, key1, &intVal));
481  check (!intVal);
482  check (tr_variantDictFindInt (&top, key2, &intVal));
483  check (!intVal);
484  check (tr_variantDictFindInt (&top, key3, &intVal));
485  check (intVal);
486  check (tr_variantDictFindInt (&top, key4, &intVal));
487  check (intVal);
488
489  tr_variantFree (&top);
490  return 0;
491}
492
493static int
494testParse2 (void)
495{
496  tr_variant top;
497  tr_variant top2;
498  int64_t intVal;
499  const char * strVal;
500  double realVal;
501  bool boolVal;
502  int len;
503  char * benc;
504  const char * end;
505  size_t strLen;
506  const tr_quark key_bool = tr_quark_new ("this-is-a-bool", -1);
507  const tr_quark key_real = tr_quark_new ("this-is-a-real", -1);
508  const tr_quark key_int  = tr_quark_new ("this-is-an-int", -1);
509  const tr_quark key_str  = tr_quark_new ("this-is-a-string", -1);
510
511  tr_variantInitDict (&top, 0);
512  tr_variantDictAddBool (&top, key_bool, true);
513  tr_variantDictAddInt  (&top, key_int,  1234);
514  tr_variantDictAddReal (&top, key_real, 0.5);
515  tr_variantDictAddStr  (&top, key_str, "this-is-a-string");
516
517  benc = tr_variantToStr (&top, TR_VARIANT_FMT_BENC, &len);
518  check_streq ("d14:this-is-a-booli1e14:this-is-a-real8:0.50000016:this-is-a-string16:this-is-a-string14:this-is-an-inti1234ee", benc);
519  check (!tr_variantFromBencFull (&top2, benc, len, NULL, &end));
520  check (end == benc + len);
521  check (tr_variantIsDict (&top2));
522  check (tr_variantDictFindInt (&top, key_int, &intVal));
523  check_int_eq (1234, intVal);
524  check (tr_variantDictFindBool (&top, key_bool, &boolVal));
525  check (boolVal == true);
526  check (tr_variantDictFindStr (&top, key_str, &strVal, &strLen));
527  check_int_eq (16, strLen);
528  check_streq ("this-is-a-string", strVal);
529  check (tr_variantDictFindReal (&top, key_real, &realVal));
530  check_int_eq (50, (int)(realVal*100));
531
532  tr_variantFree (&top2);
533  tr_free (benc);
534  tr_variantFree (&top);
535
536  return 0;
537}
538
539int
540main (void)
541{
542  static const testFunc tests[] = { testInt,
543                                    testStr,
544                                    testParse,
545                                    testJSON,
546                                    testMerge,
547                                    testBool,
548                                    testParse2,
549                                    testStackSmash };
550  return runTests (tests, NUM_TESTS (tests));
551}
Note: See TracBrowser for help on using the repository browser.