summaryrefslogtreecommitdiff
path: root/libs/hwui/tests/unit/ThreadBaseTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/tests/unit/ThreadBaseTests.cpp')
-rw-r--r--libs/hwui/tests/unit/ThreadBaseTests.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/libs/hwui/tests/unit/ThreadBaseTests.cpp b/libs/hwui/tests/unit/ThreadBaseTests.cpp
new file mode 100644
index 000000000000..1168ff211202
--- /dev/null
+++ b/libs/hwui/tests/unit/ThreadBaseTests.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "thread/ThreadBase.h"
+#include "utils/TimeUtils.h"
+
+#include <chrono>
+#include "unistd.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+static ThreadBase& thread() {
+ class TestThread : public ThreadBase, public virtual RefBase {};
+ static sp<TestThread> thread = []() -> auto {
+ sp<TestThread> ret{new TestThread};
+ ret->start("TestThread");
+ return ret;
+ }
+ ();
+ return *thread;
+}
+
+static WorkQueue& queue() {
+ return thread().queue();
+}
+
+TEST(ThreadBase, post) {
+ std::atomic_bool ran(false);
+ queue().post([&ran]() { ran = true; });
+ for (int i = 0; !ran && i < 1000; i++) {
+ usleep(1);
+ }
+ ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
+}
+
+TEST(ThreadBase, postDelay) {
+ using clock = WorkQueue::clock;
+
+ std::promise<nsecs_t> ranAtPromise;
+ auto queuedAt = clock::now();
+ queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
+ auto ranAt = ranAtPromise.get_future().get();
+ auto ranAfter = ranAt - queuedAt;
+ ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
+}
+
+TEST(ThreadBase, runSync) {
+ pid_t thisTid = gettid();
+ pid_t otherTid = thisTid;
+
+ auto result = queue().runSync([&otherTid]() -> auto {
+ otherTid = gettid();
+ return 42;
+ });
+
+ ASSERT_EQ(42, result);
+ ASSERT_NE(thisTid, otherTid);
+}
+
+TEST(ThreadBase, async) {
+ pid_t thisTid = gettid();
+ pid_t thisPid = getpid();
+
+ auto otherTid = queue().async([]() -> auto { return gettid(); });
+ auto otherPid = queue().async([]() -> auto { return getpid(); });
+ auto result = queue().async([]() -> auto { return 42; });
+
+ ASSERT_NE(thisTid, otherTid.get());
+ ASSERT_EQ(thisPid, otherPid.get());
+ ASSERT_EQ(42, result.get());
+}
+
+TEST(ThreadBase, lifecyclePerf) {
+ struct EventCount {
+ std::atomic_int construct{0};
+ std::atomic_int destruct{0};
+ std::atomic_int copy{0};
+ std::atomic_int move{0};
+ };
+
+ struct Counter {
+ Counter(EventCount* count) : mCount(count) { mCount->construct++; }
+
+ Counter(const Counter& other) : mCount(other.mCount) {
+ if (mCount) mCount->copy++;
+ }
+
+ Counter(Counter&& other) : mCount(other.mCount) {
+ other.mCount = nullptr;
+ if (mCount) mCount->move++;
+ }
+
+ Counter& operator=(const Counter& other) {
+ mCount = other.mCount;
+ if (mCount) mCount->copy++;
+ return *this;
+ }
+
+ Counter& operator=(Counter&& other) {
+ mCount = other.mCount;
+ other.mCount = nullptr;
+ if (mCount) mCount->move++;
+ return *this;
+ }
+
+ ~Counter() {
+ if (mCount) mCount->destruct++;
+ }
+
+ EventCount* mCount;
+ };
+
+ EventCount count;
+ {
+ Counter counter{&count};
+ queue().runSync([c = std::move(counter)](){});
+ }
+ ASSERT_EQ(1, count.construct.load());
+ ASSERT_EQ(1, count.destruct.load());
+ ASSERT_EQ(0, count.copy.load());
+ ASSERT_LE(1, count.move.load());
+}
+
+int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
+ return queue().runSync([t = test]()->int { return t->getStrongCount(); });
+}
+
+TEST(ThreadBase, lifecycle) {
+ sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+ ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+ ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
+ ASSERT_EQ(1, dummyObject->getStrongCount());
+} \ No newline at end of file