lru_renderer_cache_test.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Copyright 2018 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 "chromecast/browser/lru_renderer_cache.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/memory/ptr_util.h"
  8. #include "chromecast/browser/renderer_prelauncher.h"
  9. #include "content/public/browser/site_instance.h"
  10. #include "content/public/test/browser_task_environment.h"
  11. #include "content/public/test/test_browser_context.h"
  12. #include "testing/gmock/include/gmock/gmock.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. #include "url/gurl.h"
  15. #define EXPECT_CREATE_AND_PRELAUNCH(ptr, url) \
  16. ptr = new MockPrelauncher(&browser_context_, url); \
  17. EXPECT_CALL(*ptr, Prelaunch()); \
  18. EXPECT_CALL(factory_, Create(&browser_context_, url)) \
  19. .WillOnce(Return(ByMove(std::unique_ptr<MockPrelauncher>(ptr))));
  20. #define EXPECT_EVICTION(ptr) EXPECT_CALL(*ptr, Destroy());
  21. using ::testing::_;
  22. using ::testing::ByMove;
  23. using ::testing::Expectation;
  24. using ::testing::Mock;
  25. using ::testing::Return;
  26. using ::testing::StrictMock;
  27. namespace chromecast {
  28. class MockPrelauncher : public RendererPrelauncher {
  29. public:
  30. MockPrelauncher(content::BrowserContext* browser_context,
  31. const GURL& page_url)
  32. : RendererPrelauncher(browser_context,
  33. page_url) {}
  34. virtual ~MockPrelauncher() { Destroy(); }
  35. MOCK_METHOD0(Prelaunch, void());
  36. MOCK_METHOD0(Destroy, void());
  37. };
  38. class MockFactory : public RendererPrelauncherFactory {
  39. public:
  40. MOCK_METHOD2(Create,
  41. std::unique_ptr<RendererPrelauncher>(
  42. content::BrowserContext* browser_context,
  43. const GURL& page_url));
  44. };
  45. class LRURendererCacheTest : public testing::Test {
  46. protected:
  47. void SetUp() override {}
  48. void SetFactory() {
  49. DCHECK(lru_cache_);
  50. lru_cache_->SetFactoryForTesting(&factory_);
  51. }
  52. content::BrowserTaskEnvironment task_environment_;
  53. content::TestBrowserContext browser_context_;
  54. MockFactory factory_;
  55. std::unique_ptr<LRURendererCache> lru_cache_;
  56. };
  57. TEST_F(LRURendererCacheTest, SimpleTakeAndRelease) {
  58. const GURL kUrl("https://www.one.com");
  59. lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
  60. SetFactory();
  61. MockPrelauncher* p1;
  62. std::unique_ptr<RendererPrelauncher> taken;
  63. // Don't return a prelauncher the first time, since the cache is empty.
  64. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  65. taken = lru_cache_->TakeRendererPrelauncher(kUrl);
  66. ASSERT_FALSE(taken);
  67. // Cache: []
  68. // In-use: [ 1 ]
  69. // Releasing the prelauncher will cache it and prelaunch for later use.
  70. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
  71. lru_cache_->ReleaseRendererPrelauncher(kUrl);
  72. task_environment_.RunUntilIdle();
  73. // Cache: [ 1 ]
  74. // In-use: []
  75. // Get the cached prelauncher.
  76. taken = lru_cache_->TakeRendererPrelauncher(kUrl);
  77. ASSERT_TRUE(taken);
  78. ASSERT_TRUE(taken->IsForURL(kUrl));
  79. // Cache: [ ]
  80. // In-use: [ 1 ]
  81. // Return the prelauncher again, it should be cached the same as before.
  82. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
  83. lru_cache_->ReleaseRendererPrelauncher(kUrl);
  84. task_environment_.RunUntilIdle();
  85. // Cache: [ 1 ]
  86. // In-use: []
  87. }
  88. TEST_F(LRURendererCacheTest, SimpleCacheEviction) {
  89. const GURL kUrl("https://www.one.com");
  90. lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
  91. SetFactory();
  92. MockPrelauncher* p1;
  93. std::unique_ptr<RendererPrelauncher> taken;
  94. // Fill the cache.
  95. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  96. taken = lru_cache_->TakeRendererPrelauncher(kUrl);
  97. ASSERT_FALSE(taken);
  98. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
  99. lru_cache_->ReleaseRendererPrelauncher(kUrl);
  100. task_environment_.RunUntilIdle();
  101. // Cache: [ 1 ]
  102. // In-use: []
  103. // Taking a different prelauncher destroys the cached one.
  104. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  105. EXPECT_EVICTION(p1);
  106. taken = lru_cache_->TakeRendererPrelauncher(GURL("https://www.two.com"));
  107. ASSERT_FALSE(taken);
  108. // Cache: [ ]
  109. // In-use: [ 2 ]
  110. }
  111. TEST_F(LRURendererCacheTest, CapacityOne) {
  112. const GURL kUrl1("https://www.one.com");
  113. const GURL kUrl2("https://www.two.com");
  114. lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
  115. SetFactory();
  116. MockPrelauncher* p1;
  117. MockPrelauncher* p2;
  118. std::unique_ptr<RendererPrelauncher> taken;
  119. // Don't return a prelauncher the first time, since the cache is empty.
  120. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  121. taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
  122. ASSERT_FALSE(taken);
  123. // Cache: []
  124. // In-use: [ 1 ]
  125. // Releasing the prelauncher will cache it and prelaunch for later use.
  126. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
  127. lru_cache_->ReleaseRendererPrelauncher(kUrl1);
  128. task_environment_.RunUntilIdle();
  129. // Cache: [ 1 ]
  130. // In-use: []
  131. // Get the cached prelauncher.
  132. taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
  133. ASSERT_TRUE(taken);
  134. ASSERT_TRUE(taken->IsForURL(kUrl1));
  135. // Cache: [ ]
  136. // In-use: [ 1 ]
  137. // Return the prelauncher again, it should be cached the same as before.
  138. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
  139. lru_cache_->ReleaseRendererPrelauncher(kUrl1);
  140. task_environment_.RunUntilIdle();
  141. // Cache: [ 1 ]
  142. // In-use: []
  143. // Getting the prelauncher for a non-cached URL will return nullptr. The cache
  144. // will evict 1 to stay below the renderer limit.
  145. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  146. EXPECT_EVICTION(p1);
  147. taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
  148. ASSERT_FALSE(taken);
  149. // Cache: [ ]
  150. // In-use: [ 2 ]
  151. // Return prelauncher 2, it should be cached.
  152. EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
  153. lru_cache_->ReleaseRendererPrelauncher(kUrl2);
  154. task_environment_.RunUntilIdle();
  155. // Cache: [ 2 ]
  156. // In-use: [ ]
  157. taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
  158. ASSERT_TRUE(taken);
  159. ASSERT_TRUE(taken->IsForURL(kUrl2));
  160. // Cache: [ ]
  161. // In-use: [ 2 ]
  162. // Return prelauncher 2 once more, it will be cached.
  163. EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
  164. lru_cache_->ReleaseRendererPrelauncher(kUrl2);
  165. task_environment_.RunUntilIdle();
  166. // Cache: [ 2 ]
  167. // In-use: [ ]
  168. // Prelauncher 1 was evicted when 2 was cached. Taking 1 will evict 2.
  169. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  170. EXPECT_EVICTION(p2);
  171. taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
  172. ASSERT_FALSE(taken);
  173. // Cache: [ ]
  174. // In-use: [ 1 ]
  175. // Prelauncher 2 was evicted when 1 was taken.
  176. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  177. taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
  178. ASSERT_FALSE(taken);
  179. // Cache: [ ]
  180. // In-use: [ 1, 2 ]
  181. // Returning one of the two in-use pages to the cache won't actually cache it,
  182. // since there's still exactly 1 renderer in-use.
  183. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  184. lru_cache_->ReleaseRendererPrelauncher(kUrl2);
  185. task_environment_.RunUntilIdle();
  186. // Cache: [ ]
  187. // In-use: [ 1 ]
  188. }
  189. TEST_F(LRURendererCacheTest, CapacityTwo) {
  190. const GURL kUrl1("https://www.one.com");
  191. const GURL kUrl2("https://www.two.com");
  192. const GURL kUrl3("https://www.three.com");
  193. lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 2);
  194. SetFactory();
  195. MockPrelauncher* p1;
  196. MockPrelauncher* p2;
  197. std::unique_ptr<RendererPrelauncher> taken;
  198. // Take three renderers.
  199. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  200. taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
  201. ASSERT_FALSE(taken);
  202. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  203. taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
  204. ASSERT_FALSE(taken);
  205. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  206. taken = lru_cache_->TakeRendererPrelauncher(kUrl3);
  207. ASSERT_FALSE(taken);
  208. // Cache: []
  209. // In-use: [ 1, 2, 3 ]
  210. // Don't cache renderer 3 since there are still 2 in use.
  211. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  212. lru_cache_->ReleaseRendererPrelauncher(kUrl3);
  213. task_environment_.RunUntilIdle();
  214. // In-use: [ 1, 2 ]
  215. // Fill the cache with remaining 2 renderers.
  216. EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
  217. lru_cache_->ReleaseRendererPrelauncher(kUrl2);
  218. task_environment_.RunUntilIdle();
  219. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
  220. lru_cache_->ReleaseRendererPrelauncher(kUrl1);
  221. task_environment_.RunUntilIdle();
  222. // Cache: [ 1, 2 ]
  223. // In-use: [ ]
  224. // Cache hit for renderer 1.
  225. taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
  226. ASSERT_TRUE(taken);
  227. ASSERT_TRUE(taken->IsForURL(kUrl1));
  228. // Cache: [ 2 ]
  229. // In-use: [ 1 ]
  230. // Return renderer 1.
  231. EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
  232. lru_cache_->ReleaseRendererPrelauncher(kUrl1);
  233. task_environment_.RunUntilIdle();
  234. // Cache: [ 1, 2 ]
  235. // In-use: [ ]
  236. // Evict the least-recently cached renderer (2).
  237. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  238. EXPECT_EVICTION(p2);
  239. taken = lru_cache_->TakeRendererPrelauncher(kUrl3);
  240. ASSERT_FALSE(taken);
  241. // Cache: [ 1 ]
  242. // In-use: [ 3 ]
  243. // Getting renderer 2 will fail since it's no long cached. This will evict
  244. // renderer 1.
  245. EXPECT_CALL(factory_, Create(_, _)).Times(0);
  246. EXPECT_EVICTION(p1);
  247. taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
  248. ASSERT_FALSE(taken);
  249. // Cache: [ ]
  250. // In-use: [ 2, 3 ]
  251. }
  252. } // namespace chromecast