File: animation_throughput_reporter_unittest.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (301 lines) | stat: -rw-r--r-- 10,733 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/compositor/animation_throughput_reporter.h"

#include <memory>

#include "base/test/bind.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor/test/compositor_metrics_report_checker.h"
#include "ui/compositor/test/compositor_metrics_reporter_test_base.h"
#include "ui/gfx/geometry/rect.h"

namespace ui {

using AnimationThroughputReporterTest = CompositorMetricsReporterTestBase;

// Tests animation throughput collection with implicit animation scenario.
TEST_F(AnimationThroughputReporterTest, ImplicitAnimation) {
  Layer layer;
  layer.SetOpacity(0.5f);
  root_layer()->Add(&layer);

  CompositorMetricsReportChecker checker(this);
  {
    LayerAnimator* animator = layer.GetAnimator();
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());

    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer.SetOpacity(1.0f);
  }
  // The animation starts in next frame (16ms) and ends 48 ms later.
  EXPECT_TRUE(checker.WaitUntilReported());
}

// Tests animation throughput collection with implicit animation setup before
// Layer is attached to a compositor.
TEST_F(AnimationThroughputReporterTest, ImplicitAnimationLateAttach) {
  Layer layer;
  layer.SetOpacity(0.5f);

  CompositorMetricsReportChecker checker(this);
  {
    LayerAnimator* animator = layer.GetAnimator();
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());

    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer.SetOpacity(1.0f);
  }

  // Attach to root after animation setup.
  root_layer()->Add(&layer);
  EXPECT_TRUE(checker.WaitUntilReported());
}

// Tests animation throughput collection with explicitly created animation
// sequence scenario.
TEST_F(AnimationThroughputReporterTest, ExplicitAnimation) {
  Layer layer;
  layer.SetOpacity(0.5f);
  root_layer()->Add(&layer);

  CompositorMetricsReportChecker checker(this);
  LayerAnimator* animator = layer.GetAnimator();
  AnimationThroughputReporter reporter(animator, checker.repeating_callback());

  animator->ScheduleAnimation(
      new LayerAnimationSequence(LayerAnimationElement::CreateOpacityElement(
          1.0f, base::Milliseconds(48))));

  EXPECT_TRUE(checker.WaitUntilReported());
}

// Tests animation throughput collection for a persisted animator of a Layer.
TEST_F(AnimationThroughputReporterTest, PersistedAnimation) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);
  root_layer()->Add(layer.get());

  // Set a persisted animator to |layer|.
  LayerAnimator* animator = new LayerAnimator(base::Milliseconds(48));
  layer->SetAnimator(animator);

  // |reporter| keeps reporting as long as it is alive.
  CompositorMetricsReportChecker checker(this);
  AnimationThroughputReporter reporter(animator, checker.repeating_callback());

  // Report data for animation of opacity goes to 1.
  layer->SetOpacity(1.0f);
  EXPECT_TRUE(checker.WaitUntilReported());

  // Report data for animation of opacity goes to 0.5.
  checker.reset();
  layer->SetOpacity(0.5f);
  EXPECT_TRUE(checker.WaitUntilReported());
}

// Tests animation throughput not reported when animation is aborted.
TEST_F(AnimationThroughputReporterTest, AbortedAnimation) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);
  root_layer()->Add(layer.get());

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);

  // Reporter started monitoring animation, then deleted, which should be
  // reported when the animation ends.
  {
    LayerAnimator* animator = layer->GetAnimator();
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());

    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer->SetOpacity(1.0f);
  }

  // Delete |layer| to abort on-going animations.
  layer.reset();

  // Wait a bit to ensure that report does not happen.
  Advance(base::Milliseconds(100));

  // TODO(crbug.com/40161328): Test the scenario where the report exists when
  // the layer is removed.
}

// Tests no report and no leak when underlying layer is gone before reporter.
TEST_F(AnimationThroughputReporterTest, LayerDestroyedBeforeReporter) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);
  root_layer()->Add(layer.get());

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  LayerAnimator* animator = layer->GetAnimator();
  AnimationThroughputReporter reporter(animator, checker.repeating_callback());
  {
    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer->SetOpacity(1.0f);
  }

  // Delete |layer| to before the reporter.
  layer.reset();

  // Wait a bit to ensure that report does not happen.
  Advance(base::Milliseconds(100));
}

