test_custom_allocators.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /**
  2. * \file test_custom_allocators.cpp
  3. * \brief Custom allocators test
  4. *
  5. * \copyright Copyright (C) 2016 Jeremy Tan.
  6. * This file is released under the MIT license.
  7. * See LICENSE for details.
  8. */
  9. /*
  10. * I thought about using gmock and came to the conclusion that it's easier
  11. * to make my own mocks. Tests should *not* be run in parallel.
  12. */
  13. #include <gtest/gtest.h>
  14. #include <libclipboard.h>
  15. #include <atomic>
  16. #include <assert.h>
  17. #include "libclipboard-test-private.h"
  18. struct {
  19. std::atomic<int> alloc_fail_count;
  20. std::atomic<int> malloc_count;
  21. std::atomic<int> calloc_count;
  22. std::atomic<int> realloc_count;
  23. std::atomic<int> free_count;
  24. } g_alloc_counts;
  25. struct {
  26. std::atomic<clipboard_malloc_fn> malloc_ptr;
  27. std::atomic<clipboard_calloc_fn> calloc_ptr;
  28. std::atomic<clipboard_realloc_fn> realloc_ptr;
  29. std::atomic<clipboard_free_fn> free_ptr;
  30. } g_alloc_ptrs;
  31. static void *mock_malloc(size_t size) {
  32. g_alloc_counts.malloc_count++;
  33. if (g_alloc_ptrs.malloc_ptr.load()) {
  34. void *ret;
  35. ret = g_alloc_ptrs.malloc_ptr.load()(size);
  36. assert(ret != NULL);
  37. return ret;
  38. }
  39. g_alloc_counts.alloc_fail_count++;
  40. return NULL;
  41. }
  42. static void *mock_calloc(size_t nmemb, size_t size) {
  43. g_alloc_counts.calloc_count++;
  44. if (g_alloc_ptrs.calloc_ptr.load()) {
  45. void *ret;
  46. ret = g_alloc_ptrs.calloc_ptr.load()(nmemb, size);
  47. assert(ret != NULL);
  48. return ret;
  49. }
  50. g_alloc_counts.alloc_fail_count++;
  51. return NULL;
  52. }
  53. static void *mock_realloc(void *ptr, size_t size) {
  54. g_alloc_counts.realloc_count++;
  55. if (ptr == NULL) {
  56. g_alloc_counts.malloc_count++;
  57. }
  58. if (g_alloc_ptrs.realloc_ptr.load()) {
  59. void *ret;
  60. ret = g_alloc_ptrs.realloc_ptr.load()(ptr, size);
  61. assert(ret != NULL);
  62. return ret;
  63. }
  64. g_alloc_counts.alloc_fail_count++;
  65. return NULL;
  66. }
  67. static void mock_free(void *ptr) {
  68. g_alloc_counts.free_count++;
  69. if (g_alloc_ptrs.free_ptr.load()) {
  70. g_alloc_ptrs.free_ptr.load()(ptr);
  71. }
  72. }
  73. class CustomAllocatorsTest : public ::testing::Test {
  74. protected:
  75. CustomAllocatorsTest() : std_mock{} {
  76. std_mock.user_malloc_fn = mock_malloc;
  77. std_mock.user_calloc_fn = mock_calloc;
  78. std_mock.user_realloc_fn = mock_realloc;
  79. std_mock.user_free_fn = mock_free;
  80. g_alloc_counts.alloc_fail_count = 0;
  81. g_alloc_counts.malloc_count = 0;
  82. g_alloc_counts.calloc_count = 0;
  83. g_alloc_counts.realloc_count = 0;
  84. g_alloc_counts.free_count = 0;
  85. g_alloc_ptrs.malloc_ptr = malloc;
  86. g_alloc_ptrs.calloc_ptr = calloc;
  87. g_alloc_ptrs.realloc_ptr = realloc;
  88. g_alloc_ptrs.free_ptr = free;
  89. }
  90. clipboard_opts std_mock;
  91. };
  92. TEST_F(CustomAllocatorsTest, TestAllocatorsFail) {
  93. g_alloc_ptrs.malloc_ptr = nullptr;
  94. g_alloc_ptrs.calloc_ptr = nullptr;
  95. g_alloc_ptrs.realloc_ptr = nullptr;
  96. g_alloc_ptrs.free_ptr = nullptr;
  97. clipboard_c *cb = clipboard_new(&std_mock);
  98. ASSERT_TRUE(cb == NULL);
  99. int alloc_counts = g_alloc_counts.malloc_count + g_alloc_counts.calloc_count;
  100. // Expect at least one alloc call
  101. ASSERT_GT(alloc_counts, 0);
  102. // No. of frees should at least match no. of successful allocs.
  103. ASSERT_GE(g_alloc_counts.free_count, alloc_counts - g_alloc_counts.alloc_fail_count);
  104. }
  105. TEST_F(CustomAllocatorsTest, TestAllocationsMatchesFrees) {
  106. clipboard_c *cb = clipboard_new(&std_mock);
  107. ASSERT_TRUE(cb != NULL);
  108. ASSERT_TRUE(clipboard_set_text(cb, "allocTest"));
  109. mock_free(clipboard_text(cb));
  110. clipboard_free(cb);
  111. int alloc_counts = g_alloc_counts.malloc_count + g_alloc_counts.calloc_count;
  112. // Expect at least one alloc call
  113. ASSERT_GT(alloc_counts, 0);
  114. // No. of frees should at least match no. of successful allocs.
  115. ASSERT_GE(g_alloc_counts.free_count, alloc_counts - g_alloc_counts.alloc_fail_count);
  116. }
  117. TEST_F(CustomAllocatorsTest, TestAllocationsMatchesFreesEx) {
  118. clipboard_c *cb1 = clipboard_new(NULL);
  119. clipboard_c *cb2 = clipboard_new(&std_mock);
  120. char *text;
  121. ASSERT_TRUE(cb1 != NULL);
  122. ASSERT_TRUE(cb2 != NULL);
  123. ASSERT_TRUE(clipboard_set_text(cb1, "allocTest"));
  124. TRY_RUN_STRNE(clipboard_text(cb2), "allocTest", text);
  125. ASSERT_STREQ("allocTest", text);
  126. mock_free(text);
  127. clipboard_free(cb1);
  128. clipboard_free(cb2);
  129. int alloc_counts = g_alloc_counts.malloc_count + g_alloc_counts.calloc_count;
  130. // Expect at least one alloc call
  131. ASSERT_GT(alloc_counts, 0);
  132. // No. of frees should at least match no. of successful allocs.
  133. ASSERT_GE(g_alloc_counts.free_count, alloc_counts - g_alloc_counts.alloc_fail_count);
  134. }
  135. TEST_F(CustomAllocatorsTest, TestAllocationFailOnGetText) {
  136. clipboard_c *cb = clipboard_new(&std_mock);
  137. ASSERT_TRUE(cb != NULL);
  138. ASSERT_TRUE(clipboard_set_text(cb, "allocTest2"));
  139. g_alloc_ptrs.malloc_ptr = nullptr;
  140. g_alloc_ptrs.calloc_ptr = nullptr;
  141. g_alloc_ptrs.realloc_ptr = nullptr;
  142. ASSERT_TRUE(clipboard_text(cb) == NULL);
  143. clipboard_free(cb);
  144. int alloc_counts = g_alloc_counts.malloc_count + g_alloc_counts.calloc_count;
  145. // Expect at least one alloc call
  146. ASSERT_GT(alloc_counts, 0);
  147. // No. of frees should at least match no. of successful allocs.
  148. ASSERT_GE(g_alloc_counts.free_count, alloc_counts - g_alloc_counts.alloc_fail_count);
  149. }