| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <algorithm> |
| #include "android_webview/browser/global_tile_manager.h" |
| #include "android_webview/browser/global_tile_manager_client.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| // This should be the same as the one defined global_tile_manager.cc |
| const size_t kNumTilesLimit = 450; |
| const size_t kDefaultNumTiles = 150; |
| |
| } // namespace |
| |
| using android_webview::GlobalTileManager; |
| using android_webview::GlobalTileManagerClient; |
| using testing::Test; |
| |
| class MockGlobalTileManagerClient : public GlobalTileManagerClient { |
| public: |
| virtual size_t GetNumTiles() const OVERRIDE { return num_tiles_; } |
| virtual void SetNumTiles(size_t num_tiles, |
| bool effective_immediately) OVERRIDE { |
| num_tiles_ = num_tiles; |
| } |
| |
| MockGlobalTileManagerClient() { |
| num_tiles_ = 0; |
| tile_request_ = kDefaultNumTiles; |
| key_ = GlobalTileManager::GetInstance()->PushBack(this); |
| } |
| |
| virtual ~MockGlobalTileManagerClient() { |
| GlobalTileManager::GetInstance()->Remove(key_); |
| } |
| |
| size_t GetTileRequest() { return tile_request_; } |
| GlobalTileManager::Key GetKey() { return key_; } |
| |
| private: |
| size_t num_tiles_; |
| size_t tile_request_; |
| GlobalTileManager::Key key_; |
| }; |
| |
| class GlobalTileManagerTest : public Test { |
| public: |
| virtual void SetUp() {} |
| |
| GlobalTileManager* manager() { return GlobalTileManager::GetInstance(); } |
| }; |
| |
| TEST_F(GlobalTileManagerTest, RequestTilesUnderLimit) { |
| MockGlobalTileManagerClient clients[2]; |
| |
| for (size_t i = 0; i < 2; i++) { |
| manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); |
| manager()->DidUse(clients[i].GetKey()); |
| |
| // Ensure clients get what they asked for when the manager is under tile |
| // limit. |
| EXPECT_EQ(clients[i].GetNumTiles(), kDefaultNumTiles); |
| } |
| } |
| |
| TEST_F(GlobalTileManagerTest, EvictHappensWhenOverLimit) { |
| MockGlobalTileManagerClient clients[4]; |
| |
| for (size_t i = 0; i < 4; i++) { |
| manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); |
| manager()->DidUse(clients[i].GetKey()); |
| } |
| |
| size_t total_tiles = 0; |
| for (size_t i = 0; i < 4; i++) { |
| total_tiles += clients[i].GetNumTiles(); |
| } |
| |
| // Ensure that eviction happened and kept the total number of tiles within |
| // kNumTilesLimit. |
| EXPECT_LE(total_tiles, kNumTilesLimit); |
| } |
| |
| TEST_F(GlobalTileManagerTest, RandomizedStressRequests) { |
| MockGlobalTileManagerClient clients[100]; |
| size_t index[100]; |
| for (size_t i = 0; i < 100; i++) { |
| index[i] = i; |
| } |
| |
| // Simulate a random request order of clients. |
| std::random_shuffle(&index[0], &index[99]); |
| |
| for (size_t i = 0; i < 100; i++) { |
| size_t j = index[i]; |
| manager()->RequestTiles(clients[j].GetTileRequest(), clients[j].GetKey()); |
| manager()->DidUse(clients[j].GetKey()); |
| } |
| |
| size_t total_tiles = 0; |
| for (size_t i = 0; i < 100; i++) { |
| total_tiles += clients[i].GetNumTiles(); |
| } |
| |
| // Ensure that eviction happened and kept the total number of tiles within |
| // kNumTilesLimit. |
| EXPECT_LE(total_tiles, kNumTilesLimit); |
| } |
| |
| TEST_F(GlobalTileManagerTest, FixedOrderedRequests) { |
| MockGlobalTileManagerClient clients[10]; |
| |
| // 10 clients requesting resources in a fixed order. Do that for 5 rounds. |
| for (int round = 0; round < 5; round++) { |
| for (size_t i = 0; i < 10; i++) { |
| manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); |
| manager()->DidUse(clients[i].GetKey()); |
| } |
| } |
| |
| // Ensure that the total tiles are divided evenly among all clients. |
| for (size_t i = 0; i < 10; i++) { |
| EXPECT_EQ(clients[i].GetNumTiles(), kNumTilesLimit / 10); |
| } |
| } |
| |
| TEST_F(GlobalTileManagerTest, FixedOrderedRequestsWithInactiveClients) { |
| MockGlobalTileManagerClient clients[20]; |
| |
| // 20 clients request resources. |
| for (size_t i = 0; i < 20; i++) { |
| manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); |
| manager()->DidUse(clients[i].GetKey()); |
| } |
| |
| // Now the last 10 clients become inactive. Only the first 10 clients remain |
| // active resource requesters. |
| // 10 clients requesting resources in a fixed order. Do that for 5 rounds. |
| for (int round = 0; round < 5; round++) { |
| for (size_t i = 0; i < 10; i++) { |
| manager()->RequestTiles(clients[i].GetTileRequest(), clients[i].GetKey()); |
| manager()->DidUse(clients[i].GetKey()); |
| } |
| } |
| |
| // Ensure that the total tiles are divided evenly among all clients. |
| for (size_t i = 0; i < 10; i++) { |
| EXPECT_EQ(clients[i].GetNumTiles(), kNumTilesLimit / 10); |
| } |
| |
| // Ensure that the inactive tiles are evicted. |
| for (size_t i = 11; i < 20; i++) { |
| EXPECT_EQ(clients[i].GetNumTiles(), 0u); |
| } |
| } |