source: vendor/current/lib/talloc/testsuite.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 47.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 local testing of talloc routines.
5
6 Copyright (C) Andrew Tridgell 2004
7
8 ** NOTE! The following LGPL license applies to the talloc
9 ** library. This does NOT imply that all of Samba is released
10 ** under the LGPL
11
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
16
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
21
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
24*/
25
26#include "replace.h"
27#include "system/time.h"
28#include <talloc.h>
29
30#ifdef HAVE_PTHREAD
31#include <pthread.h>
32#endif
33
34#include <unistd.h>
35#include <sys/wait.h>
36
37#include "talloc_testsuite.h"
38
39static struct timeval timeval_current(void)
40{
41 struct timeval tv;
42 gettimeofday(&tv, NULL);
43 return tv;
44}
45
46static double timeval_elapsed(struct timeval *tv)
47{
48 struct timeval tv2 = timeval_current();
49 return (tv2.tv_sec - tv->tv_sec) +
50 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
51}
52
53#define torture_assert(test, expr, str) if (!(expr)) { \
54 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
55 test, __location__, #expr, str); \
56 return false; \
57}
58
59#define torture_assert_str_equal(test, arg1, arg2, desc) \
60 if (arg1 == NULL && arg2 == NULL) { \
61 } else if (strcmp(arg1, arg2)) { \
62 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
63 test, __location__, arg1, arg2, desc); \
64 return false; \
65 }
66
67#define CHECK_SIZE(test, ptr, tsize) do { \
68 if (talloc_total_size(ptr) != (tsize)) { \
69 printf("failed: %s [\n%s: wrong '%s' tree size: got %u expected %u\n]\n", \
70 test, __location__, #ptr, \
71 (unsigned)talloc_total_size(ptr), \
72 (unsigned)tsize); \
73 talloc_report_full(ptr, stdout); \
74 return false; \
75 } \
76} while (0)
77
78#define CHECK_BLOCKS(test, ptr, tblocks) do { \
79 if (talloc_total_blocks(ptr) != (tblocks)) { \
80 printf("failed: %s [\n%s: wrong '%s' tree blocks: got %u expected %u\n]\n", \
81 test, __location__, #ptr, \
82 (unsigned)talloc_total_blocks(ptr), \
83 (unsigned)tblocks); \
84 talloc_report_full(ptr, stdout); \
85 return false; \
86 } \
87} while (0)
88
89#define CHECK_PARENT(test, ptr, parent) do { \
90 if (talloc_parent(ptr) != (parent)) { \
91 printf("failed: %s [\n%s: '%s' has wrong parent: got %p expected %p\n]\n", \
92 test, __location__, #ptr, \
93 talloc_parent(ptr), \
94 (parent)); \
95 talloc_report_full(ptr, stdout); \
96 talloc_report_full(parent, stdout); \
97 talloc_report_full(NULL, stdout); \
98 return false; \
99 } \
100} while (0)
101
102static unsigned int test_abort_count;
103
104#if 0
105static void test_abort_fn(const char *reason)
106{
107 printf("# test_abort_fn(%s)\n", reason);
108 test_abort_count++;
109}
110
111static void test_abort_start(void)
112{
113 test_abort_count = 0;
114 talloc_set_abort_fn(test_abort_fn);
115}
116#endif
117
118static void test_abort_stop(void)
119{
120 test_abort_count = 0;
121 talloc_set_abort_fn(NULL);
122}
123
124static void test_log_stdout(const char *message)
125{
126 fprintf(stdout, "%s", message);
127}
128
129/*
130 test references
131*/
132static bool test_ref1(void)
133{
134 void *root, *p1, *p2, *ref, *r1;
135
136 printf("test: ref1\n# SINGLE REFERENCE FREE\n");
137
138 root = talloc_named_const(NULL, 0, "root");
139 p1 = talloc_named_const(root, 1, "p1");
140 p2 = talloc_named_const(p1, 1, "p2");
141 talloc_named_const(p1, 1, "x1");
142 talloc_named_const(p1, 2, "x2");
143 talloc_named_const(p1, 3, "x3");
144
145 r1 = talloc_named_const(root, 1, "r1");
146 ref = talloc_reference(r1, p2);
147 talloc_report_full(root, stderr);
148
149 CHECK_BLOCKS("ref1", p1, 5);
150 CHECK_BLOCKS("ref1", p2, 1);
151 CHECK_BLOCKS("ref1", ref, 1);
152 CHECK_BLOCKS("ref1", r1, 2);
153
154 fprintf(stderr, "Freeing p2\n");
155 talloc_unlink(r1, p2);
156 talloc_report_full(root, stderr);
157
158 CHECK_BLOCKS("ref1", p1, 5);
159 CHECK_BLOCKS("ref1", p2, 1);
160 CHECK_BLOCKS("ref1", r1, 1);
161
162 fprintf(stderr, "Freeing p1\n");
163 talloc_free(p1);
164 talloc_report_full(root, stderr);
165
166 CHECK_BLOCKS("ref1", r1, 1);
167
168 fprintf(stderr, "Freeing r1\n");
169 talloc_free(r1);
170 talloc_report_full(NULL, stderr);
171
172 fprintf(stderr, "Testing NULL\n");
173 if (talloc_reference(root, NULL)) {
174 return false;
175 }
176
177 CHECK_BLOCKS("ref1", root, 1);
178
179 CHECK_SIZE("ref1", root, 0);
180
181 talloc_free(root);
182 printf("success: ref1\n");
183 return true;
184}
185
186/*
187 test references
188*/
189static bool test_ref2(void)
190{
191 void *root, *p1, *p2, *ref, *r1;
192
193 printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
194 root = talloc_named_const(NULL, 0, "root");
195 p1 = talloc_named_const(root, 1, "p1");
196 talloc_named_const(p1, 1, "x1");
197 talloc_named_const(p1, 1, "x2");
198 talloc_named_const(p1, 1, "x3");
199 p2 = talloc_named_const(p1, 1, "p2");
200
201 r1 = talloc_named_const(root, 1, "r1");
202 ref = talloc_reference(r1, p2);
203 talloc_report_full(root, stderr);
204
205 CHECK_BLOCKS("ref2", p1, 5);
206 CHECK_BLOCKS("ref2", p2, 1);
207 CHECK_BLOCKS("ref2", r1, 2);
208
209 fprintf(stderr, "Freeing ref\n");
210 talloc_unlink(r1, ref);
211 talloc_report_full(root, stderr);
212
213 CHECK_BLOCKS("ref2", p1, 5);
214 CHECK_BLOCKS("ref2", p2, 1);
215 CHECK_BLOCKS("ref2", r1, 1);
216
217 fprintf(stderr, "Freeing p2\n");
218 talloc_free(p2);
219 talloc_report_full(root, stderr);
220
221 CHECK_BLOCKS("ref2", p1, 4);
222 CHECK_BLOCKS("ref2", r1, 1);
223
224 fprintf(stderr, "Freeing p1\n");
225 talloc_free(p1);
226 talloc_report_full(root, stderr);
227
228 CHECK_BLOCKS("ref2", r1, 1);
229
230 fprintf(stderr, "Freeing r1\n");
231 talloc_free(r1);
232 talloc_report_full(root, stderr);
233
234 CHECK_SIZE("ref2", root, 0);
235
236 talloc_free(root);
237 printf("success: ref2\n");
238 return true;
239}
240
241/*
242 test references
243*/
244static bool test_ref3(void)
245{
246 void *root, *p1, *p2, *ref, *r1;
247
248 printf("test: ref3\n# PARENT REFERENCE FREE\n");
249
250 root = talloc_named_const(NULL, 0, "root");
251 p1 = talloc_named_const(root, 1, "p1");
252 p2 = talloc_named_const(root, 1, "p2");
253 r1 = talloc_named_const(p1, 1, "r1");
254 ref = talloc_reference(p2, r1);
255 talloc_report_full(root, stderr);
256
257 CHECK_BLOCKS("ref3", p1, 2);
258 CHECK_BLOCKS("ref3", p2, 2);
259 CHECK_BLOCKS("ref3", r1, 1);
260 CHECK_BLOCKS("ref3", ref, 1);
261
262 fprintf(stderr, "Freeing p1\n");
263 talloc_free(p1);
264 talloc_report_full(root, stderr);
265
266 CHECK_BLOCKS("ref3", p2, 2);
267 CHECK_BLOCKS("ref3", r1, 1);
268
269 fprintf(stderr, "Freeing p2\n");
270 talloc_free(p2);
271 talloc_report_full(root, stderr);
272
273 CHECK_SIZE("ref3", root, 0);
274
275 talloc_free(root);
276
277 printf("success: ref3\n");
278 return true;
279}
280
281/*
282 test references
283*/
284static bool test_ref4(void)
285{
286 void *root, *p1, *p2, *ref, *r1;
287
288 printf("test: ref4\n# REFERRER REFERENCE FREE\n");
289
290 root = talloc_named_const(NULL, 0, "root");
291 p1 = talloc_named_const(root, 1, "p1");
292 talloc_named_const(p1, 1, "x1");
293 talloc_named_const(p1, 1, "x2");
294 talloc_named_const(p1, 1, "x3");
295 p2 = talloc_named_const(p1, 1, "p2");
296
297 r1 = talloc_named_const(root, 1, "r1");
298 ref = talloc_reference(r1, p2);
299 talloc_report_full(root, stderr);
300
301 CHECK_BLOCKS("ref4", p1, 5);
302 CHECK_BLOCKS("ref4", p2, 1);
303 CHECK_BLOCKS("ref4", ref, 1);
304 CHECK_BLOCKS("ref4", r1, 2);
305
306 fprintf(stderr, "Freeing r1\n");
307 talloc_free(r1);
308 talloc_report_full(root, stderr);
309
310 CHECK_BLOCKS("ref4", p1, 5);
311 CHECK_BLOCKS("ref4", p2, 1);
312
313 fprintf(stderr, "Freeing p2\n");
314 talloc_free(p2);
315 talloc_report_full(root, stderr);
316
317 CHECK_BLOCKS("ref4", p1, 4);
318
319 fprintf(stderr, "Freeing p1\n");
320 talloc_free(p1);
321 talloc_report_full(root, stderr);
322
323 CHECK_SIZE("ref4", root, 0);
324
325 talloc_free(root);
326
327 printf("success: ref4\n");
328 return true;
329}
330
331
332/*
333 test references
334*/
335static bool test_unlink1(void)
336{
337 void *root, *p1, *p2, *ref, *r1;
338
339 printf("test: unlink\n# UNLINK\n");
340
341 root = talloc_named_const(NULL, 0, "root");
342 p1 = talloc_named_const(root, 1, "p1");
343 talloc_named_const(p1, 1, "x1");
344 talloc_named_const(p1, 1, "x2");
345 talloc_named_const(p1, 1, "x3");
346 p2 = talloc_named_const(p1, 1, "p2");
347
348 r1 = talloc_named_const(p1, 1, "r1");
349 ref = talloc_reference(r1, p2);
350 talloc_report_full(root, stderr);
351
352 CHECK_BLOCKS("unlink", p1, 7);
353 CHECK_BLOCKS("unlink", p2, 1);
354 CHECK_BLOCKS("unlink", ref, 1);
355 CHECK_BLOCKS("unlink", r1, 2);
356
357 fprintf(stderr, "Unreferencing r1\n");
358 talloc_unlink(r1, p2);
359 talloc_report_full(root, stderr);
360
361 CHECK_BLOCKS("unlink", p1, 6);
362 CHECK_BLOCKS("unlink", p2, 1);
363 CHECK_BLOCKS("unlink", r1, 1);
364
365 fprintf(stderr, "Freeing p1\n");
366 talloc_free(p1);
367 talloc_report_full(root, stderr);
368
369 CHECK_SIZE("unlink", root, 0);
370
371 talloc_free(root);
372
373 printf("success: unlink\n");
374 return true;
375}
376
377static int fail_destructor(void *ptr)
378{
379 return -1;
380}
381
382/*
383 miscellaneous tests to try to get a higher test coverage percentage
384*/
385static bool test_misc(void)
386{
387 void *root, *p1;
388 char *p2;
389 double *d;
390 const char *name;
391
392 printf("test: misc\n# MISCELLANEOUS\n");
393
394 root = talloc_new(NULL);
395
396 p1 = talloc_size(root, 0x7fffffff);
397 torture_assert("misc", !p1, "failed: large talloc allowed\n");
398
399 p1 = talloc_strdup(root, "foo");
400 talloc_increase_ref_count(p1);
401 talloc_increase_ref_count(p1);
402 talloc_increase_ref_count(p1);
403 CHECK_BLOCKS("misc", p1, 1);
404 CHECK_BLOCKS("misc", root, 2);
405 talloc_unlink(NULL, p1);
406 CHECK_BLOCKS("misc", p1, 1);
407 CHECK_BLOCKS("misc", root, 2);
408 talloc_unlink(NULL, p1);
409 CHECK_BLOCKS("misc", p1, 1);
410 CHECK_BLOCKS("misc", root, 2);
411 p2 = talloc_strdup(p1, "foo");
412 torture_assert("misc", talloc_unlink(root, p2) == -1,
413 "failed: talloc_unlink() of non-reference context should return -1\n");
414 torture_assert("misc", talloc_unlink(p1, p2) == 0,
415 "failed: talloc_unlink() of parent should succeed\n");
416 talloc_unlink(NULL, p1);
417 CHECK_BLOCKS("misc", p1, 1);
418 CHECK_BLOCKS("misc", root, 2);
419
420 name = talloc_set_name(p1, "my name is %s", "foo");
421 torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
422 "failed: wrong name after talloc_set_name(my name is foo)");
423 torture_assert_str_equal("misc", talloc_get_name(p1), name,
424 "failed: wrong name after talloc_set_name(my name is foo)");
425 CHECK_BLOCKS("misc", p1, 2);
426 CHECK_BLOCKS("misc", root, 3);
427
428 talloc_set_name_const(p1, NULL);
429 torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
430 "failed: wrong name after talloc_set_name(NULL)");
431 CHECK_BLOCKS("misc", p1, 2);
432 CHECK_BLOCKS("misc", root, 3);
433
434 torture_assert("misc", talloc_free(NULL) == -1,
435 "talloc_free(NULL) should give -1\n");
436
437 talloc_set_destructor(p1, fail_destructor);
438 torture_assert("misc", talloc_free(p1) == -1,
439 "Failed destructor should cause talloc_free to fail\n");
440 talloc_set_destructor(p1, NULL);
441
442 talloc_report(root, stderr);
443
444
445 p2 = (char *)talloc_zero_size(p1, 20);
446 torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
447 talloc_free(p2);
448
449 torture_assert("misc", talloc_strdup(root, NULL) == NULL,
450 "failed: strdup on NULL should give NULL\n");
451
452 p2 = talloc_strndup(p1, "foo", 2);
453 torture_assert("misc", strcmp("fo", p2) == 0,
454 "strndup doesn't work\n");
455 p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
456 torture_assert("misc", strcmp("food", p2) == 0,
457 "talloc_asprintf_append_buffer doesn't work\n");
458 CHECK_BLOCKS("misc", p2, 1);
459 CHECK_BLOCKS("misc", p1, 3);
460
461 p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
462 torture_assert("misc", strcmp("hello world", p2) == 0,
463 "talloc_asprintf_append_buffer doesn't work\n");
464 CHECK_BLOCKS("misc", p2, 1);
465 CHECK_BLOCKS("misc", p1, 3);
466 talloc_free(p2);
467
468 d = talloc_array(p1, double, 0x20000000);
469 torture_assert("misc", !d, "failed: integer overflow not detected\n");
470
471 d = talloc_realloc(p1, d, double, 0x20000000);
472 torture_assert("misc", !d, "failed: integer overflow not detected\n");
473
474 talloc_free(p1);
475 CHECK_BLOCKS("misc", root, 1);
476
477 p1 = talloc_named(root, 100, "%d bytes", 100);
478 CHECK_BLOCKS("misc", p1, 2);
479 CHECK_BLOCKS("misc", root, 3);
480 talloc_unlink(root, p1);
481
482 p1 = talloc_init("%d bytes", 200);
483 p2 = talloc_asprintf(p1, "my test '%s'", "string");
484 torture_assert_str_equal("misc", p2, "my test 'string'",
485 "failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
486 CHECK_BLOCKS("misc", p1, 3);
487 CHECK_SIZE("misc", p2, 17);
488 CHECK_BLOCKS("misc", root, 1);
489 talloc_unlink(NULL, p1);
490
491 p1 = talloc_named_const(root, 10, "p1");
492 p2 = (char *)talloc_named_const(root, 20, "p2");
493 (void)talloc_reference(p1, p2);
494 talloc_report_full(root, stderr);
495 talloc_unlink(root, p2);
496 talloc_report_full(root, stderr);
497 CHECK_BLOCKS("misc", p2, 1);
498 CHECK_BLOCKS("misc", p1, 2);
499 CHECK_BLOCKS("misc", root, 3);
500 talloc_unlink(p1, p2);
501 talloc_unlink(root, p1);
502
503 p1 = talloc_named_const(root, 10, "p1");
504 p2 = (char *)talloc_named_const(root, 20, "p2");
505 (void)talloc_reference(NULL, p2);
506 talloc_report_full(root, stderr);
507 talloc_unlink(root, p2);
508 talloc_report_full(root, stderr);
509 CHECK_BLOCKS("misc", p2, 1);
510 CHECK_BLOCKS("misc", p1, 1);
511 CHECK_BLOCKS("misc", root, 2);
512 talloc_unlink(NULL, p2);
513 talloc_unlink(root, p1);
514
515 /* Test that talloc_unlink is a no-op */
516
517 torture_assert("misc", talloc_unlink(root, NULL) == -1,
518 "failed: talloc_unlink(root, NULL) == -1\n");
519
520 talloc_report(root, stderr);
521 talloc_report(NULL, stderr);
522
523 CHECK_SIZE("misc", root, 0);
524
525 talloc_free(root);
526
527 CHECK_SIZE("misc", NULL, 0);
528
529 talloc_enable_null_tracking_no_autofree();
530 talloc_enable_leak_report();
531 talloc_enable_leak_report_full();
532
533 printf("success: misc\n");
534
535 return true;
536}
537
538
539/*
540 test realloc
541*/
542static bool test_realloc(void)
543{
544 void *root, *p1, *p2;
545
546 printf("test: realloc\n# REALLOC\n");
547
548 root = talloc_new(NULL);
549
550 p1 = talloc_size(root, 10);
551 CHECK_SIZE("realloc", p1, 10);
552
553 p1 = talloc_realloc_size(NULL, p1, 20);
554 CHECK_SIZE("realloc", p1, 20);
555
556 talloc_new(p1);
557
558 p2 = talloc_realloc_size(p1, NULL, 30);
559
560 talloc_new(p1);
561
562 p2 = talloc_realloc_size(p1, p2, 40);
563
564 CHECK_SIZE("realloc", p2, 40);
565 CHECK_SIZE("realloc", root, 60);
566 CHECK_BLOCKS("realloc", p1, 4);
567
568 p1 = talloc_realloc_size(NULL, p1, 20);
569 CHECK_SIZE("realloc", p1, 60);
570
571 talloc_increase_ref_count(p2);
572 torture_assert("realloc", talloc_realloc_size(NULL, p2, 5) == NULL,
573 "failed: talloc_realloc() on a referenced pointer should fail\n");
574 CHECK_BLOCKS("realloc", p1, 4);
575
576 talloc_realloc_size(NULL, p2, 0);
577 talloc_realloc_size(NULL, p2, 0);
578 CHECK_BLOCKS("realloc", p1, 4);
579 talloc_realloc_size(p1, p2, 0);
580 CHECK_BLOCKS("realloc", p1, 3);
581
582 torture_assert("realloc", talloc_realloc_size(NULL, p1, 0x7fffffff) == NULL,
583 "failed: oversize talloc should fail\n");
584
585 talloc_realloc_size(NULL, p1, 0);
586 CHECK_BLOCKS("realloc", root, 4);
587 talloc_realloc_size(root, p1, 0);
588 CHECK_BLOCKS("realloc", root, 1);
589
590 CHECK_SIZE("realloc", root, 0);
591
592 talloc_free(root);
593
594 printf("success: realloc\n");
595
596 return true;
597}
598
599/*
600 test realloc with a child
601*/
602static bool test_realloc_child(void)
603{
604 void *root;
605 struct el2 {
606 const char *name;
607 } *el2;
608 struct el1 {
609 int count;
610 struct el2 **list, **list2, **list3;
611 } *el1;
612
613 printf("test: REALLOC WITH CHILD\n");
614
615 root = talloc_new(NULL);
616
617 el1 = talloc(root, struct el1);
618 el1->list = talloc(el1, struct el2 *);
619 el1->list[0] = talloc(el1->list, struct el2);
620 el1->list[0]->name = talloc_strdup(el1->list[0], "testing");
621
622 el1->list2 = talloc(el1, struct el2 *);
623 el1->list2[0] = talloc(el1->list2, struct el2);
624 el1->list2[0]->name = talloc_strdup(el1->list2[0], "testing2");
625
626 el1->list3 = talloc(el1, struct el2 *);
627 el1->list3[0] = talloc(el1->list3, struct el2);
628 el1->list3[0]->name = talloc_strdup(el1->list3[0], "testing2");
629
630 el2 = talloc(el1->list, struct el2);
631 el2 = talloc(el1->list2, struct el2);
632 el2 = talloc(el1->list3, struct el2);
633 (void)el2;
634
635 el1->list = talloc_realloc(el1, el1->list, struct el2 *, 100);
636 el1->list2 = talloc_realloc(el1, el1->list2, struct el2 *, 200);
637 el1->list3 = talloc_realloc(el1, el1->list3, struct el2 *, 300);
638
639 talloc_free(root);
640
641 printf("success: REALLOC WITH CHILD\n");
642 return true;
643}
644
645/*
646 test type checking
647*/
648static bool test_type(void)
649{
650 void *root;
651 struct el1 {
652 int count;
653 };
654 struct el2 {
655 int count;
656 };
657 struct el1 *el1;
658
659 printf("test: type\n# talloc type checking\n");
660
661 root = talloc_new(NULL);
662
663 el1 = talloc(root, struct el1);
664
665 el1->count = 1;
666
667 torture_assert("type", talloc_get_type(el1, struct el1) == el1,
668 "type check failed on el1\n");
669 torture_assert("type", talloc_get_type(el1, struct el2) == NULL,
670 "type check failed on el1 with el2\n");
671 talloc_set_type(el1, struct el2);
672 torture_assert("type", talloc_get_type(el1, struct el2) == (struct el2 *)el1,
673 "type set failed on el1 with el2\n");
674
675 talloc_free(root);
676
677 printf("success: type\n");
678 return true;
679}
680
681/*
682 test steal
683*/
684static bool test_steal(void)
685{
686 void *root, *p1, *p2;
687
688 printf("test: steal\n# STEAL\n");
689
690 root = talloc_new(NULL);
691
692 p1 = talloc_array(root, char, 10);
693 CHECK_SIZE("steal", p1, 10);
694
695 p2 = talloc_realloc(root, NULL, char, 20);
696 CHECK_SIZE("steal", p1, 10);
697 CHECK_SIZE("steal", root, 30);
698
699 torture_assert("steal", talloc_steal(p1, NULL) == NULL,
700 "failed: stealing NULL should give NULL\n");
701
702 torture_assert("steal", talloc_steal(p1, p1) == p1,
703 "failed: stealing to ourselves is a nop\n");
704 CHECK_BLOCKS("steal", root, 3);
705 CHECK_SIZE("steal", root, 30);
706
707 talloc_steal(NULL, p1);
708 talloc_steal(NULL, p2);
709 CHECK_BLOCKS("steal", root, 1);
710 CHECK_SIZE("steal", root, 0);
711
712 talloc_free(p1);
713 talloc_steal(root, p2);
714 CHECK_BLOCKS("steal", root, 2);
715 CHECK_SIZE("steal", root, 20);
716
717 talloc_free(p2);
718
719 CHECK_BLOCKS("steal", root, 1);
720 CHECK_SIZE("steal", root, 0);
721
722 talloc_free(root);
723
724 p1 = talloc_size(NULL, 3);
725 talloc_report_full(NULL, stderr);
726 CHECK_SIZE("steal", NULL, 3);
727 talloc_free(p1);
728
729 printf("success: steal\n");
730 return true;
731}
732
733/*
734 test move
735*/
736static bool test_move(void)
737{
738 void *root;
739 struct t_move {
740 char *p;
741 int *x;
742 } *t1, *t2;
743
744 printf("test: move\n# MOVE\n");
745
746 root = talloc_new(NULL);
747
748 t1 = talloc(root, struct t_move);
749 t2 = talloc(root, struct t_move);
750 t1->p = talloc_strdup(t1, "foo");
751 t1->x = talloc(t1, int);
752 *t1->x = 42;
753
754 t2->p = talloc_move(t2, &t1->p);
755 t2->x = talloc_move(t2, &t1->x);
756 torture_assert("move", t1->p == NULL && t1->x == NULL &&
757 strcmp(t2->p, "foo") == 0 && *t2->x == 42,
758 "talloc move failed");
759
760 talloc_free(root);
761
762 printf("success: move\n");
763
764 return true;
765}
766
767/*
768 test talloc_realloc_fn
769*/
770static bool test_realloc_fn(void)
771{
772 void *root, *p1;
773
774 printf("test: realloc_fn\n# talloc_realloc_fn\n");
775
776 root = talloc_new(NULL);
777
778 p1 = talloc_realloc_fn(root, NULL, 10);
779 CHECK_BLOCKS("realloc_fn", root, 2);
780 CHECK_SIZE("realloc_fn", root, 10);
781 p1 = talloc_realloc_fn(root, p1, 20);
782 CHECK_BLOCKS("realloc_fn", root, 2);
783 CHECK_SIZE("realloc_fn", root, 20);
784 p1 = talloc_realloc_fn(root, p1, 0);
785 CHECK_BLOCKS("realloc_fn", root, 1);
786 CHECK_SIZE("realloc_fn", root, 0);
787
788 talloc_free(root);
789
790 printf("success: realloc_fn\n");
791 return true;
792}
793
794
795static bool test_unref_reparent(void)
796{
797 void *root, *p1, *p2, *c1;
798
799 printf("test: unref_reparent\n# UNREFERENCE AFTER PARENT FREED\n");
800
801 root = talloc_named_const(NULL, 0, "root");
802 p1 = talloc_named_const(root, 1, "orig parent");
803 p2 = talloc_named_const(root, 1, "parent by reference");
804
805 c1 = talloc_named_const(p1, 1, "child");
806 talloc_reference(p2, c1);
807
808 CHECK_PARENT("unref_reparent", c1, p1);
809
810 talloc_free(p1);
811
812 CHECK_PARENT("unref_reparent", c1, p2);
813
814 talloc_unlink(p2, c1);
815
816 CHECK_SIZE("unref_reparent", root, 1);
817
818 talloc_free(p2);
819 talloc_free(root);
820
821 printf("success: unref_reparent\n");
822 return true;
823}
824
825/*
826 measure the speed of talloc versus malloc
827*/
828static bool test_speed(void)
829{
830 void *ctx = talloc_new(NULL);
831 unsigned count;
832 const int loop = 1000;
833 int i;
834 struct timeval tv;
835
836 printf("test: speed\n# TALLOC VS MALLOC SPEED\n");
837
838 tv = timeval_current();
839 count = 0;
840 do {
841 void *p1, *p2, *p3;
842 for (i=0;i<loop;i++) {
843 p1 = talloc_size(ctx, loop % 100);
844 p2 = talloc_strdup(p1, "foo bar");
845 p3 = talloc_size(p1, 300);
846 (void)p2;
847 (void)p3;
848 talloc_free(p1);
849 }
850 count += 3 * loop;
851 } while (timeval_elapsed(&tv) < 5.0);
852
853 fprintf(stderr, "talloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
854
855 talloc_free(ctx);
856
857 ctx = talloc_pool(NULL, 1024);
858
859 tv = timeval_current();
860 count = 0;
861 do {
862 void *p1, *p2, *p3;
863 for (i=0;i<loop;i++) {
864 p1 = talloc_size(ctx, loop % 100);
865 p2 = talloc_strdup(p1, "foo bar");
866 p3 = talloc_size(p1, 300);
867 (void)p2;
868 (void)p3;
869 talloc_free(p1);
870 }
871 count += 3 * loop;
872 } while (timeval_elapsed(&tv) < 5.0);
873
874 talloc_free(ctx);
875
876 fprintf(stderr, "talloc_pool: %.0f ops/sec\n", count/timeval_elapsed(&tv));
877
878 tv = timeval_current();
879 count = 0;
880 do {
881 void *p1, *p2, *p3;
882 for (i=0;i<loop;i++) {
883 p1 = malloc(loop % 100);
884 p2 = strdup("foo bar");
885 p3 = malloc(300);
886 free(p1);
887 free(p2);
888 free(p3);
889 }
890 count += 3 * loop;
891 } while (timeval_elapsed(&tv) < 5.0);
892 fprintf(stderr, "malloc: %.0f ops/sec\n", count/timeval_elapsed(&tv));
893
894 printf("success: speed\n");
895
896 return true;
897}
898
899static bool test_lifeless(void)
900{
901 void *top = talloc_new(NULL);
902 char *parent, *child;
903 void *child_owner = talloc_new(NULL);
904
905 printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");
906
907 parent = talloc_strdup(top, "parent");
908 child = talloc_strdup(parent, "child");
909 (void)talloc_reference(child, parent);
910 (void)talloc_reference(child_owner, child);
911 talloc_report_full(top, stderr);
912 talloc_unlink(top, parent);
913 talloc_unlink(top, child);
914 talloc_report_full(top, stderr);
915 talloc_free(top);
916 talloc_free(child_owner);
917 talloc_free(child);
918
919 printf("success: lifeless\n");
920 return true;
921}
922
923static int loop_destructor_count;
924
925static int test_loop_destructor(char *ptr)
926{
927 loop_destructor_count++;
928 return 0;
929}
930
931static bool test_loop(void)
932{
933 void *top = talloc_new(NULL);
934 char *parent;
935 struct req1 {
936 char *req2, *req3;
937 } *req1;
938
939 printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");
940
941 parent = talloc_strdup(top, "parent");
942 req1 = talloc(parent, struct req1);
943 req1->req2 = talloc_strdup(req1, "req2");
944 talloc_set_destructor(req1->req2, test_loop_destructor);
945 req1->req3 = talloc_strdup(req1, "req3");
946 (void)talloc_reference(req1->req3, req1);
947 talloc_report_full(top, stderr);
948 talloc_free(parent);
949 talloc_report_full(top, stderr);
950 talloc_report_full(NULL, stderr);
951 talloc_free(top);
952
953 torture_assert("loop", loop_destructor_count == 1,
954 "FAILED TO FIRE LOOP DESTRUCTOR\n");
955 loop_destructor_count = 0;
956
957 printf("success: loop\n");
958 return true;
959}
960
961static int fail_destructor_str(char *ptr)
962{
963 return -1;
964}
965
966static bool test_free_parent_deny_child(void)
967{
968 void *top = talloc_new(NULL);
969 char *level1;
970 char *level2;
971 char *level3;
972
973 printf("test: free_parent_deny_child\n# TALLOC FREE PARENT DENY CHILD\n");
974
975 level1 = talloc_strdup(top, "level1");
976 level2 = talloc_strdup(level1, "level2");
977 level3 = talloc_strdup(level2, "level3");
978
979 talloc_set_destructor(level3, fail_destructor_str);
980 talloc_free(level1);
981 talloc_set_destructor(level3, NULL);
982
983 CHECK_PARENT("free_parent_deny_child", level3, top);
984
985 talloc_free(top);
986
987 printf("success: free_parent_deny_child\n");
988 return true;
989}
990
991struct new_parent {
992 void *new_parent;
993 char val[20];
994};
995
996static int reparenting_destructor(struct new_parent *np)
997{
998 talloc_set_destructor(np, NULL);
999 (void)talloc_move(np->new_parent, &np);
1000 return -1;
1001}
1002
1003static bool test_free_parent_reparent_child(void)
1004{
1005 void *top = talloc_new(NULL);
1006 char *level1;
1007 char *alternate_level1;
1008 char *level2;
1009 struct new_parent *level3;
1010
1011 printf("test: free_parent_reparent_child\n# "
1012 "TALLOC FREE PARENT REPARENT CHILD\n");
1013
1014 level1 = talloc_strdup(top, "level1");
1015 alternate_level1 = talloc_strdup(top, "alternate_level1");
1016 level2 = talloc_strdup(level1, "level2");
1017 level3 = talloc(level2, struct new_parent);
1018 level3->new_parent = alternate_level1;
1019 memset(level3->val, 'x', sizeof(level3->val));
1020
1021 talloc_set_destructor(level3, reparenting_destructor);
1022 talloc_free(level1);
1023
1024 CHECK_PARENT("free_parent_reparent_child",
1025 level3, alternate_level1);
1026
1027 talloc_free(top);
1028
1029 printf("success: free_parent_reparent_child\n");
1030 return true;
1031}
1032
1033static bool test_free_parent_reparent_child_in_pool(void)
1034{
1035 void *top = talloc_new(NULL);
1036 char *level1;
1037 char *alternate_level1;
1038 char *level2;
1039 void *pool;
1040 struct new_parent *level3;
1041
1042 printf("test: free_parent_reparent_child_in_pool\n# "
1043 "TALLOC FREE PARENT REPARENT CHILD IN POOL\n");
1044
1045 pool = talloc_pool(top, 1024);
1046 level1 = talloc_strdup(pool, "level1");
1047 alternate_level1 = talloc_strdup(top, "alternate_level1");
1048 level2 = talloc_strdup(level1, "level2");
1049 level3 = talloc(level2, struct new_parent);
1050 level3->new_parent = alternate_level1;
1051 memset(level3->val, 'x', sizeof(level3->val));
1052
1053 talloc_set_destructor(level3, reparenting_destructor);
1054 talloc_free(level1);
1055 talloc_set_destructor(level3, NULL);
1056
1057 CHECK_PARENT("free_parent_reparent_child_in_pool",
1058 level3, alternate_level1);
1059
1060 /* Even freeing alternate_level1 should leave pool alone. */
1061 talloc_free(alternate_level1);
1062 talloc_free(top);
1063
1064 printf("success: free_parent_reparent_child_in_pool\n");
1065 return true;
1066}
1067
1068
1069static bool test_talloc_ptrtype(void)
1070{
1071 void *top = talloc_new(NULL);
1072 struct struct1 {
1073 int foo;
1074 int bar;
1075 } *s1, *s2, **s3, ***s4;
1076 const char *location1;
1077 const char *location2;
1078 const char *location3;
1079 const char *location4;
1080
1081 printf("test: ptrtype\n# TALLOC PTRTYPE\n");
1082
1083 s1 = talloc_ptrtype(top, s1);location1 = __location__;
1084
1085 if (talloc_get_size(s1) != sizeof(struct struct1)) {
1086 printf("failure: ptrtype [\n"
1087 "talloc_ptrtype() allocated the wrong size %lu (should be %lu)\n"
1088 "]\n", (unsigned long)talloc_get_size(s1),
1089 (unsigned long)sizeof(struct struct1));
1090 return false;
1091 }
1092
1093 if (strcmp(location1, talloc_get_name(s1)) != 0) {
1094 printf("failure: ptrtype [\n"
1095 "talloc_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1096 talloc_get_name(s1), location1);
1097 return false;
1098 }
1099
1100 s2 = talloc_array_ptrtype(top, s2, 10);location2 = __location__;
1101
1102 if (talloc_get_size(s2) != (sizeof(struct struct1) * 10)) {
1103 printf("failure: ptrtype [\n"
1104 "talloc_array_ptrtype() allocated the wrong size "
1105 "%lu (should be %lu)\n]\n",
1106 (unsigned long)talloc_get_size(s2),
1107 (unsigned long)(sizeof(struct struct1)*10));
1108 return false;
1109 }
1110
1111 if (strcmp(location2, talloc_get_name(s2)) != 0) {
1112 printf("failure: ptrtype [\n"
1113 "talloc_array_ptrtype() sets the wrong name '%s' (should be '%s')\n]\n",
1114 talloc_get_name(s2), location2);
1115 return false;
1116 }
1117
1118 s3 = talloc_array_ptrtype(top, s3, 10);location3 = __location__;
1119
1120 if (talloc_get_size(s3) != (sizeof(struct struct1 *) * 10)) {
1121 printf("failure: ptrtype [\n"
1122 "talloc_array_ptrtype() allocated the wrong size "
1123 "%lu (should be %lu)\n]\n",
1124 (unsigned long)talloc_get_size(s3),
1125 (unsigned long)(sizeof(struct struct1 *)*10));
1126 return false;
1127 }
1128
1129 torture_assert_str_equal("ptrtype", location3, talloc_get_name(s3),
1130 "talloc_array_ptrtype() sets the wrong name");
1131
1132 s4 = talloc_array_ptrtype(top, s4, 10);location4 = __location__;
1133
1134 if (talloc_get_size(s4) != (sizeof(struct struct1 **) * 10)) {
1135 printf("failure: ptrtype [\n"
1136 "talloc_array_ptrtype() allocated the wrong size "
1137 "%lu (should be %lu)\n]\n",
1138 (unsigned long)talloc_get_size(s4),
1139 (unsigned long)(sizeof(struct struct1 **)*10));
1140 return false;
1141 }
1142
1143 torture_assert_str_equal("ptrtype", location4, talloc_get_name(s4),
1144 "talloc_array_ptrtype() sets the wrong name");
1145
1146 talloc_free(top);
1147
1148 printf("success: ptrtype\n");
1149 return true;
1150}
1151
1152static int _test_talloc_free_in_destructor(void **ptr)
1153{
1154 talloc_free(*ptr);
1155 return 0;
1156}
1157
1158static bool test_talloc_free_in_destructor(void)
1159{
1160 void *level0;
1161 void *level1;
1162 void *level2;
1163 void *level3;
1164 void *level4;
1165 void **level5;
1166
1167 printf("test: free_in_destructor\n# TALLOC FREE IN DESTRUCTOR\n");
1168
1169 level0 = talloc_new(NULL);
1170 level1 = talloc_new(level0);
1171 level2 = talloc_new(level1);
1172 level3 = talloc_new(level2);
1173 level4 = talloc_new(level3);
1174 level5 = talloc(level4, void *);
1175
1176 *level5 = level3;
1177 (void)talloc_reference(level0, level3);
1178 (void)talloc_reference(level3, level3);
1179 (void)talloc_reference(level5, level3);
1180
1181 talloc_set_destructor(level5, _test_talloc_free_in_destructor);
1182
1183 talloc_free(level1);
1184
1185 talloc_free(level0);
1186
1187 printf("success: free_in_destructor\n");
1188 return true;
1189}
1190
1191static bool test_autofree(void)
1192{
1193#if _SAMBA_BUILD_ < 4
1194 /* autofree test would kill smbtorture */
1195 void *p;
1196 printf("test: autofree\n# TALLOC AUTOFREE CONTEXT\n");
1197
1198 p = talloc_autofree_context();
1199 talloc_free(p);
1200
1201 p = talloc_autofree_context();
1202 talloc_free(p);
1203
1204 printf("success: autofree\n");
1205#endif
1206 return true;
1207}
1208
1209static bool test_pool(void)
1210{
1211 void *pool;
1212 void *p1, *p2, *p3, *p4;
1213 void *p2_2;
1214
1215 pool = talloc_pool(NULL, 1024);
1216
1217 p1 = talloc_size(pool, 80);
1218 memset(p1, 0x11, talloc_get_size(p1));
1219 p2 = talloc_size(pool, 20);
1220 memset(p2, 0x11, talloc_get_size(p2));
1221 p3 = talloc_size(p1, 50);
1222 memset(p3, 0x11, talloc_get_size(p3));
1223 p4 = talloc_size(p3, 1000);
1224 memset(p4, 0x11, talloc_get_size(p4));
1225
1226#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1227 p2_2 = talloc_realloc_size(pool, p2, 20+1);
1228 torture_assert("pool realloc 20+1", p2_2 == p2, "failed: pointer changed");
1229 memset(p2, 0x11, talloc_get_size(p2));
1230 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1231 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1232 memset(p2, 0x11, talloc_get_size(p2));
1233 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1234 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1235 memset(p2, 0x11, talloc_get_size(p2));
1236
1237 talloc_free(p3);
1238
1239 /* this should reclaim the memory of p4 and p3 */
1240 p2_2 = talloc_realloc_size(pool, p2, 400);
1241 torture_assert("pool realloc 400", p2_2 == p2, "failed: pointer changed");
1242 memset(p2, 0x11, talloc_get_size(p2));
1243
1244 talloc_free(p1);
1245
1246 /* this should reclaim the memory of p1 */
1247 p2_2 = talloc_realloc_size(pool, p2, 800);
1248 torture_assert("pool realloc 800", p2_2 == p1, "failed: pointer not changed");
1249 p2 = p2_2;
1250 memset(p2, 0x11, talloc_get_size(p2));
1251
1252 /* this should do a malloc */
1253 p2_2 = talloc_realloc_size(pool, p2, 1800);
1254 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1255 p2 = p2_2;
1256 memset(p2, 0x11, talloc_get_size(p2));
1257
1258 /* this should reclaim the memory from the pool */
1259 p3 = talloc_size(pool, 80);
1260 torture_assert("pool alloc 80", p3 == p1, "failed: pointer changed");
1261 memset(p3, 0x11, talloc_get_size(p3));
1262
1263 talloc_free(p2);
1264 talloc_free(p3);
1265
1266 p1 = talloc_size(pool, 80);
1267 memset(p1, 0x11, talloc_get_size(p1));
1268 p2 = talloc_size(pool, 20);
1269 memset(p2, 0x11, talloc_get_size(p2));
1270
1271 talloc_free(p1);
1272
1273 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1274 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1275 memset(p2, 0x11, talloc_get_size(p2));
1276 p2_2 = talloc_realloc_size(pool, p2, 20-1);
1277 torture_assert("pool realloc 20-1", p2_2 == p2, "failed: pointer changed");
1278 memset(p2, 0x11, talloc_get_size(p2));
1279
1280 /* this should do a malloc */
1281 p2_2 = talloc_realloc_size(pool, p2, 1800);
1282 torture_assert("pool realloc 1800", p2_2 != p2, "failed: pointer not changed");
1283 p2 = p2_2;
1284 memset(p2, 0x11, talloc_get_size(p2));
1285
1286 /* this should reclaim the memory from the pool */
1287 p3 = talloc_size(pool, 800);
1288 torture_assert("pool alloc 800", p3 == p1, "failed: pointer changed");
1289 memset(p3, 0x11, talloc_get_size(p3));
1290
1291#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1292
1293 talloc_free(pool);
1294
1295 return true;
1296}
1297
1298static bool test_pool_steal(void)
1299{
1300 void *root;
1301 void *pool;
1302 void *p1, *p2;
1303 void *p1_2, *p2_2;
1304 size_t hdr;
1305 size_t ofs1, ofs2;
1306
1307 root = talloc_new(NULL);
1308 pool = talloc_pool(root, 1024);
1309
1310 p1 = talloc_size(pool, 4 * 16);
1311 torture_assert("pool allocate 4 * 16", p1 != NULL, "failed ");
1312 memset(p1, 0x11, talloc_get_size(p1));
1313 p2 = talloc_size(pool, 4 * 16);
1314 torture_assert("pool allocate 4 * 16", p2 > p1, "failed: !(p2 > p1) ");
1315 memset(p2, 0x11, talloc_get_size(p2));
1316
1317 ofs1 = PTR_DIFF(p2, p1);
1318 hdr = ofs1 - talloc_get_size(p1);
1319
1320 talloc_steal(root, p1);
1321 talloc_steal(root, p2);
1322
1323 talloc_free(pool);
1324
1325 p1_2 = p1;
1326
1327#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1328 p1_2 = talloc_realloc_size(root, p1, 5 * 16);
1329 torture_assert("pool realloc 5 * 16", p1_2 > p2, "failed: pointer not changed");
1330 memset(p1_2, 0x11, talloc_get_size(p1_2));
1331 ofs1 = PTR_DIFF(p1_2, p2);
1332 ofs2 = talloc_get_size(p2) + hdr;
1333
1334 torture_assert("pool realloc ", ofs1 == ofs2, "failed: pointer offset unexpected");
1335
1336 p2_2 = talloc_realloc_size(root, p2, 3 * 16);
1337 torture_assert("pool realloc 5 * 16", p2_2 == p2, "failed: pointer changed");
1338 memset(p2_2, 0x11, talloc_get_size(p2_2));
1339#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1340
1341 talloc_free(p1_2);
1342
1343 p2_2 = p2;
1344
1345#if 1 /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1346 /* now we should reclaim the full pool */
1347 p2_2 = talloc_realloc_size(root, p2, 8 * 16);
1348 torture_assert("pool realloc 8 * 16", p2_2 == p1, "failed: pointer not expected");
1349 p2 = p2_2;
1350 memset(p2_2, 0x11, talloc_get_size(p2_2));
1351
1352 /* now we malloc and free the full pool space */
1353 p2_2 = talloc_realloc_size(root, p2, 2 * 1024);
1354 torture_assert("pool realloc 2 * 1024", p2_2 != p1, "failed: pointer not expected");
1355 memset(p2_2, 0x11, talloc_get_size(p2_2));
1356
1357#endif /* this relies on ALWAYS_REALLOC == 0 in talloc.c */
1358
1359 talloc_free(p2_2);
1360
1361 talloc_free(root);
1362
1363 return true;
1364}
1365
1366static bool test_pool_nest(void)
1367{
1368 void *p1, *p2, *p3;
1369 void *e = talloc_new(NULL);
1370
1371 p1 = talloc_pool(NULL, 1024);
1372 torture_assert("talloc_pool", p1 != NULL, "failed");
1373
1374 p2 = talloc_pool(p1, 500);
1375 torture_assert("talloc_pool", p2 != NULL, "failed");
1376
1377 p3 = talloc_size(p2, 10);
1378
1379 talloc_steal(e, p3);
1380
1381 talloc_free(p2);
1382
1383 talloc_free(p3);
1384
1385 talloc_free(p1);
1386
1387 return true;
1388}
1389
1390struct pooled {
1391 char *s1;
1392 char *s2;
1393 char *s3;
1394};
1395
1396static bool test_pooled_object(void)
1397{
1398 struct pooled *p;
1399 const char *s1 = "hello";
1400 const char *s2 = "world";
1401 const char *s3 = "";
1402
1403 p = talloc_pooled_object(NULL, struct pooled, 3,
1404 strlen(s1)+strlen(s2)+strlen(s3)+3);
1405
1406 if (talloc_get_size(p) != sizeof(struct pooled)) {
1407 return false;
1408 }
1409
1410 p->s1 = talloc_strdup(p, s1);
1411
1412 TALLOC_FREE(p->s1);
1413 p->s1 = talloc_strdup(p, s2);
1414 TALLOC_FREE(p->s1);
1415
1416 p->s1 = talloc_strdup(p, s1);
1417 p->s2 = talloc_strdup(p, s2);
1418 p->s3 = talloc_strdup(p, s3);
1419
1420 TALLOC_FREE(p);
1421 return true;
1422}
1423
1424static bool test_free_ref_null_context(void)
1425{
1426 void *p1, *p2, *p3;
1427 int ret;
1428
1429 talloc_disable_null_tracking();
1430 p1 = talloc_new(NULL);
1431 p2 = talloc_new(NULL);
1432
1433 p3 = talloc_reference(p2, p1);
1434 torture_assert("reference", p3 == p1, "failed: reference on null");
1435
1436 ret = talloc_free(p1);
1437 torture_assert("ref free with null parent", ret == 0, "failed: free with null parent");
1438 talloc_free(p2);
1439
1440 talloc_enable_null_tracking_no_autofree();
1441 p1 = talloc_new(NULL);
1442 p2 = talloc_new(NULL);
1443
1444 p3 = talloc_reference(p2, p1);
1445 torture_assert("reference", p3 == p1, "failed: reference on null");
1446
1447 ret = talloc_free(p1);
1448 torture_assert("ref free with null tracked parent", ret == 0, "failed: free with null parent");
1449 talloc_free(p2);
1450
1451 return true;
1452}
1453
1454static bool test_rusty(void)
1455{
1456 void *root;
1457 const char *p1;
1458
1459 talloc_enable_null_tracking();
1460 root = talloc_new(NULL);
1461 p1 = talloc_strdup(root, "foo");
1462 talloc_increase_ref_count(p1);
1463 talloc_report_full(root, stdout);
1464 talloc_free(root);
1465 CHECK_BLOCKS("null_context", NULL, 2);
1466 return true;
1467}
1468
1469static bool test_free_children(void)
1470{
1471 void *root;
1472 char *p1, *p2;
1473 const char *name, *name2;
1474
1475 talloc_enable_null_tracking();
1476 root = talloc_new(NULL);
1477 p1 = talloc_strdup(root, "foo1");
1478 p2 = talloc_strdup(p1, "foo2");
1479 (void)p2;
1480
1481 talloc_set_name(p1, "%s", "testname");
1482 talloc_free_children(p1);
1483 /* check its still a valid talloc ptr */
1484 talloc_get_size(talloc_get_name(p1));
1485 if (strcmp(talloc_get_name(p1), "testname") != 0) {
1486 return false;
1487 }
1488
1489 talloc_set_name(p1, "%s", "testname");
1490 name = talloc_get_name(p1);
1491 talloc_free_children(p1);
1492 /* check its still a valid talloc ptr */
1493 talloc_get_size(talloc_get_name(p1));
1494 torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
1495 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
1496 "wrong name");
1497 CHECK_BLOCKS("name1", p1, 2);
1498
1499 /* note that this does not free the old child name */
1500 talloc_set_name_const(p1, "testname2");
1501 name2 = talloc_get_name(p1);
1502 /* but this does */
1503 talloc_free_children(p1);
1504 (void)name2;
1505 torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
1506 "wrong name");
1507 CHECK_BLOCKS("name1", p1, 1);
1508
1509 talloc_report_full(root, stdout);
1510 talloc_free(root);
1511 return true;
1512}
1513
1514static bool test_memlimit(void)
1515{
1516 void *root;
1517 char *l1, *l2, *l3, *l4, *l5, *t;
1518 char *pool;
1519 int i;
1520
1521 printf("test: memlimit\n# MEMORY LIMITS\n");
1522
1523 printf("==== talloc_new(NULL)\n");
1524 root = talloc_new(NULL);
1525
1526 talloc_report_full(root, stdout);
1527
1528 printf("==== talloc_size(root, 2048)\n");
1529 l1 = talloc_size(root, 2048);
1530 torture_assert("memlimit", l1 != NULL,
1531 "failed: alloc should not fail due to memory limit\n");
1532
1533 talloc_report_full(root, stdout);
1534
1535 printf("==== talloc_free(l1)\n");
1536 talloc_free(l1);
1537
1538 talloc_report_full(root, stdout);
1539
1540 printf("==== talloc_strdup(root, level 1)\n");
1541 l1 = talloc_strdup(root, "level 1");
1542 torture_assert("memlimit", l1 != NULL,
1543 "failed: alloc should not fail due to memory limit\n");
1544
1545 talloc_report_full(root, stdout);
1546
1547 printf("==== talloc_set_memlimit(l1, 2048)\n");
1548 torture_assert("memlimit", talloc_set_memlimit(l1, 2048) == 0,
1549 "failed: setting memlimit should never fail\n");
1550
1551 talloc_report_full(root, stdout);
1552
1553 printf("==== talloc_size(root, 2048)\n");
1554 l2 = talloc_size(l1, 2048);
1555 torture_assert("memlimit", l2 == NULL,
1556 "failed: alloc should fail due to memory limit\n");
1557
1558 talloc_report_full(root, stdout);
1559
1560 printf("==== talloc_strdup(l1, level 2)\n");
1561 l2 = talloc_strdup(l1, "level 2");
1562 torture_assert("memlimit", l2 != NULL,
1563 "failed: alloc should not fail due to memory limit\n");
1564
1565 talloc_report_full(root, stdout);
1566
1567 printf("==== talloc_free(l2)\n");
1568 talloc_free(l2);
1569
1570 talloc_report_full(root, stdout);
1571
1572 printf("==== talloc_size(NULL, 2048)\n");
1573 l2 = talloc_size(NULL, 2048);
1574
1575 talloc_report_full(root, stdout);
1576
1577 printf("==== talloc_steal(l1, l2)\n");
1578 talloc_steal(l1, l2);
1579
1580 talloc_report_full(root, stdout);
1581
1582 printf("==== talloc_strdup(l2, level 3)\n");
1583 l3 = talloc_strdup(l2, "level 3");
1584 torture_assert("memlimit", l3 == NULL,
1585 "failed: alloc should fail due to memory limit\n");
1586
1587 talloc_report_full(root, stdout);
1588
1589 printf("==== talloc_free(l2)\n");
1590 talloc_free(l2);
1591
1592 talloc_report_full(root, stdout);
1593
1594 printf("==== talloc_strdup(NULL, level 2)\n");
1595 l2 = talloc_strdup(NULL, "level 2");
1596 talloc_steal(l1, l2);
1597
1598 talloc_report_full(root, stdout);
1599
1600 printf("==== talloc_strdup(l2, level 3)\n");
1601 l3 = talloc_strdup(l2, "level 3");
1602 torture_assert("memlimit", l3 != NULL,
1603 "failed: alloc should not fail due to memory limit\n");
1604
1605 talloc_report_full(root, stdout);
1606
1607 printf("==== talloc_set_memlimit(l3, 1024)\n");
1608 torture_assert("memlimit", talloc_set_memlimit(l3, 1024) == 0,
1609 "failed: setting memlimit should never fail\n");
1610
1611 talloc_report_full(root, stdout);
1612
1613 printf("==== talloc_strdup(l3, level 4)\n");
1614 l4 = talloc_strdup(l3, "level 4");
1615 torture_assert("memlimit", l4 != NULL,
1616 "failed: alloc should not fail due to memory limit\n");
1617
1618 talloc_report_full(root, stdout);
1619
1620 printf("==== talloc_set_memlimit(l4, 512)\n");
1621 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1622 "failed: setting memlimit should never fail\n");
1623
1624 talloc_report_full(root, stdout);
1625
1626 printf("==== talloc_strdup(l4, level 5)\n");
1627 l5 = talloc_strdup(l4, "level 5");
1628 torture_assert("memlimit", l5 != NULL,
1629 "failed: alloc should not fail due to memory limit\n");
1630
1631 talloc_report_full(root, stdout);
1632
1633 printf("==== talloc_realloc(NULL, l5, char, 600)\n");
1634 t = talloc_realloc(NULL, l5, char, 600);
1635 torture_assert("memlimit", t == NULL,
1636 "failed: alloc should fail due to memory limit\n");
1637
1638 talloc_report_full(root, stdout);
1639
1640 printf("==== talloc_realloc(NULL, l5, char, 5)\n");
1641 l5 = talloc_realloc(NULL, l5, char, 5);
1642 torture_assert("memlimit", l5 != NULL,
1643 "failed: alloc should not fail due to memory limit\n");
1644
1645 talloc_report_full(root, stdout);
1646
1647 printf("==== talloc_strdup(l3, level 4)\n");
1648 l4 = talloc_strdup(l3, "level 4");
1649 torture_assert("memlimit", l4 != NULL,
1650 "failed: alloc should not fail due to memory limit\n");
1651
1652 talloc_report_full(root, stdout);
1653
1654 printf("==== talloc_set_memlimit(l4, 512)\n");
1655 torture_assert("memlimit", talloc_set_memlimit(l4, 512) == 0,
1656 "failed: setting memlimit should never fail\n");
1657
1658 talloc_report_full(root, stdout);
1659
1660 printf("==== talloc_strdup(l4, level 5)\n");
1661 l5 = talloc_strdup(l4, "level 5");
1662 torture_assert("memlimit", l5 != NULL,
1663 "failed: alloc should not fail due to memory limit\n");
1664
1665 talloc_report_full(root, stdout);
1666
1667 printf("==== Make new temp context and steal l5\n");
1668 t = talloc_new(root);
1669 talloc_steal(t, l5);
1670
1671 talloc_report_full(root, stdout);
1672
1673 printf("==== talloc_size(t, 2048)\n");
1674 l1 = talloc_size(t, 2048);
1675 torture_assert("memlimit", l1 != NULL,
1676 "failed: alloc should not fail due to memory limit\n");
1677
1678 talloc_report_full(root, stdout);
1679 talloc_free(root);
1680
1681 /* Test memlimits with pools. */
1682 pool = talloc_pool(NULL, 10*1024);
1683 torture_assert("memlimit", pool != NULL,
1684 "failed: alloc should not fail due to memory limit\n");
1685 talloc_set_memlimit(pool, 10*1024);
1686 for (i = 0; i < 9; i++) {
1687 l1 = talloc_size(pool, 1024);
1688 torture_assert("memlimit", l1 != NULL,
1689 "failed: alloc should not fail due to memory limit\n");
1690 }
1691 /* The next alloc should fail. */
1692 l2 = talloc_size(pool, 1024);
1693 torture_assert("memlimit", l2 == NULL,
1694 "failed: alloc should fail due to memory limit\n");
1695
1696 /* Moving one of the children shouldn't change the limit,
1697 as it's still inside the pool. */
1698 root = talloc_new(NULL);
1699 talloc_steal(root, l1);
1700 l2 = talloc_size(pool, 1024);
1701 torture_assert("memlimit", l2 == NULL,
1702 "failed: alloc should fail due to memory limit\n");
1703
1704 talloc_free(pool);
1705 talloc_free(root);
1706 printf("success: memlimit\n");
1707
1708 return true;
1709}
1710
1711#ifdef HAVE_PTHREAD
1712
1713#define NUM_THREADS 100
1714
1715/* Sync variables. */
1716static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
1717static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;
1718static void *intermediate_ptr;
1719
1720/* Subthread. */
1721static void *thread_fn(void *arg)
1722{
1723 int ret;
1724 const char *ctx_name = (const char *)arg;
1725 void *sub_ctx = NULL;
1726 /*
1727 * Do stuff that creates a new talloc hierarchy in
1728 * this thread.
1729 */
1730 void *top_ctx = talloc_named_const(NULL, 0, "top");
1731 if (top_ctx == NULL) {
1732 return NULL;
1733 }
1734 sub_ctx = talloc_named_const(top_ctx, 100, ctx_name);
1735 if (sub_ctx == NULL) {
1736 return NULL;
1737 }
1738
1739 /*
1740 * Now transfer a pointer from our hierarchy
1741 * onto the intermediate ptr.
1742 */
1743 ret = pthread_mutex_lock(&mtx);
1744 if (ret != 0) {
1745 talloc_free(top_ctx);
1746 return NULL;
1747 }
1748 /* Wait for intermediate_ptr to be free. */
1749 while (intermediate_ptr != NULL) {
1750 ret = pthread_cond_wait(&condvar, &mtx);
1751 if (ret != 0) {
1752 talloc_free(top_ctx);
1753 pthread_mutex_unlock(&mtx);
1754 return NULL;
1755 }
1756 }
1757
1758 /* and move our memory onto it from our toplevel hierarchy. */
1759 intermediate_ptr = talloc_move(NULL, &sub_ctx);
1760
1761 /* Tell the main thread it's ready for pickup. */
1762 pthread_cond_broadcast(&condvar);
1763 pthread_mutex_unlock(&mtx);
1764
1765 talloc_free(top_ctx);
1766 return NULL;
1767}
1768
1769/* Main thread. */
1770static bool test_pthread_talloc_passing(void)
1771{
1772 int i;
1773 int ret;
1774 char str_array[NUM_THREADS][20];
1775 pthread_t thread_id;
1776 void *mem_ctx;
1777
1778 /*
1779 * Important ! Null tracking breaks threaded talloc.
1780 * It *must* be turned off.
1781 */
1782 talloc_disable_null_tracking();
1783
1784 printf("test: pthread_talloc_passing\n# PTHREAD TALLOC PASSING\n");
1785
1786 /* Main thread toplevel context. */
1787 mem_ctx = talloc_named_const(NULL, 0, "toplevel");
1788 if (mem_ctx == NULL) {
1789 printf("failed to create toplevel context\n");
1790 return false;
1791 }
1792
1793 /*
1794 * Spin off NUM_THREADS threads.
1795 * They will use their own toplevel contexts.
1796 */
1797 for (i = 0; i < NUM_THREADS; i++) {
1798 (void)snprintf(str_array[i],
1799 20,
1800 "thread:%d",
1801 i);
1802 if (str_array[i] == NULL) {
1803 printf("snprintf %d failed\n", i);
1804 return false;
1805 }
1806 ret = pthread_create(&thread_id,
1807 NULL,
1808 thread_fn,
1809 str_array[i]);
1810 if (ret != 0) {
1811 printf("failed to create thread %d (%d)\n", i, ret);
1812 return false;
1813 }
1814 }
1815
1816 printf("Created %d threads\n", NUM_THREADS);
1817
1818 /* Now wait for NUM_THREADS transfers of the talloc'ed memory. */
1819 for (i = 0; i < NUM_THREADS; i++) {
1820 ret = pthread_mutex_lock(&mtx);
1821 if (ret != 0) {
1822 printf("pthread_mutex_lock %d failed (%d)\n", i, ret);
1823 talloc_free(mem_ctx);
1824 return false;
1825 }
1826
1827 /* Wait for intermediate_ptr to have our data. */
1828 while (intermediate_ptr == NULL) {
1829 ret = pthread_cond_wait(&condvar, &mtx);
1830 if (ret != 0) {
1831 printf("pthread_cond_wait %d failed (%d)\n", i,
1832 ret);
1833 talloc_free(mem_ctx);
1834 pthread_mutex_unlock(&mtx);
1835 return false;
1836 }
1837 }
1838
1839 /* and move it onto our toplevel hierarchy. */
1840 (void)talloc_move(mem_ctx, &intermediate_ptr);
1841
1842 /* Tell the sub-threads we're ready for another. */
1843 pthread_cond_broadcast(&condvar);
1844 pthread_mutex_unlock(&mtx);
1845 }
1846
1847 CHECK_SIZE("pthread_talloc_passing", mem_ctx, NUM_THREADS * 100);
1848#if 1
1849 /* Dump the hierarchy. */
1850 talloc_report(mem_ctx, stdout);
1851#endif
1852 talloc_free(mem_ctx);
1853 printf("success: pthread_talloc_passing\n");
1854 return true;
1855}
1856#endif
1857
1858static void test_magic_protection_abort(const char *reason)
1859{
1860 /* exit with errcode 42 to communicate successful test to the parent process */
1861 if (strcmp(reason, "Bad talloc magic value - unknown value") == 0) {
1862 _exit(42);
1863 } else {
1864 printf("talloc aborted for an unexpected reason\n");
1865 }
1866}
1867
1868static bool test_magic_protection(void)
1869{
1870 void *pool = talloc_pool(NULL, 1024);
1871 int *p1, *p2;
1872 pid_t pid;
1873 int exit_status;
1874
1875 printf("test: magic_protection\n");
1876 p1 = talloc(pool, int);
1877 p2 = talloc(pool, int);
1878
1879 /* To avoid complaints from the compiler assign values to the p1 & p2. */
1880 *p1 = 6;
1881 *p2 = 9;
1882
1883 pid = fork();
1884 if (pid == 0) {
1885 talloc_set_abort_fn(test_magic_protection_abort);
1886
1887 /*
1888 * Simulate a security attack
1889 * by triggering a buffer overflow in memset to overwrite the
1890 * constructor in the next pool chunk.
1891 *
1892 * Real attacks would attempt to set a real destructor.
1893 */
1894 memset(p1, '\0', 32);
1895
1896 /* Then the attack takes effect when the memory's freed. */
1897 talloc_free(pool);
1898
1899 /* Never reached. Make compilers happy */
1900 return true;
1901 }
1902
1903 while (wait(&exit_status) != pid);
1904
1905 if (!WIFEXITED(exit_status)) {
1906 printf("Child exited through unexpected abnormal means\n");
1907 return false;
1908 }
1909 if (WEXITSTATUS(exit_status) != 42) {
1910 printf("Child exited with wrong exit status\n");
1911 return false;
1912 }
1913 if (WIFSIGNALED(exit_status)) {
1914 printf("Child recieved unexpected signal\n");
1915 return false;
1916 }
1917
1918 printf("success: magic_protection\n");
1919 return true;
1920}
1921
1922static void test_reset(void)
1923{
1924 talloc_set_log_fn(test_log_stdout);
1925 test_abort_stop();
1926 talloc_disable_null_tracking();
1927 talloc_enable_null_tracking_no_autofree();
1928}
1929
1930bool torture_local_talloc(struct torture_context *tctx)
1931{
1932 bool ret = true;
1933
1934 setlinebuf(stdout);
1935
1936 test_reset();
1937 ret &= test_pooled_object();
1938 test_reset();
1939 ret &= test_pool_nest();
1940 test_reset();
1941 ret &= test_ref1();
1942 test_reset();
1943 ret &= test_ref2();
1944 test_reset();
1945 ret &= test_ref3();
1946 test_reset();
1947 ret &= test_ref4();
1948 test_reset();
1949 ret &= test_unlink1();
1950 test_reset();
1951 ret &= test_misc();
1952 test_reset();
1953 ret &= test_realloc();
1954 test_reset();
1955 ret &= test_realloc_child();
1956 test_reset();
1957 ret &= test_steal();
1958 test_reset();
1959 ret &= test_move();
1960 test_reset();
1961 ret &= test_unref_reparent();
1962 test_reset();
1963 ret &= test_realloc_fn();
1964 test_reset();
1965 ret &= test_type();
1966 test_reset();
1967 ret &= test_lifeless();
1968 test_reset();
1969 ret &= test_loop();
1970 test_reset();
1971 ret &= test_free_parent_deny_child();
1972 test_reset();
1973 ret &= test_free_parent_reparent_child();
1974 test_reset();
1975 ret &= test_free_parent_reparent_child_in_pool();
1976 test_reset();
1977 ret &= test_talloc_ptrtype();
1978 test_reset();
1979 ret &= test_talloc_free_in_destructor();
1980 test_reset();
1981 ret &= test_pool();
1982 test_reset();
1983 ret &= test_pool_steal();
1984 test_reset();
1985 ret &= test_free_ref_null_context();
1986 test_reset();
1987 ret &= test_rusty();
1988 test_reset();
1989 ret &= test_free_children();
1990 test_reset();
1991 ret &= test_memlimit();
1992#ifdef HAVE_PTHREAD
1993 test_reset();
1994 ret &= test_pthread_talloc_passing();
1995#endif
1996
1997
1998 if (ret) {
1999 test_reset();
2000 ret &= test_speed();
2001 }
2002 test_reset();
2003 ret &= test_autofree();
2004 test_reset();
2005 ret &= test_magic_protection();
2006
2007 test_reset();
2008 talloc_disable_null_tracking();
2009 return ret;
2010}
Note: See TracBrowser for help on using the repository browser.