~ubuntu-branches/ubuntu/oneiric/gconf/oneiric-proposed

« back to all changes in this revision

Viewing changes to tests/testlisteners.c

  • Committer: Bazaar Package Importer
  • Author(s): Takuo KITAME
  • Date: 2002-03-17 01:51:39 UTC
  • Revision ID: james.westby@ubuntu.com-20020317015139-z4f8fdg1hoe049g0
Tags: upstream-1.0.9
ImportĀ upstreamĀ versionĀ 1.0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GConf
 
2
 * Copyright (C) 1999, 2000 Red Hat Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#include <gconf/gconf-listeners.h>
 
21
#include <stdio.h>
 
22
#include <unistd.h>
 
23
#include <math.h>
 
24
#include <string.h>
 
25
#include <stdlib.h>
 
26
 
 
27
static void
 
28
check(gboolean condition, const gchar* fmt, ...)
 
29
{
 
30
  va_list args;
 
31
  gchar* description;
 
32
  
 
33
  va_start (args, fmt);
 
34
  description = g_strdup_vprintf(fmt, args);
 
35
  va_end (args);
 
36
  
 
37
  if (condition)
 
38
    {
 
39
      printf(".");
 
40
      fflush(stdout);
 
41
    }
 
42
  else
 
43
    {
 
44
      fprintf(stderr, "\n*** FAILED: %s\n", description);
 
45
      exit(1);
 
46
    }
 
47
  
 
48
  g_free(description);
 
49
}
 
50
 
 
51
static const gchar*
 
52
keys[] = {
 
53
  "/testing/foo/tar",
 
54
  "/testing/foo/bar",
 
55
  "/testing/quad",
 
56
  "/testing/blah",
 
57
  "/testing/q/a/b/c/z/w/x/y/z",
 
58
  "/testing/foo/baz",
 
59
  "/testing/dup",
 
60
  "/testing/oops/bloo",
 
61
  "/testing/oops/snoo",
 
62
  "/testing/dup",
 
63
  "/testing/oops/kwoo",
 
64
  "/testing/foo/quaz",
 
65
  "/testing",
 
66
  "/testing/oops",
 
67
  "/testing/dup",
 
68
  "/",
 
69
  "/blah/blah/blah",
 
70
  "/blah/blah/foo",
 
71
  "/blah/blah/bar",
 
72
  "/boo",
 
73
  "/baz",
 
74
  "/bap",
 
75
  "/duplicate",
 
76
  "/duplicate",
 
77
  NULL
 
78
};
 
79
 
 
80
struct stuff {
 
81
  guint id;
 
82
  gchar* key;
 
83
  guint* id_retloc;
 
84
  gchar** key_retloc;
 
85
};
 
86
 
 
87
static void
 
88
test_destroy_notify(gpointer data)
 
89
{
 
90
  struct stuff* s = data;
 
91
 
 
92
  *s->id_retloc = s->id;
 
93
 
 
94
  *s->key_retloc = s->key;
 
95
 
 
96
  g_free(s);
 
97
}
 
98
 
 
99
static void
 
100
check_add_remove(GConfListeners* listeners)
 
