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

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

separate out the sandbox code so that test sandboxes can be created without a tr_session

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