SF: Introduce libsurfaceflinger_unittest
This is meant to be a framework for running function-level unit tests
against the various SurfaceFlinger classes.
The point of this patch is to set up the test framework, as well as
demonstrate a pattern to be used to allow private implementation
functions to be tested.
Note that this patch configures the base surfaceflinger code to now use
ThinLTO, and enables -fwhole-program-vtables. This is done as ThinLTO
with that option will perform a devirtualization pass, turning virtual
function calls back into non-virtual function calls (and possibly even
inlining the call) when it detects that there is only one possible
implementation being called. The cost is a slight increase in build time
(similar to -O2), but is still much less than the original LTO.
Even here that LTO pass does something to the surfaceflinger binary,
reducing the file size by 4Kb.
Test: libsurfaceflinger_unittest passes on Pixel XL
Test: atest libsurfaceflinger_unittest runs the new test
Bug: None
Change-Id: I362ec1fcf1a909c4d6769710d8d8a6b0b158600d
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index b1a3017..9f3189a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -17,7 +17,6 @@
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
- logtags: ["EventLog/EventLogTags.logtags"],
shared_libs: [
"android.frameworks.vr.composer@1.0",
"android.hardware.configstore-utils",
@@ -131,10 +130,17 @@
srcs: [
":libsurfaceflinger_sources",
],
+ logtags: ["EventLog/EventLogTags.logtags"],
include_dirs: [
"external/vulkan-validation-layers/libs/vkjson",
"frameworks/native/vulkan/include",
],
+ cppflags: [
+ "-fwhole-program-vtables", // requires ThinLTO
+ ],
+ lto: {
+ thin: true,
+ },
}
cc_binary {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1349bec..bde1a8e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -316,6 +316,9 @@
friend class BufferLayer;
friend class MonitoredProducer;
+ // For unit tests
+ friend class TestableSurfaceFlinger;
+
// This value is specified in number of frames. Log frame stats at most
// every half hour.
enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 04c62b3..7d3da32 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -44,6 +44,7 @@
subdirs = [
"fakehwc",
"hwc2",
+ "unittests",
"vsync",
"waitforvsync",
]
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
new file mode 100644
index 0000000..72e0a0f
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2018 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.
+
+cc_test {
+ name: "libsurfaceflinger_unittest",
+ tags: ["test"],
+ defaults: ["libsurfaceflinger_defaults"],
+ test_suites: ["device-tests"],
+ srcs: [
+ ":libsurfaceflinger_sources",
+ "DisplayTransactionTest.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ ],
+ header_libs: [
+ "libsurfaceflinger_headers",
+ ],
+}
diff --git a/services/surfaceflinger/tests/unittests/AndroidTest.xml b/services/surfaceflinger/tests/unittests/AndroidTest.xml
new file mode 100644
index 0000000..5e8b03b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Config for libsurfaceflinger_unittest">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="libsurfaceflinger_unittest->/data/local/tmp/libsurfaceflinger_unittest" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="libsurfaceflinger_unittest" />
+ </test>
+</configuration>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
new file mode 100644
index 0000000..fc1b564
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+
+#include "TestableSurfaceFlinger.h"
+
+namespace android {
+namespace {
+
+class DisplayTransactionTest : public testing::Test {
+protected:
+ DisplayTransactionTest();
+ ~DisplayTransactionTest() override;
+
+ void setupComposer(int virtualDisplayCount);
+ void setupPrimaryDisplay(int width, int height);
+
+ TestableSurfaceFlinger mFlinger;
+};
+
+DisplayTransactionTest::DisplayTransactionTest() {
+ 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());
+}
+
+DisplayTransactionTest::~DisplayTransactionTest() {
+ 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());
+}
+
+TEST_F(DisplayTransactionTest, PlaceholderTrivialTest) {
+ auto result = mFlinger.getDefaultDisplayDeviceLocked();
+ EXPECT_EQ(nullptr, result.get());
+
+ EXPECT_EQ(nullptr, mFlinger.mutableBuiltinDisplays()[0].get());
+ mFlinger.mutableBuiltinDisplays()[0] = new BBinder();
+ EXPECT_NE(nullptr, mFlinger.mutableBuiltinDisplays()[0].get());
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
new file mode 100644
index 0000000..4aa59a5
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "DisplayDevice.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+class TestableSurfaceFlinger {
+public:
+ // Extend this as needed for accessing SurfaceFlinger private (and public)
+ // functions.
+
+ /* ------------------------------------------------------------------------
+ * Forwarding for functions being tested
+ */
+ auto getDefaultDisplayDeviceLocked() const { return mFlinger->getDefaultDisplayDeviceLocked(); }
+
+ auto processDisplayChangesLocked() { return mFlinger->processDisplayChangesLocked(); }
+
+ /* ------------------------------------------------------------------------
+ * Read-write access to private data to set up preconditions and assert
+ * post-conditions.
+ */
+ auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
+
+ sp<SurfaceFlinger> mFlinger = new SurfaceFlinger();
+};
+
+} // namespace android