101
{
 
102
  guint ids[128];
 
103
  guint i;
 
104
  const gchar** keyp;
 
105
  guint id_retloc;
 
106
  gchar* key_retloc;
 
107
  
 
108
  memset(ids, 0, sizeof(ids[0]) * 128);
 
109
  
 
110
  i = 0;
 
111
  keyp = keys;
 
112
 
 
113
  while (i < 128 && *keyp)
 
114
    {
 
115
      struct stuff* s;
 
116
 
 
117
      s = g_new0(struct stuff, 1);
 
118
 
 
119
      s->id_retloc = &id_retloc;
 
120
      s->key_retloc = &key_retloc;
 
121
      
 
122
      s->id = ids[i] = gconf_listeners_add(listeners,
 
123
                                           *keyp,
 
124
                                           s,
 
125
                                           test_destroy_notify);
 
126
 
 
127
      s->key = g_strdup(*keyp);
 
128
 
 
129
      check(ids[i] != 0, "invalid connection ID returned for added listener");
 
130
      
 
131
      ++i;
 
132
      ++keyp;
 
133
    }
 
134
 
 
135
  check(gconf_listeners_count(listeners) == i,
 
136
        "number of listeners added (%u) don't now exist in the GConfListeners (%u exist)", i, gconf_listeners_count(listeners));
 
137
  
 
138
  i = 0;
 
139
  keyp = keys;
 
140
 
 
141
  while (i < 128 && *keyp)
 
142
    {
 
143
      id_retloc = 0;
 
144
      key_retloc = NULL;
 
145
      
 
146
      gconf_listeners_remove(listeners, ids[i]);
 
147
 
 
148
      check(strcmp(key_retloc, *keyp) == 0,
 
149
            "listener removed has different key from listener added (`%s' vs. `%s')", *keyp, key_retloc);
 
150
 
 
151
      g_free(key_retloc);
 
152
 
 
153
      check(ids[i] == id_retloc, "listener removed had different id from that added (%u vs. %u)", ids[i], id_retloc);            
 
154
      
 
155
      ++i;
 
156
      ++keyp;
 
157
    }
 
158
 
 
159
  check(gconf_listeners_count(listeners) == 0,
 
160
        "listener count isn't 0 after removing all the listeners");
 
161
}
 
162
 
 
163
static void
 
164
check_immediate_remove_after_add(GConfListeners* listeners)
 
165
{
 
166
  guint ids[128];
 
167
  guint i;
 
168
  const gchar** keyp;
 
169
  guint id_retloc;
 
170
  gchar* key_retloc;
 
171
  
 
172
  memset(ids, 0, sizeof(ids[0]) * 128);
 
173
  
 
174
  i = 0;
 
175
  keyp = keys;
 
176
 
 
177
  while (i < 128 && *keyp)
 
178
    {
 
179
      struct stuff* s;
 
180
 
 
181
      s = g_new0(struct stuff, 1);
 
182
 
 
183
      s->id_retloc = &id_retloc;
 
184
      s->key_retloc = &key_retloc;
 
185
      
 
186
      s->id = ids[i] = gconf_listeners_add(listeners,
 
187
                                           *keyp,
 
188
                                           s,
 
189
                                           test_destroy_notify);
 
190
 
 
191
      s->key = g_strdup(*keyp);
 
192
 
 
193
      check(ids[i] != 0, "invalid connection ID returned for added listener");
 
194
 
 
195
      if (i > 0)
 
196
        {
 
197
          check((ids[i] & 0xFFFFFF) == (ids[i-1] & 0xFFFFFF), "connection ID was not properly recycled");
 
198
          check(ids[i] != ids[i-1], "connection ID was not properly uniqueized");
 
199
        }
 
200
          
 
201
      check(gconf_listeners_count(listeners) == 1,
 
202
            "didn't have 1 listener as expected");
 
203
      
 
204
      id_retloc = 0;
 
205
      key_retloc = NULL;
 
206
      
 
207
      gconf_listeners_remove(listeners, ids[i]);
 
208
 
 
209
      check(strcmp(key_retloc, *keyp) == 0,
 
210
            "listener removed has different key from listener added (`%s' vs. `%s')", *keyp, key_retloc);
 
211
 
 
212
      g_free(key_retloc);
 
213
      
 
214
      check(ids[i] == id_retloc, "listener removed had different id from that added (%u vs. %u)", ids[i], id_retloc);
 
215
 
 
216
      check(gconf_listeners_count(listeners) == 0,
 
217
            "didn't have 0 listeners as expected");
 
218
      
 
219
      ++i;
 
220
      ++keyp;
 
221
    }
 
222
  
 
223
  check(gconf_listeners_count(listeners) == 0,
 
224
        "listener count isn't 0 after removing all the listeners");
 
225
}
 
226
 
 
227
static void
 
228
check_double_add_remove(GConfListeners* listeners)
 
