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

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

(libT) change the API signature for tr_torrentVerify() s.t. client code can be notified when the verify is finished

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