blob: 6e6e85eda03d2c3759650800dd404f20e1619e56 [file] [log] [blame]
Avi Drissmand878a5012022-09-12 19:13:301// Copyright 2018 The Chromium Authors
Sean Toppingb80d72cc2018-05-11 00:24:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chromecast/browser/lru_renderer_cache.h"
6
7#include <memory>
James West53c12a222018-05-12 01:00:588#include <utility>
Sean Toppingb80d72cc2018-05-11 00:24:459
10#include "base/memory/ptr_util.h"
11#include "chromecast/browser/renderer_prelauncher.h"
12#include "content/public/browser/site_instance.h"
Gabriel Charettec7108742019-08-23 03:31:4013#include "content/public/test/browser_task_environment.h"
Sean Toppingb80d72cc2018-05-11 00:24:4514#include "content/public/test/test_browser_context.h"
Sean Toppingb80d72cc2018-05-11 00:24:4515#include "testing/gmock/include/gmock/gmock.h"
16#include "testing/gtest/include/gtest/gtest.h"
17#include "url/gurl.h"
18
Luke Halliwell4bebcd982018-08-17 05:32:5919#define EXPECT_CREATE_AND_PRELAUNCH(ptr, url) \
20 ptr = new MockPrelauncher(&browser_context_, url); \
21 EXPECT_CALL(*ptr, Prelaunch()); \
22 EXPECT_CALL(factory_, Create(&browser_context_, url)) \
Sean Toppingb80d72cc2018-05-11 00:24:4523 .WillOnce(Return(ByMove(std::unique_ptr<MockPrelauncher>(ptr))));
24
25#define EXPECT_EVICTION(ptr) EXPECT_CALL(*ptr, Destroy());
26
27using ::testing::_;
28using ::testing::ByMove;
29using ::testing::Expectation;
30using ::testing::Mock;
31using ::testing::Return;
32using ::testing::StrictMock;
33
34namespace chromecast {
35
Sean Toppingb80d72cc2018-05-11 00:24:4536class MockPrelauncher : public RendererPrelauncher {
37 public:
38 MockPrelauncher(content::BrowserContext* browser_context,
39 const GURL& page_url)
James West53c12a222018-05-12 01:00:5840 : RendererPrelauncher(browser_context,
James West53c12a222018-05-12 01:00:5841 page_url) {}
Arthur Eubanksb34721e2022-08-24 17:47:2042 ~MockPrelauncher() override { Destroy(); }
Sean Toppingb80d72cc2018-05-11 00:24:4543
44 MOCK_METHOD0(Prelaunch, void());
45 MOCK_METHOD0(Destroy, void());
46};
47
48class MockFactory : public RendererPrelauncherFactory {
49 public:
50 MOCK_METHOD2(Create,
51 std::unique_ptr<RendererPrelauncher>(
52 content::BrowserContext* browser_context,
53 const GURL& page_url));
54};
55
56class LRURendererCacheTest : public testing::Test {
57 protected:
58 void SetUp() override {}
59
60 void SetFactory() {
61 DCHECK(lru_cache_);
62 lru_cache_->SetFactoryForTesting(&factory_);
63 }
64
Gabriel Charettef893a282019-08-21 20:37:1965 content::BrowserTaskEnvironment task_environment_;
Sean Toppingb80d72cc2018-05-11 00:24:4566 content::TestBrowserContext browser_context_;
67 MockFactory factory_;
68 std::unique_ptr<LRURendererCache> lru_cache_;
69};
70
71TEST_F(LRURendererCacheTest, SimpleTakeAndRelease) {
Peter Kasting8bdc82812020-02-17 18:25:1672 const GURL kUrl("https://www.one.com");
73
Luke Halliwell4bebcd982018-08-17 05:32:5974 lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
Sean Toppingb80d72cc2018-05-11 00:24:4575 SetFactory();
76 MockPrelauncher* p1;
77 std::unique_ptr<RendererPrelauncher> taken;
78
79 // Don't return a prelauncher the first time, since the cache is empty.
80 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:1681 taken = lru_cache_->TakeRendererPrelauncher(kUrl);
Sean Toppingb80d72cc2018-05-11 00:24:4582 ASSERT_FALSE(taken);
83 // Cache: []
84 // In-use: [ 1 ]
85
86 // Releasing the prelauncher will cache it and prelaunch for later use.
Peter Kasting8bdc82812020-02-17 18:25:1687 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
88 lru_cache_->ReleaseRendererPrelauncher(kUrl);
Gabriel Charettef893a282019-08-21 20:37:1989 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:4590 // Cache: [ 1 ]
91 // In-use: []
92
93 // Get the cached prelauncher.
Peter Kasting8bdc82812020-02-17 18:25:1694 taken = lru_cache_->TakeRendererPrelauncher(kUrl);
Sean Toppingb80d72cc2018-05-11 00:24:4595 ASSERT_TRUE(taken);
Peter Kasting8bdc82812020-02-17 18:25:1696 ASSERT_TRUE(taken->IsForURL(kUrl));
Sean Toppingb80d72cc2018-05-11 00:24:4597 // Cache: [ ]
98 // In-use: [ 1 ]
99
100 // Return the prelauncher again, it should be cached the same as before.
Peter Kasting8bdc82812020-02-17 18:25:16101 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
102 lru_cache_->ReleaseRendererPrelauncher(kUrl);
Gabriel Charettef893a282019-08-21 20:37:19103 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45104 // Cache: [ 1 ]
105 // In-use: []
106}
107
108TEST_F(LRURendererCacheTest, SimpleCacheEviction) {
Peter Kasting8bdc82812020-02-17 18:25:16109 const GURL kUrl("https://www.one.com");
110
Luke Halliwell4bebcd982018-08-17 05:32:59111 lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
Sean Toppingb80d72cc2018-05-11 00:24:45112 SetFactory();
113 MockPrelauncher* p1;
114 std::unique_ptr<RendererPrelauncher> taken;
115
116 // Fill the cache.
117 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16118 taken = lru_cache_->TakeRendererPrelauncher(kUrl);
Sean Toppingb80d72cc2018-05-11 00:24:45119 ASSERT_FALSE(taken);
Peter Kasting8bdc82812020-02-17 18:25:16120 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl);
121 lru_cache_->ReleaseRendererPrelauncher(kUrl);
Gabriel Charettef893a282019-08-21 20:37:19122 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45123 // Cache: [ 1 ]
124 // In-use: []
125
126 // Taking a different prelauncher destroys the cached one.
127 EXPECT_CALL(factory_, Create(_, _)).Times(0);
128 EXPECT_EVICTION(p1);
Peter Kasting8bdc82812020-02-17 18:25:16129 taken = lru_cache_->TakeRendererPrelauncher(GURL("https://www.two.com"));
Sean Toppingb80d72cc2018-05-11 00:24:45130 ASSERT_FALSE(taken);
131 // Cache: [ ]
132 // In-use: [ 2 ]
133}
134
135TEST_F(LRURendererCacheTest, CapacityOne) {
Peter Kasting8bdc82812020-02-17 18:25:16136 const GURL kUrl1("https://www.one.com");
137 const GURL kUrl2("https://www.two.com");
138
Luke Halliwell4bebcd982018-08-17 05:32:59139 lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 1);
Sean Toppingb80d72cc2018-05-11 00:24:45140 SetFactory();
141 MockPrelauncher* p1;
142 MockPrelauncher* p2;
143 std::unique_ptr<RendererPrelauncher> taken;
144
145 // Don't return a prelauncher the first time, since the cache is empty.
146 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16147 taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
Sean Toppingb80d72cc2018-05-11 00:24:45148 ASSERT_FALSE(taken);
149 // Cache: []
150 // In-use: [ 1 ]
151
152 // Releasing the prelauncher will cache it and prelaunch for later use.
Peter Kasting8bdc82812020-02-17 18:25:16153 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
154 lru_cache_->ReleaseRendererPrelauncher(kUrl1);
Gabriel Charettef893a282019-08-21 20:37:19155 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45156 // Cache: [ 1 ]
157 // In-use: []
158
159 // Get the cached prelauncher.
Peter Kasting8bdc82812020-02-17 18:25:16160 taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
Sean Toppingb80d72cc2018-05-11 00:24:45161 ASSERT_TRUE(taken);
Peter Kasting8bdc82812020-02-17 18:25:16162 ASSERT_TRUE(taken->IsForURL(kUrl1));
Sean Toppingb80d72cc2018-05-11 00:24:45163 // Cache: [ ]
164 // In-use: [ 1 ]
165
166 // Return the prelauncher again, it should be cached the same as before.
Peter Kasting8bdc82812020-02-17 18:25:16167 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
168 lru_cache_->ReleaseRendererPrelauncher(kUrl1);
Gabriel Charettef893a282019-08-21 20:37:19169 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45170 // Cache: [ 1 ]
171 // In-use: []
172
173 // Getting the prelauncher for a non-cached URL will return nullptr. The cache
174 // will evict 1 to stay below the renderer limit.
175 EXPECT_CALL(factory_, Create(_, _)).Times(0);
176 EXPECT_EVICTION(p1);
Peter Kasting8bdc82812020-02-17 18:25:16177 taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
Sean Toppingb80d72cc2018-05-11 00:24:45178 ASSERT_FALSE(taken);
179 // Cache: [ ]
180 // In-use: [ 2 ]
181
182 // Return prelauncher 2, it should be cached.
Peter Kasting8bdc82812020-02-17 18:25:16183 EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
184 lru_cache_->ReleaseRendererPrelauncher(kUrl2);
Gabriel Charettef893a282019-08-21 20:37:19185 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45186 // Cache: [ 2 ]
187 // In-use: [ ]
Peter Kasting8bdc82812020-02-17 18:25:16188 taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
Sean Toppingb80d72cc2018-05-11 00:24:45189 ASSERT_TRUE(taken);
Peter Kasting8bdc82812020-02-17 18:25:16190 ASSERT_TRUE(taken->IsForURL(kUrl2));
Sean Toppingb80d72cc2018-05-11 00:24:45191 // Cache: [ ]
192 // In-use: [ 2 ]
193
194 // Return prelauncher 2 once more, it will be cached.
Peter Kasting8bdc82812020-02-17 18:25:16195 EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
196 lru_cache_->ReleaseRendererPrelauncher(kUrl2);
Gabriel Charettef893a282019-08-21 20:37:19197 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45198 // Cache: [ 2 ]
199 // In-use: [ ]
200
201 // Prelauncher 1 was evicted when 2 was cached. Taking 1 will evict 2.
202 EXPECT_CALL(factory_, Create(_, _)).Times(0);
203 EXPECT_EVICTION(p2);
Peter Kasting8bdc82812020-02-17 18:25:16204 taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
Sean Toppingb80d72cc2018-05-11 00:24:45205 ASSERT_FALSE(taken);
206 // Cache: [ ]
207 // In-use: [ 1 ]
208
209 // Prelauncher 2 was evicted when 1 was taken.
210 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16211 taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
Sean Toppingb80d72cc2018-05-11 00:24:45212 ASSERT_FALSE(taken);
213 // Cache: [ ]
214 // In-use: [ 1, 2 ]
215
216 // Returning one of the two in-use pages to the cache won't actually cache it,
217 // since there's still exactly 1 renderer in-use.
218 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16219 lru_cache_->ReleaseRendererPrelauncher(kUrl2);
Gabriel Charettef893a282019-08-21 20:37:19220 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45221 // Cache: [ ]
222 // In-use: [ 1 ]
223}
224
225TEST_F(LRURendererCacheTest, CapacityTwo) {
Peter Kasting8bdc82812020-02-17 18:25:16226 const GURL kUrl1("https://www.one.com");
227 const GURL kUrl2("https://www.two.com");
228 const GURL kUrl3("https://www.three.com");
229
Luke Halliwell4bebcd982018-08-17 05:32:59230 lru_cache_ = std::make_unique<LRURendererCache>(&browser_context_, 2);
Sean Toppingb80d72cc2018-05-11 00:24:45231 SetFactory();
232 MockPrelauncher* p1;
233 MockPrelauncher* p2;
234 std::unique_ptr<RendererPrelauncher> taken;
235
236 // Take three renderers.
237 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16238 taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
Sean Toppingb80d72cc2018-05-11 00:24:45239 ASSERT_FALSE(taken);
240 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16241 taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
Sean Toppingb80d72cc2018-05-11 00:24:45242 ASSERT_FALSE(taken);
243 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16244 taken = lru_cache_->TakeRendererPrelauncher(kUrl3);
Sean Toppingb80d72cc2018-05-11 00:24:45245 ASSERT_FALSE(taken);
246 // Cache: []
247 // In-use: [ 1, 2, 3 ]
248
249 // Don't cache renderer 3 since there are still 2 in use.
250 EXPECT_CALL(factory_, Create(_, _)).Times(0);
Peter Kasting8bdc82812020-02-17 18:25:16251 lru_cache_->ReleaseRendererPrelauncher(kUrl3);
Gabriel Charettef893a282019-08-21 20:37:19252 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45253 // In-use: [ 1, 2 ]
254
255 // Fill the cache with remaining 2 renderers.
Peter Kasting8bdc82812020-02-17 18:25:16256 EXPECT_CREATE_AND_PRELAUNCH(p2, kUrl2);
257 lru_cache_->ReleaseRendererPrelauncher(kUrl2);
Gabriel Charettef893a282019-08-21 20:37:19258 task_environment_.RunUntilIdle();
Peter Kasting8bdc82812020-02-17 18:25:16259 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
260 lru_cache_->ReleaseRendererPrelauncher(kUrl1);
Gabriel Charettef893a282019-08-21 20:37:19261 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45262 // Cache: [ 1, 2 ]
263 // In-use: [ ]
264
265 // Cache hit for renderer 1.
Peter Kasting8bdc82812020-02-17 18:25:16266 taken = lru_cache_->TakeRendererPrelauncher(kUrl1);
Sean Toppingb80d72cc2018-05-11 00:24:45267 ASSERT_TRUE(taken);
Peter Kasting8bdc82812020-02-17 18:25:16268 ASSERT_TRUE(taken->IsForURL(kUrl1));
Sean Toppingb80d72cc2018-05-11 00:24:45269 // Cache: [ 2 ]
270 // In-use: [ 1 ]
271
272 // Return renderer 1.
Peter Kasting8bdc82812020-02-17 18:25:16273 EXPECT_CREATE_AND_PRELAUNCH(p1, kUrl1);
274 lru_cache_->ReleaseRendererPrelauncher(kUrl1);
Gabriel Charettef893a282019-08-21 20:37:19275 task_environment_.RunUntilIdle();
Sean Toppingb80d72cc2018-05-11 00:24:45276 // Cache: [ 1, 2 ]
277 // In-use: [ ]
278
279 // Evict the least-recently cached renderer (2).
280 EXPECT_CALL(factory_, Create(_, _)).Times(0);
281 EXPECT_EVICTION(p2);
Peter Kasting8bdc82812020-02-17 18:25:16282 taken = lru_cache_->TakeRendererPrelauncher(kUrl3);
Sean Toppingb80d72cc2018-05-11 00:24:45283 ASSERT_FALSE(taken);
284 // Cache: [ 1 ]
285 // In-use: [ 3 ]
286
287 // Getting renderer 2 will fail since it's no long cached. This will evict
288 // renderer 1.
289 EXPECT_CALL(factory_, Create(_, _)).Times(0);
290 EXPECT_EVICTION(p1);
Peter Kasting8bdc82812020-02-17 18:25:16291 taken = lru_cache_->TakeRendererPrelauncher(kUrl2);
Sean Toppingb80d72cc2018-05-11 00:24:45292 ASSERT_FALSE(taken);
293 // Cache: [ ]
294 // In-use: [ 2, 3 ]
295}
296
297} // namespace chromecast