229
{
 
230
  guint ids[128];
 
231
  guint i;
 
232
  const gchar** keyp;
 
233
  guint id_retloc;
 
234
  gchar* key_retloc;
 
235
  
 
236
  memset(ids, 0, sizeof(ids[0]) * 128);
 
237
  
 
238
  i = 0;
 
239
  keyp = keys;
 
240
 
 
241
  while (i < 128 && *keyp)
 
242
    {
 
243
      struct stuff* s;
 
244
 
 
245
      s = g_new0(struct stuff, 1);
 
246
 
 
247
      s->id_retloc = &id_retloc;
 
248
      s->key_retloc = &key_retloc;
 
249
      
 
250
      s->id = ids[i] = gconf_listeners_add(listeners,
 
251
                                           *keyp,
 
252
                                           s,
 
253
                                           test_destroy_notify);
 
254
 
 
255
      s->key = g_strdup(*keyp);
 
256
 
 
257
      check(ids[i] != 0, "invalid connection ID returned for added listener");
 
258
      
 
259
      ++i;
 
260
      if ((i % 2) == 0)
 
261
        ++keyp;
 
262
    }
 
263
 
 
264
  check(gconf_listeners_count(listeners) == i,
 
265
        "number of listeners added (%u) don't now exist in the GConfListeners (%u exist)", i, gconf_listeners_count(listeners));
 
266
  
 
267
  i = 0;
 
268
  keyp = keys;
 
269
 
 
270
  while (i < 128 && *keyp)
 
271
    {
 
272
      id_retloc = 0;
 
273
      key_retloc = NULL;
 
274
      
 
275
      gconf_listeners_remove(listeners, ids[i]);
 
276
 
 
277
      check(strcmp(key_retloc, *keyp) == 0,
 
278
            "listener removed has different key from listener added (`%s' vs. `%s')", *keyp, key_retloc);
 
279
 
 
280
      g_free(key_retloc);
 
281
 
 
282
      check(ids[i] == id_retloc, "listener removed had different id from that added (%u vs. %u)", ids[i], id_retloc);            
 
283
      
 
284
      ++i;
 
285
      if ((i % 2) == 0)
 
286
        ++keyp;
 
287
    }
 
288
 
 
289
  check(gconf_listeners_count(listeners) == 0,
 
290
        "listener count isn't 0 after removing all the listeners");
 
291
}
 
292
 
 
293
static gboolean
 
294
should_be_notified(const gchar* changed_key,
 
295
                   const gchar* listener_watchpoint)
 
296
{
 
297
  return strncmp(changed_key, listener_watchpoint, strlen(listener_watchpoint)) == 0;
 
298
}
 
299
 
 
300
struct notify_data {
 
301
  const gchar* notify_key;
 
302
  GSList* notified;
 
303
};
 
304
 
 
305
void
 
306
notify_callback(GConfListeners* listeners,
 
307
                const gchar* all_above_key,
 
308
                guint cnxn_id,
 
309
                gpointer listener_data,
 
310
                gpointer user_data)
 
311
{
 
312
  struct notify_data* nd = user_data;
 
313
  struct stuff* s = listener_data;
 
314
  
 
315
  check(strcmp(all_above_key, nd->notify_key) == 0,        "notify key `%s' is not the notify key received in callback `%s'",
 
316
        nd->notify_key, all_above_key);
 
317
 
 
318
  check(cnxn_id == s->id,
 
319
        "listener ID is wrong in callback (%u vs. %u)",
 
320
        cnxn_id, s->id);
 
321
  
 
322
  check(should_be_notified(all_above_key, s->key),
 
323
        "listener %u at `%s' shouldn't have been notified of change to `%s'",
 
324
        s->id, s->key, all_above_key);
 
325
 
 
326
  nd->notified = g_slist_prepend(nd->notified, s);
 
327
}
 
328
 
 
329
void
 
330
check_notification(GConfListeners* listeners)
 
