1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18
19 #include "thread/ThreadBase.h"
20 #include "utils/TimeUtils.h"
21
22 #include <chrono>
23 #include "unistd.h"
24
25 using namespace android;
26 using namespace android::uirenderer;
27
thread()28 static ThreadBase& thread() {
29 class TestThread : public ThreadBase, public virtual RefBase {};
30 static sp<TestThread> thread = []() -> auto {
31 sp<TestThread> ret{new TestThread};
32 ret->start("TestThread");
33 return ret;
34 }
35 ();
36 return *thread;
37 }
38
queue()39 static WorkQueue& queue() {
40 return thread().queue();
41 }
42
TEST(ThreadBase,post)43 TEST(ThreadBase, post) {
44 std::atomic_bool ran(false);
45 queue().post([&ran]() { ran = true; });
46 for (int i = 0; !ran && i < 1000; i++) {
47 usleep(1);
48 }
49 ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
50 }
51
TEST(ThreadBase,postDelay)52 TEST(ThreadBase, postDelay) {
53 using clock = WorkQueue::clock;
54
55 std::promise<nsecs_t> ranAtPromise;
56 auto queuedAt = clock::now();
57 queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
58 auto ranAt = ranAtPromise.get_future().get();
59 auto ranAfter = ranAt - queuedAt;
60 ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
61 }
62
TEST(ThreadBase,runSync)63 TEST(ThreadBase, runSync) {
64 pid_t thisTid = gettid();
65 pid_t otherTid = thisTid;
66
67 auto result = queue().runSync([&otherTid]() -> auto {
68 otherTid = gettid();
69 return 42;
70 });
71
72 ASSERT_EQ(42, result);
73 ASSERT_NE(thisTid, otherTid);
74 }
75
TEST(ThreadBase,async)76 TEST(ThreadBase, async) {
77 pid_t thisTid = gettid();
78 pid_t thisPid = getpid();
79
80 auto otherTid = queue().async([]() -> auto { return gettid(); });
81 auto otherPid = queue().async([]() -> auto { return getpid(); });
82 auto result = queue().async([]() -> auto { return 42; });
83
84 ASSERT_NE(thisTid, otherTid.get());
85 ASSERT_EQ(thisPid, otherPid.get());
86 ASSERT_EQ(42, result.get());
87 }
88
TEST(ThreadBase,lifecyclePerf)89 TEST(ThreadBase, lifecyclePerf) {
90 struct EventCount {
91 std::atomic_int construct{0};
92 std::atomic_int destruct{0};
93 std::atomic_int copy{0};
94 std::atomic_int move{0};
95 };
96
97 struct Counter {
98 explicit Counter(EventCount* count) : mCount(count) { mCount->construct++; }
99
100 Counter(const Counter& other) : mCount(other.mCount) {
101 if (mCount) mCount->copy++;
102 }
103
104 Counter(Counter&& other) : mCount(other.mCount) {
105 other.mCount = nullptr;
106 if (mCount) mCount->move++;
107 }
108
109 Counter& operator=(const Counter& other) {
110 mCount = other.mCount;
111 if (mCount) mCount->copy++;
112 return *this;
113 }
114
115 Counter& operator=(Counter&& other) {
116 mCount = other.mCount;
117 other.mCount = nullptr;
118 if (mCount) mCount->move++;
119 return *this;
120 }
121
122 ~Counter() {
123 if (mCount) mCount->destruct++;
124 }
125
126 EventCount* mCount;
127 };
128
129 EventCount count;
130 {
131 Counter counter{&count};
132 queue().runSync([c = std::move(counter)](){});
133 }
134 ASSERT_EQ(1, count.construct.load());
135 ASSERT_EQ(1, count.destruct.load());
136 ASSERT_EQ(0, count.copy.load());
137 ASSERT_LE(1, count.move.load());
138 }
139
lifecycleTestHelper(const sp<VirtualLightRefBase> & test)140 int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
141 return queue().runSync([t = test]()->int { return t->getStrongCount(); });
142 }
143
TEST(ThreadBase,lifecycle)144 TEST(ThreadBase, lifecycle) {
145 sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
146 ASSERT_EQ(1, dummyObject->getStrongCount());
147 ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
148 ASSERT_EQ(1, dummyObject->getStrongCount());
149 ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
150 ASSERT_EQ(1, dummyObject->getStrongCount());
151 }
152