resource_interface_unittest.cc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/reporting/resources/resource_interface.h"
  5. #include <cstdint>
  6. #include <utility>
  7. #include "base/memory/scoped_refptr.h"
  8. #include "base/task/task_runner.h"
  9. #include "base/task/thread_pool.h"
  10. #include "base/test/task_environment.h"
  11. #include "components/reporting/resources/disk_resource_impl.h"
  12. #include "components/reporting/resources/memory_resource_impl.h"
  13. #include "components/reporting/util/test_support_callbacks.h"
  14. #include "testing/gmock/include/gmock/gmock.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. using ::testing::Eq;
  17. namespace reporting {
  18. namespace {
  19. class ResourceInterfaceTest
  20. : public ::testing::TestWithParam<scoped_refptr<ResourceInterface>> {
  21. protected:
  22. void SetUp() override {
  23. // Make sure parameters define reasonably large total resource size.
  24. ASSERT_GE(resource_interface()->GetTotal(), 1u * 1024LLu * 1024LLu);
  25. }
  26. scoped_refptr<ResourceInterface> resource_interface() const {
  27. return GetParam();
  28. }
  29. void TearDown() override {
  30. EXPECT_THAT(resource_interface()->GetUsed(), Eq(0u));
  31. }
  32. private:
  33. base::test::TaskEnvironment task_environment_;
  34. };
  35. TEST_P(ResourceInterfaceTest, NestedReservationTest) {
  36. uint64_t size = resource_interface()->GetTotal();
  37. while ((size / 2) > 0u) {
  38. size /= 2;
  39. EXPECT_TRUE(resource_interface()->Reserve(size));
  40. }
  41. for (; size < resource_interface()->GetTotal(); size *= 2) {
  42. resource_interface()->Discard(size);
  43. }
  44. }
  45. TEST_P(ResourceInterfaceTest, SimultaneousReservationTest) {
  46. uint64_t size = resource_interface()->GetTotal();
  47. // Schedule reservations.
  48. test::TestCallbackWaiter reserve_waiter;
  49. while ((size / 2) > 0u) {
  50. size /= 2;
  51. reserve_waiter.Attach();
  52. base::ThreadPool::PostTask(
  53. FROM_HERE, {base::TaskPriority::BEST_EFFORT},
  54. base::BindOnce(
  55. [](size_t size, scoped_refptr<ResourceInterface> resource_interface,
  56. test::TestCallbackWaiter* waiter) {
  57. EXPECT_TRUE(resource_interface->Reserve(size));
  58. waiter->Signal();
  59. },
  60. size, resource_interface(), &reserve_waiter));
  61. }
  62. reserve_waiter.Wait();
  63. // Schedule discards.
  64. test::TestCallbackWaiter discard_waiter;
  65. for (; size < resource_interface()->GetTotal(); size *= 2) {
  66. discard_waiter.Attach();
  67. base::ThreadPool::PostTask(
  68. FROM_HERE, {base::TaskPriority::BEST_EFFORT},
  69. base::BindOnce(
  70. [](size_t size, scoped_refptr<ResourceInterface> resource_interface,
  71. test::TestCallbackWaiter* waiter) {
  72. resource_interface->Discard(size);
  73. waiter->Signal();
  74. },
  75. size, resource_interface(), &discard_waiter));
  76. }
  77. discard_waiter.Wait();
  78. }
  79. TEST_P(ResourceInterfaceTest, SimultaneousScopedReservationTest) {
  80. uint64_t size = resource_interface()->GetTotal();
  81. test::TestCallbackWaiter waiter;
  82. while ((size / 2) > 0u) {
  83. size /= 2;
  84. waiter.Attach();
  85. base::ThreadPool::PostTask(
  86. FROM_HERE, {base::TaskPriority::BEST_EFFORT},
  87. base::BindOnce(
  88. [](size_t size, scoped_refptr<ResourceInterface> resource_interface,
  89. test::TestCallbackWaiter* waiter) {
  90. { ScopedReservation(size, resource_interface); }
  91. waiter->Signal();
  92. },
  93. size, resource_interface(), &waiter));
  94. }
  95. waiter.Wait();
  96. }
  97. TEST_P(ResourceInterfaceTest, MoveScopedReservationTest) {
  98. uint64_t size = resource_interface()->GetTotal();
  99. ScopedReservation scoped_reservation(size / 2, resource_interface());
  100. EXPECT_TRUE(scoped_reservation.reserved());
  101. {
  102. ScopedReservation moved_scoped_reservation(std::move(scoped_reservation));
  103. EXPECT_TRUE(moved_scoped_reservation.reserved());
  104. EXPECT_FALSE(scoped_reservation.reserved());
  105. }
  106. EXPECT_FALSE(scoped_reservation.reserved());
  107. }
  108. TEST_P(ResourceInterfaceTest, ScopedReservationBasicReduction) {
  109. uint64_t size = resource_interface()->GetTotal() / 2;
  110. ScopedReservation scoped_reservation(size, resource_interface());
  111. EXPECT_TRUE(scoped_reservation.reserved());
  112. EXPECT_TRUE(scoped_reservation.Reduce(size / 2));
  113. }
  114. TEST_P(ResourceInterfaceTest, ScopedReservationReductionWithLargerNewSize) {
  115. uint64_t size = resource_interface()->GetTotal() / 2;
  116. ScopedReservation scoped_reservation(size, resource_interface());
  117. EXPECT_TRUE(scoped_reservation.reserved());
  118. EXPECT_FALSE(scoped_reservation.Reduce(size + 1));
  119. }
  120. TEST_P(ResourceInterfaceTest, ScopedReservationReductionWithNegativeNewSize) {
  121. uint64_t size = resource_interface()->GetTotal() / 2;
  122. ScopedReservation scoped_reservation(size, resource_interface());
  123. EXPECT_TRUE(scoped_reservation.reserved());
  124. EXPECT_FALSE(scoped_reservation.Reduce(-(size / 2)));
  125. }
  126. TEST_P(ResourceInterfaceTest, ScopedReservationRepeatingReductions) {
  127. uint64_t size = resource_interface()->GetTotal() / 2;
  128. ScopedReservation scoped_reservation(size, resource_interface());
  129. EXPECT_TRUE(scoped_reservation.reserved());
  130. for (; size >= 2; size /= 2) {
  131. EXPECT_TRUE(scoped_reservation.Reduce(size / 2));
  132. }
  133. EXPECT_TRUE(scoped_reservation.Reduce(size / 2));
  134. EXPECT_FALSE(scoped_reservation.reserved());
  135. }
  136. TEST_P(ResourceInterfaceTest, ScopedReservationBasicHandOver) {
  137. uint64_t size = resource_interface()->GetTotal() / 2;
  138. ScopedReservation scoped_reservation(size, resource_interface());
  139. ASSERT_TRUE(scoped_reservation.reserved());
  140. {
  141. ScopedReservation another_reservation(size - 1, resource_interface());
  142. ASSERT_TRUE(another_reservation.reserved());
  143. EXPECT_THAT(resource_interface()->GetUsed(),
  144. Eq(resource_interface()->GetTotal() - 1));
  145. EXPECT_TRUE(scoped_reservation.reserved());
  146. EXPECT_TRUE(another_reservation.reserved());
  147. scoped_reservation.HandOver(another_reservation);
  148. EXPECT_THAT(resource_interface()->GetUsed(),
  149. Eq(resource_interface()->GetTotal() - 1));
  150. }
  151. // Destruction of |anoter_reservation| does not change the amount used.
  152. EXPECT_THAT(resource_interface()->GetUsed(),
  153. Eq(resource_interface()->GetTotal() - 1));
  154. }
  155. TEST_P(ResourceInterfaceTest, ScopedReservationRepeatingHandOvers) {
  156. uint64_t size = resource_interface()->GetTotal() / 2;
  157. ScopedReservation scoped_reservation(size, resource_interface());
  158. EXPECT_TRUE(scoped_reservation.reserved());
  159. for (; size >= 2; size /= 2) {
  160. ScopedReservation another_reservation(size / 2, resource_interface());
  161. scoped_reservation.HandOver(another_reservation);
  162. }
  163. EXPECT_THAT(resource_interface()->GetUsed(),
  164. Eq(resource_interface()->GetTotal() - 1));
  165. }
  166. TEST_P(ResourceInterfaceTest, ScopedReservationRepeatingCopyHandOvers) {
  167. uint64_t size = resource_interface()->GetTotal() / 2;
  168. ScopedReservation scoped_reservation(size, resource_interface());
  169. EXPECT_TRUE(scoped_reservation.reserved());
  170. for (; size >= 2; size /= 2) {
  171. ScopedReservation another_reservation(size / 2, scoped_reservation);
  172. EXPECT_TRUE(another_reservation.reserved());
  173. scoped_reservation.HandOver(another_reservation);
  174. }
  175. EXPECT_THAT(resource_interface()->GetUsed(),
  176. Eq(resource_interface()->GetTotal() - 1));
  177. }
  178. TEST_P(ResourceInterfaceTest, ScopedReservationFailureToCopyFromEmpty) {
  179. ScopedReservation scoped_reservation;
  180. uint64_t size = resource_interface()->GetTotal() / 2;
  181. ScopedReservation another_reservation(size, scoped_reservation);
  182. EXPECT_FALSE(scoped_reservation.reserved());
  183. }
  184. TEST_P(ResourceInterfaceTest, ScopedReservationRepeatingHandOversToEmpty) {
  185. ScopedReservation scoped_reservation;
  186. EXPECT_FALSE(scoped_reservation.reserved());
  187. uint64_t size = resource_interface()->GetTotal();
  188. for (; size >= 2; size /= 2) {
  189. ScopedReservation another_reservation(size / 2, resource_interface());
  190. scoped_reservation.HandOver(another_reservation);
  191. }
  192. EXPECT_THAT(resource_interface()->GetUsed(),
  193. Eq(resource_interface()->GetTotal() - 1));
  194. }
  195. TEST_P(ResourceInterfaceTest, ScopedReservationEmptyHandOver) {
  196. uint64_t size = resource_interface()->GetTotal() / 2;
  197. ScopedReservation scoped_reservation(size, resource_interface());
  198. ASSERT_TRUE(scoped_reservation.reserved());
  199. {
  200. ScopedReservation another_reservation(size - 1, resource_interface());
  201. ASSERT_TRUE(another_reservation.reserved());
  202. EXPECT_THAT(resource_interface()->GetUsed(),
  203. Eq(resource_interface()->GetTotal() - 1));
  204. EXPECT_TRUE(scoped_reservation.reserved());
  205. EXPECT_TRUE(another_reservation.reserved());
  206. another_reservation.Reduce(0);
  207. ASSERT_FALSE(another_reservation.reserved());
  208. scoped_reservation.HandOver(another_reservation);
  209. EXPECT_THAT(resource_interface()->GetUsed(), Eq(size));
  210. }
  211. // Destruction of |anoter_reservation| does not change the amount used.
  212. EXPECT_THAT(resource_interface()->GetUsed(), Eq(size));
  213. }
  214. TEST_P(ResourceInterfaceTest, ReservationOverMaxTest) {
  215. EXPECT_FALSE(
  216. resource_interface()->Reserve(resource_interface()->GetTotal() + 1));
  217. EXPECT_TRUE(resource_interface()->Reserve(resource_interface()->GetTotal()));
  218. resource_interface()->Discard(resource_interface()->GetTotal());
  219. }
  220. INSTANTIATE_TEST_SUITE_P(
  221. VariousResources,
  222. ResourceInterfaceTest,
  223. testing::Values(
  224. base::MakeRefCounted<DiskResourceImpl>(16u * 1024LLu * 1024LLu),
  225. base::MakeRefCounted<MemoryResourceImpl>(4u * 1024LLu * 1024LLu)));
  226. } // namespace
  227. } // namespace reporting