run-allocfail.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include <ccan/tal/tal.h>
  2. #include <ccan/tal/tal.c>
  3. #include <ccan/tap/tap.h>
  4. static int alloc_count, when_to_fail, err_count;
  5. static bool stealing;
  6. static void *failing_alloc(size_t len)
  7. {
  8. if (alloc_count++ == when_to_fail)
  9. return NULL;
  10. /* once we've failed once, it shouldn't ask again (steal can though). */
  11. assert(stealing || alloc_count <= when_to_fail);
  12. return malloc(len);
  13. }
  14. static void *failing_realloc(void *p, size_t len)
  15. {
  16. if (alloc_count++ == when_to_fail)
  17. return NULL;
  18. return realloc(p, len);
  19. }
  20. static void nofail_on_error(const char *msg)
  21. {
  22. diag("ERROR: %s", msg);
  23. err_count++;
  24. }
  25. static void destroy_p(void *p UNNEEDED)
  26. {
  27. }
  28. int main(void)
  29. {
  30. char *p, *c1, *c2;
  31. bool success;
  32. plan_tests(25);
  33. tal_set_backend(failing_alloc, failing_realloc, NULL, nofail_on_error);
  34. /* Fail at each possible point in an allocation. */
  35. when_to_fail = err_count = 0;
  36. do {
  37. alloc_count = 0;
  38. p = tal(NULL, char);
  39. when_to_fail++;
  40. } while (!p);
  41. ok1(alloc_count >= 1);
  42. ok1(when_to_fail > 1);
  43. ok1(err_count == when_to_fail - 1);
  44. /* Do it again. */
  45. when_to_fail = err_count = 0;
  46. do {
  47. alloc_count = 0;
  48. c1 = tal(p, char);
  49. when_to_fail++;
  50. } while (!c1);
  51. ok1(alloc_count >= 1);
  52. ok1(when_to_fail > 1);
  53. ok1(err_count == when_to_fail - 1);
  54. /* Now during resize. */
  55. c2 = c1;
  56. when_to_fail = err_count = 0;
  57. for (;;) {
  58. alloc_count = 0;
  59. if (tal_resize(&c1, 100))
  60. break;
  61. /* Failing alloc will not change pointer. */
  62. ok1(c1 == c2);
  63. when_to_fail++;
  64. };
  65. ok1(alloc_count == 1);
  66. ok1(when_to_fail == 1);
  67. ok1(err_count == 1);
  68. /* Make sure it's really resized. */
  69. memset(c1, 1, 100);
  70. /* Now for second child. */
  71. when_to_fail = err_count = 0;
  72. do {
  73. alloc_count = 0;
  74. c2 = tal(p, char);
  75. when_to_fail++;
  76. } while (!c2);
  77. ok1(alloc_count >= 1);
  78. ok1(when_to_fail > 1);
  79. /* Note: adding a child will fall through if group alloc fails. */
  80. ok1 (err_count == when_to_fail - 1 || err_count == when_to_fail);
  81. /* Now while adding a destructor. */
  82. when_to_fail = err_count = 0;
  83. do {
  84. alloc_count = 0;
  85. success = tal_add_destructor(p, destroy_p);
  86. when_to_fail++;
  87. } while (!success);
  88. ok1(alloc_count >= 1);
  89. ok1(when_to_fail > 1);
  90. ok1(err_count == when_to_fail - 1);
  91. /* Now while adding a name. */
  92. when_to_fail = err_count = 0;
  93. do {
  94. const char name[] = "some name";
  95. alloc_count = 0;
  96. success = tal_set_name(p, name);
  97. when_to_fail++;
  98. } while (!success);
  99. ok1(alloc_count >= 1);
  100. ok1(when_to_fail > 1);
  101. ok1(err_count == when_to_fail - 1);
  102. /* Now while stealing. */
  103. stealing = true;
  104. when_to_fail = err_count = 0;
  105. do {
  106. alloc_count = 0;
  107. success = tal_steal(c2, c1) != NULL;
  108. when_to_fail++;
  109. } while (!success);
  110. ok1(alloc_count >= 1);
  111. ok1(when_to_fail > 1);
  112. ok1(err_count == when_to_fail - 1);
  113. /* Now stealing with more children (more coverage). */
  114. when_to_fail = 1000;
  115. (void)tal(p, char);
  116. c1 = tal(p, char);
  117. c2 = tal(p, char);
  118. (void)tal(p, char);
  119. /* Now steal again. */
  120. when_to_fail = err_count = 0;
  121. do {
  122. alloc_count = 0;
  123. success = tal_steal(c2, c1) != NULL;
  124. when_to_fail++;
  125. } while (!success);
  126. ok1(alloc_count >= 1);
  127. ok1(when_to_fail > 1);
  128. ok1(err_count == when_to_fail - 1);
  129. tal_free(p);
  130. tal_cleanup();
  131. return exit_status();
  132. }