tab_node_pool_unittest.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright 2014 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/sync_sessions/tab_node_pool.h"
  5. #include <vector>
  6. #include "testing/gmock/include/gmock/gmock.h"
  7. #include "testing/gtest/include/gtest/gtest.h"
  8. namespace sync_sessions {
  9. namespace {
  10. using testing::ElementsAre;
  11. using testing::UnorderedElementsAre;
  12. const int kTabNodeId1 = 10;
  13. const int kTabNodeId2 = 5;
  14. const SessionID kTabId1 = SessionID::FromSerializedValue(1010);
  15. const SessionID kTabId2 = SessionID::FromSerializedValue(1020);
  16. const SessionID kTabId3 = SessionID::FromSerializedValue(1030);
  17. const SessionID kTabId4 = SessionID::FromSerializedValue(1040);
  18. const SessionID kTabId5 = SessionID::FromSerializedValue(1050);
  19. const SessionID kTabId6 = SessionID::FromSerializedValue(1060);
  20. class SyncTabNodePoolTest : public testing::Test {
  21. protected:
  22. SyncTabNodePoolTest() = default;
  23. int GetMaxUsedTabNodeId() const { return pool_.GetMaxUsedTabNodeIdForTest(); }
  24. void AddFreeTabNodes(const std::vector<int>& node_ids) {
  25. const SessionID kTmpTabId = SessionID::FromSerializedValue(123);
  26. for (int node_id : node_ids) {
  27. pool_.ReassociateTabNode(node_id, kTmpTabId);
  28. pool_.FreeTab(kTmpTabId);
  29. }
  30. }
  31. TabNodePool pool_;
  32. };
  33. TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldIncrease) {
  34. EXPECT_EQ(-1, GetMaxUsedTabNodeId());
  35. pool_.ReassociateTabNode(10, kTabId1);
  36. EXPECT_EQ(10, GetMaxUsedTabNodeId());
  37. pool_.ReassociateTabNode(5, kTabId2);
  38. EXPECT_EQ(10, GetMaxUsedTabNodeId());
  39. pool_.ReassociateTabNode(20, kTabId3);
  40. EXPECT_EQ(20, GetMaxUsedTabNodeId());
  41. }
  42. TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldDecrease) {
  43. pool_.ReassociateTabNode(10, kTabId1);
  44. pool_.ReassociateTabNode(5, kTabId2);
  45. pool_.ReassociateTabNode(20, kTabId3);
  46. EXPECT_EQ(20, GetMaxUsedTabNodeId());
  47. pool_.FreeTab(kTabId3);
  48. ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(20));
  49. EXPECT_EQ(10, GetMaxUsedTabNodeId());
  50. pool_.FreeTab(kTabId1);
  51. ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(10));
  52. EXPECT_EQ(5, GetMaxUsedTabNodeId());
  53. pool_.FreeTab(kTabId2);
  54. ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(5));
  55. EXPECT_EQ(-1, GetMaxUsedTabNodeId());
  56. }
  57. TEST_F(SyncTabNodePoolTest, MaxTabNodeIdShouldNotChange) {
  58. pool_.ReassociateTabNode(10, kTabId1);
  59. pool_.ReassociateTabNode(5, kTabId2);
  60. pool_.ReassociateTabNode(20, kTabId3);
  61. EXPECT_EQ(20, GetMaxUsedTabNodeId());
  62. pool_.FreeTab(kTabId1);
  63. ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(10));
  64. EXPECT_EQ(20, GetMaxUsedTabNodeId());
  65. pool_.FreeTab(kTabId2);
  66. ASSERT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(5));
  67. EXPECT_EQ(20, GetMaxUsedTabNodeId());
  68. }
  69. TEST_F(SyncTabNodePoolTest, Reassociation) {
  70. // Reassociate tab node 1 with tab id 1.
  71. pool_.ReassociateTabNode(kTabNodeId1, kTabId1);
  72. EXPECT_EQ(kTabId1, pool_.GetTabIdFromTabNodeId(kTabNodeId1));
  73. EXPECT_FALSE(pool_.GetTabIdFromTabNodeId(kTabNodeId2).is_valid());
  74. // Introduce a new tab node associated with the same tab. The old tab node
  75. // should get added to the free pool
  76. pool_.ReassociateTabNode(kTabNodeId2, kTabId1);
  77. EXPECT_FALSE(pool_.GetTabIdFromTabNodeId(kTabNodeId1).is_valid());
  78. EXPECT_EQ(kTabId1, pool_.GetTabIdFromTabNodeId(kTabNodeId2));
  79. // Reassociating the same tab node/tab should have no effect.
  80. pool_.ReassociateTabNode(kTabNodeId2, kTabId1);
  81. EXPECT_FALSE(pool_.GetTabIdFromTabNodeId(kTabNodeId1).is_valid());
  82. EXPECT_EQ(kTabId1, pool_.GetTabIdFromTabNodeId(kTabNodeId2));
  83. // Reassociating the new tab node with a new tab should just update the
  84. // association tables.
  85. pool_.ReassociateTabNode(kTabNodeId2, kTabId2);
  86. EXPECT_FALSE(pool_.GetTabIdFromTabNodeId(kTabNodeId1).is_valid());
  87. EXPECT_EQ(kTabId2, pool_.GetTabIdFromTabNodeId(kTabNodeId2));
  88. // Reassociating the first tab node should make the pool empty.
  89. pool_.ReassociateTabNode(kTabNodeId1, kTabId1);
  90. EXPECT_EQ(kTabId1, pool_.GetTabIdFromTabNodeId(kTabNodeId1));
  91. EXPECT_EQ(kTabId2, pool_.GetTabIdFromTabNodeId(kTabNodeId2));
  92. }
  93. TEST_F(SyncTabNodePoolTest, ReassociateThenFree) {
  94. // Verify old tab nodes are reassociated correctly.
  95. pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1);
  96. pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2);
  97. pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3);
  98. // Free tabs 2 and 3.
  99. pool_.FreeTab(kTabId2);
  100. pool_.FreeTab(kTabId3);
  101. EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
  102. pool_.GetTabNodeIdFromTabId(kTabId2));
  103. EXPECT_EQ(TabNodePool::kInvalidTabNodeID,
  104. pool_.GetTabNodeIdFromTabId(kTabId3));
  105. EXPECT_NE(TabNodePool::kInvalidTabNodeID,
  106. pool_.GetTabNodeIdFromTabId(kTabId1));
  107. // Free node pool should have 1 (for kTabId2) and 2 (for kTabId3).
  108. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId4));
  109. EXPECT_EQ(2, pool_.AssociateWithFreeTabNode(kTabId5));
  110. }
  111. TEST_F(SyncTabNodePoolTest, AssociateWithFreeTabNode) {
  112. ASSERT_EQ(TabNodePool::kInvalidTabNodeID,
  113. pool_.GetTabNodeIdFromTabId(kTabId1));
  114. ASSERT_EQ(TabNodePool::kInvalidTabNodeID,
  115. pool_.GetTabNodeIdFromTabId(kTabId2));
  116. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId1));
  117. EXPECT_EQ(0, pool_.GetTabNodeIdFromTabId(kTabId1));
  118. ASSERT_EQ(TabNodePool::kInvalidTabNodeID,
  119. pool_.GetTabNodeIdFromTabId(kTabId2));
  120. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId2));
  121. EXPECT_EQ(1, pool_.GetTabNodeIdFromTabId(kTabId2));
  122. pool_.FreeTab(kTabId1);
  123. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId3));
  124. }
  125. TEST_F(SyncTabNodePoolTest, AssociateWithFreeTabNodesContiguous) {
  126. pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId1);
  127. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId2));
  128. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId3));
  129. // Tab node 2 is already used, so it should be skipped.
  130. EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId4));
  131. }
  132. // Tests that, when *both* a free tab node and a "hole" exists,
  133. // AssociateWithFreeTabNode() returns the smallest of them.
  134. TEST_F(SyncTabNodePoolTest, AssociateWithFreeTabNodeReturnsMinimum) {
  135. // Set up the pool such that tab node 1 is freed, and nodes 0 and 2 are holes
  136. // (missing).
  137. pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId1);
  138. pool_.ReassociateTabNode(/*tab_node_id=*/3, kTabId2);
  139. pool_.FreeTab(kTabId1);
  140. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId3));
  141. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId4));
  142. EXPECT_EQ(2, pool_.AssociateWithFreeTabNode(kTabId5));
  143. }
  144. TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMiddle) {
  145. pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1);
  146. pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2);
  147. pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3);
  148. pool_.FreeTab(kTabId2);
  149. EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(1));
  150. EXPECT_EQ(2, GetMaxUsedTabNodeId());
  151. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId4));
  152. EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId5));
  153. }
  154. TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMax) {
  155. pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1);
  156. pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2);
  157. pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3);
  158. pool_.FreeTab(kTabId3);
  159. EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(2));
  160. EXPECT_EQ(1, GetMaxUsedTabNodeId());
  161. EXPECT_EQ(2, pool_.AssociateWithFreeTabNode(kTabId4));
  162. EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId5));
  163. }
  164. TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesMultiple) {
  165. pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1);
  166. pool_.ReassociateTabNode(/*tab_node_id=*/1, kTabId2);
  167. pool_.ReassociateTabNode(/*tab_node_id=*/2, kTabId3);
  168. pool_.FreeTab(kTabId1);
  169. pool_.FreeTab(kTabId2);
  170. EXPECT_THAT(pool_.CleanupFreeTabNodes(), UnorderedElementsAre(0, 1));
  171. EXPECT_EQ(2, GetMaxUsedTabNodeId());
  172. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId4));
  173. EXPECT_EQ(1, pool_.AssociateWithFreeTabNode(kTabId5));
  174. EXPECT_EQ(3, pool_.AssociateWithFreeTabNode(kTabId6));
  175. }
  176. TEST_F(SyncTabNodePoolTest, AggressiveCleanupFreeTabNodesAll) {
  177. pool_.ReassociateTabNode(/*tab_node_id=*/0, kTabId1);
  178. pool_.FreeTab(kTabId1);
  179. EXPECT_THAT(pool_.CleanupFreeTabNodes(), ElementsAre(0));
  180. EXPECT_EQ(-1, GetMaxUsedTabNodeId());
  181. EXPECT_EQ(0, pool_.AssociateWithFreeTabNode(kTabId4));
  182. }
  183. } // namespace
  184. } // namespace sync_sessions