331
{
 
332
  guint ids[128];
 
333
  guint i;
 
334
  const gchar** keyp;
 
335
  guint id_retloc;
 
336
  gchar* key_retloc;
 
337
  
 
338
  memset(ids, 0, sizeof(ids[0]) * 128);
 
339
  
 
340
  i = 0;
 
341
  keyp = keys;
 
342
 
 
343
  while (i < 128 && *keyp)
 
344
    {
 
345
      struct stuff* s;
 
346
 
 
347
      s = g_new0(struct stuff, 1);
 
348
 
 
349
      s->id_retloc = &id_retloc;
 
350
      s->key_retloc = &key_retloc;
 
351
      
 
352
      s->id = ids[i] = gconf_listeners_add(listeners,
 
353
                                           *keyp,
 
354
                                           s,
 
355
                                           test_destroy_notify);
 
356
 
 
357
      s->key = g_strdup(*keyp);
 
358
 
 
359
      check(ids[i] != 0, "invalid connection ID returned for added listener");
 
360
 
 
361
      /*       printf("%u added at `%s'\n", s->id, s->key); */
 
362
      
 
363
      ++i;
 
364
      ++keyp;
 
365
    }
 
366
 
 
367
  check(gconf_listeners_count(listeners) == i,
 
368
        "number of listeners added (%u) don't now exist in the GConfListeners (%u exist)", i, gconf_listeners_count(listeners));
 
369
 
 
370
  keyp = keys;
 
371
 
 
372
  while (*keyp)
 
373
    {
 
374
      GSList* tmp = NULL;
 
375
      const gchar** sub_keyp;
 
376
      struct notify_data nd = { NULL, NULL };
 
377
 
 
378
      nd.notify_key = *keyp;
 
379
      
 
380
      gconf_listeners_notify(listeners, *keyp,
 
381
                             notify_callback,
 
382
                             &nd);
 
383
      
 
384
      /* Check that the list that was notified matches
 
385
         the list that should have been */
 
386
      sub_keyp = keys;
 
387
      while (*sub_keyp)
 
388
        {
 
389
          struct stuff* s = NULL;
 
390
          gboolean should_be = should_be_notified(*keyp, *sub_keyp);
 
391
 
 
392
          tmp = nd.notified;
 
393
          while (tmp != NULL)
 
394
            {
 
395
              s = tmp->data;
 
396
              
 
397
              if (strcmp(s->key, *sub_keyp) == 0)
 
398
                break;
 
399
              
 
400
              tmp = g_slist_next(tmp);
 
401
            }
 
402
 
 
403
          if (should_be)
 
404
            {
 
405
              check (tmp != NULL, "listener at `%s' should have been notified of change to `%s' and was not", *sub_keyp, *keyp);
 
406
              s = tmp->data;
 
407
              /* remove so we can handle duplicate keys */
 
408
              nd.notified = g_slist_remove(nd.notified, tmp->data);
 
409
 
 
410
#if 0              
 
411
              g_assert(strcmp(s->key, *sub_keyp) == 0);
 
412
              printf("%u at `%s' notified properly of `%s'\n",
 
413
                     s->id, *sub_keyp, *keyp);
 
414
#endif
 
415
            }
 
416
          else
 
417
            {
 
418
              check(tmp == NULL, "listener at `%s' should not have been notified of change to `%s' but it was", *sub_keyp, *keyp);
 
419
#if 0
 
420
              printf("`%s' properly not notified of `%s'\n",
 
421
                     *sub_keyp, *keyp);
 
422
#endif
 
423
            }
 
424
          
 
425
          ++sub_keyp;
 
426
        }
 
427
 
 
428
      if (nd.notified != NULL)
 
429
        {
 
430
          GSList* tmp = nd.notified;
 
431
          while (tmp != NULL)
 
432
            {
 
433
              struct stuff* s = tmp->data;
 
434
              fprintf(stderr, "leftover: %u at `%s' notified of `%s'\n",
 
435
                      s->id, s->key, *keyp);
 
436
              tmp = g_slist_next(tmp);
 
437
            }
 
438
        }
 
439
      check (nd.notified == NULL, "superfluous listeners were notified of `%s'; perhaps listeners were notified twice?", *keyp);
 
440
      
 
441
      ++keyp;
 
442
    }
 
443
  
 
444
  i = 0;
 
445
  keyp = keys;
 
446
 
 
447
  while (i < 128 && *keyp)
 
448
    {
 
449
      id_retloc = 0;
 
450
      key_retloc = NULL;
 
451
      
 
452
      gconf_listeners_remove(listeners, ids[i]);
 
453
 
 
454
      check(strcmp(key_retloc, *keyp) == 0,
 
455
            "listener removed has different key from listener added (`%s' vs. `%s')", *keyp, key_retloc);
 
456
 
 
457
      g_free(key_retloc);
 
458
 
 
459
      check(ids[i] == id_retloc, "listener removed had different id from that added (%u vs. %u)", ids[i], id_retloc);            
 
460
      
 
461
      ++i;
 
462
      ++keyp;
 
463
    }
 
464
 
 
465
  check(gconf_listeners_count(listeners) == 0,
 
466
        "listener count isn't 0 after removing all the listeners");
 
467
}
 
