Home | History | Annotate | Download | only in sessions
      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 
      5 #include "chrome/browser/sync/sessions/tab_node_pool.h"
      6 
      7 #include "base/logging.h"
      8 #include "sync/api/sync_change.h"
      9 #include "sync/protocol/session_specifics.pb.h"
     10 #include "sync/protocol/sync.pb.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace browser_sync {
     14 
     15 class SyncTabNodePoolTest : public testing::Test {
     16  protected:
     17   SyncTabNodePoolTest() { pool_.SetMachineTag("tag"); }
     18 
     19   int GetMaxUsedTabNodeId() const { return pool_.max_used_tab_node_id_; }
     20 
     21   void AddFreeTabNodes(size_t size, const int node_ids[]);
     22 
     23   TabNodePool pool_;
     24 };
     25 
     26 void SyncTabNodePoolTest::AddFreeTabNodes(
     27     size_t size, const int node_ids[]) {
     28   for (size_t i = 0; i < size; ++i) {
     29     pool_.free_nodes_pool_.insert(node_ids[i]);
     30   }
     31 }
     32 
     33 namespace {
     34 
     35 TEST_F(SyncTabNodePoolTest, TabNodeIdIncreases) {
     36   syncer::SyncChangeList changes;
     37   // max_used_tab_node_ always increases.
     38   pool_.AddTabNode(10);
     39   EXPECT_EQ(10, GetMaxUsedTabNodeId());
     40   pool_.AddTabNode(5);
     41   EXPECT_EQ(10, GetMaxUsedTabNodeId());
     42   pool_.AddTabNode(1000);
     43   EXPECT_EQ(1000, GetMaxUsedTabNodeId());
     44   pool_.ReassociateTabNode(1000, 1);
     45   pool_.ReassociateTabNode(5, 2);
     46   pool_.ReassociateTabNode(10, 3);
     47   // Freeing a tab node does not change max_used_tab_node_id_.
     48   pool_.FreeTabNode(1000, &changes);
     49   EXPECT_TRUE(changes.empty());
     50   pool_.FreeTabNode(5, &changes);
     51   EXPECT_TRUE(changes.empty());
     52   pool_.FreeTabNode(10, &changes);
     53   EXPECT_TRUE(changes.empty());
     54   for (int i = 0; i < 3; ++i) {
     55     pool_.AssociateTabNode(pool_.GetFreeTabNode(&changes), i + 1);
     56     EXPECT_EQ(1000, GetMaxUsedTabNodeId());
     57   }
     58   EXPECT_TRUE(changes.empty());
     59   EXPECT_EQ(1000, GetMaxUsedTabNodeId());
     60   EXPECT_TRUE(pool_.Empty());
     61 }
     62 
     63 TEST_F(SyncTabNodePoolTest, OldTabNodesAddAndRemove) {
     64   syncer::SyncChangeList changes;
     65   // VerifyOldTabNodes are added.
     66   pool_.AddTabNode(1);
     67   pool_.AddTabNode(2);
     68   EXPECT_EQ(2u, pool_.Capacity());
     69   EXPECT_TRUE(pool_.Empty());
     70   EXPECT_TRUE(pool_.IsUnassociatedTabNode(1));
     71   EXPECT_TRUE(pool_.IsUnassociatedTabNode(2));
     72   pool_.ReassociateTabNode(1, 2);
     73   EXPECT_TRUE(pool_.Empty());
     74   pool_.AssociateTabNode(2, 3);
     75   EXPECT_FALSE(pool_.IsUnassociatedTabNode(1));
     76   EXPECT_FALSE(pool_.IsUnassociatedTabNode(2));
     77   pool_.FreeTabNode(2, &changes);
     78   EXPECT_TRUE(changes.empty());
     79   // 2 should be returned to free node pool_.
     80   EXPECT_EQ(2u, pool_.Capacity());
     81   // Should be able to free 1.
     82   pool_.FreeTabNode(1, &changes);
     83   EXPECT_FALSE(pool_.Empty());
     84   EXPECT_TRUE(pool_.Full());
     85   EXPECT_EQ(1, pool_.GetFreeTabNode(&changes));
     86   EXPECT_TRUE(changes.empty());
     87   pool_.AssociateTabNode(1, 1);
     88   EXPECT_EQ(2, pool_.GetFreeTabNode(&changes));
     89   EXPECT_TRUE(changes.empty());
     90   pool_.AssociateTabNode(2, 1);
     91   EXPECT_TRUE(pool_.Empty());
     92   EXPECT_FALSE(pool_.Full());
     93   EXPECT_FALSE(pool_.Full());
     94 }
     95 
     96 TEST_F(SyncTabNodePoolTest, OldTabNodesReassociation) {
     97   // VerifyOldTabNodes are reassociated correctly.
     98   pool_.AddTabNode(4);
     99   pool_.AddTabNode(5);
    100   pool_.AddTabNode(6);
    101   EXPECT_EQ(3u, pool_.Capacity());
    102   EXPECT_TRUE(pool_.Empty());
    103   EXPECT_TRUE(pool_.IsUnassociatedTabNode(4));
    104   pool_.ReassociateTabNode(4, 5);
    105   pool_.AssociateTabNode(5, 6);
    106   pool_.AssociateTabNode(6, 7);
    107   // Free 5 and 6.
    108   syncer::SyncChangeList changes;
    109   pool_.FreeTabNode(5, &changes);
    110   pool_.FreeTabNode(6, &changes);
    111   EXPECT_TRUE(changes.empty());
    112   // 5 and 6 nodes should not be unassociated.
    113   EXPECT_FALSE(pool_.IsUnassociatedTabNode(5));
    114   EXPECT_FALSE(pool_.IsUnassociatedTabNode(6));
    115   // Free node pool should have 5 and 6.
    116   EXPECT_FALSE(pool_.Empty());
    117   EXPECT_EQ(3u, pool_.Capacity());
    118 
    119   // Free all nodes
    120   pool_.FreeTabNode(4, &changes);
    121   EXPECT_TRUE(changes.empty());
    122   EXPECT_TRUE(pool_.Full());
    123   std::set<int> free_sync_ids;
    124   for (int i = 0; i < 3; ++i) {
    125     free_sync_ids.insert(pool_.GetFreeTabNode(&changes));
    126     // GetFreeTabNode will return the same value till the node is
    127     // reassociated.
    128     pool_.AssociateTabNode(pool_.GetFreeTabNode(&changes), i + 1);
    129   }
    130 
    131   EXPECT_TRUE(pool_.Empty());
    132   EXPECT_EQ(3u, free_sync_ids.size());
    133   EXPECT_EQ(1u, free_sync_ids.count(4));
    134   EXPECT_EQ(1u, free_sync_ids.count(5));
    135   EXPECT_EQ(1u, free_sync_ids.count(6));
    136 }
    137 
    138 TEST_F(SyncTabNodePoolTest, Init) {
    139   EXPECT_TRUE(pool_.Empty());
    140   EXPECT_TRUE(pool_.Full());
    141 }
    142 
    143 TEST_F(SyncTabNodePoolTest, AddGet) {
    144   syncer::SyncChangeList changes;
    145   int free_nodes[] = {5, 10};
    146   AddFreeTabNodes(2, free_nodes);
    147 
    148   EXPECT_EQ(2U, pool_.Capacity());
    149   EXPECT_EQ(5, pool_.GetFreeTabNode(&changes));
    150   pool_.AssociateTabNode(5, 1);
    151   EXPECT_FALSE(pool_.Empty());
    152   EXPECT_FALSE(pool_.Full());
    153   EXPECT_EQ(2U, pool_.Capacity());
    154   // 5 is now used, should return 10.
    155   EXPECT_EQ(10, pool_.GetFreeTabNode(&changes));
    156 }
    157 
    158 TEST_F(SyncTabNodePoolTest, All) {
    159   syncer::SyncChangeList changes;
    160   EXPECT_TRUE(pool_.Empty());
    161   EXPECT_TRUE(pool_.Full());
    162   EXPECT_EQ(0U, pool_.Capacity());
    163 
    164   // GetFreeTabNode returns the lowest numbered free node.
    165   EXPECT_EQ(0, pool_.GetFreeTabNode(&changes));
    166   EXPECT_EQ(1U, changes.size());
    167   EXPECT_FALSE(pool_.Empty());
    168   EXPECT_TRUE(pool_.Full());
    169   EXPECT_EQ(1U, pool_.Capacity());
    170 
    171   // Associate 5, next free node should be 10.
    172   pool_.AssociateTabNode(0, 1);
    173   EXPECT_EQ(1, pool_.GetFreeTabNode(&changes));
    174   EXPECT_EQ(2U, changes.size());
    175   changes.clear();
    176   pool_.AssociateTabNode(1, 2);
    177   EXPECT_TRUE(pool_.Empty());
    178   EXPECT_FALSE(pool_.Full());
    179   EXPECT_EQ(2U, pool_.Capacity());
    180   // Release them in reverse order.
    181   pool_.FreeTabNode(1, &changes);
    182   pool_.FreeTabNode(0, &changes);
    183   EXPECT_EQ(2U, pool_.Capacity());
    184   EXPECT_FALSE(pool_.Empty());
    185   EXPECT_TRUE(pool_.Full());
    186   EXPECT_EQ(0, pool_.GetFreeTabNode(&changes));
    187   EXPECT_TRUE(changes.empty());
    188   EXPECT_FALSE(pool_.Empty());
    189   EXPECT_TRUE(pool_.Full());
    190   EXPECT_EQ(2U, pool_.Capacity());
    191   EXPECT_FALSE(pool_.Empty());
    192   EXPECT_TRUE(pool_.Full());
    193   pool_.AssociateTabNode(0, 1);
    194   EXPECT_EQ(2U, pool_.Capacity());
    195   EXPECT_EQ(1, pool_.GetFreeTabNode(&changes));
    196   EXPECT_TRUE(changes.empty());
    197   pool_.AssociateTabNode(1, 2);
    198   EXPECT_TRUE(pool_.Empty());
    199   EXPECT_FALSE(pool_.Full());
    200   EXPECT_EQ(2U, pool_.Capacity());
    201   // Release them again.
    202   pool_.FreeTabNode(1, &changes);
    203   pool_.FreeTabNode(0, &changes);
    204   EXPECT_FALSE(pool_.Empty());
    205   EXPECT_TRUE(pool_.Full());
    206   EXPECT_EQ(2U, pool_.Capacity());
    207   pool_.Clear();
    208   EXPECT_TRUE(pool_.Empty());
    209   EXPECT_TRUE(pool_.Full());
    210   EXPECT_EQ(0U, pool_.Capacity());
    211 }
    212 
    213 TEST_F(SyncTabNodePoolTest, GetFreeTabNodeCreate) {
    214   syncer::SyncChangeList changes;
    215   EXPECT_EQ(0, pool_.GetFreeTabNode(&changes));
    216   EXPECT_TRUE(changes[0].IsValid());
    217   EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
    218   EXPECT_TRUE(changes[0].sync_data().IsValid());
    219   sync_pb::EntitySpecifics entity = changes[0].sync_data().GetSpecifics();
    220   sync_pb::SessionSpecifics specifics(entity.session());
    221   EXPECT_EQ(0, specifics.tab_node_id());
    222 }
    223 
    224 TEST_F(SyncTabNodePoolTest, TabPoolFreeNodeLimits) {
    225   // Allocate TabNodePool::kFreeNodesHighWatermark + 1 nodes and verify that
    226   // freeing the last node reduces the free node pool size to
    227   // kFreeNodesLowWatermark.
    228   syncer::SyncChangeList changes;
    229   SessionID session_id;
    230   std::vector<int> used_sync_ids;
    231   for (size_t i = 1; i <= TabNodePool::kFreeNodesHighWatermark + 1; ++i) {
    232     session_id.set_id(i);
    233     int sync_id = pool_.GetFreeTabNode(&changes);
    234     pool_.AssociateTabNode(sync_id, i);
    235     used_sync_ids.push_back(sync_id);
    236   }
    237 
    238   // Free all except one node.
    239   int last_sync_id = used_sync_ids.back();
    240   used_sync_ids.pop_back();
    241 
    242   for (size_t i = 0; i < used_sync_ids.size(); ++i) {
    243     pool_.FreeTabNode(used_sync_ids[i], &changes);
    244   }
    245 
    246   // Except one node all nodes should be in FreeNode pool.
    247   EXPECT_FALSE(pool_.Full());
    248   EXPECT_FALSE(pool_.Empty());
    249   // Total capacity = 1 Associated Node + kFreeNodesHighWatermark free node.
    250   EXPECT_EQ(TabNodePool::kFreeNodesHighWatermark + 1, pool_.Capacity());
    251 
    252   // Freeing the last sync node should drop the free nodes to
    253   // kFreeNodesLowWatermark.
    254   pool_.FreeTabNode(last_sync_id, &changes);
    255   EXPECT_FALSE(pool_.Empty());
    256   EXPECT_TRUE(pool_.Full());
    257   EXPECT_EQ(TabNodePool::kFreeNodesLowWatermark, pool_.Capacity());
    258 }
    259 
    260 }  // namespace
    261 
    262 }  // namespace browser_sync
    263