From 4d5db7ab45ca1afeed30fbccd51d568e861ff2eb Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Mon, 13 Feb 2023 15:24:20 -0500 Subject: Add tests for VsyncSchedule Follow-on to I54a1304a3428968134cc707b24d5b325927c31df. This is somewhat covered by existing unit tests, but add more thorough tests just for VsyncSchedule. Include thread_annotations.h to fix build. Update MockSchedulerCallback to include the new interface header. Bug: 241286146 Test: this Change-Id: I79e14d67fea896752f0afaba00adc6d47efc3c71 Merged-In: I79e14d67fea896752f0afaba00adc6d47efc3c71 --- services/surfaceflinger/Scheduler/VsyncSchedule.h | 3 + services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/VsyncScheduleTest.cpp | 215 +++++++++++++++++++++ .../tests/unittests/mock/MockSchedulerCallback.h | 2 +- 4 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/tests/unittests/VsyncScheduleTest.cpp diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h index d88f1d1f0b..a32acc7509 100644 --- a/services/surfaceflinger/Scheduler/VsyncSchedule.h +++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ namespace android { class EventThreadTest; +class VsyncScheduleTest; } namespace android::fuzz { @@ -96,6 +98,7 @@ public: private: friend class TestableScheduler; friend class android::EventThreadTest; + friend class android::VsyncScheduleTest; friend class android::fuzz::SchedulerFuzzer; using TrackerPtr = std::unique_ptr; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index a5b508acea..eac9edc6dd 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -134,6 +134,7 @@ cc_test { "VSyncPredictorTest.cpp", "VSyncReactorTest.cpp", "VsyncConfigurationTest.cpp", + "VsyncScheduleTest.cpp", ], } diff --git a/services/surfaceflinger/tests/unittests/VsyncScheduleTest.cpp b/services/surfaceflinger/tests/unittests/VsyncScheduleTest.cpp new file mode 100644 index 0000000000..652d3132f9 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/VsyncScheduleTest.cpp @@ -0,0 +1,215 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include + +#include +#include "Scheduler/VsyncSchedule.h" +#include "ThreadContext.h" +#include "mock/MockSchedulerCallback.h" +#include "mock/MockVSyncDispatch.h" +#include "mock/MockVSyncTracker.h" +#include "mock/MockVsyncController.h" + +using testing::_; + +namespace android { + +class VsyncScheduleTest : public testing::Test { +protected: + VsyncScheduleTest(); + ~VsyncScheduleTest() override; + + scheduler::mock::SchedulerCallback mCallback; + const std::unique_ptr mVsyncSchedule = + std::unique_ptr( + new scheduler::VsyncSchedule(std::make_unique(), + std::make_unique(), + std::make_unique())); + + mock::VsyncController& getController() { + return *static_cast(&mVsyncSchedule->getController()); + } +}; + +VsyncScheduleTest::VsyncScheduleTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +VsyncScheduleTest::~VsyncScheduleTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +namespace { + +using namespace testing; + +TEST_F(VsyncScheduleTest, InitiallyDisallowed) { + ASSERT_FALSE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); +} + +TEST_F(VsyncScheduleTest, EnableDoesNothingWhenDisallowed) { + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + + mVsyncSchedule->enableHardwareVsync(mCallback); +} + +TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisallowed) { + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + + mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */); +} + +TEST_F(VsyncScheduleTest, MakeAllowed) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); +} + +TEST_F(VsyncScheduleTest, DisableDoesNothingWhenDisabled) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + + mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */); +} + +TEST_F(VsyncScheduleTest, EnableWorksWhenDisabled) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + EXPECT_CALL(mCallback, setVsyncEnabled(true)); + + mVsyncSchedule->enableHardwareVsync(mCallback); +} + +TEST_F(VsyncScheduleTest, EnableWorksOnce) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + EXPECT_CALL(mCallback, setVsyncEnabled(true)); + + mVsyncSchedule->enableHardwareVsync(mCallback); + + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + mVsyncSchedule->enableHardwareVsync(mCallback); +} + +TEST_F(VsyncScheduleTest, AllowedIsSticky) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(false /* makeAllowed */)); +} + +TEST_F(VsyncScheduleTest, EnableDisable) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + EXPECT_CALL(mCallback, setVsyncEnabled(true)); + + mVsyncSchedule->enableHardwareVsync(mCallback); + + EXPECT_CALL(mCallback, setVsyncEnabled(false)); + mVsyncSchedule->disableHardwareVsync(mCallback, false /* disallow */); +} + +TEST_F(VsyncScheduleTest, StartPeriodTransition) { + // Note: startPeriodTransition is only called when hardware vsyncs are + // allowed. + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + + const Period period = (60_Hz).getPeriod(); + + EXPECT_CALL(mCallback, setVsyncEnabled(true)); + EXPECT_CALL(getController(), startPeriodTransition(period.ns())); + + mVsyncSchedule->startPeriodTransition(mCallback, period); +} + +TEST_F(VsyncScheduleTest, StartPeriodTransitionAlreadyEnabled) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + mVsyncSchedule->enableHardwareVsync(mCallback); + + const Period period = (60_Hz).getPeriod(); + + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + EXPECT_CALL(getController(), startPeriodTransition(period.ns())); + + mVsyncSchedule->startPeriodTransition(mCallback, period); +} + +TEST_F(VsyncScheduleTest, AddResyncSampleDisallowed) { + const Period period = (60_Hz).getPeriod(); + const auto timestamp = TimePoint::now(); + + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0); + + mVsyncSchedule->addResyncSample(mCallback, timestamp, period); +} + +TEST_F(VsyncScheduleTest, AddResyncSampleDisabled) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + const Period period = (60_Hz).getPeriod(); + const auto timestamp = TimePoint::now(); + + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + EXPECT_CALL(getController(), addHwVsyncTimestamp(_, _, _)).Times(0); + + mVsyncSchedule->addResyncSample(mCallback, timestamp, period); +} + +TEST_F(VsyncScheduleTest, AddResyncSampleReturnsTrue) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + mVsyncSchedule->enableHardwareVsync(mCallback); + + const Period period = (60_Hz).getPeriod(); + const auto timestamp = TimePoint::now(); + + EXPECT_CALL(mCallback, setVsyncEnabled(_)).Times(0); + EXPECT_CALL(getController(), + addHwVsyncTimestamp(timestamp.ns(), std::optional(period.ns()), _)) + .WillOnce(Return(true)); + + mVsyncSchedule->addResyncSample(mCallback, timestamp, period); +} + +TEST_F(VsyncScheduleTest, AddResyncSampleReturnsFalse) { + ASSERT_TRUE(mVsyncSchedule->isHardwareVsyncAllowed(true /* makeAllowed */)); + mVsyncSchedule->enableHardwareVsync(mCallback); + + const Period period = (60_Hz).getPeriod(); + const auto timestamp = TimePoint::now(); + + EXPECT_CALL(mCallback, setVsyncEnabled(false)); + EXPECT_CALL(getController(), + addHwVsyncTimestamp(timestamp.ns(), std::optional(period.ns()), _)) + .WillOnce(Return(false)); + + mVsyncSchedule->addResyncSample(mCallback, timestamp, period); +} + +TEST_F(VsyncScheduleTest, PendingState) FTL_FAKE_GUARD(kMainThreadContext) { + ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState()); + mVsyncSchedule->setPendingHardwareVsyncState(true); + ASSERT_TRUE(mVsyncSchedule->getPendingHardwareVsyncState()); + + mVsyncSchedule->setPendingHardwareVsyncState(false); + ASSERT_FALSE(mVsyncSchedule->getPendingHardwareVsyncState()); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h index 7d4b159e5e..103beb5fc0 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -18,7 +18,7 @@ #include -#include "Scheduler/Scheduler.h" +#include "Scheduler/ISchedulerCallback.h" namespace android::scheduler::mock { -- cgit v1.2.3-59-g8ed1b