| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" | 5 #include "components/scheduler/renderer/renderer_scheduler_impl.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/test/simple_test_tick_clock.h" | 8 #include "base/test/simple_test_tick_clock.h" |
| 9 #include "cc/output/begin_frame_args.h" | 9 #include "cc/output/begin_frame_args.h" |
| 10 #include "cc/test/ordered_simple_task_runner.h" | 10 #include "cc/test/ordered_simple_task_runner.h" |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 } | 301 } |
| 302 | 302 |
| 303 void ForceMainThreadScrollingUseCase() { | 303 void ForceMainThreadScrollingUseCase() { |
| 304 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create( | 304 cc::BeginFrameArgs begin_frame_args = cc::BeginFrameArgs::Create( |
| 305 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), | 305 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), |
| 306 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); | 306 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); |
| 307 begin_frame_args.on_critical_path = true; | 307 begin_frame_args.on_critical_path = true; |
| 308 scheduler_->WillBeginFrame(begin_frame_args); | 308 scheduler_->WillBeginFrame(begin_frame_args); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void ForceTouchStartToBeExpectedSoon() { |
| 312 scheduler_->DidHandleInputEventOnCompositorThread( |
| 313 FakeInputEvent(blink::WebInputEvent::GestureScrollEnd), |
| 314 RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); |
| 315 clock_->Advance(priority_escalation_after_input_duration() * 2); |
| 316 scheduler_->ForceUpdatePolicy(); |
| 317 } |
| 318 |
| 319 void SimulateExpensiveTasks( |
| 320 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { |
| 321 // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance |
| 322 // tasks unless we set AutoAdvanceNow to true :/ |
| 323 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); |
| 324 |
| 325 // Simulate a bunch of expensive tasks |
| 326 for (int i = 0; i < 10; i++) { |
| 327 task_runner->PostTask(FROM_HERE, |
| 328 base::Bind(&base::SimpleTestTickClock::Advance, |
| 329 base::Unretained(clock_.get()), |
| 330 base::TimeDelta::FromMilliseconds(500))); |
| 331 } |
| 332 |
| 333 RunUntilIdle(); |
| 334 |
| 335 // Switch back to not auto-advancing because we want to be in control of |
| 336 // when time advances. |
| 337 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false); |
| 338 } |
| 339 |
| 311 void EnableIdleTasks() { DoMainFrame(); } | 340 void EnableIdleTasks() { DoMainFrame(); } |
| 312 | 341 |
| 313 UseCase CurrentUseCase() { | 342 UseCase CurrentUseCase() { |
| 314 return scheduler_->MainThreadOnly().current_use_case; | 343 return scheduler_->MainThreadOnly().current_use_case; |
| 315 } | 344 } |
| 316 | 345 |
| 317 UseCase ForceUpdatePolicyAndGetCurrentUseCase() { | 346 UseCase ForceUpdatePolicyAndGetCurrentUseCase() { |
| 318 scheduler_->ForceUpdatePolicy(); | 347 scheduler_->ForceUpdatePolicy(); |
| 319 return scheduler_->MainThreadOnly().current_use_case; | 348 return scheduler_->MainThreadOnly().current_use_case; |
| 320 } | 349 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 std::string("D2"), std::string("C2"), | 734 std::string("D2"), std::string("C2"), |
| 706 std::string("I1"))); | 735 std::string("I1"))); |
| 707 EXPECT_EQ(RendererScheduler::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); | 736 EXPECT_EQ(RendererScheduler::UseCase::COMPOSITOR_GESTURE, CurrentUseCase()); |
| 708 } | 737 } |
| 709 | 738 |
| 710 TEST_F( | 739 TEST_F( |
| 711 RendererSchedulerImplTest, | 740 RendererSchedulerImplTest, |
| 712 TestCompositorPolicy_ExpensiveTimersDontRunWhenMainThreadOnCriticalPath) { | 741 TestCompositorPolicy_ExpensiveTimersDontRunWhenMainThreadOnCriticalPath) { |
| 713 std::vector<std::string> run_order; | 742 std::vector<std::string> run_order; |
| 714 | 743 |
| 715 // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance | 744 SimulateExpensiveTasks(timer_task_runner_); |
| 716 // tasks unless we set AutoAdvanceNow to true :/ | |
| 717 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
| 718 | |
| 719 // Simulate a bunch of expensive timer tasks | |
| 720 for (int i = 0; i < 10; i++) { | |
| 721 timer_task_runner_->PostTask( | |
| 722 FROM_HERE, base::Bind(&base::SimpleTestTickClock::Advance, | |
| 723 base::Unretained(clock_.get()), | |
| 724 base::TimeDelta::FromMilliseconds(500))); | |
| 725 } | |
| 726 | |
| 727 RunUntilIdle(); | |
| 728 | |
| 729 // Switch back to not auto-advancing because we want to be in control of when | |
| 730 // time advances. | |
| 731 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false); | |
| 732 | 745 |
| 733 // Timers should now be disabled during main thread user user interactions. | 746 // Timers should now be disabled during main thread user user interactions. |
| 734 PostTestTasks(&run_order, "C1 T1"); | 747 PostTestTasks(&run_order, "C1 T1"); |
| 735 | 748 |
| 736 // Trigger main_thread_gesture UseCase | 749 // Trigger main_thread_gesture UseCase |
| 737 scheduler_->DidAnimateForInputOnCompositorThread(); | 750 scheduler_->DidAnimateForInputOnCompositorThread(); |
| 738 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create( | 751 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create( |
| 739 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), | 752 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), |
| 740 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL); | 753 base::TimeDelta::FromMilliseconds(16), cc::BeginFrameArgs::NORMAL); |
| 741 begin_frame_args1.on_critical_path = true; | 754 begin_frame_args1.on_critical_path = true; |
| 742 scheduler_->WillBeginFrame(begin_frame_args1); | 755 scheduler_->WillBeginFrame(begin_frame_args1); |
| 743 RunUntilIdle(); | 756 RunUntilIdle(); |
| 744 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()); | 757 EXPECT_EQ(RendererScheduler::UseCase::MAIN_THREAD_GESTURE, CurrentUseCase()); |
| 745 | 758 |
| 746 EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1"))); | 759 EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1"))); |
| 747 clock_->Advance(subsequent_input_expected_after_input_duration() * 2); | 760 clock_->Advance(subsequent_input_expected_after_input_duration() * 2); |
| 748 | 761 |
| 749 run_order.clear(); | 762 run_order.clear(); |
| 750 RunUntilIdle(); | 763 RunUntilIdle(); |
| 751 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); | 764 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); |
| 752 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1"))); | 765 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1"))); |
| 753 } | 766 } |
| 754 | 767 |
| 755 TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) { | 768 TEST_F(RendererSchedulerImplTest, Navigation_ResetsTaskCostEstimations) { |
| 756 std::vector<std::string> run_order; | 769 std::vector<std::string> run_order; |
| 757 | 770 |
| 758 // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance | 771 SimulateExpensiveTasks(timer_task_runner_); |
| 759 // tasks unless we set AutoAdvanceNow to true :/ | 772 scheduler_->OnNavigationStarted(); |
| 760 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
| 761 | |
| 762 // Simulate a bunch of expensive timer tasks | |
| 763 for (int i = 0; i < 10; i++) { | |
| 764 timer_task_runner_->PostTask( | |
| 765 FROM_HERE, base::Bind(&base::SimpleTestTickClock::Advance, | |
| 766 base::Unretained(clock_.get()), | |
| 767 base::TimeDelta::FromMilliseconds(500))); | |
| 768 } | |
| 769 | |
| 770 RunUntilIdle(); | |
| 771 | |
| 772 // Switch back to not auto-advancing because we want to be in control of when | |
| 773 // time advances. | |
| 774 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(false); | |
| 775 | |
| 776 scheduler_->OnPageLoadStarted(); | |
| 777 PostTestTasks(&run_order, "C1 T1"); | 773 PostTestTasks(&run_order, "C1 T1"); |
| 778 | 774 |
| 779 scheduler_->DidAnimateForInputOnCompositorThread(); | 775 scheduler_->DidAnimateForInputOnCompositorThread(); |
| 780 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create( | 776 cc::BeginFrameArgs begin_frame_args1 = cc::BeginFrameArgs::Create( |
| 781 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), | 777 BEGINFRAME_FROM_HERE, clock_->NowTicks(), base::TimeTicks(), |
| 782 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); | 778 base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL); |
| 783 begin_frame_args1.on_critical_path = true; | 779 begin_frame_args1.on_critical_path = true; |
| 784 scheduler_->WillBeginFrame(begin_frame_args1); | 780 scheduler_->WillBeginFrame(begin_frame_args1); |
| 785 scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period | 781 scheduler_->DidCommitFrameToCompositor(); // Starts Idle Period |
| 786 RunUntilIdle(); | 782 RunUntilIdle(); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 EXPECT_THAT(run_order, | 905 EXPECT_THAT(run_order, |
| 910 testing::ElementsAre(std::string("L1"), std::string("T1"), | 906 testing::ElementsAre(std::string("L1"), std::string("T1"), |
| 911 std::string("T2"))); | 907 std::string("T2"))); |
| 912 } | 908 } |
| 913 | 909 |
| 914 // TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase. | 910 // TODO(alexclarke): Reenable once we've reinstaed the Loading UseCase. |
| 915 TEST_F(RendererSchedulerImplTest, DISABLED_LoadingUseCase) { | 911 TEST_F(RendererSchedulerImplTest, DISABLED_LoadingUseCase) { |
| 916 std::vector<std::string> run_order; | 912 std::vector<std::string> run_order; |
| 917 PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2"); | 913 PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2"); |
| 918 | 914 |
| 919 scheduler_->OnPageLoadStarted(); | 915 scheduler_->OnNavigationStarted(); |
| 920 EnableIdleTasks(); | 916 EnableIdleTasks(); |
| 921 RunUntilIdle(); | 917 RunUntilIdle(); |
| 922 | 918 |
| 923 // In loading policy, loading tasks are prioritized other others. | 919 // In loading policy, loading tasks are prioritized other others. |
| 924 std::string loading_policy_expected[] = { | 920 std::string loading_policy_expected[] = { |
| 925 std::string("D1"), std::string("L1"), std::string("D2"), | 921 std::string("D1"), std::string("L1"), std::string("D2"), |
| 926 std::string("L2"), std::string("C1"), std::string("T1"), | 922 std::string("L2"), std::string("C1"), std::string("T1"), |
| 927 std::string("C2"), std::string("T2"), std::string("I1")}; | 923 std::string("C2"), std::string("T2"), std::string("I1")}; |
| 928 EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected)); | 924 EXPECT_THAT(run_order, testing::ElementsAreArray(loading_policy_expected)); |
| 929 EXPECT_EQ(RendererScheduler::UseCase::LOADING, CurrentUseCase()); | 925 EXPECT_EQ(RendererScheduler::UseCase::LOADING, CurrentUseCase()); |
| (...skipping 1049 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 run_order.clear(); | 1975 run_order.clear(); |
| 1980 PostTestTasks(&run_order, "T6"); | 1976 PostTestTasks(&run_order, "T6"); |
| 1981 RunUntilIdle(); | 1977 RunUntilIdle(); |
| 1982 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T6"))); | 1978 EXPECT_THAT(run_order, testing::ElementsAre(std::string("T6"))); |
| 1983 } | 1979 } |
| 1984 | 1980 |
| 1985 TEST_F(RendererSchedulerImplTest, | 1981 TEST_F(RendererSchedulerImplTest, |
| 1986 ExpensiveLoadingTasksNotBlockedTillFirstBeginMainFrame) { | 1982 ExpensiveLoadingTasksNotBlockedTillFirstBeginMainFrame) { |
| 1987 std::vector<std::string> run_order; | 1983 std::vector<std::string> run_order; |
| 1988 | 1984 |
| 1989 // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance | 1985 SimulateExpensiveTasks(loading_task_runner_); |
| 1990 // tasks unless we set AutoAdvanceNow to true :/ | 1986 ForceTouchStartToBeExpectedSoon(); |
| 1991 mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true); | |
| 1992 | |
| 1993 // Simulate a bunch of expensive loading tasks | |
| 1994 for (int i = 0; i < 10; i++) { | |
| 1995 loading_task_runner_->PostTask( | |
| 1996 FROM_HERE, base::Bind(&base::SimpleTestTickClock::Advance, | |
| 1997 base::Unretained(clock_.get()), | |
| 1998 base::TimeDelta::FromMilliseconds(500))); | |
| 1999 } | |
| 2000 | |
| 2001 RunUntilIdle(); | |
| 2002 | |
| 2003 PostTestTasks(&run_order, "L1 D1"); | 1987 PostTestTasks(&run_order, "L1 D1"); |
| 2004 RunUntilIdle(); | 1988 RunUntilIdle(); |
| 2005 | 1989 |
| 2006 EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase()); | 1990 EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase()); |
| 2007 EXPECT_FALSE(HaveSeenABeginMainframe()); | 1991 EXPECT_FALSE(HaveSeenABeginMainframe()); |
| 2008 EXPECT_TRUE(LoadingTasksSeemExpensive()); | 1992 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2009 EXPECT_FALSE(TimerTasksSeemExpensive()); | 1993 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 1994 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2010 EXPECT_THAT(run_order, | 1995 EXPECT_THAT(run_order, |
| 2011 testing::ElementsAre(std::string("L1"), std::string("D1"))); | 1996 testing::ElementsAre(std::string("L1"), std::string("D1"))); |
| 2012 | 1997 |
| 2013 // Emit a BeginMainFrame, and the loading task should get blocked. | 1998 // Emit a BeginMainFrame, and the loading task should get blocked. |
| 2014 DoMainFrame(); | 1999 DoMainFrame(); |
| 2015 run_order.clear(); | 2000 run_order.clear(); |
| 2016 | 2001 |
| 2017 PostTestTasks(&run_order, "L1 D1"); | 2002 PostTestTasks(&run_order, "L1 D1"); |
| 2003 RunUntilIdle(); |
| 2004 |
| 2005 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); |
| 2006 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2007 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2008 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2009 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2010 EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); |
| 2011 } |
| 2012 |
| 2013 TEST_F(RendererSchedulerImplTest, |
| 2014 ExpensiveLoadingTasksNotBlockedIfNavigationExpected) { |
| 2015 std::vector<std::string> run_order; |
| 2016 |
| 2017 DoMainFrame(); |
| 2018 SimulateExpensiveTasks(loading_task_runner_); |
| 2019 ForceTouchStartToBeExpectedSoon(); |
| 2020 scheduler_->AddPendingNavigation(); |
| 2021 |
| 2022 PostTestTasks(&run_order, "L1 D1"); |
| 2023 RunUntilIdle(); |
| 2024 |
| 2025 EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase()); |
| 2026 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2027 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2028 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2029 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2030 EXPECT_THAT(run_order, |
| 2031 testing::ElementsAre(std::string("L1"), std::string("D1"))); |
| 2032 |
| 2033 // After the nagigation has been cancelled, the expensive loading tasks should |
| 2034 // get blocked. |
| 2035 scheduler_->RemovePendingNavigation(); |
| 2036 run_order.clear(); |
| 2037 |
| 2038 PostTestTasks(&run_order, "L1 D1"); |
| 2018 RunUntilIdle(); | 2039 RunUntilIdle(); |
| 2019 | 2040 |
| 2020 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); | 2041 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); |
| 2021 EXPECT_TRUE(HaveSeenABeginMainframe()); | 2042 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2022 EXPECT_TRUE(LoadingTasksSeemExpensive()); | 2043 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2023 EXPECT_FALSE(TimerTasksSeemExpensive()); | 2044 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2045 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2046 EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); |
| 2047 } |
| 2048 |
| 2049 TEST_F( |
| 2050 RendererSchedulerImplTest, |
| 2051 ExpensiveLoadingTasksNotBlockedIfNavigationExpected_MultipleNavigations) { |
| 2052 std::vector<std::string> run_order; |
| 2053 |
| 2054 DoMainFrame(); |
| 2055 SimulateExpensiveTasks(loading_task_runner_); |
| 2056 ForceTouchStartToBeExpectedSoon(); |
| 2057 scheduler_->AddPendingNavigation(); |
| 2058 scheduler_->AddPendingNavigation(); |
| 2059 |
| 2060 PostTestTasks(&run_order, "L1 D1"); |
| 2061 RunUntilIdle(); |
| 2062 |
| 2063 EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase()); |
| 2064 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2065 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2066 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2067 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2024 EXPECT_THAT(run_order, | 2068 EXPECT_THAT(run_order, |
| 2025 testing::ElementsAre(std::string("L1"), std::string("D1"))); | 2069 testing::ElementsAre(std::string("L1"), std::string("D1"))); |
| 2070 |
| 2071 |
| 2072 run_order.clear(); |
| 2073 scheduler_->RemovePendingNavigation(); |
| 2074 // Navigation task expected ref count non-zero so expensive tasks still not |
| 2075 // blocked. |
| 2076 PostTestTasks(&run_order, "L1 D1"); |
| 2077 RunUntilIdle(); |
| 2078 |
| 2079 EXPECT_EQ(UseCase::NONE, ForceUpdatePolicyAndGetCurrentUseCase()); |
| 2080 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2081 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2082 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2083 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2084 EXPECT_THAT(run_order, |
| 2085 testing::ElementsAre(std::string("L1"), std::string("D1"))); |
| 2086 |
| 2087 |
| 2088 run_order.clear(); |
| 2089 scheduler_->RemovePendingNavigation(); |
| 2090 // Navigation task expected ref count is now zero, the expensive loading tasks |
| 2091 // should get blocked. |
| 2092 PostTestTasks(&run_order, "L1 D1"); |
| 2093 RunUntilIdle(); |
| 2094 |
| 2095 EXPECT_EQ(RendererScheduler::UseCase::NONE, CurrentUseCase()); |
| 2096 EXPECT_TRUE(HaveSeenABeginMainframe()); |
| 2097 EXPECT_TRUE(LoadingTasksSeemExpensive()); |
| 2098 EXPECT_FALSE(TimerTasksSeemExpensive()); |
| 2099 EXPECT_TRUE(TouchStartExpectedSoon()); |
| 2100 EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1"))); |
| 2026 } | 2101 } |
| 2027 | 2102 |
| 2103 |
| 2028 } // namespace scheduler | 2104 } // namespace scheduler |
| OLD | NEW |