468
 
 
469
struct destroy_data {
 
470
  gchar* key;
 
471
  guint* destroy_count_loc;
 
472
};
 
473
 
 
474
static void
 
475
destroy_test_destroy_notify(gpointer data)
 
476
{
 
477
  struct destroy_data* d = data;
 
478
 
 
479
  *d->destroy_count_loc += 1;
 
480
  
 
481
  g_free(d->key);
 
482
  
 
483
  g_free(d);
 
484
}
 
485
 
 
486
/* This is mostly for use with memory leak detection tools */
 
487
void
 
488
check_destroy(void)
 
489
{
 
490
  GConfListeners* listeners;
 
491
  guint ids[128];
 
492
  guint i;
 
493
  const gchar** keyp;
 
494
  guint destroy_count = 0;
 
495
  
 
496
  listeners = gconf_listeners_new();
 
497
  
 
498
  memset(ids, 0, sizeof(ids[0]) * 128);
 
499
  
 
500
  i = 0;
 
501
  keyp = keys;
 
502
 
 
503
  while (i < 128 && *keyp)
 
504
    {
 
505
      struct destroy_data* d;
 
506
 
 
507
      d = g_new0(struct destroy_data, 1);
 
508
      
 
509
      d->destroy_count_loc = &destroy_count;
 
510
      
 
511
      ids[i] = gconf_listeners_add(listeners,
 
512
                                   *keyp,
 
513
                                   d,
 
514
                                   destroy_test_destroy_notify);
 
515
 
 
516
      d->key = g_strdup(*keyp);
 
517
 
 
518
      check(ids[i] != 0, "invalid connection ID returned for added listener");
 
519
      
 
520
      ++i;
 
521
      ++keyp;
 
522
    }
 
523
 
 
524
  check(gconf_listeners_count(listeners) == i,
 
525
        "number of listeners added (%u) don't now exist in the GConfListeners (%u exist)", i, gconf_listeners_count(listeners));
 
526
 
 
527
  gconf_listeners_free(listeners);
 
528
 
 
529
  check(destroy_count == i,
 
530
        "number of listeners added (%u) doesn't match number destroyed (%u) on GConfListeners destruction", i, destroy_count);
 
531
}
 
532
 
 
533
int 
 
534
main (int argc, char** argv)
 
535
{
 
536
  GConfListeners* listeners;
 
537
 
 
538
  listeners = gconf_listeners_new();
 
539
 
 
540
  check_add_remove(listeners);
 
541
 
 
542
  g_assert(gconf_listeners_count(listeners) == 0);
 
543
  
 
544
  check_immediate_remove_after_add(listeners);
 
545
 
 
546
  g_assert(gconf_listeners_count(listeners) == 0);
 
547
  
 
548
  check_double_add_remove(listeners);
 
549
 
 
550
  g_assert(gconf_listeners_count(listeners) == 0);
 
551
  
 
552
  check_notification(listeners);
 
553
 
 
554
  g_assert(gconf_listeners_count(listeners) == 0);
 
555
  
 
556
  gconf_listeners_free(listeners);
 
557
 
 
558
  check_destroy();
 
559
  
 
560
  printf("\n");
 
561
  
 
562
  return 0;
 
563
}