blob: 7aad34836bfee17f555ba995cd52dca9645fdabf [file] [log] [blame]
John Reckf8441e62017-10-23 13:10:41 -07001/*
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
25using namespace android;
26using namespace android::uirenderer;
27
28static 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 return *thread;
36}
37
38static WorkQueue& queue() {
39 return thread().queue();
40}
41
42TEST(ThreadBase, post) {
43 std::atomic_bool ran(false);
44 queue().post([&ran]() {
45 ran = true;
46 });
47 for (int i = 0; !ran && i < 1000; i++) {
48 usleep(1);
49 }
50 ASSERT_TRUE(ran) << "Failed to flip atomic after 1 second";
51}
52
53TEST(ThreadBase, postDelay) {
54 using clock = WorkQueue::clock;
55
56 std::promise<nsecs_t> ranAtPromise;
57 auto queuedAt = clock::now();
58 queue().postDelayed(100_us, [&]() {
59 ranAtPromise.set_value(clock::now());
60 });
61 auto ranAt = ranAtPromise.get_future().get();
62 auto ranAfter = ranAt - queuedAt;
63 ASSERT_TRUE(ranAfter > 90_us) << "Ran after " << ns2us(ranAfter) << "us <= 90us";
64}
65
66TEST(ThreadBase, runSync) {
67 pid_t thisTid = gettid();
68 pid_t otherTid = thisTid;
69
70 auto result = queue().runSync([&otherTid]() -> auto {
71 otherTid = gettid();
72 return 42;
73 });
74
75 ASSERT_EQ(42, result);
76 ASSERT_NE(thisTid, otherTid);
77}
78
79TEST(ThreadBase, async) {
80 pid_t thisTid = gettid();
81 pid_t thisPid = getpid();
82
83 auto otherTid = queue().async([]() -> auto {
84 return gettid();
85 });
86 auto otherPid = queue().async([]() -> auto {
87 return getpid();
88 });
89 auto result = queue().async([]() -> auto {
90 return 42;
91 });
92
93 ASSERT_NE(thisTid, otherTid.get());
94 ASSERT_EQ(thisPid, otherPid.get());
95 ASSERT_EQ(42, result.get());
96}
97
98TEST(ThreadBase, lifecyclePerf) {
99 struct EventCount {
100 std::atomic_int construct{0};
101 std::atomic_int destruct{0};
102 std::atomic_int copy{0};
103 std::atomic_int move{0};
104 };
105
106 struct Counter {
107 Counter(EventCount* count) : mCount(count) {
108 mCount->construct++;
109 }
110
111 Counter(const Counter& other) : mCount(other.mCount) {
112 if (mCount) mCount->copy++;
113 }
114
115 Counter(Counter&& other) : mCount(other.mCount) {
116 other.mCount = nullptr;
117 if (mCount) mCount->move++;
118 }
119
120 Counter& operator=(const Counter& other) {
121 mCount = other.mCount;
122 if (mCount) mCount->copy++;
123 return *this;
124 }
125
126 Counter& operator=(Counter&& other) {
127 mCount = other.mCount;
128 other.mCount = nullptr;
129 if (mCount) mCount->move++;
130 return *this;
131 }
132
133 ~Counter() {
134 if (mCount) mCount->destruct++;
135 }
136
137 EventCount* mCount;
138 };
139
140 EventCount count;
141 {
142 Counter counter{&count};
143 queue().runSync([c = std::move(counter)](){});
144 }
145 ASSERT_EQ(1, count.construct.load());
146 ASSERT_EQ(1, count.destruct.load());
147 ASSERT_EQ(0, count.copy.load());
148 ASSERT_LE(1, count.move.load());
149}
150
151int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
152 return queue().runSync([t = test]() -> int {
153 return t->getStrongCount();
154 });
155}
156
157TEST(ThreadBase, lifecycle) {
158 sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
159 ASSERT_EQ(1, dummyObject->getStrongCount());
160 ASSERT_EQ(2, queue().runSync([dummyObject]() -> int {
161 return dummyObject->getStrongCount();
162 }));
163 ASSERT_EQ(1, dummyObject->getStrongCount());
164 ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
165 ASSERT_EQ(1, dummyObject->getStrongCount());
166}