Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / cc / resources / resource_update_controller_unittest.cc
blob3d943a8fe76aef5de4175420764b9b7eaf22deef
1 // Copyright 2012 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.
5 #include "cc/resources/resource_update_controller.h"
7 #include "base/test/test_simple_task_runner.h"
8 #include "cc/resources/prioritized_resource_manager.h"
9 #include "cc/test/fake_output_surface.h"
10 #include "cc/test/fake_output_surface_client.h"
11 #include "cc/test/fake_proxy.h"
12 #include "cc/test/fake_resource_provider.h"
13 #include "cc/test/scheduler_test_common.h"
14 #include "cc/test/test_shared_bitmap_manager.h"
15 #include "cc/test/test_web_graphics_context_3d.h"
16 #include "cc/test/tiled_layer_test_common.h"
17 #include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/khronos/GLES2/gl2ext.h"
21 using testing::Test;
23 namespace cc {
24 namespace {
26 const int kFlushPeriodFull = 4;
27 const int kFlushPeriodPartial = kFlushPeriodFull;
29 class ResourceUpdateControllerTest;
31 class WebGraphicsContext3DForUploadTest : public TestWebGraphicsContext3D {
32 public:
33 explicit WebGraphicsContext3DForUploadTest(ResourceUpdateControllerTest* test)
34 : test_(test) {}
36 void flush() override;
37 void shallowFlushCHROMIUM() override;
38 void texSubImage2D(GLenum target,
39 GLint level,
40 GLint xoffset,
41 GLint yoffset,
42 GLsizei width,
43 GLsizei height,
44 GLenum format,
45 GLenum type,
46 const void* pixels) override;
48 void getQueryObjectuivEXT(GLuint id, GLenum pname, GLuint* value) override;
50 private:
51 ResourceUpdateControllerTest* test_;
54 class ResourceUpdateControllerTest : public Test {
55 public:
56 ResourceUpdateControllerTest()
57 : proxy_(),
58 queue_(make_scoped_ptr(new ResourceUpdateQueue)),
59 resource_manager_(PrioritizedResourceManager::Create(&proxy_)),
60 query_results_available_(0),
61 full_upload_count_expected_(0),
62 partial_count_expected_(0),
63 total_upload_count_expected_(0),
64 max_upload_count_per_update_(0),
65 num_consecutive_flushes_(0),
66 num_dangling_uploads_(0),
67 num_total_uploads_(0),
68 num_total_flushes_(0) {}
70 ~ResourceUpdateControllerTest() override {
71 DebugScopedSetImplThreadAndMainThreadBlocked
72 impl_thread_and_main_thread_blocked(&proxy_);
73 resource_manager_->ClearAllMemory(resource_provider_.get());
76 public:
77 void OnFlush() {
78 // Check for back-to-back flushes.
79 EXPECT_EQ(0, num_consecutive_flushes_) << "Back-to-back flushes detected.";
81 num_dangling_uploads_ = 0;
82 num_consecutive_flushes_++;
83 num_total_flushes_++;
86 void OnUpload() {
87 // Check for too many consecutive uploads
88 if (num_total_uploads_ < full_upload_count_expected_) {
89 EXPECT_LT(num_dangling_uploads_, kFlushPeriodFull)
90 << "Too many consecutive full uploads detected.";
91 } else {
92 EXPECT_LT(num_dangling_uploads_, kFlushPeriodPartial)
93 << "Too many consecutive partial uploads detected.";
96 num_consecutive_flushes_ = 0;
97 num_dangling_uploads_++;
98 num_total_uploads_++;
101 bool IsQueryResultAvailable() {
102 if (!query_results_available_)
103 return false;
105 query_results_available_--;
106 return true;
109 protected:
110 void SetUp() override {
111 bitmap_.allocN32Pixels(300, 150);
113 for (int i = 0; i < 4; i++) {
114 textures_[i] = PrioritizedResource::Create(resource_manager_.get(),
115 gfx::Size(300, 150),
116 RGBA_8888);
117 textures_[i]->
118 set_request_priority(PriorityCalculator::VisiblePriority(true));
120 resource_manager_->PrioritizeTextures();
122 output_surface_ = FakeOutputSurface::Create3d(
123 scoped_ptr<TestWebGraphicsContext3D>(
124 new WebGraphicsContext3DForUploadTest(this)));
125 CHECK(output_surface_->BindToClient(&output_surface_client_));
127 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
128 resource_provider_ = FakeResourceProvider::Create(
129 output_surface_.get(), shared_bitmap_manager_.get());
132 void AppendFullUploadsOfIndexedTextureToUpdateQueue(int count,
133 int texture_index) {
134 full_upload_count_expected_ += count;
135 total_upload_count_expected_ += count;
137 const gfx::Rect rect(0, 0, 300, 150);
138 const ResourceUpdate upload = ResourceUpdate::Create(
139 textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d());
140 for (int i = 0; i < count; i++)
141 queue_->AppendFullUpload(upload);
144 void AppendFullUploadsToUpdateQueue(int count) {
145 AppendFullUploadsOfIndexedTextureToUpdateQueue(count, 0);
148 void AppendPartialUploadsOfIndexedTextureToUpdateQueue(int count,
149 int texture_index) {
150 partial_count_expected_ += count;
151 total_upload_count_expected_ += count;
153 const gfx::Rect rect(0, 0, 100, 100);
154 const ResourceUpdate upload = ResourceUpdate::Create(
155 textures_[texture_index].get(), &bitmap_, rect, rect, gfx::Vector2d());
156 for (int i = 0; i < count; i++)
157 queue_->AppendPartialUpload(upload);
160 void AppendPartialUploadsToUpdateQueue(int count) {
161 AppendPartialUploadsOfIndexedTextureToUpdateQueue(count, 0);
164 void SetMaxUploadCountPerUpdate(int count) {
165 max_upload_count_per_update_ = count;
168 void UpdateTextures() {
169 DebugScopedSetImplThreadAndMainThreadBlocked
170 impl_thread_and_main_thread_blocked(&proxy_);
171 scoped_ptr<ResourceUpdateController> update_controller =
172 ResourceUpdateController::Create(NULL,
173 proxy_.ImplThreadTaskRunner(),
174 queue_.Pass(),
175 resource_provider_.get());
176 update_controller->Finalize();
179 void MakeQueryResultAvailable() { query_results_available_++; }
181 protected:
182 // Classes required to interact and test the ResourceUpdateController
183 FakeProxy proxy_;
184 FakeOutputSurfaceClient output_surface_client_;
185 scoped_ptr<OutputSurface> output_surface_;
186 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
187 scoped_ptr<ResourceProvider> resource_provider_;
188 scoped_ptr<ResourceUpdateQueue> queue_;
189 scoped_ptr<PrioritizedResource> textures_[4];
190 scoped_ptr<PrioritizedResourceManager> resource_manager_;
191 SkBitmap bitmap_;
192 int query_results_available_;
194 // Properties / expectations of this test
195 int full_upload_count_expected_;
196 int partial_count_expected_;
197 int total_upload_count_expected_;
198 int max_upload_count_per_update_;
200 // Dynamic properties of this test
201 int num_consecutive_flushes_;
202 int num_dangling_uploads_;
203 int num_total_uploads_;
204 int num_total_flushes_;
207 void WebGraphicsContext3DForUploadTest::flush() { test_->OnFlush(); }
209 void WebGraphicsContext3DForUploadTest::shallowFlushCHROMIUM() {
210 test_->OnFlush();
213 void WebGraphicsContext3DForUploadTest::texSubImage2D(GLenum target,
214 GLint level,
215 GLint xoffset,
216 GLint yoffset,
217 GLsizei width,
218 GLsizei height,
219 GLenum format,
220 GLenum type,
221 const void* pixels) {
222 test_->OnUpload();
225 void WebGraphicsContext3DForUploadTest::getQueryObjectuivEXT(GLuint id,
226 GLenum pname,
227 GLuint* params) {
228 if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
229 *params = test_->IsQueryResultAvailable();
232 // ZERO UPLOADS TESTS
233 TEST_F(ResourceUpdateControllerTest, ZeroUploads) {
234 AppendFullUploadsToUpdateQueue(0);
235 AppendPartialUploadsToUpdateQueue(0);
236 UpdateTextures();
238 EXPECT_EQ(0, num_total_flushes_);
239 EXPECT_EQ(0, num_total_uploads_);
242 // ONE UPLOAD TESTS
243 TEST_F(ResourceUpdateControllerTest, OneFullUpload) {
244 AppendFullUploadsToUpdateQueue(1);
245 AppendPartialUploadsToUpdateQueue(0);
246 UpdateTextures();
248 EXPECT_EQ(1, num_total_flushes_);
249 EXPECT_EQ(1, num_total_uploads_);
250 EXPECT_EQ(0, num_dangling_uploads_)
251 << "Last upload wasn't followed by a flush.";
254 TEST_F(ResourceUpdateControllerTest, OnePartialUpload) {
255 AppendFullUploadsToUpdateQueue(0);
256 AppendPartialUploadsToUpdateQueue(1);
257 UpdateTextures();
259 EXPECT_EQ(1, num_total_flushes_);
260 EXPECT_EQ(1, num_total_uploads_);
261 EXPECT_EQ(0, num_dangling_uploads_)
262 << "Last upload wasn't followed by a flush.";
265 TEST_F(ResourceUpdateControllerTest, OneFullOnePartialUpload) {
266 AppendFullUploadsToUpdateQueue(1);
267 AppendPartialUploadsToUpdateQueue(1);
268 UpdateTextures();
270 EXPECT_EQ(1, num_total_flushes_);
271 EXPECT_EQ(2, num_total_uploads_);
272 EXPECT_EQ(0, num_dangling_uploads_)
273 << "Last upload wasn't followed by a flush.";
276 // This class of tests upload a number of textures that is a multiple
277 // of the flush period.
278 const int full_upload_flush_multipler = 7;
279 const int full_count = full_upload_flush_multipler * kFlushPeriodFull;
281 const int partial_upload_flush_multipler = 11;
282 const int partial_count =
283 partial_upload_flush_multipler * kFlushPeriodPartial;
285 TEST_F(ResourceUpdateControllerTest, ManyFullUploads) {
286 AppendFullUploadsToUpdateQueue(full_count);
287 AppendPartialUploadsToUpdateQueue(0);
288 UpdateTextures();
290 EXPECT_EQ(full_upload_flush_multipler, num_total_flushes_);
291 EXPECT_EQ(full_count, num_total_uploads_);
292 EXPECT_EQ(0, num_dangling_uploads_)
293 << "Last upload wasn't followed by a flush.";
296 TEST_F(ResourceUpdateControllerTest, ManyPartialUploads) {
297 AppendFullUploadsToUpdateQueue(0);
298 AppendPartialUploadsToUpdateQueue(partial_count);
299 UpdateTextures();
301 EXPECT_EQ(partial_upload_flush_multipler, num_total_flushes_);
302 EXPECT_EQ(partial_count, num_total_uploads_);
303 EXPECT_EQ(0, num_dangling_uploads_)
304 << "Last upload wasn't followed by a flush.";
307 TEST_F(ResourceUpdateControllerTest, ManyFullManyPartialUploads) {
308 AppendFullUploadsToUpdateQueue(full_count);
309 AppendPartialUploadsToUpdateQueue(partial_count);
310 UpdateTextures();
312 EXPECT_EQ(full_upload_flush_multipler + partial_upload_flush_multipler,
313 num_total_flushes_);
314 EXPECT_EQ(full_count + partial_count, num_total_uploads_);
315 EXPECT_EQ(0, num_dangling_uploads_)
316 << "Last upload wasn't followed by a flush.";
319 class FakeResourceUpdateControllerClient
320 : public ResourceUpdateControllerClient {
321 public:
322 FakeResourceUpdateControllerClient() { Reset(); }
323 void Reset() { ready_to_finalize_called_ = false; }
324 bool ReadyToFinalizeCalled() const { return ready_to_finalize_called_; }
326 void ReadyToFinalizeTextureUpdates() override {
327 ready_to_finalize_called_ = true;
330 protected:
331 bool ready_to_finalize_called_;
334 class FakeResourceUpdateController : public ResourceUpdateController {
335 public:
336 static scoped_ptr<FakeResourceUpdateController> Create(
337 ResourceUpdateControllerClient* client,
338 base::TestSimpleTaskRunner* task_runner,
339 scoped_ptr<ResourceUpdateQueue> queue,
340 ResourceProvider* resource_provider) {
341 return make_scoped_ptr(new FakeResourceUpdateController(
342 client, task_runner, queue.Pass(), resource_provider));
345 void SetNow(base::TimeTicks time) { now_ = time; }
346 base::TimeTicks Now() const { return now_; }
347 void SetUpdateTextureTime(base::TimeDelta time) {
348 update_textures_time_ = time;
350 base::TimeTicks UpdateMoreTexturesCompletionTime() override {
351 size_t total_updates =
352 resource_provider_->NumBlockingUploads() + update_more_textures_size_;
353 return now_ + total_updates * update_textures_time_;
355 void SetUpdateMoreTexturesSize(size_t size) {
356 update_more_textures_size_ = size;
358 size_t UpdateMoreTexturesSize() const override {
359 return update_more_textures_size_;
362 protected:
363 FakeResourceUpdateController(ResourceUpdateControllerClient* client,
364 base::TestSimpleTaskRunner* task_runner,
365 scoped_ptr<ResourceUpdateQueue> queue,
366 ResourceProvider* resource_provider)
367 : ResourceUpdateController(
368 client, task_runner, queue.Pass(), resource_provider),
369 resource_provider_(resource_provider),
370 update_more_textures_size_(0) {}
372 ResourceProvider* resource_provider_;
373 base::TimeTicks now_;
374 base::TimeDelta update_textures_time_;
375 size_t update_more_textures_size_;
378 static void RunPendingTask(base::TestSimpleTaskRunner* task_runner,
379 FakeResourceUpdateController* controller) {
380 EXPECT_TRUE(task_runner->HasPendingTask());
381 controller->SetNow(controller->Now() + task_runner->NextPendingTaskDelay());
382 task_runner->RunPendingTasks();
385 TEST_F(ResourceUpdateControllerTest, UpdateMoreTextures) {
386 FakeResourceUpdateControllerClient client;
387 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
388 new base::TestSimpleTaskRunner;
390 SetMaxUploadCountPerUpdate(1);
391 AppendFullUploadsToUpdateQueue(3);
392 AppendPartialUploadsToUpdateQueue(0);
394 DebugScopedSetImplThreadAndMainThreadBlocked
395 impl_thread_and_main_thread_blocked(&proxy_);
396 scoped_ptr<FakeResourceUpdateController> controller(
397 FakeResourceUpdateController::Create(&client,
398 task_runner.get(),
399 queue_.Pass(),
400 resource_provider_.get()));
402 controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
403 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
404 controller->SetUpdateMoreTexturesSize(1);
405 // Not enough time for any updates.
406 controller->PerformMoreUpdates(controller->Now() +
407 base::TimeDelta::FromMilliseconds(90));
408 EXPECT_FALSE(task_runner->HasPendingTask());
410 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
411 controller->SetUpdateMoreTexturesSize(1);
412 // Only enough time for 1 update.
413 controller->PerformMoreUpdates(controller->Now() +
414 base::TimeDelta::FromMilliseconds(120));
415 EXPECT_FALSE(task_runner->HasPendingTask());
416 EXPECT_EQ(1, num_total_uploads_);
418 // Complete one upload.
419 MakeQueryResultAvailable();
421 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
422 controller->SetUpdateMoreTexturesSize(1);
423 // Enough time for 2 updates.
424 controller->PerformMoreUpdates(controller->Now() +
425 base::TimeDelta::FromMilliseconds(220));
426 RunPendingTask(task_runner.get(), controller.get());
427 EXPECT_FALSE(task_runner->HasPendingTask());
428 EXPECT_TRUE(client.ReadyToFinalizeCalled());
429 EXPECT_EQ(3, num_total_uploads_);
432 TEST_F(ResourceUpdateControllerTest, NoMoreUpdates) {
433 FakeResourceUpdateControllerClient client;
434 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
435 new base::TestSimpleTaskRunner;
437 SetMaxUploadCountPerUpdate(1);
438 AppendFullUploadsToUpdateQueue(2);
439 AppendPartialUploadsToUpdateQueue(0);
441 DebugScopedSetImplThreadAndMainThreadBlocked
442 impl_thread_and_main_thread_blocked(&proxy_);
443 scoped_ptr<FakeResourceUpdateController> controller(
444 FakeResourceUpdateController::Create(&client,
445 task_runner.get(),
446 queue_.Pass(),
447 resource_provider_.get()));
449 controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
450 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
451 controller->SetUpdateMoreTexturesSize(1);
452 // Enough time for 3 updates but only 2 necessary.
453 controller->PerformMoreUpdates(controller->Now() +
454 base::TimeDelta::FromMilliseconds(310));
455 RunPendingTask(task_runner.get(), controller.get());
456 EXPECT_FALSE(task_runner->HasPendingTask());
457 EXPECT_TRUE(client.ReadyToFinalizeCalled());
458 EXPECT_EQ(2, num_total_uploads_);
460 client.Reset();
461 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(100));
462 controller->SetUpdateMoreTexturesSize(1);
463 // Enough time for updates but no more updates left.
464 controller->PerformMoreUpdates(controller->Now() +
465 base::TimeDelta::FromMilliseconds(310));
467 // ReadyToFinalizeTextureUpdates should only be called once.
468 EXPECT_FALSE(task_runner->HasPendingTask());
469 EXPECT_FALSE(client.ReadyToFinalizeCalled());
470 EXPECT_EQ(2, num_total_uploads_);
473 TEST_F(ResourceUpdateControllerTest, UpdatesCompleteInFiniteTime) {
474 FakeResourceUpdateControllerClient client;
475 scoped_refptr<base::TestSimpleTaskRunner> task_runner =
476 new base::TestSimpleTaskRunner;
478 SetMaxUploadCountPerUpdate(1);
479 AppendFullUploadsToUpdateQueue(2);
480 AppendPartialUploadsToUpdateQueue(0);
482 DebugScopedSetImplThreadAndMainThreadBlocked
483 impl_thread_and_main_thread_blocked(&proxy_);
484 scoped_ptr<FakeResourceUpdateController> controller(
485 FakeResourceUpdateController::Create(&client,
486 task_runner.get(),
487 queue_.Pass(),
488 resource_provider_.get()));
490 controller->SetNow(controller->Now() + base::TimeDelta::FromMilliseconds(1));
491 controller->SetUpdateTextureTime(base::TimeDelta::FromMilliseconds(500));
492 controller->SetUpdateMoreTexturesSize(1);
494 for (int i = 0; i < 100; i++) {
495 if (client.ReadyToFinalizeCalled())
496 break;
498 // Not enough time for any updates.
499 controller->PerformMoreUpdates(controller->Now() +
500 base::TimeDelta::FromMilliseconds(400));
502 if (task_runner->HasPendingTask())
503 RunPendingTask(task_runner.get(), controller.get());
506 EXPECT_FALSE(task_runner->HasPendingTask());
507 EXPECT_TRUE(client.ReadyToFinalizeCalled());
508 EXPECT_EQ(2, num_total_uploads_);
511 } // namespace
512 } // namespace cc