source: trunk/libtransmission/libtransmission-test.c @ 14359

Last change on this file since 14359 was 14359, checked in by mikedld, 8 years ago

#4400, #5462: Move BASE64 helpers to crypto-utils

On a way to factoring out OpenSSL support to a standalone file to ease
addition of other crypto libraries support in the future, move helpers
providing BASE64 encoding and decoding to crypto-utils.{c,h}. OpenSSL-
related functionality is moved to crypto-utils-openssl.c.

Add new functions to be implemented by crypto backends:

  • tr_base64_encode_impl - encode from binary to BASE64,
  • tr_base64_decode_impl - decode from BASE64 to binary.

Change tr_base64_encode and tr_base64_decode functions to expect
non-negative input data length which is considered real and never adjusted.
To process null-terminated strings (which was achieved before by passing 0
or -1 as input data length), add new tr_base64_encode_str and
tr_base64_decode_str functions which do not accept input data length as
an argument but calculate it on their own.

  • Property svn:keywords set to Date Rev Author Id
File size: 11.9 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: libtransmission-test.c 14359 2014-12-04 19:58:34Z mikedld $
8 */
9
10#include <assert.h>
11#include <stdio.h>
12#include <stdlib.h> /* mkstemp() */
13
14#include <unistd.h>
15
16#include "transmission.h"
17#include "crypto-utils.h"
18#include "error.h"
19#include "file.h"
20#include "platform.h" /* TR_PATH_DELIMETER */
21#include "torrent.h"
22#include "trevent.h"
23#include "libtransmission-test.h"
24
25bool verbose = false;
26
27int current_test = 0;
28
29bool
30should_print (bool pass)
31{
32  if (!pass)
33    return true;
34
35  if (verbose)
36    return true;
37
38  return false;
39#ifdef VERBOSE
40  return true;
41#else
42  return false;
43#endif
44}
45
46bool
47check_condition_impl (const char * file, int line, bool condition)
48{
49  const bool pass = condition;
50
51  if (should_print (pass))
52    fprintf (stderr, "%s %s:%d\n", pass?"PASS":"FAIL", file, line);
53
54  return pass;
55}
56
57bool
58check_streq_impl (const char * file, int line, const char * expected, const char * actual)
59{
60  const bool pass = !tr_strcmp0 (expected, actual);
61
62  if (should_print (pass)) {
63    if (pass)
64      fprintf (stderr, "PASS %s:%d\n", file, line);
65    else
66      fprintf (stderr, "FAIL %s:%d, expected \"%s\", got \"%s\"\n", file, line, expected?expected:" (null)", actual?actual:" (null)");
67  }
68
69  return pass;
70}
71
72bool
73check_int_eq_impl (const char * file, int line, int64_t expected, int64_t actual)
74{
75  const bool pass = expected == actual;
76
77  if (should_print (pass)) {
78    if (pass)
79      fprintf (stderr, "PASS %s:%d\n", file, line);
80    else
81      fprintf (stderr, "FAIL %s:%d, expected \"%"PRId64"\", got \"%"PRId64"\"\n", file, line, expected, actual);
82  }
83
84  return pass;
85}
86
87bool
88check_ptr_eq_impl (const char * file, int line, const void * expected, const void * actual)
89{
90  const bool pass = expected == actual;
91
92  if (should_print (pass)) {
93    if (pass)
94      fprintf (stderr, "PASS %s:%d\n", file, line);
95    else
96      fprintf (stderr, "FAIL %s:%d, expected \"%p\", got \"%p\"\n", file, line, expected, actual);
97  }
98
99  return pass;
100}
101
102int
103runTests (const testFunc * const tests, int numTests)
104{
105  int i;
106  int ret;
107
108  (void) current_test; /* Use test even if we don't have any tests to run */
109
110  for (i=0; i<numTests; i++)
111    if ((ret = (*tests[i])()))
112      return ret;
113
114  return 0; /* All tests passed */
115}
116
117/***
118****
119***/
120
121#include <unistd.h> /* sync() */
122
123#include <errno.h>
124#include <string.h> /* strcmp() */
125
126#include "variant.h"
127
128/***
129****
130***/
131
132static char*
133tr_getcwd (void)
134{
135  char * result;
136  tr_error * error = NULL;
137
138  result = tr_sys_dir_get_current (&error);
139
140  if (result == NULL)
141    {
142      fprintf (stderr, "getcwd error: \"%s\"", error->message);
143      tr_error_free (error);
144      result = tr_strdup ("");
145    }
146
147  return result;
148}
149
150char *
151libtest_sandbox_create (void)
152{
153  char * path = tr_getcwd ();
154  char * sandbox = tr_buildPath (path, "sandbox-XXXXXX", NULL);
155  tr_free (path);
156  tr_sys_dir_create_temp (sandbox, NULL);
157  return sandbox;
158}
159
160static void
161rm_rf (const char * killme)
162{
163  tr_sys_path_info info;
164
165  if (tr_sys_path_get_info (killme, 0, &info, NULL))
166    {
167      tr_sys_dir_t odir;
168
169      if (info.type == TR_SYS_PATH_IS_DIRECTORY &&
170          (odir = tr_sys_dir_open (killme, NULL)) != TR_BAD_SYS_DIR)
171        {
172          const char * name;
173          while ((name = tr_sys_dir_read_name (odir, NULL)) != NULL)
174            {
175              if (strcmp (name, ".") != 0 && strcmp (name, "..") != 0)
176                {
177                  char * tmp = tr_buildPath (killme, name, NULL);
178                  rm_rf (tmp);
179                  tr_free (tmp);
180                }
181            }
182          tr_sys_dir_close (odir, NULL);
183        }
184
185      if (verbose)
186        fprintf (stderr, "cleanup: removing %s\n", killme);
187
188      tr_sys_path_remove (killme, NULL);
189    }
190}
191
192void
193libtest_sandbox_destroy (const char * sandbox)
194{
195  rm_rf (sandbox);
196}
197
198/***
199****
200***/
201
202#define MEM_K 1024
203#define MEM_B_STR   "B"
204#define MEM_K_STR "KiB"
205#define MEM_M_STR "MiB"
206#define MEM_G_STR "GiB"
207#define MEM_T_STR "TiB"
208
209#define DISK_K 1000
210#define DISK_B_STR  "B"
211#define DISK_K_STR "kB"
212#define DISK_M_STR "MB"
213#define DISK_G_STR "GB"
214#define DISK_T_STR "TB"
215
216#define SPEED_K 1000
217#define SPEED_B_STR  "B/s"
218#define SPEED_K_STR "kB/s"
219#define SPEED_M_STR "MB/s"
220#define SPEED_G_STR "GB/s"
221#define SPEED_T_STR "TB/s"
222
223tr_session *
224libttest_session_init (tr_variant * settings)
225{
226  size_t len;
227  const char * str;
228  char * sandbox;
229  char * path;
230  tr_quark q;
231  static bool formatters_inited = false;
232  tr_session * session;
233  tr_variant local_settings;
234
235  tr_variantInitDict (&local_settings, 10);
236
237  if (settings == NULL)
238    settings = &local_settings;
239
240  sandbox = libtest_sandbox_create ();
241
242  if (!formatters_inited)
243    {
244      formatters_inited = true;
245      tr_formatter_mem_init (MEM_K, MEM_K_STR, MEM_M_STR, MEM_G_STR, MEM_T_STR);
246      tr_formatter_size_init (DISK_K,DISK_K_STR, DISK_M_STR, DISK_G_STR, DISK_T_STR);
247      tr_formatter_speed_init (SPEED_K, SPEED_K_STR, SPEED_M_STR, SPEED_G_STR, SPEED_T_STR);
248    }
249
250  /* download dir */
251  q = TR_KEY_download_dir;
252  if (tr_variantDictFindStr (settings, q, &str, &len))
253    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
254  else
255    path = tr_buildPath (sandbox, "Downloads", NULL);
256  tr_sys_dir_create (path, TR_SYS_DIR_CREATE_PARENTS, 0700, NULL);
257  tr_variantDictAddStr (settings, q, path);
258  tr_free (path);
259
260  /* incomplete dir */
261  q = TR_KEY_incomplete_dir;
262  if (tr_variantDictFindStr (settings, q, &str, &len))
263    path = tr_strdup_printf ("%s/%*.*s", sandbox, (int)len, (int)len, str);
264  else
265    path = tr_buildPath (sandbox, "Incomplete", NULL);
266  tr_variantDictAddStr (settings, q, path);
267  tr_free (path);
268
269  path = tr_buildPath (sandbox, "blocklists", NULL);
270  tr_sys_dir_create (path, TR_SYS_DIR_CREATE_PARENTS, 0700, NULL);
271  tr_free (path);
272
273  q = TR_KEY_port_forwarding_enabled;
274  if (!tr_variantDictFind (settings, q))
275    tr_variantDictAddBool (settings, q, false);
276
277  q = TR_KEY_dht_enabled;
278  if (!tr_variantDictFind (settings, q))
279    tr_variantDictAddBool (settings, q, false);
280
281  q = TR_KEY_message_level;
282  if (!tr_variantDictFind (settings, q))
283    tr_variantDictAddInt (settings, q, verbose ? TR_LOG_DEBUG : TR_LOG_ERROR);
284
285  session = tr_sessionInit ("libtransmission-test", sandbox, !verbose, settings);
286
287  tr_free (sandbox);
288  tr_variantFree (&local_settings);
289  return session;
290}
291
292void
293libttest_session_close (tr_session * session)
294{
295  char * sandbox;
296
297  sandbox = tr_strdup (tr_sessionGetConfigDir (session));
298  tr_sessionClose (session);
299  tr_logFreeQueue (tr_logGetQueue ());
300  session = NULL;
301
302  libtest_sandbox_destroy (sandbox);
303  tr_free (sandbox);
304}
305
306/***
307****
308***/
309
310tr_torrent *
311libttest_zero_torrent_init (tr_session * session)
312{
313  int err;
314  size_t metainfo_len;
315  char * metainfo;
316  const char * metainfo_base64;
317  tr_torrent * tor;
318  tr_ctor * ctor;
319
320  /*
321     1048576 files-filled-with-zeroes/1048576
322        4096 files-filled-with-zeroes/4096
323         512 files-filled-with-zeroes/512
324   */
325  metainfo_base64 =
326    "ZDg6YW5ub3VuY2UzMTpodHRwOi8vd3d3LmV4YW1wbGUuY29tL2Fubm91bmNlMTA6Y3JlYXRlZCBi"
327    "eTI1OlRyYW5zbWlzc2lvbi8yLjYxICgxMzQwNykxMzpjcmVhdGlvbiBkYXRlaTEzNTg3MDQwNzVl"
328    "ODplbmNvZGluZzU6VVRGLTg0OmluZm9kNTpmaWxlc2xkNjpsZW5ndGhpMTA0ODU3NmU0OnBhdGhs"
329    "NzoxMDQ4NTc2ZWVkNjpsZW5ndGhpNDA5NmU0OnBhdGhsNDo0MDk2ZWVkNjpsZW5ndGhpNTEyZTQ6"
330    "cGF0aGwzOjUxMmVlZTQ6bmFtZTI0OmZpbGVzLWZpbGxlZC13aXRoLXplcm9lczEyOnBpZWNlIGxl"
331    "bmd0aGkzMjc2OGU2OnBpZWNlczY2MDpRiEMYSbRhMVL9e9umo/8KT9ZCS1GIQxhJtGExUv1726aj"
332    "/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8KT9ZCS1GIQxhJtGExUv17"
333    "26aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8KT9ZCS1GIQxhJtGEx"
334    "Uv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8KT9ZCS1GIQxhJ"
335    "tGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8KT9ZCS1GI"
336    "QxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8KT9ZC"
337    "S1GIQxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9umo/8K"
338    "T9ZCS1GIQxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9e9um"
339    "o/8KT9ZCS1GIQxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRhMVL9"
340    "e9umo/8KT9ZCS1GIQxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMYSbRh"
341    "MVL9e9umo/8KT9ZCS1GIQxhJtGExUv1726aj/wpP1kJLUYhDGEm0YTFS/XvbpqP/Ck/WQktRiEMY"
342    "SbRhMVL9e9umo/8KT9ZCS1GIQxhJtGExUv1726aj/wpP1kJLOlf5A+Tz30nMBVuNM2hpV3wg/103"
343    "OnByaXZhdGVpMGVlZQ==";
344
345  /* create the torrent ctor */
346  metainfo = tr_base64_decode_str (metainfo_base64, &metainfo_len);
347  assert (metainfo != NULL);
348  assert (metainfo_len > 0);
349  assert (session != NULL);
350  ctor = tr_ctorNew (session);
351  tr_ctorSetMetainfo (ctor, (uint8_t*)metainfo, metainfo_len);
352  tr_ctorSetPaused (ctor, TR_FORCE, true);
353
354  /* create the torrent */
355  err = 0;
356  tor = tr_torrentNew (ctor, &err, NULL);
357  assert (!err);
358
359  /* cleanup */
360  tr_free (metainfo);
361  tr_ctorFree (ctor);
362  return tor;
363}
364
365void
366libttest_zero_torrent_populate (tr_torrent * tor, bool complete)
367{
368  tr_file_index_t i;
369
370  for (i=0; i<tor->info.fileCount; ++i)
371    {
372      int err;
373      uint64_t j;
374      tr_sys_file_t fd;
375      char * path;
376      char * dirname;
377      const tr_file * file = &tor->info.files[i];
378
379      if (!complete && (i==0))
380        path = tr_strdup_printf ("%s%c%s.part", tor->currentDir, TR_PATH_DELIMITER, file->name);
381      else
382        path = tr_strdup_printf ("%s%c%s", tor->currentDir, TR_PATH_DELIMITER, file->name);
383      dirname = tr_sys_path_dirname (path, NULL);
384      tr_sys_dir_create (dirname, TR_SYS_DIR_CREATE_PARENTS, 0700, NULL);
385      fd = tr_sys_file_open (path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600, NULL);
386      for (j=0; j<file->length; ++j)
387        tr_sys_file_write (fd, ((!complete) && (i==0) && (j<tor->info.pieceSize)) ? "\1" : "\0", 1, NULL, NULL);
388      tr_sys_file_close (fd, NULL);
389
390      tr_free (dirname);
391      tr_free (path);
392
393      path = tr_torrentFindFile (tor, i);
394      assert (path != NULL);
395      err = errno;
396      assert (tr_sys_path_exists (path, NULL));
397      errno = err; 
398      tr_free (path);
399    }
400
401  sync ();
402  libttest_blockingTorrentVerify (tor);
403
404  if (complete)
405    assert (tr_torrentStat(tor)->leftUntilDone == 0);
406  else
407    assert (tr_torrentStat(tor)->leftUntilDone == tor->info.pieceSize);
408}
409
410/***
411****
412***/
413
414static void
415onVerifyDone (tr_torrent * tor UNUSED, bool aborted UNUSED, void * done)
416{
417  *(bool*)done = true;
418}
419
420void
421libttest_blockingTorrentVerify (tr_torrent * tor)
422{
423  bool done = false;
424
425  assert (tor->session != NULL);
426  assert (!tr_amInEventThread (tor->session));
427
428  tr_torrentVerify (tor, onVerifyDone, &done);
429  while (!done)
430    tr_wait_msec (10);
431}
432
433static void
434build_parent_dir (const char* path)
435{
436  char * dir;
437  tr_error * error = NULL;
438  const int tmperr = errno;
439
440  dir = tr_sys_path_dirname (path, NULL);
441  tr_sys_dir_create (dir, TR_SYS_DIR_CREATE_PARENTS, 0700, &error);
442  assert (error == NULL);
443  tr_free (dir);
444
445  errno = tmperr;
446}
447
448void
449libtest_create_file_with_contents (const char* path, const void* payload, size_t n)
450{
451  tr_sys_file_t fd;
452  const int tmperr = errno;
453
454  build_parent_dir (path);
455
456  fd = tr_sys_file_open (path, TR_SYS_FILE_WRITE | TR_SYS_FILE_CREATE | TR_SYS_FILE_TRUNCATE, 0600, NULL);
457  tr_sys_file_write (fd, payload, n, NULL, NULL);
458  tr_sys_file_close (fd, NULL);
459
460  sync ();
461
462  errno = tmperr;
463}
464
465void
466libtest_create_file_with_string_contents (const char * path, const char* str)
467{
468  libtest_create_file_with_contents (path, str, strlen(str));
469}
470
471void
472libtest_create_tmpfile_with_contents (char* tmpl, const void* payload, size_t n)
473{
474  tr_sys_file_t fd;
475  const int tmperr = errno;
476  uint64_t n_left = n;
477  tr_error * error = NULL;
478
479  build_parent_dir (tmpl);
480
481  fd = tr_sys_file_open_temp (tmpl, NULL);
482  while (n_left > 0)
483    {
484      uint64_t n;
485      if (!tr_sys_file_write (fd, payload, n_left, &n, &error))
486        {
487          fprintf (stderr, "Error writing '%s': %s\n", tmpl, error->message);
488          tr_error_free (error);
489          break;
490        }
491      n_left -= n;
492    }
493  tr_sys_file_close (fd, NULL);
494
495  sync ();
496
497  errno = tmperr;
498}
Note: See TracBrowser for help on using the repository browser.