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

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

(trunk, libt) #4160 - the slow slog to catch trunk up to mike.dld's 4160 diff continues. This step applies 4160-03b-file.patch, which replaces native file operations with the tr_sys_file_*() portability wrappers added in r14321.

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