source: trunk/libtransmission/watchdir-test.c

Last change on this file was 14721, checked in by jordan, 5 years ago

fix a handful of minor compiler warnings, mostly in the unit tests, eg field width shortening or implicit signed/unsigned conversions

  • Property svn:keywords set to Date Rev Author Id
File size: 9.7 KB
Line 
1/*
2 * This file Copyright (C) 2015-2016 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: watchdir-test.c 14721 2016-03-29 03:04:54Z mikedld $
8 */
9
10#include <event2/event.h>
11
12#include "transmission.h"
13#include "file.h"
14#include "net.h"
15#include "utils.h"
16#include "watchdir.h"
17
18#include "libtransmission-test.h"
19
20/***
21****
22***/
23
24typedef struct callback_data
25{
26  tr_watchdir_t        dir;
27  char               * name;
28  tr_watchdir_status   result;
29}
30callback_data;
31
32#define CB_DATA_STATIC_INIT { NULL, NULL, 0 }
33
34static struct event_base * ev_base = NULL;
35
36extern struct timeval tr_watchdir_generic_interval;
37extern unsigned int   tr_watchdir_retry_limit;
38extern struct timeval tr_watchdir_retry_start_interval;
39extern struct timeval tr_watchdir_retry_max_interval;
40
41static const struct timeval FIFTY_MSEC       = { 0,  50000 };
42static const struct timeval ONE_HUNDRED_MSEC = { 0, 100000 };
43static const struct timeval TWO_HUNDRED_MSEC = { 0, 200000 };
44
45static void
46process_events (void)
47{
48  event_base_loopexit (ev_base, &TWO_HUNDRED_MSEC);
49  event_base_dispatch (ev_base);
50}
51
52static tr_watchdir_status
53callback (tr_watchdir_t   dir,
54          const char    * name,
55          void          * context)
56{
57  callback_data * const data = context;
58
59  if (data->result != TR_WATCHDIR_RETRY)
60    {
61      data->dir = dir;
62
63      if (data->name != NULL)
64        tr_free (data->name);
65      data->name = tr_strdup (name);
66    }
67
68  return data->result;
69}
70
71static void
72reset_callback_data (callback_data      * data,
73                     tr_watchdir_status   result)
74{
75  tr_free (data->name);
76
77  data->dir = NULL;
78  data->name = NULL;
79  data->result = result;
80}
81
82static void
83create_file (const char * parent_dir,
84             const char * name)
85{
86  char * const path = tr_buildPath (parent_dir, name, NULL);
87  libtest_create_file_with_string_contents (path, "");
88  tr_free (path);
89}
90
91static void
92create_dir (const char * parent_dir,
93            const char * name)
94{
95  char * const path = tr_buildPath (parent_dir, name, NULL);
96  tr_sys_dir_create (path, 0, 0700, NULL);
97  tr_free (path);
98}
99
100static tr_watchdir_t
101create_watchdir (const char        * path,
102                 tr_watchdir_cb      callback,
103                 void              * callback_user_data,
104                 struct event_base * event_base)
105{
106#ifdef WATCHDIR_TEST_FORCE_GENERIC
107  const bool force_generic = true;
108#else
109  const bool force_generic = false;
110#endif
111
112  return tr_watchdir_new (path, callback, callback_user_data, event_base, force_generic);
113}
114
115/***
116****
117***/
118
119static int
120test_construct (void)
121{
122  char * const test_dir = libtest_sandbox_create ();
123  tr_watchdir_t wd;
124
125  ev_base = event_base_new();
126
127  wd = create_watchdir (test_dir, &callback, NULL, ev_base);
128  check (wd != NULL);
129  check (tr_sys_path_is_same (test_dir, tr_watchdir_get_path (wd), NULL));
130
131  tr_watchdir_free (wd);
132
133  event_base_free (ev_base);
134
135  libtest_sandbox_destroy (test_dir);
136  tr_free (test_dir);
137  return 0;
138}
139
140static int
141test_initial_scan (void)
142{
143  char * const test_dir = libtest_sandbox_create ();
144
145  ev_base = event_base_new();
146
147  /* Speed up generic implementation */
148  tr_watchdir_generic_interval = ONE_HUNDRED_MSEC;
149
150  {
151    callback_data wd_data = CB_DATA_STATIC_INIT;
152    reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
153
154    tr_watchdir_t wd = create_watchdir (test_dir, &callback, &wd_data, ev_base);
155    check (wd != NULL);
156
157    process_events ();
158    check_ptr_eq (NULL, wd_data.dir);
159    check_ptr_eq (NULL, wd_data.name);
160
161    tr_watchdir_free (wd);
162    reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
163  }
164
165  create_file (test_dir, "test");
166
167  {
168    callback_data wd_data = CB_DATA_STATIC_INIT;
169    reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
170
171    tr_watchdir_t wd = create_watchdir (test_dir, &callback, &wd_data, ev_base);
172    check (wd != NULL);
173
174    process_events ();
175    check_ptr_eq (wd, wd_data.dir);
176    check_streq ("test", wd_data.name);
177
178    tr_watchdir_free (wd);
179    reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
180  }
181
182  event_base_free (ev_base);
183
184  libtest_sandbox_destroy (test_dir);
185  tr_free (test_dir);
186  return 0;
187}
188
189static int
190test_watch (void)
191{
192  char * const test_dir = libtest_sandbox_create ();
193  callback_data wd_data = CB_DATA_STATIC_INIT;
194  tr_watchdir_t wd;
195
196  ev_base = event_base_new();
197
198  /* Speed up generic implementation */
199  tr_watchdir_generic_interval = ONE_HUNDRED_MSEC;
200
201  reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
202  wd = create_watchdir (test_dir, &callback, &wd_data, ev_base);
203  check (wd != NULL);
204
205  process_events ();
206  check_ptr_eq (NULL, wd_data.dir);
207  check_ptr_eq (NULL, wd_data.name);
208
209  create_file (test_dir, "test");
210
211  process_events ();
212  check_ptr_eq (wd, wd_data.dir);
213  check_streq ("test", wd_data.name);
214
215  reset_callback_data (&wd_data, TR_WATCHDIR_IGNORE);
216  create_file (test_dir, "test2");
217
218  process_events ();
219  check_ptr_eq (wd, wd_data.dir);
220  check_streq ("test2", wd_data.name);
221
222  reset_callback_data (&wd_data, TR_WATCHDIR_IGNORE);
223  create_dir (test_dir, "test3");
224
225  process_events ();
226  check_ptr_eq (NULL, wd_data.dir);
227  check_ptr_eq (NULL, wd_data.name);
228
229  tr_watchdir_free (wd);
230  reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
231
232  event_base_free (ev_base);
233
234  libtest_sandbox_destroy (test_dir);
235  tr_free (test_dir);
236  return 0;
237}
238
239static int
240test_watch_two_dirs (void)
241{
242  char * const test_dir = libtest_sandbox_create ();
243  char * const dir1 = tr_buildPath (test_dir, "a", NULL);
244  char * const dir2 = tr_buildPath (test_dir, "b", NULL);
245  callback_data wd1_data = CB_DATA_STATIC_INIT, wd2_data = CB_DATA_STATIC_INIT;
246  tr_watchdir_t wd1, wd2;
247
248  ev_base = event_base_new();
249
250  /* Speed up generic implementation */
251  tr_watchdir_generic_interval = ONE_HUNDRED_MSEC;
252
253  create_dir (dir1, NULL);
254  create_dir (dir2, NULL);
255
256  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
257  wd1 = create_watchdir (dir1, &callback, &wd1_data, ev_base);
258  check (wd1 != NULL);
259
260  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
261  wd2 = create_watchdir (dir2, &callback, &wd2_data, ev_base);
262  check (wd2 != NULL);
263
264  process_events ();
265  check_ptr_eq (NULL, wd1_data.dir);
266  check_ptr_eq (NULL, wd1_data.name);
267  check_ptr_eq (NULL, wd2_data.dir);
268  check_ptr_eq (NULL, wd2_data.name);
269
270  create_file (dir1, "test");
271
272  process_events ();
273  check_ptr_eq (wd1, wd1_data.dir);
274  check_streq ("test", wd1_data.name);
275  check_ptr_eq (NULL, wd2_data.dir);
276  check_ptr_eq (NULL, wd2_data.name);
277
278  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
279  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
280  create_file (dir2, "test2");
281
282  process_events ();
283  check_ptr_eq (NULL, wd1_data.dir);
284  check_ptr_eq (NULL, wd1_data.name);
285  check_ptr_eq (wd2, wd2_data.dir);
286  check_streq ("test2", wd2_data.name);
287
288  reset_callback_data (&wd1_data, TR_WATCHDIR_IGNORE);
289  reset_callback_data (&wd2_data, TR_WATCHDIR_IGNORE);
290  create_file (dir1, "test3");
291  create_file (dir2, "test4");
292
293  process_events ();
294  check_ptr_eq (wd1, wd1_data.dir);
295  check_streq ("test3", wd1_data.name);
296  check_ptr_eq (wd2, wd2_data.dir);
297  check_streq ("test4", wd2_data.name);
298
299  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
300  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
301  create_file (dir1, "test5");
302  create_dir (dir2, "test5");
303
304  process_events ();
305  check_ptr_eq (wd1, wd1_data.dir);
306  check_streq ("test5", wd1_data.name);
307  check_ptr_eq (NULL, wd2_data.dir);
308  check_ptr_eq (NULL, wd2_data.name);
309
310  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
311  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
312  create_dir (dir1, "test6");
313  create_file (dir2, "test6");
314
315  process_events ();
316  check_ptr_eq (NULL, wd1_data.dir);
317  check_ptr_eq (NULL, wd1_data.name);
318  check_ptr_eq (wd2, wd2_data.dir);
319  check_streq ("test6", wd2_data.name);
320
321  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
322  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
323  create_dir (dir1, "test7");
324  create_dir (dir2, "test7");
325
326  process_events ();
327  check_ptr_eq (NULL, wd1_data.dir);
328  check_ptr_eq (NULL, wd1_data.name);
329  check_ptr_eq (NULL, wd2_data.dir);
330  check_ptr_eq (NULL, wd2_data.name);
331
332  tr_watchdir_free (wd2);
333  reset_callback_data (&wd2_data, TR_WATCHDIR_ACCEPT);
334
335  tr_watchdir_free (wd1);
336  reset_callback_data (&wd1_data, TR_WATCHDIR_ACCEPT);
337
338  event_base_free (ev_base);
339
340  tr_free (dir2);
341  tr_free (dir1);
342  libtest_sandbox_destroy (test_dir);
343  tr_free (test_dir);
344  return 0;
345}
346
347static int
348test_retry (void)
349{
350  char * const test_dir = libtest_sandbox_create ();
351  callback_data wd_data = CB_DATA_STATIC_INIT;
352  tr_watchdir_t wd;
353
354  ev_base = event_base_new();
355
356  /* Speed up generic implementation */
357  tr_watchdir_generic_interval = ONE_HUNDRED_MSEC;
358
359  /* Tune retry logic */
360  tr_watchdir_retry_limit = 10;
361  tr_watchdir_retry_start_interval = FIFTY_MSEC;
362  tr_watchdir_retry_max_interval = tr_watchdir_retry_start_interval;
363
364  reset_callback_data (&wd_data, TR_WATCHDIR_RETRY);
365  wd = create_watchdir (test_dir, &callback, &wd_data, ev_base);
366  check (wd != NULL);
367
368  process_events ();
369  check_ptr_eq (NULL, wd_data.dir);
370  check_ptr_eq (NULL, wd_data.name);
371
372  create_file (test_dir, "test");
373
374  process_events ();
375  check_ptr_eq (NULL, wd_data.dir);
376  check_ptr_eq (NULL, wd_data.name);
377
378  reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
379
380  process_events ();
381  check_ptr_eq (wd, wd_data.dir);
382  check_streq ("test", wd_data.name);
383
384  tr_watchdir_free (wd);
385  reset_callback_data (&wd_data, TR_WATCHDIR_ACCEPT);
386
387  event_base_free (ev_base);
388
389  libtest_sandbox_destroy (test_dir);
390  tr_free (test_dir);
391  return 0;
392}
393
394/***
395****
396***/
397
398int
399main (void)
400{
401  const testFunc tests[] = { test_construct,
402                             test_initial_scan,
403                             test_watch,
404                             test_watch_two_dirs,
405                             test_retry };
406
407  tr_net_init ();
408
409  return runTests (tests, NUM_TESTS (tests));
410}
Note: See TracBrowser for help on using the repository browser.