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
5 #include "content/browser/scheduler/responsiveness/calculator.h"
6
7 #include "build/build_config.h"
8 #include "content/public/test/browser_task_environment.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace content {
13 namespace responsiveness {
14
15 using JankType = Calculator::JankType;
16 using ::testing::_;
17
18 namespace {
19 // Copied from calculator.cc.
20 constexpr int kMeasurementIntervalInMs = 30 * 1000;
21 constexpr int kJankThresholdInMs = 100;
22
23 class FakeCalculator : public Calculator {
24 public:
25 MOCK_METHOD3(EmitResponsiveness,
26 void(JankType jank_type,
27 size_t janky_slices,
28 bool was_process_suspended));
29
30 using Calculator::GetLastCalculationTime;
31 };
32
33 } // namespace
34
35 class ResponsivenessCalculatorTest : public testing::Test {
36 public:
SetUp()37 void SetUp() override {
38 calculator_ = std::make_unique<testing::StrictMock<FakeCalculator>>();
39 last_calculation_time_ = calculator_->GetLastCalculationTime();
40 #if defined(OS_ANDROID)
41 base::android::ApplicationStatusListener::NotifyApplicationStateChange(
42 base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
43 base::RunLoop().RunUntilIdle();
44 #endif
45 }
46
AddEventUI(int queue_time_in_ms,int execution_start_time_in_ms,int execution_finish_time_in_ms)47 void AddEventUI(int queue_time_in_ms,
48 int execution_start_time_in_ms,
49 int execution_finish_time_in_ms) {
50 calculator_->TaskOrEventFinishedOnUIThread(
51 last_calculation_time_ +
52 base::TimeDelta::FromMilliseconds(queue_time_in_ms),
53 last_calculation_time_ +
54 base::TimeDelta::FromMilliseconds(execution_start_time_in_ms),
55 last_calculation_time_ +
56 base::TimeDelta::FromMilliseconds(execution_finish_time_in_ms));
57 }
58
AddEventIO(int queue_time_in_ms,int execution_start_time_in_ms,int execution_finish_time_in_ms)59 void AddEventIO(int queue_time_in_ms,
60 int execution_start_time_in_ms,
61 int execution_finish_time_in_ms) {
62 calculator_->TaskOrEventFinishedOnIOThread(
63 last_calculation_time_ +
64 base::TimeDelta::FromMilliseconds(queue_time_in_ms),
65 last_calculation_time_ +
66 base::TimeDelta::FromMilliseconds(execution_start_time_in_ms),
67 last_calculation_time_ +
68 base::TimeDelta::FromMilliseconds(execution_finish_time_in_ms));
69 }
70
TriggerCalculation()71 void TriggerCalculation() {
72 AddEventUI(kMeasurementIntervalInMs + 1, kMeasurementIntervalInMs + 1,
73 kMeasurementIntervalInMs + 1);
74 last_calculation_time_ = calculator_->GetLastCalculationTime();
75 }
76
77 protected:
78 // This member sets up BrowserThread::IO and BrowserThread::UI. It must be the
79 // first member, as other members may depend on these abstractions.
80 content::BrowserTaskEnvironment task_environment_;
81
82 std::unique_ptr<FakeCalculator> calculator_;
83 base::TimeTicks last_calculation_time_;
84 };
85
86 #define EXPECT_EXECUTION_JANKY_SLICES(num_slices) \
87 EXPECT_CALL(*calculator_, \
88 EmitResponsiveness(JankType::kExecution, num_slices, false));
89 #define EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(num_slices) \
90 EXPECT_CALL(*calculator_, EmitResponsiveness(JankType::kQueueAndExecution, \
91 num_slices, false));
92
93 // A single event executing slightly longer than kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,ShortExecutionJank)94 TEST_F(ResponsivenessCalculatorTest, ShortExecutionJank) {
95 constexpr int kQueueTime = 35;
96 constexpr int kStartTime = 40;
97 constexpr int kFinishTime = kStartTime + kJankThresholdInMs + 5;
98
99 AddEventUI(kQueueTime, kStartTime, kFinishTime);
100 EXPECT_EXECUTION_JANKY_SLICES(1u);
101 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
102 TriggerCalculation();
103 }
104
105 // A single event queued slightly longer than kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,ShortQueueJank)106 TEST_F(ResponsivenessCalculatorTest, ShortQueueJank) {
107 constexpr int kQueueTime = 35;
108 constexpr int kStartTime = kQueueTime + kJankThresholdInMs + 5;
109 constexpr int kFinishTime = kStartTime + 5;
110
111 AddEventUI(kQueueTime, kStartTime, kFinishTime);
112 EXPECT_EXECUTION_JANKY_SLICES(0u);
113 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
114 TriggerCalculation();
115 }
116
117 // A single event whose queuing and execution time together take longer than
118 // kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,ShortCombinedQueueAndExecutionJank)119 TEST_F(ResponsivenessCalculatorTest, ShortCombinedQueueAndExecutionJank) {
120 constexpr int kQueueTime = 35;
121 constexpr int kStartTime = kQueueTime + (kJankThresholdInMs / 2);
122 constexpr int kFinishTime = kStartTime + (kJankThresholdInMs / 2) + 1;
123
124 AddEventUI(kQueueTime, kStartTime, kFinishTime);
125 EXPECT_EXECUTION_JANKY_SLICES(0u);
126 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
127 TriggerCalculation();
128 }
129
130 // A single event executing slightly longer than 10 * kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,LongExecutionJank)131 TEST_F(ResponsivenessCalculatorTest, LongExecutionJank) {
132 constexpr int kQueueTime = 35;
133 constexpr int kStartTime = 40;
134 constexpr int kFinishTime = kStartTime + 10 * kJankThresholdInMs + 5;
135
136 AddEventUI(kQueueTime, kStartTime, kFinishTime);
137 EXPECT_EXECUTION_JANKY_SLICES(10u);
138 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(10u);
139 TriggerCalculation();
140 }
141
142 // A single event executing slightly longer than 10 * kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,LongQueueJank)143 TEST_F(ResponsivenessCalculatorTest, LongQueueJank) {
144 constexpr int kQueueTime = 35;
145 constexpr int kStartTime = kQueueTime + 10 * kJankThresholdInMs + 5;
146 constexpr int kFinishTime = kStartTime + 5;
147
148 AddEventUI(kQueueTime, kStartTime, kFinishTime);
149 EXPECT_EXECUTION_JANKY_SLICES(0u);
150 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(10u);
151 TriggerCalculation();
152 }
153
154 // Events that execute in less than 100ms do not jank, regardless of start time.
TEST_F(ResponsivenessCalculatorTest,NoExecutionJank)155 TEST_F(ResponsivenessCalculatorTest, NoExecutionJank) {
156 int base_time = 30;
157 for (int i = 0; i < kJankThresholdInMs; ++i) {
158 AddEventUI(base_time, base_time, base_time + i);
159 }
160
161 base_time += kJankThresholdInMs;
162 for (int i = 0; i < kJankThresholdInMs; ++i) {
163 AddEventUI(base_time + i, base_time + i, base_time + 2 * i);
164 }
165
166 EXPECT_EXECUTION_JANKY_SLICES(0u);
167 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(0u);
168 TriggerCalculation();
169 }
170
171 // Events that are queued and execute in less than 100ms do not jank, regardless
172 // of start time.
TEST_F(ResponsivenessCalculatorTest,NoQueueJank)173 TEST_F(ResponsivenessCalculatorTest, NoQueueJank) {
174 int base_time = 30;
175 for (int i = 0; i < kJankThresholdInMs; ++i) {
176 AddEventUI(base_time, base_time + i, base_time + i);
177 }
178
179 base_time += kJankThresholdInMs;
180 for (int i = 0; i < kJankThresholdInMs; ++i) {
181 AddEventUI(base_time + i, base_time + 2 * i, base_time + 2 * i);
182 }
183
184 EXPECT_EXECUTION_JANKY_SLICES(0u);
185 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(0u);
186 TriggerCalculation();
187 }
188
189 // 10 execution jank events, but very closely overlapping. Time slices are
190 // discretized and fixed, e.g. [0 100] [100 200] [200 300]. In this test, the
191 // events all start in the [0 100] slice and end in the [100 200] slice. All of
192 // them end up marking the [100 200] slice as janky.
TEST_F(ResponsivenessCalculatorTest,OverlappingExecutionJank)193 TEST_F(ResponsivenessCalculatorTest, OverlappingExecutionJank) {
194 int base_time = 30;
195 for (int i = 0; i < 10; ++i) {
196 const int queue_time = base_time;
197 const int start_time = base_time;
198 const int finish_time = start_time + kJankThresholdInMs + i;
199 AddEventUI(queue_time, start_time, finish_time);
200 }
201
202 EXPECT_EXECUTION_JANKY_SLICES(1u);
203 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
204 TriggerCalculation();
205 }
206
207 // 10 queue jank events, but very closely overlapping. Time slices are
208 // discretized and fixed, e.g. [0 100] [100 200] [200 300]. In this test, the
209 // events are all queued in the [0 100] slice and start executing in the [100
210 // 200] slice. All of them end up marking the [100 200] slice as janky.
TEST_F(ResponsivenessCalculatorTest,OverlappingQueueJank)211 TEST_F(ResponsivenessCalculatorTest, OverlappingQueueJank) {
212 int base_time = 30;
213 for (int i = 0; i < 10; ++i) {
214 const int queue_time = base_time;
215 const int start_time = base_time + kJankThresholdInMs + i;
216 const int finish_time = start_time + 1;
217 AddEventUI(queue_time, start_time, finish_time);
218 }
219
220 EXPECT_EXECUTION_JANKY_SLICES(0u);
221 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
222 TriggerCalculation();
223 }
224
225 // UI thread has 3 execution jank events on slices 1, 2, 3
226 // IO thread has 3 execution jank events on slices 3, 4, 5,
227 // There should be a total of 5 jank events.
TEST_F(ResponsivenessCalculatorTest,OverlappingExecutionJankMultipleThreads)228 TEST_F(ResponsivenessCalculatorTest, OverlappingExecutionJankMultipleThreads) {
229 int base_time = 105;
230 for (int i = 0; i < 3; ++i) {
231 const int queue_time = base_time + i * kJankThresholdInMs;
232 const int start_time = queue_time;
233 const int finish_time = start_time + kJankThresholdInMs + 10;
234 AddEventUI(queue_time, start_time, finish_time);
235 }
236
237 base_time = 305;
238 for (int i = 0; i < 3; ++i) {
239 const int queue_time = base_time + i * kJankThresholdInMs;
240 const int start_time = queue_time;
241 const int finish_time = start_time + kJankThresholdInMs + 10;
242 AddEventIO(queue_time, start_time, finish_time);
243 }
244
245 EXPECT_EXECUTION_JANKY_SLICES(5u);
246 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(5u);
247 TriggerCalculation();
248 }
249
250 // UI thread has 3 queue jank events on slices 1, 2, 3
251 // IO thread has 3 queue jank events on slices 3, 4, 5,
252 // There should be a total of 5 jank events.
TEST_F(ResponsivenessCalculatorTest,OverlappingQueueJankMultipleThreads)253 TEST_F(ResponsivenessCalculatorTest, OverlappingQueueJankMultipleThreads) {
254 int base_time = 105;
255 for (int i = 0; i < 3; ++i) {
256 const int queue_time = base_time + i * kJankThresholdInMs;
257 const int start_time = queue_time + kJankThresholdInMs + 10;
258 const int finish_time = start_time;
259 AddEventUI(queue_time, start_time, finish_time);
260 }
261
262 base_time = 305;
263 for (int i = 0; i < 3; ++i) {
264 const int queue_time = base_time + i * kJankThresholdInMs;
265 const int start_time = queue_time + kJankThresholdInMs + 10;
266 const int finish_time = start_time;
267 AddEventIO(queue_time, start_time, finish_time);
268 }
269
270 EXPECT_EXECUTION_JANKY_SLICES(0u);
271 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(5u);
272 TriggerCalculation();
273 }
274
275 // Three execution janks, each of length 2, separated by some shorter events.
TEST_F(ResponsivenessCalculatorTest,SeparatedExecutionJanks)276 TEST_F(ResponsivenessCalculatorTest, SeparatedExecutionJanks) {
277 int base_time = 105;
278
279 for (int i = 0; i < 3; ++i) {
280 {
281 const int queue_time = base_time;
282 const int start_time = base_time;
283 const int finish_time = base_time + 1;
284 AddEventUI(queue_time, start_time, finish_time);
285 }
286 {
287 const int queue_time = base_time;
288 const int start_time = base_time;
289 const int finish_time = base_time + 2 * kJankThresholdInMs + 1;
290 AddEventUI(queue_time, start_time, finish_time);
291 }
292 base_time += 10 * kJankThresholdInMs;
293 }
294
295 EXPECT_EXECUTION_JANKY_SLICES(6u);
296 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(6u);
297 TriggerCalculation();
298 }
299
300 // Three queue janks, each of length 2, separated by some shorter events.
TEST_F(ResponsivenessCalculatorTest,SeparatedQueueJanks)301 TEST_F(ResponsivenessCalculatorTest, SeparatedQueueJanks) {
302 int base_time = 105;
303
304 for (int i = 0; i < 3; ++i) {
305 {
306 const int queue_time = base_time;
307 const int start_time = base_time + 1;
308 const int finish_time = start_time;
309 AddEventUI(queue_time, start_time, finish_time);
310 }
311 {
312 const int queue_time = base_time;
313 const int start_time = base_time + 2 * kJankThresholdInMs + 1;
314 const int finish_time = start_time;
315 AddEventUI(queue_time, start_time, finish_time);
316 }
317 base_time += 10 * kJankThresholdInMs;
318 }
319
320 EXPECT_EXECUTION_JANKY_SLICES(0u);
321 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(6u);
322 TriggerCalculation();
323 }
324
TEST_F(ResponsivenessCalculatorTest,MultipleTrigger)325 TEST_F(ResponsivenessCalculatorTest, MultipleTrigger) {
326 int base_time = 105;
327
328 // 3 Janks, then trigger, then repeat.
329 for (int i = 0; i < 10; ++i) {
330 for (int j = 0; j < 3; ++j) {
331 AddEventUI(base_time, base_time, base_time + 3 * kJankThresholdInMs + 1);
332 base_time += 3 * kJankThresholdInMs;
333 }
334
335 EXPECT_EXECUTION_JANKY_SLICES(9u);
336 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(9u);
337 TriggerCalculation();
338 testing::Mock::VerifyAndClear(calculator_.get());
339 }
340 }
341
342 // A long delay means that the machine likely went to sleep.
TEST_F(ResponsivenessCalculatorTest,LongDelay)343 TEST_F(ResponsivenessCalculatorTest, LongDelay) {
344 int base_time = 105;
345 AddEventUI(base_time, base_time, base_time + 3 * kJankThresholdInMs + 1);
346 base_time += 10 * kMeasurementIntervalInMs;
347 AddEventUI(base_time, base_time, base_time + 1);
348
349 EXPECT_CALL(*calculator_, EmitResponsiveness(_, _, _)).Times(0);
350 }
351
352 // A long event means that the machine likely went to sleep.
TEST_F(ResponsivenessCalculatorTest,LongEvent)353 TEST_F(ResponsivenessCalculatorTest, LongEvent) {
354 int base_time = 105;
355 AddEventUI(base_time, base_time, base_time + 10 * kMeasurementIntervalInMs);
356
357 EXPECT_CALL(*calculator_, EmitResponsiveness(_, _, _)).Times(0);
358 }
359
360 #if defined(OS_ANDROID)
361 // Metric should not be recorded when application is in background.
TEST_F(ResponsivenessCalculatorTest,ApplicationInBackground)362 TEST_F(ResponsivenessCalculatorTest, ApplicationInBackground) {
363 constexpr int kQueueTime = 35;
364 constexpr int kStartTime = 40;
365 constexpr int kFinishTime = kStartTime + kJankThresholdInMs + 5;
366 AddEventUI(kQueueTime, kStartTime, kFinishTime);
367
368 base::android::ApplicationStatusListener::NotifyApplicationStateChange(
369 base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES);
370 base::RunLoop().RunUntilIdle();
371
372 AddEventUI(kQueueTime, kStartTime + 1, kFinishTime + 1);
373
374 EXPECT_CALL(*calculator_, EmitResponsiveness(_, _, _)).Times(0);
375 TriggerCalculation();
376 }
377 #endif
378
379 // The suspended state must be passed to EmitResponsiveness(...).
380 // A single event executing slightly longer than 10 * kJankThresholdInMs.
TEST_F(ResponsivenessCalculatorTest,JankWithPowerSuspend)381 TEST_F(ResponsivenessCalculatorTest, JankWithPowerSuspend) {
382 constexpr int kQueueTime = 35;
383 constexpr int kStartTime = 40;
384 constexpr int kFinishTime = kStartTime + 10 * kJankThresholdInMs + 5;
385
386 AddEventUI(kQueueTime, kStartTime, kFinishTime);
387 EXPECT_CALL(*calculator_,
388 EmitResponsiveness(JankType::kExecution, 10, false));
389 EXPECT_CALL(*calculator_,
390 EmitResponsiveness(JankType::kQueueAndExecution, 10, false));
391 TriggerCalculation();
392
393 calculator_->SetProcessSuspended(true);
394 AddEventUI(kQueueTime, kStartTime, kFinishTime);
395 EXPECT_CALL(*calculator_, EmitResponsiveness(JankType::kExecution, 10, true));
396 EXPECT_CALL(*calculator_,
397 EmitResponsiveness(JankType::kQueueAndExecution, 10, true));
398 TriggerCalculation();
399
400 calculator_->SetProcessSuspended(false);
401 AddEventUI(kQueueTime, kStartTime, kFinishTime);
402 EXPECT_CALL(*calculator_, EmitResponsiveness(JankType::kExecution, 10, true));
403 EXPECT_CALL(*calculator_,
404 EmitResponsiveness(JankType::kQueueAndExecution, 10, true));
405 TriggerCalculation();
406
407 calculator_->SetProcessSuspended(true);
408 AddEventUI(kQueueTime, kStartTime, kFinishTime);
409 calculator_->SetProcessSuspended(false);
410 EXPECT_CALL(*calculator_, EmitResponsiveness(JankType::kExecution, 10, true));
411 EXPECT_CALL(*calculator_,
412 EmitResponsiveness(JankType::kQueueAndExecution, 10, true));
413 TriggerCalculation();
414
415 // The whole slice must be flagged as containing suspend/resume events.
416 calculator_->SetProcessSuspended(true);
417 calculator_->SetProcessSuspended(false);
418 AddEventUI(kQueueTime, kStartTime, kFinishTime);
419 EXPECT_CALL(*calculator_, EmitResponsiveness(JankType::kExecution, 10, true));
420 EXPECT_CALL(*calculator_,
421 EmitResponsiveness(JankType::kQueueAndExecution, 10, true));
422 TriggerCalculation();
423
424 AddEventUI(kQueueTime, kStartTime, kFinishTime);
425 EXPECT_CALL(*calculator_,
426 EmitResponsiveness(JankType::kExecution, 10, false));
427 EXPECT_CALL(*calculator_,
428 EmitResponsiveness(JankType::kQueueAndExecution, 10, false));
429 TriggerCalculation();
430 }
431
432 // An event execution that crosses a measurement interval boundary should count
433 // towards both measurement intervals.
TEST_F(ResponsivenessCalculatorTest,ExecutionCrossesBoundary)434 TEST_F(ResponsivenessCalculatorTest, ExecutionCrossesBoundary) {
435 // Dummy event so that Calculator doesn't think the process is suspended.
436 {
437 const int kTime = 0.5 * kMeasurementIntervalInMs;
438 AddEventUI(kTime, kTime, kTime);
439 }
440
441 // The event goes from [29801, 30150]. It should count as 1 jank in the first
442 // measurement interval and 2 in the second.
443 {
444 EXPECT_EXECUTION_JANKY_SLICES(1u);
445 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
446 const int queue_time =
447 kMeasurementIntervalInMs - 2 * kJankThresholdInMs + 1;
448 const int start_time = queue_time;
449 const int finish_time = kMeasurementIntervalInMs + 1.5 * kJankThresholdInMs;
450 AddEventUI(queue_time, start_time, finish_time);
451 }
452
453 // Dummy event so that Calculator doesn't think the process is suspended.
454 {
455 const int kTime = 1.5 * kMeasurementIntervalInMs;
456 AddEventUI(kTime, kTime, kTime);
457 }
458
459 // Trigger another calculation.
460 EXPECT_EXECUTION_JANKY_SLICES(2u);
461 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(2u);
462
463 const int kTime = 2 * kMeasurementIntervalInMs + 1;
464 AddEventUI(kTime, kTime, kTime);
465 }
466
467 // An event queuing that crosses a measurement interval boundary should count
468 // towards both measurement intervals.
TEST_F(ResponsivenessCalculatorTest,QueuingCrossesBoundary)469 TEST_F(ResponsivenessCalculatorTest, QueuingCrossesBoundary) {
470 // Dummy event so that Calculator doesn't think the process is suspended.
471 {
472 const int kTime = 0.5 * kMeasurementIntervalInMs;
473 AddEventUI(kTime, kTime, kTime);
474 }
475
476 // The event goes from [29801, 30150]. It should count as 1 jank in the first
477 // measurement interval and 2 in the second.
478 {
479 EXPECT_EXECUTION_JANKY_SLICES(0u);
480 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(1u);
481 const int queue_time =
482 kMeasurementIntervalInMs - 2 * kJankThresholdInMs + 1;
483 const int start_time = kMeasurementIntervalInMs + 1.5 * kJankThresholdInMs;
484 const int finish_time = start_time;
485 AddEventUI(queue_time, start_time, finish_time);
486 }
487
488 // Dummy event so that Calculator doesn't think the process is suspended.
489 {
490 const int kTime = 1.5 * kMeasurementIntervalInMs;
491 AddEventUI(kTime, kTime, kTime);
492 }
493
494 // Trigger another calculation.
495 EXPECT_EXECUTION_JANKY_SLICES(0u);
496 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(2u);
497
498 const int kTime = 2 * kMeasurementIntervalInMs + 1;
499 AddEventUI(kTime, kTime, kTime);
500 }
501
502 // Events may not be ordered by start or end time.
TEST_F(ResponsivenessCalculatorTest,UnorderedEvents)503 TEST_F(ResponsivenessCalculatorTest, UnorderedEvents) {
504 // We add the following tasks:
505 // [100, 100, 250]
506 // [150, 150, 300]
507 // [50, 50, 200]
508 // [50, 50, 390] <- A
509 //
510 // [1100, 1250, 1251]
511 // [1150, 1300, 1301]
512 // [1050, 1200, 1201]
513 // [1050, 1390, 1391] <- B
514 //
515 // The execution jank in A subsumes all other execution janks. The queue jank
516 // in B subsumes all other queue janks.
517 AddEventUI(100, 100, 250);
518 AddEventUI(150, 150, 300);
519 AddEventUI(50, 50, 200);
520 AddEventUI(50, 50, 390);
521
522 AddEventUI(1100, 1250, 1251);
523 AddEventUI(1150, 1300, 1301);
524 AddEventUI(1050, 1200, 1201);
525 AddEventUI(1050, 1390, 1391);
526
527 EXPECT_EXECUTION_JANKY_SLICES(3u);
528 EXPECT_QUEUE_AND_EXECUTION_JANKY_SLICES(6u);
529 TriggerCalculation();
530 }
531
532 } // namespace responsiveness
533 } // namespace content
534