// Tests animation throughput not reported when detached from timeline.
TEST_F(AnimationThroughputReporterTest, NoReportOnDetach) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);
  root_layer()->Add(layer.get());

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  {
    LayerAnimator* animator = layer->GetAnimator();
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());
    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer->SetOpacity(1.0f);
  }

  // Detach from the root and attach to a root.
  root_layer()->Remove(layer.get());
  root_layer()->Add(layer.get());

  // Wait a bit to ensure that report does not happen.
  Advance(base::Milliseconds(100));
}

// Tests animation throughput not reported and no leak when animation is stopped
// without being attached to a root.
TEST_F(AnimationThroughputReporterTest, EndDetachedNoReportNoLeak) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  LayerAnimator* animator = layer->GetAnimator();
  // Schedule an animation without being attached to a root.
  {
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());
    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(50));
    layer->SetOpacity(1.0f);
  }

  // End the animation without being attached to a root.
  animator->StopAnimating();

  // Wait a bit to ensure that report does not happen.
  Advance(base::Milliseconds(100));

  // AnimationTracker in |reporter| should not leak in asan.
}

// Tests animation throughput are reported if there was a previous animation
// preempted under IMMEDIATELY_ANIMATE_TO_NEW_TARGET strategy.
TEST_F(AnimationThroughputReporterTest, ReportForAnimateToNewTarget) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.f);
  layer->SetBounds(gfx::Rect(0, 0, 1, 2));
  root_layer()->Add(layer.get());

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  LayerAnimator* animator = layer->GetAnimator();
  // Schedule an animation that will be preempted. No report should happen.
  {
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());
    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(50));
    layer->SetOpacity(0.5f);
    layer->SetBounds(gfx::Rect(0, 0, 3, 4));
  }

  // Animate to new target. Report should happen.
  CompositorMetricsReportChecker checker2(this);
  {
    AnimationThroughputReporter reporter(animator,
                                         checker2.repeating_callback());
    ScopedLayerAnimationSettings settings(animator);
    settings.SetPreemptionStrategy(
        LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    settings.SetTransitionDuration(base::Milliseconds(48));
    layer->SetOpacity(1.0f);
    layer->SetBounds(gfx::Rect(0, 0, 5, 6));
  }
  EXPECT_TRUE(checker2.WaitUntilReported());
}

// Tests AnimationThroughputReporter does not leak its AnimationTracker when
// there are existing animations but no new animation sequence starts after it
// is created.
TEST_F(AnimationThroughputReporterTest, NoLeakWithNoAnimationStart) {
  auto layer = std::make_unique<Layer>();
  layer->SetOpacity(0.5f);
  root_layer()->Add(layer.get());

  LayerAnimator* animator = layer->GetAnimator();

  // Create an existing animation.
  {
    ScopedLayerAnimationSettings settings(animator);
    settings.SetTransitionDuration(base::Milliseconds(50));
    layer->SetOpacity(0.0f);
  }

  // Create the reporter with the existing animation.
  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  {
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());
  }

  // Wait a bit to ensure to let the existing animation finish.
  // There should be no report and no leak.
  Advance(base::Milliseconds(100));
}

// Tests smoothness is not reported if the animation will not run.
TEST_F(AnimationThroughputReporterTest, NoReportForNoRunAnimations) {
  Layer layer;
  root_layer()->Add(&layer);

  CompositorMetricsReportChecker checker(this, /*fail_if_reported=*/true);
  {
    LayerAnimator* animator = layer.GetAnimator();
    AnimationThroughputReporter reporter(animator,
                                         checker.repeating_callback());

    // Simulate views::AnimationBuilder to create an animation that will not
    // run.
    ScopedLayerAnimationSettings settings(animator);
    settings.SetPreemptionStrategy(
        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
    std::vector<ui::LayerAnimationSequence*> sequences;
    sequences.push_back(new LayerAnimationSequence(
        LayerAnimationElement::CreateOpacityElement(1.0f, base::TimeDelta())));
    animator->StartTogether(std::move(sequences));
  }

  // Wait a bit to ensure that report does not happen.
  Advance(base::Milliseconds(100));
}

}  // namespace ui