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 <algorithm> 6#include "android_webview/browser/global_tile_manager.h" 7#include "android_webview/browser/global_tile_manager_client.h" 8#include "testing/gtest/include/gtest/gtest.h" 9 10namespace { 11// This should be the same as the one defined global_tile_manager.cc 12const size_t kNumTilesLimit = 450; 13const size_t kDefaultNumTiles = 150; 14 15} // namespace 16 17using android_webview::GlobalTileManager; 18using android_webview::GlobalTileManagerClient; 19using content::SynchronousCompositorMemoryPolicy; 20using testing::Test; 21 22class MockGlobalTileManagerClient : public GlobalTileManagerClient { 23 public: 24 virtual SynchronousCompositorMemoryPolicy GetMemoryPolicy() const OVERRIDE { 25 return memory_policy_; 26 } 27 28 virtual void SetMemoryPolicy(SynchronousCompositorMemoryPolicy new_policy, 29 bool effective_immediately) OVERRIDE { 30 memory_policy_ = new_policy; 31 } 32 33 MockGlobalTileManagerClient() { 34 tile_request_.num_resources_limit = kDefaultNumTiles; 35 key_ = GlobalTileManager::GetInstance()->PushBack(this); 36 } 37 38 virtual ~MockGlobalTileManagerClient() { 39 GlobalTileManager::GetInstance()->Remove(key_); 40 } 41 42 SynchronousCompositorMemoryPolicy GetTileRequest() { return tile_request_; } 43 GlobalTileManager::Key GetKey() { return key_; } 44 45 private: 46 SynchronousCompositorMemoryPolicy memory_policy_; 47 SynchronousCompositorMemoryPolicy tile_request_; 48 GlobalTileManager::Key key_; 49}; 50 51class GlobalTileManagerTest : public Test { 52 public: 53 virtual void SetUp() {} 54 55 GlobalTileManager* manager() { return GlobalTileManager::GetInstance(); } 56}; 57 58TEST_F(GlobalTileManagerTest, RequestTilesUnderLimit) { 59 MockGlobalTileManagerClient clients[2]; 60 61 for (size_t i = 0; i < 2; i++) { 62 manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); 63 manager()->DidUse(clients[i].GetKey()); 64 65 // Ensure clients get what they asked for when the manager is under tile 66 // limit. 67 EXPECT_EQ(clients[i].GetMemoryPolicy().num_resources_limit, 68 kDefaultNumTiles); 69 } 70} 71 72TEST_F(GlobalTileManagerTest, EvictHappensWhenOverLimit) { 73 MockGlobalTileManagerClient clients[4]; 74 75 for (size_t i = 0; i < 4; i++) { 76 manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); 77 manager()->DidUse(clients[i].GetKey()); 78 } 79 80 size_t total_tiles = 0; 81 for (size_t i = 0; i < 4; i++) { 82 total_tiles += clients[i].GetMemoryPolicy().num_resources_limit; 83 } 84 85 // Ensure that eviction happened and kept the total number of tiles within 86 // kNumTilesLimit. 87 EXPECT_LE(total_tiles, kNumTilesLimit); 88} 89 90TEST_F(GlobalTileManagerTest, RandomizedStressRequests) { 91 MockGlobalTileManagerClient clients[100]; 92 size_t index[100]; 93 for (size_t i = 0; i < 100; i++) { 94 index[i] = i; 95 } 96 97 // Fix the seed so that tests are reproducible. 98 std::srand(1); 99 // Simulate a random request order of clients. 100 std::random_shuffle(&index[0], &index[99]); 101 102 for (size_t i = 0; i < 100; i++) { 103 size_t j = index[i]; 104 manager()->RequestTiles(clients[j].GetTileRequest(), clients[j].GetKey()); 105 manager()->DidUse(clients[j].GetKey()); 106 } 107 108 size_t total_tiles = 0; 109 for (size_t i = 0; i < 100; i++) { 110 total_tiles += clients[i].GetMemoryPolicy().num_resources_limit; 111 } 112 113 // Ensure that eviction happened and kept the total number of tiles within 114 // kNumTilesLimit. 115 EXPECT_LE(total_tiles, kNumTilesLimit); 116} 117 118TEST_F(GlobalTileManagerTest, FixedOrderedRequests) { 119 MockGlobalTileManagerClient clients[10]; 120 121 // 10 clients requesting resources in a fixed order. Do that for 5 rounds. 122 for (int round = 0; round < 5; round++) { 123 for (size_t i = 0; i < 10; i++) { 124 manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); 125 manager()->DidUse(clients[i].GetKey()); 126 } 127 } 128 129 // Ensure that the total tiles are divided evenly among all clients. 130 for (size_t i = 0; i < 10; i++) { 131 EXPECT_EQ(clients[i].GetMemoryPolicy().num_resources_limit, 132 kNumTilesLimit / 10); 133 } 134} 135 136TEST_F(GlobalTileManagerTest, FixedOrderedRequestsWithInactiveClients) { 137 MockGlobalTileManagerClient clients[20]; 138 139 // 20 clients request resources. 140 for (size_t i = 0; i < 20; i++) { 141 manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); 142 manager()->DidUse(clients[i].GetKey()); 143 } 144 145 // Now the last 10 clients become inactive. Only the first 10 clients remain 146 // active resource requesters. 147 // 10 clients requesting resources in a fixed order. Do that for 5 rounds. 148 for (int round = 0; round < 5; round++) { 149 for (size_t i = 0; i < 10; i++) { 150 manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); 151 manager()->DidUse(clients[i].GetKey()); 152 } 153 } 154 155 // Ensure that the total tiles are divided evenly among all clients. 156 for (size_t i = 0; i < 10; i++) { 157 EXPECT_EQ(clients[i].GetMemoryPolicy().num_resources_limit, 158 kNumTilesLimit / 10); 159 } 160 161 // Ensure that the inactive tiles are evicted. 162 for (size_t i = 11; i < 20; i++) { 163 EXPECT_EQ(clients[i].GetMemoryPolicy().num_resources_limit, 0u); 164 } 165} 166