presentation_time_recorder_unittest.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2019 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 "ui/compositor/presentation_time_recorder.h"
  5. #include "base/run_loop.h"
  6. #include "base/test/bind.h"
  7. #include "base/test/metrics/histogram_tester.h"
  8. #include "base/test/task_environment.h"
  9. #include "base/time/time.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. #include "ui/compositor/compositor.h"
  12. #include "ui/compositor/layer.h"
  13. #include "ui/compositor/test/test_compositor_host.h"
  14. #include "ui/compositor/test/test_context_factories.h"
  15. #include "ui/compositor/test/test_utils.h"
  16. #include "ui/gfx/presentation_feedback.h"
  17. namespace ui {
  18. class PresentationTimeRecorderTest : public testing::Test {
  19. protected:
  20. void SetUp() override {
  21. context_factories_ = std::make_unique<TestContextFactories>(false);
  22. const gfx::Rect bounds(100, 100);
  23. host_.reset(TestCompositorHost::Create(
  24. bounds, context_factories_->GetContextFactory()));
  25. host_->Show();
  26. host_->GetCompositor()->SetRootLayer(&root_);
  27. }
  28. void TearDown() override {
  29. host_.reset();
  30. context_factories_.reset();
  31. }
  32. base::test::TaskEnvironment task_environment_{
  33. base::test::TaskEnvironment::MainThreadType::UI};
  34. Layer root_;
  35. std::unique_ptr<TestContextFactories> context_factories_;
  36. std::unique_ptr<TestCompositorHost> host_;
  37. };
  38. constexpr char kName[] = "Histogram";
  39. constexpr char kMaxLatencyName[] = "MaxLatency.Histogram";
  40. TEST_F(PresentationTimeRecorderTest, Histogram) {
  41. base::HistogramTester histogram_tester;
  42. auto* compositor = host_->GetCompositor();
  43. auto test_recorder = CreatePresentationTimeHistogramRecorder(
  44. compositor, kName, kMaxLatencyName);
  45. // Flush pending draw callbask by waiting for presentation until it times out.
  46. // We assume if the new frame wasn't generated for 100ms (6 frames worth
  47. // time) there is no pending draw request.
  48. while (ui::WaitForNextFrameToBePresented(compositor, base::Milliseconds(100)))
  49. ;
  50. compositor->ScheduleFullRedraw();
  51. histogram_tester.ExpectTotalCount(kName, 0);
  52. test_recorder->RequestNext();
  53. histogram_tester.ExpectTotalCount(kName, 0);
  54. test_recorder->RequestNext();
  55. histogram_tester.ExpectTotalCount(kName, 0);
  56. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  57. EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor));
  58. histogram_tester.ExpectTotalCount(kName, 1);
  59. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  60. compositor->ScheduleFullRedraw();
  61. EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor));
  62. histogram_tester.ExpectTotalCount(kName, 1);
  63. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  64. test_recorder->RequestNext();
  65. compositor->ScheduleFullRedraw();
  66. EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor));
  67. histogram_tester.ExpectTotalCount(kName, 2);
  68. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  69. // Drawing without RequestNext should not affect histogram.
  70. compositor->ScheduleFullRedraw();
  71. EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor));
  72. histogram_tester.ExpectTotalCount(kName, 2);
  73. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  74. // Make sure the max latency is recorded upon deletion.
  75. test_recorder.reset();
  76. histogram_tester.ExpectTotalCount(kName, 2);
  77. histogram_tester.ExpectTotalCount(kMaxLatencyName, 1);
  78. }
  79. TEST_F(PresentationTimeRecorderTest, NoSuccessNoHistogram) {
  80. base::HistogramTester histogram_tester;
  81. auto* compositor = host_->GetCompositor();
  82. auto test_recorder = CreatePresentationTimeHistogramRecorder(
  83. compositor, kName, kMaxLatencyName);
  84. PresentationTimeRecorder::TestApi test_api(test_recorder.get());
  85. base::TimeDelta interval_not_used = base::Milliseconds(0);
  86. gfx::PresentationFeedback failure(
  87. base::TimeTicks() + base::Milliseconds(2000), interval_not_used,
  88. gfx::PresentationFeedback::kFailure);
  89. base::TimeTicks start = base::TimeTicks() + base::Milliseconds(1000);
  90. test_recorder->RequestNext();
  91. test_api.OnPresented(0, start, failure);
  92. test_recorder.reset();
  93. histogram_tester.ExpectTotalCount(kName, 0);
  94. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  95. }
  96. TEST_F(PresentationTimeRecorderTest, DelayedHistogram) {
  97. base::HistogramTester histogram_tester;
  98. auto* compositor = host_->GetCompositor();
  99. auto test_recorder = CreatePresentationTimeHistogramRecorder(
  100. compositor, kName, kMaxLatencyName);
  101. test_recorder->RequestNext();
  102. // Delete the recorder while waiting for the presentation callback.
  103. test_recorder.reset();
  104. histogram_tester.ExpectTotalCount(kName, 0);
  105. histogram_tester.ExpectTotalCount(kMaxLatencyName, 0);
  106. // Draw next frame and make sure the histgoram is recorded.
  107. compositor->ScheduleFullRedraw();
  108. EXPECT_TRUE(ui::WaitForNextFrameToBePresented(compositor));
  109. histogram_tester.ExpectTotalCount(kName, 1);
  110. histogram_tester.ExpectTotalCount(kMaxLatencyName, 1);
  111. }
  112. TEST_F(PresentationTimeRecorderTest, Failure) {
  113. auto* compositor = host_->GetCompositor();
  114. auto test_recorder = CreatePresentationTimeHistogramRecorder(
  115. compositor, kName, kMaxLatencyName);
  116. PresentationTimeRecorder::TestApi test_api(test_recorder.get());
  117. test_recorder->RequestNext();
  118. test_api.OnCompositingDidCommit(compositor);
  119. base::TimeDelta interval_not_used = base::Milliseconds(0);
  120. base::TimeTicks start = base::TimeTicks() + base::Milliseconds(1000);
  121. gfx::PresentationFeedback success(
  122. base::TimeTicks() + base::Milliseconds(1100), interval_not_used,
  123. /*flags=*/0);
  124. test_api.OnPresented(0, start, success);
  125. EXPECT_EQ(100, test_api.GetMaxLatencyMs());
  126. EXPECT_EQ(1, test_api.GetSuccessCount());
  127. gfx::PresentationFeedback failure(
  128. base::TimeTicks() + base::Milliseconds(2000), interval_not_used,
  129. gfx::PresentationFeedback::kFailure);
  130. test_api.OnPresented(0, start, failure);
  131. // Failure should not be included in max latency.
  132. EXPECT_EQ(100, test_api.GetMaxLatencyMs());
  133. EXPECT_EQ(50, test_api.GetFailureRatio());
  134. }
  135. } // namespace ui