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 "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher_impl.h"
6 
7 #include "base/run_loop.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/test/metrics/histogram_tester.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/blink/public/platform/platform.h"
14 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h"
15 #include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
16 #include "third_party/blink/renderer/platform/heap/handle.h"
17 #include "third_party/blink/renderer/platform/heap/persistent.h"
18 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
19 #include "third_party/blink/renderer/platform/scheduler/public/thread.h"
20 #include "third_party/blink/renderer/platform/scheduler/public/thread_type.h"
21 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
22 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
23 
24 #include <memory>
25 
26 using ::testing::_;
27 using ::testing::AtLeast;
28 using ::testing::Mock;
29 using ::testing::Return;
30 using ::testing::Sequence;
31 using ::testing::StrictMock;
32 using ::testing::Truly;
33 
34 // This test uses actual threads since mutator logic requires it. This means we
35 // have dependency on Blink platform to create threads.
36 
37 namespace blink {
38 namespace {
39 
CreateThread(const char * name)40 std::unique_ptr<Thread> CreateThread(const char* name) {
41   return Platform::Current()->CreateThread(
42       ThreadCreationParams(ThreadType::kTestThread).SetThreadNameForTest(name));
43 }
44 
45 class MockAnimationWorkletMutator
46     : public GarbageCollected<MockAnimationWorkletMutator>,
47       public AnimationWorkletMutator {
48   USING_GARBAGE_COLLECTED_MIXIN(MockAnimationWorkletMutator);
49 
50  public:
MockAnimationWorkletMutator(scoped_refptr<base::SingleThreadTaskRunner> expected_runner)51   MockAnimationWorkletMutator(
52       scoped_refptr<base::SingleThreadTaskRunner> expected_runner)
53       : expected_runner_(expected_runner) {}
54 
~MockAnimationWorkletMutator()55   ~MockAnimationWorkletMutator() override {}
56 
Mutate(std::unique_ptr<AnimationWorkletInput> input)57   std::unique_ptr<AnimationWorkletOutput> Mutate(
58       std::unique_ptr<AnimationWorkletInput> input) override {
59     return std::unique_ptr<AnimationWorkletOutput>(MutateRef(*input));
60   }
61 
62   // Blocks the worklet thread by posting a task that will complete only when
63   // signaled. This blocking ensures that tests of async mutations do not
64   // encounter race conditions when validating queuing strategies.
BlockWorkletThread()65   void BlockWorkletThread() {
66     PostCrossThreadTask(
67         *expected_runner_, FROM_HERE,
68         CrossThreadBindOnce(
69             [](base::WaitableEvent* start_processing_event) {
70               start_processing_event->Wait();
71             },
72             WTF::CrossThreadUnretained(&start_processing_event_)));
73   }
74 
UnblockWorkletThread()75   void UnblockWorkletThread() { start_processing_event_.Signal(); }
76 
77   MOCK_CONST_METHOD0(GetWorkletId, int());
78   MOCK_METHOD1(MutateRef,
79                AnimationWorkletOutput*(const AnimationWorkletInput&));
80 
81   scoped_refptr<base::SingleThreadTaskRunner> expected_runner_;
82   base::WaitableEvent start_processing_event_;
83 };
84 
85 class MockCompositorMutatorClient : public CompositorMutatorClient {
86  public:
MockCompositorMutatorClient(std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator)87   MockCompositorMutatorClient(
88       std::unique_ptr<AnimationWorkletMutatorDispatcherImpl> mutator)
89       : CompositorMutatorClient(std::move(mutator)) {}
~MockCompositorMutatorClient()90   ~MockCompositorMutatorClient() override {}
91   // gmock cannot mock methods with move-only args so we forward it to ourself.
SetMutationUpdate(std::unique_ptr<cc::MutatorOutputState> output_state)92   void SetMutationUpdate(
93       std::unique_ptr<cc::MutatorOutputState> output_state) override {
94     SetMutationUpdateRef(output_state.get());
95   }
96 
97   MOCK_METHOD1(SetMutationUpdateRef,
98                void(cc::MutatorOutputState* output_state));
99 };
100 
101 class AnimationWorkletMutatorDispatcherImplTest : public ::testing::Test {
102  public:
SetUp()103   void SetUp() override {
104     auto mutator = std::make_unique<AnimationWorkletMutatorDispatcherImpl>(
105         /*main_thread_task_runner=*/true);
106     mutator_ = mutator.get();
107     client_ =
108         std::make_unique<::testing::StrictMock<MockCompositorMutatorClient>>(
109             std::move(mutator));
110   }
111 
TearDown()112   void TearDown() override { mutator_ = nullptr; }
113 
114   std::unique_ptr<::testing::StrictMock<MockCompositorMutatorClient>> client_;
115   AnimationWorkletMutatorDispatcherImpl* mutator_;
116 };
117 
CreateTestMutatorInput()118 std::unique_ptr<AnimationWorkletDispatcherInput> CreateTestMutatorInput() {
119   AnimationWorkletInput::AddAndUpdateState state1{
120       {11, 1}, "test1", 5000, nullptr, nullptr};
121 
122   AnimationWorkletInput::AddAndUpdateState state2{
123       {22, 2}, "test2", 5000, nullptr, nullptr};
124 
125   auto input = std::make_unique<AnimationWorkletDispatcherInput>();
126   input->Add(std::move(state1));
127   input->Add(std::move(state2));
128 
129   return input;
130 }
131 
OnlyIncludesAnimation1(const AnimationWorkletInput & in)132 bool OnlyIncludesAnimation1(const AnimationWorkletInput& in) {
133   return in.added_and_updated_animations.size() == 1 &&
134          in.added_and_updated_animations[0].worklet_animation_id.animation_id ==
135              1;
136 }
137 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,RegisteredAnimatorShouldOnlyReceiveInputForItself)138 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
139        RegisteredAnimatorShouldOnlyReceiveInputForItself) {
140   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
141   MockAnimationWorkletMutator* first_mutator =
142       MakeGarbageCollected<MockAnimationWorkletMutator>(
143           first_thread->GetTaskRunner());
144 
145   mutator_->RegisterAnimationWorkletMutator(
146       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
147 
148   EXPECT_CALL(*first_mutator, GetWorkletId())
149       .Times(AtLeast(1))
150       .WillRepeatedly(Return(11));
151   EXPECT_CALL(*first_mutator, MutateRef(Truly(OnlyIncludesAnimation1)))
152       .Times(1)
153       .WillOnce(Return(new AnimationWorkletOutput()));
154   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
155   mutator_->MutateSynchronously(CreateTestMutatorInput());
156 }
157 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,RegisteredAnimatorShouldNotBeMutatedWhenNoInput)158 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
159        RegisteredAnimatorShouldNotBeMutatedWhenNoInput) {
160   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
161   MockAnimationWorkletMutator* first_mutator =
162       MakeGarbageCollected<MockAnimationWorkletMutator>(
163           first_thread->GetTaskRunner());
164 
165   mutator_->RegisterAnimationWorkletMutator(
166       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
167 
168   EXPECT_CALL(*first_mutator, GetWorkletId())
169       .Times(AtLeast(1))
170       .WillRepeatedly(Return(11));
171   EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
172   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
173 
174   AnimationWorkletInput::AddAndUpdateState state{
175       {22, 2}, "test2", 5000, nullptr, nullptr};
176 
177   auto input = std::make_unique<AnimationWorkletDispatcherInput>();
178   input->Add(std::move(state));
179 
180   mutator_->MutateSynchronously(std::move(input));
181 }
182 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,MutationUpdateIsNotInvokedWithNoRegisteredAnimators)183 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
184        MutationUpdateIsNotInvokedWithNoRegisteredAnimators) {
185   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
186   std::unique_ptr<AnimationWorkletDispatcherInput> input =
187       std::make_unique<AnimationWorkletDispatcherInput>();
188   mutator_->MutateSynchronously(std::move(input));
189 }
190 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,MutationUpdateIsNotInvokedWithNullOutput)191 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
192        MutationUpdateIsNotInvokedWithNullOutput) {
193   // Create a thread to run mutator tasks.
194   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
195   MockAnimationWorkletMutator* first_mutator =
196       MakeGarbageCollected<MockAnimationWorkletMutator>(
197           first_thread->GetTaskRunner());
198 
199   mutator_->RegisterAnimationWorkletMutator(
200       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
201 
202   EXPECT_CALL(*first_mutator, GetWorkletId())
203       .Times(AtLeast(1))
204       .WillRepeatedly(Return(11));
205   EXPECT_CALL(*first_mutator, MutateRef(_)).Times(1).WillOnce(Return(nullptr));
206   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
207   mutator_->MutateSynchronously(CreateTestMutatorInput());
208 }
209 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator)210 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
211        MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) {
212   // Create a thread to run mutator tasks.
213   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
214   MockAnimationWorkletMutator* first_mutator =
215       MakeGarbageCollected<MockAnimationWorkletMutator>(
216           first_thread->GetTaskRunner());
217 
218   mutator_->RegisterAnimationWorkletMutator(
219       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
220 
221   EXPECT_CALL(*first_mutator, GetWorkletId())
222       .Times(AtLeast(1))
223       .WillRepeatedly(Return(11));
224   EXPECT_CALL(*first_mutator, MutateRef(_))
225       .Times(1)
226       .WillOnce(Return(new AnimationWorkletOutput()));
227   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
228   mutator_->MutateSynchronously(CreateTestMutatorInput());
229 
230   // The above call blocks on mutator threads running their tasks so we can
231   // safely verify here.
232   Mock::VerifyAndClearExpectations(client_.get());
233 
234   // Ensure mutator is not invoked after unregistration.
235   EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
236   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
237   mutator_->UnregisterAnimationWorkletMutator(
238       WrapCrossThreadPersistent(first_mutator));
239 
240   mutator_->MutateSynchronously(CreateTestMutatorInput());
241   Mock::VerifyAndClearExpectations(client_.get());
242 }
243 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread)244 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
245        MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) {
246   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
247   MockAnimationWorkletMutator* first_mutator =
248       MakeGarbageCollected<MockAnimationWorkletMutator>(
249           first_thread->GetTaskRunner());
250   MockAnimationWorkletMutator* second_mutator =
251       MakeGarbageCollected<MockAnimationWorkletMutator>(
252           first_thread->GetTaskRunner());
253 
254   mutator_->RegisterAnimationWorkletMutator(
255       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
256   mutator_->RegisterAnimationWorkletMutator(
257       WrapCrossThreadPersistent(second_mutator), first_thread->GetTaskRunner());
258 
259   EXPECT_CALL(*first_mutator, GetWorkletId())
260       .Times(AtLeast(1))
261       .WillRepeatedly(Return(11));
262   EXPECT_CALL(*first_mutator, MutateRef(_))
263       .Times(1)
264       .WillOnce(Return(new AnimationWorkletOutput()));
265   EXPECT_CALL(*second_mutator, GetWorkletId())
266       .Times(AtLeast(1))
267       .WillRepeatedly(Return(22));
268   EXPECT_CALL(*second_mutator, MutateRef(_))
269       .Times(1)
270       .WillOnce(Return(new AnimationWorkletOutput()));
271   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
272   mutator_->MutateSynchronously(CreateTestMutatorInput());
273 }
274 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads)275 TEST_F(
276     AnimationWorkletMutatorDispatcherImplTest,
277     MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) {
278   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
279   MockAnimationWorkletMutator* first_mutator =
280       MakeGarbageCollected<MockAnimationWorkletMutator>(
281           first_thread->GetTaskRunner());
282 
283   std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread");
284   MockAnimationWorkletMutator* second_mutator =
285       MakeGarbageCollected<MockAnimationWorkletMutator>(
286           second_thread->GetTaskRunner());
287 
288   mutator_->RegisterAnimationWorkletMutator(
289       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
290   mutator_->RegisterAnimationWorkletMutator(
291       WrapCrossThreadPersistent(second_mutator),
292       second_thread->GetTaskRunner());
293 
294   EXPECT_CALL(*first_mutator, GetWorkletId())
295       .Times(AtLeast(1))
296       .WillRepeatedly(Return(11));
297   EXPECT_CALL(*first_mutator, MutateRef(_))
298       .Times(1)
299       .WillOnce(Return(new AnimationWorkletOutput()));
300   EXPECT_CALL(*second_mutator, GetWorkletId())
301       .Times(AtLeast(1))
302       .WillRepeatedly(Return(22));
303   EXPECT_CALL(*second_mutator, MutateRef(_))
304       .Times(1)
305       .WillOnce(Return(new AnimationWorkletOutput()));
306   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
307   mutator_->MutateSynchronously(CreateTestMutatorInput());
308 
309   // The above call blocks on mutator threads running their tasks so we can
310   // safely verify here.
311   Mock::VerifyAndClearExpectations(client_.get());
312 
313   // Ensure first_mutator is not invoked after unregistration.
314   mutator_->UnregisterAnimationWorkletMutator(
315       WrapCrossThreadPersistent(first_mutator));
316 
317   EXPECT_CALL(*first_mutator, GetWorkletId()).Times(0);
318   EXPECT_CALL(*first_mutator, MutateRef(_)).Times(0);
319   EXPECT_CALL(*second_mutator, GetWorkletId())
320       .Times(AtLeast(1))
321       .WillRepeatedly(Return(22));
322   EXPECT_CALL(*second_mutator, MutateRef(_))
323       .Times(1)
324       .WillOnce(Return(new AnimationWorkletOutput()));
325   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
326   mutator_->MutateSynchronously(CreateTestMutatorInput());
327 
328   Mock::VerifyAndClearExpectations(client_.get());
329 }
330 
TEST_F(AnimationWorkletMutatorDispatcherImplTest,DispatcherShouldNotHangWhenMutatorGoesAway)331 TEST_F(AnimationWorkletMutatorDispatcherImplTest,
332        DispatcherShouldNotHangWhenMutatorGoesAway) {
333   // Create a thread to run mutator tasks.
334   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
335   MockAnimationWorkletMutator* first_mutator =
336       MakeGarbageCollected<MockAnimationWorkletMutator>(
337           first_thread->GetTaskRunner());
338 
339   mutator_->RegisterAnimationWorkletMutator(
340       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
341 
342   EXPECT_CALL(*first_mutator, GetWorkletId()).WillRepeatedly(Return(11));
343   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
344 
345   // Shutdown the thread so its task runner no longer executes tasks.
346   first_thread.reset();
347 
348   mutator_->MutateSynchronously(CreateTestMutatorInput());
349 
350   Mock::VerifyAndClearExpectations(client_.get());
351 }
352 
353 // -----------------------------------------------------------------------
354 // Asynchronous version of tests.
355 
356 using MutatorDispatcherRef =
357     scoped_refptr<AnimationWorkletMutatorDispatcherImpl>;
358 
359 class AnimationWorkletMutatorDispatcherImplAsyncTest
360     : public AnimationWorkletMutatorDispatcherImplTest {
361  public:
362   AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback
CreateIntermediateResultCallback(MutateStatus expected_result)363   CreateIntermediateResultCallback(MutateStatus expected_result) {
364     return CrossThreadBindOnce(
365         &AnimationWorkletMutatorDispatcherImplAsyncTest ::
366             VerifyExpectedMutationResult,
367         CrossThreadUnretained(this), expected_result);
368   }
369 
370   AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback
CreateNotReachedCallback()371   CreateNotReachedCallback() {
372     return CrossThreadBindOnce([](MutateStatus unused) {
373       NOTREACHED() << "Mutate complete callback should not have been triggered";
374     });
375   }
376 
377   AnimationWorkletMutatorDispatcher::AsyncMutationCompleteCallback
CreateTestCompleteCallback(MutateStatus expected_result=MutateStatus::kCompletedWithUpdate)378   CreateTestCompleteCallback(
379       MutateStatus expected_result = MutateStatus::kCompletedWithUpdate) {
380     return CrossThreadBindOnce(
381         &AnimationWorkletMutatorDispatcherImplAsyncTest ::
382             VerifyCompletedMutationResultAndFinish,
383         CrossThreadUnretained(this), expected_result);
384   }
385 
386   // Executes run loop until quit closure is called.
WaitForTestCompletion()387   void WaitForTestCompletion() { run_loop_.Run(); }
388 
VerifyExpectedMutationResult(MutateStatus expectation,MutateStatus result)389   void VerifyExpectedMutationResult(MutateStatus expectation,
390                                     MutateStatus result) {
391     EXPECT_EQ(expectation, result);
392     IntermediateResultCallbackRef();
393   }
394 
VerifyCompletedMutationResultAndFinish(MutateStatus expectation,MutateStatus result)395   void VerifyCompletedMutationResultAndFinish(MutateStatus expectation,
396                                               MutateStatus result) {
397     EXPECT_EQ(expectation, result);
398     run_loop_.Quit();
399   }
400 
401   // Verifying that intermediate result callbacks are invoked the correct number
402   // of times.
403   MOCK_METHOD0(IntermediateResultCallbackRef, void());
404 
405   static const MutateQueuingStrategy kNormalPriority =
406       MutateQueuingStrategy::kQueueAndReplaceNormalPriority;
407 
408   static const MutateQueuingStrategy kHighPriority =
409       MutateQueuingStrategy::kQueueHighPriority;
410 
411  private:
412   base::RunLoop run_loop_;
413 };
414 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,RegisteredAnimatorShouldOnlyReceiveInputForItself)415 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
416        RegisteredAnimatorShouldOnlyReceiveInputForItself) {
417   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
418   MockAnimationWorkletMutator* first_mutator =
419       MakeGarbageCollected<MockAnimationWorkletMutator>(
420           first_thread->GetTaskRunner());
421 
422   mutator_->RegisterAnimationWorkletMutator(
423       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
424 
425   EXPECT_CALL(*first_mutator, GetWorkletId())
426       .Times(AtLeast(1))
427       .WillRepeatedly(Return(11));
428   EXPECT_CALL(*first_mutator, MutateRef(_))
429       .Times(1)
430       .WillOnce(Return(new AnimationWorkletOutput()));
431   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
432 
433   EXPECT_TRUE(mutator_->MutateAsynchronously(
434       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
435 
436   WaitForTestCompletion();
437 }
438 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,RegisteredAnimatorShouldNotBeMutatedWhenNoInput)439 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
440        RegisteredAnimatorShouldNotBeMutatedWhenNoInput) {
441   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
442   MockAnimationWorkletMutator* first_mutator =
443       MakeGarbageCollected<MockAnimationWorkletMutator>(
444           first_thread->GetTaskRunner());
445 
446   mutator_->RegisterAnimationWorkletMutator(
447       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
448 
449   AnimationWorkletInput::AddAndUpdateState state{
450       {22, 2}, "test2", 5000, nullptr, nullptr};
451 
452   auto input = std::make_unique<AnimationWorkletDispatcherInput>();
453   input->Add(std::move(state));
454 
455   EXPECT_CALL(*first_mutator, GetWorkletId())
456       .Times(AtLeast(1))
457       .WillRepeatedly(Return(11));
458 
459   EXPECT_FALSE(mutator_->MutateAsynchronously(std::move(input), kNormalPriority,
460                                               CreateNotReachedCallback()));
461 }
462 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateIsNotInvokedWithNoRegisteredAnimators)463 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
464        MutationUpdateIsNotInvokedWithNoRegisteredAnimators) {
465   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
466   std::unique_ptr<AnimationWorkletDispatcherInput> input =
467       std::make_unique<AnimationWorkletDispatcherInput>();
468   EXPECT_FALSE(mutator_->MutateAsynchronously(std::move(input), kNormalPriority,
469                                               CreateNotReachedCallback()));
470 }
471 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateIsNotInvokedWithNullOutput)472 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
473        MutationUpdateIsNotInvokedWithNullOutput) {
474   // Create a thread to run mutator tasks.
475   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
476   MockAnimationWorkletMutator* first_mutator =
477       MakeGarbageCollected<MockAnimationWorkletMutator>(
478           first_thread->GetTaskRunner());
479 
480   mutator_->RegisterAnimationWorkletMutator(
481       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
482 
483   EXPECT_CALL(*first_mutator, GetWorkletId())
484       .Times(AtLeast(1))
485       .WillRepeatedly(Return(11));
486   EXPECT_CALL(*first_mutator, MutateRef(_)).Times(1).WillOnce(Return(nullptr));
487   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
488 
489   EXPECT_TRUE(mutator_->MutateAsynchronously(
490       CreateTestMutatorInput(), kNormalPriority,
491       CreateTestCompleteCallback(MutateStatus::kCompletedNoUpdate)));
492 
493   WaitForTestCompletion();
494 }
495 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator)496 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
497        MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) {
498   // Create a thread to run mutator tasks.
499   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
500   MockAnimationWorkletMutator* first_mutator =
501       MakeGarbageCollected<MockAnimationWorkletMutator>(
502           first_thread->GetTaskRunner());
503 
504   mutator_->RegisterAnimationWorkletMutator(
505       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
506 
507   EXPECT_CALL(*first_mutator, GetWorkletId())
508       .Times(AtLeast(1))
509       .WillRepeatedly(Return(11));
510   EXPECT_CALL(*first_mutator, MutateRef(_))
511       .Times(1)
512       .WillOnce(Return(new AnimationWorkletOutput()));
513   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
514 
515   EXPECT_TRUE(mutator_->MutateAsynchronously(
516       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
517 
518   WaitForTestCompletion();
519 
520   // Above call blocks until complete signal is received.
521   Mock::VerifyAndClearExpectations(client_.get());
522 
523   // Ensure mutator is not invoked after unregistration.
524   mutator_->UnregisterAnimationWorkletMutator(
525       WrapCrossThreadPersistent(first_mutator));
526   EXPECT_FALSE(mutator_->MutateAsynchronously(
527       CreateTestMutatorInput(), kNormalPriority, CreateNotReachedCallback()));
528 
529   Mock::VerifyAndClearExpectations(client_.get());
530 }
531 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread)532 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
533        MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) {
534   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
535   MockAnimationWorkletMutator* first_mutator =
536       MakeGarbageCollected<MockAnimationWorkletMutator>(
537           first_thread->GetTaskRunner());
538   MockAnimationWorkletMutator* second_mutator =
539       MakeGarbageCollected<MockAnimationWorkletMutator>(
540           first_thread->GetTaskRunner());
541 
542   mutator_->RegisterAnimationWorkletMutator(
543       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
544   mutator_->RegisterAnimationWorkletMutator(
545       WrapCrossThreadPersistent(second_mutator), first_thread->GetTaskRunner());
546 
547   EXPECT_CALL(*first_mutator, GetWorkletId())
548       .Times(AtLeast(1))
549       .WillRepeatedly(Return(11));
550   EXPECT_CALL(*first_mutator, MutateRef(_))
551       .Times(1)
552       .WillOnce(Return(new AnimationWorkletOutput()));
553   EXPECT_CALL(*second_mutator, GetWorkletId())
554       .Times(AtLeast(1))
555       .WillRepeatedly(Return(22));
556   EXPECT_CALL(*second_mutator, MutateRef(_))
557       .Times(1)
558       .WillOnce(Return(new AnimationWorkletOutput()));
559   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
560 
561   EXPECT_TRUE(mutator_->MutateAsynchronously(
562       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
563 
564   WaitForTestCompletion();
565 }
566 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads)567 TEST_F(
568     AnimationWorkletMutatorDispatcherImplAsyncTest,
569     MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) {
570   std::unique_ptr<Thread> first_thread = CreateThread("FirstAnimationThread");
571   MockAnimationWorkletMutator* first_mutator =
572       MakeGarbageCollected<MockAnimationWorkletMutator>(
573           first_thread->GetTaskRunner());
574 
575   std::unique_ptr<Thread> second_thread = CreateThread("SecondAnimationThread");
576   MockAnimationWorkletMutator* second_mutator =
577       MakeGarbageCollected<MockAnimationWorkletMutator>(
578           second_thread->GetTaskRunner());
579 
580   mutator_->RegisterAnimationWorkletMutator(
581       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
582   mutator_->RegisterAnimationWorkletMutator(
583       WrapCrossThreadPersistent(second_mutator),
584       second_thread->GetTaskRunner());
585 
586   EXPECT_CALL(*first_mutator, GetWorkletId())
587       .Times(AtLeast(1))
588       .WillRepeatedly(Return(11));
589   EXPECT_CALL(*first_mutator, MutateRef(_))
590       .Times(1)
591       .WillOnce(Return(new AnimationWorkletOutput()));
592   EXPECT_CALL(*second_mutator, GetWorkletId())
593       .Times(AtLeast(1))
594       .WillRepeatedly(Return(22));
595   EXPECT_CALL(*second_mutator, MutateRef(_))
596       .Times(1)
597       .WillOnce(Return(new AnimationWorkletOutput()));
598   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
599 
600   EXPECT_TRUE(mutator_->MutateAsynchronously(
601       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
602 
603   WaitForTestCompletion();
604 }
605 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateDroppedWhenBusy)606 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
607        MutationUpdateDroppedWhenBusy) {
608   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
609   MockAnimationWorkletMutator* first_mutator =
610       MakeGarbageCollected<MockAnimationWorkletMutator>(
611           first_thread->GetTaskRunner());
612   mutator_->RegisterAnimationWorkletMutator(
613       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
614 
615   EXPECT_CALL(*first_mutator, GetWorkletId())
616       .Times(AtLeast(1))
617       .WillRepeatedly(Return(11));
618   EXPECT_CALL(*first_mutator, MutateRef(_))
619       .Times(1)
620       .WillOnce(Return(new AnimationWorkletOutput()));
621   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
622 
623   // Block Responses until all requests have been queued.
624   first_mutator->BlockWorkletThread();
625   // Response for first mutator call is blocked until after the second
626   // call is sent.
627   EXPECT_TRUE(mutator_->MutateAsynchronously(
628       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
629   // Second request dropped since busy processing first.
630   EXPECT_FALSE(mutator_->MutateAsynchronously(CreateTestMutatorInput(),
631                                               MutateQueuingStrategy::kDrop,
632                                               CreateNotReachedCallback()));
633   // Unblock first request.
634   first_mutator->UnblockWorkletThread();
635 
636   WaitForTestCompletion();
637 }
638 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateQueuedWhenBusy)639 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
640        MutationUpdateQueuedWhenBusy) {
641   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
642 
643   MockAnimationWorkletMutator* first_mutator =
644       MakeGarbageCollected<MockAnimationWorkletMutator>(
645           first_thread->GetTaskRunner());
646   mutator_->RegisterAnimationWorkletMutator(
647       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
648 
649   EXPECT_CALL(*first_mutator, GetWorkletId())
650       .Times(AtLeast(2))
651       .WillRepeatedly(Return(11));
652   EXPECT_CALL(*first_mutator, MutateRef(_))
653       .Times(2)
654       .WillOnce(Return(new AnimationWorkletOutput()))
655       .WillOnce(Return(new AnimationWorkletOutput()));
656   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
657   EXPECT_CALL(*this, IntermediateResultCallbackRef()).Times(1);
658 
659   // Block Responses until all requests have been queued.
660   first_mutator->BlockWorkletThread();
661   // Response for first mutator call is blocked until after the second
662   // call is sent.
663   EXPECT_TRUE(mutator_->MutateAsynchronously(
664       CreateTestMutatorInput(), kNormalPriority,
665       CreateIntermediateResultCallback(MutateStatus::kCompletedWithUpdate)));
666   // First request still processing, queue request.
667   EXPECT_TRUE(mutator_->MutateAsynchronously(
668       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
669   // Unblock first request.
670   first_mutator->UnblockWorkletThread();
671 
672   WaitForTestCompletion();
673 }
674 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateQueueWithReplacementWhenBusy)675 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
676        MutationUpdateQueueWithReplacementWhenBusy) {
677   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
678 
679   MockAnimationWorkletMutator* first_mutator =
680       MakeGarbageCollected<MockAnimationWorkletMutator>(
681           first_thread->GetTaskRunner());
682   mutator_->RegisterAnimationWorkletMutator(
683       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
684 
685   EXPECT_CALL(*first_mutator, GetWorkletId())
686       .Times(AtLeast(2))
687       .WillRepeatedly(Return(11));
688   EXPECT_CALL(*first_mutator, MutateRef(_))
689       .Times(2)
690       .WillOnce(Return(new AnimationWorkletOutput()))
691       .WillOnce(Return(new AnimationWorkletOutput()));
692   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
693   EXPECT_CALL(*this, IntermediateResultCallbackRef()).Times(2);
694 
695   // Block Responses until all requests have been queued.
696   first_mutator->BlockWorkletThread();
697   // Response for first mutator call is blocked until after the second
698   // call is sent.
699   EXPECT_TRUE(mutator_->MutateAsynchronously(
700       CreateTestMutatorInput(), kNormalPriority,
701       CreateIntermediateResultCallback(MutateStatus::kCompletedWithUpdate)));
702   // First request still processing, queue a second request, which will get
703   // canceled by a third request.
704   EXPECT_TRUE(mutator_->MutateAsynchronously(
705       CreateTestMutatorInput(), kNormalPriority,
706       CreateIntermediateResultCallback(MutateStatus::kCanceled)));
707   // First request still processing, clobber second request in queue.
708   EXPECT_TRUE(mutator_->MutateAsynchronously(
709       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
710   // Unblock first request.
711   first_mutator->UnblockWorkletThread();
712 
713   WaitForTestCompletion();
714 }
715 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,MutationUpdateMultipleQueuesWhenBusy)716 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,
717        MutationUpdateMultipleQueuesWhenBusy) {
718   std::unique_ptr<Thread> first_thread = CreateThread("FirstThread");
719 
720   MockAnimationWorkletMutator* first_mutator =
721       MakeGarbageCollected<MockAnimationWorkletMutator>(
722           first_thread->GetTaskRunner());
723   mutator_->RegisterAnimationWorkletMutator(
724       WrapCrossThreadPersistent(first_mutator), first_thread->GetTaskRunner());
725 
726   EXPECT_CALL(*first_mutator, GetWorkletId())
727       .Times(AtLeast(3))
728       .WillRepeatedly(Return(11));
729   EXPECT_CALL(*first_mutator, MutateRef(_))
730       .Times(3)
731       .WillOnce(Return(new AnimationWorkletOutput()))
732       .WillOnce(Return(new AnimationWorkletOutput()))
733       .WillOnce(Return(new AnimationWorkletOutput()));
734   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(3);
735   EXPECT_CALL(*this, IntermediateResultCallbackRef()).Times(2);
736 
737   // Block Responses until all requests have been queued.
738   first_mutator->BlockWorkletThread();
739   // Response for first mutator call is blocked until after the second
740   // call is sent.
741   EXPECT_TRUE(mutator_->MutateAsynchronously(
742       CreateTestMutatorInput(), kNormalPriority,
743       CreateIntermediateResultCallback(MutateStatus::kCompletedWithUpdate)));
744   // First request still processing, queue a second request.
745   EXPECT_TRUE(mutator_->MutateAsynchronously(
746       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
747   // First request still processing. This request uses a separate queue from the
748   // second request. It should not replace the second request but should be
749   // dispatched ahead of the second request.
750   EXPECT_TRUE(mutator_->MutateAsynchronously(
751       CreateTestMutatorInput(), kHighPriority,
752       CreateIntermediateResultCallback(MutateStatus::kCompletedWithUpdate)));
753   // Unblock first request.
754   first_mutator->UnblockWorkletThread();
755 
756   WaitForTestCompletion();
757 }
758 
TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest,HistogramTester)759 TEST_F(AnimationWorkletMutatorDispatcherImplAsyncTest, HistogramTester) {
760   const char* histogram_name =
761       "Animation.AnimationWorklet.Dispatcher.AsynchronousMutateDuration";
762   base::HistogramTester histogram_tester;
763 
764   std::unique_ptr<base::TickClock> mock_clock =
765       std::make_unique<base::SimpleTestTickClock>();
766   base::SimpleTestTickClock* mock_clock_ptr =
767       static_cast<base::SimpleTestTickClock*>(mock_clock.get());
768   mutator_->SetClockForTesting(std::move(mock_clock));
769 
770   std::unique_ptr<Thread> thread = CreateThread("MyThread");
771   MockAnimationWorkletMutator* mutator =
772       MakeGarbageCollected<MockAnimationWorkletMutator>(
773           thread->GetTaskRunner());
774   mutator_->RegisterAnimationWorkletMutator(WrapCrossThreadPersistent(mutator),
775                                             thread->GetTaskRunner());
776 
777   EXPECT_CALL(*mutator, GetWorkletId())
778       .Times(AtLeast(2))
779       .WillRepeatedly(Return(11));
780   EXPECT_CALL(*mutator, MutateRef(_))
781       .Times(2)
782       .WillOnce(Return(new AnimationWorkletOutput()))
783       .WillOnce(Return(new AnimationWorkletOutput()));
784   EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
785 
786   // Block Responses until all requests have been queued.
787   mutator->BlockWorkletThread();
788 
789   base::TimeDelta time_delta = base::TimeDelta::FromMilliseconds(10);
790 
791   // Expected Elapsed time is the sum of all clock advancements until unblocked,
792   // which totals to 30 ms.
793   EXPECT_TRUE(mutator_->MutateAsynchronously(
794       CreateTestMutatorInput(), kHighPriority,
795       CreateIntermediateResultCallback(MutateStatus::kCompletedWithUpdate)));
796   mock_clock_ptr->Advance(time_delta);
797 
798   // This request will get stomped by the next request, but the start time is
799   // preserved.
800   EXPECT_TRUE(mutator_->MutateAsynchronously(
801       CreateTestMutatorInput(), kNormalPriority,
802       CreateIntermediateResultCallback(MutateStatus::kCanceled)));
803   mock_clock_ptr->Advance(time_delta);
804 
805   // Replaces previous request. Since 10 ms has elapsed prior to replacing the
806   // previous request, the expected elapsed time is 20 ms.
807   EXPECT_TRUE(mutator_->MutateAsynchronously(
808       CreateTestMutatorInput(), kNormalPriority, CreateTestCompleteCallback()));
809   mock_clock_ptr->Advance(time_delta);
810 
811   mutator->UnblockWorkletThread();
812   WaitForTestCompletion();
813 
814   histogram_tester.ExpectTotalCount(histogram_name, 2);
815   // Times are in microseconds.
816   histogram_tester.ExpectBucketCount(histogram_name, 20000, 1);
817   histogram_tester.ExpectBucketCount(histogram_name, 30000, 1);
818 }
819 
820 }  // namespace
821 
822 }  // namespace blink
823