blob: 1168ff211202cdac23ea611bad15bc0f6265ce48 [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;
John Reck1bcacfd2017-11-03 10:12:19 -070034 }
35 ();
John Reckf8441e62017-10-23 13:10:41 -070036 return *thread;
37}
38
39static WorkQueue& queue() {
40 return thread().queue();
41}
42
43TEST(ThreadBase, post) {
44 std::atomic_bool ran(false);
John Reck1bcacfd2017-11-03 10:12:19 -070045 queue().post([&ran]() { ran = true; });
John Reckf8441e62017-10-23 13:10:41 -070046 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
52TEST(ThreadBase, postDelay) {
53 using clock = WorkQueue::clock;
54
55 std::promise<nsecs_t> ranAtPromise;
56 auto queuedAt = clock::now();
John Reck1bcacfd2017-11-03 10:12:19 -070057 queue().postDelayed(100_us, [&]() { ranAtPromise.set_value(clock::now()); });
John Reckf8441e62017-10-23 13:10:41 -070058 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
63TEST(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
76TEST(ThreadBase, async) {
77 pid_t thisTid = gettid();
78 pid_t thisPid = getpid();
79
John Reck1bcacfd2017-11-03 10:12:19 -070080 auto otherTid = queue().async([]() -> auto { return gettid(); });
81 auto otherPid = queue().async([]() -> auto { return getpid(); });
82 auto result = queue().async([]() -> auto { return 42; });
John Reckf8441e62017-10-23 13:10:41 -070083
84 ASSERT_NE(thisTid, otherTid.get());
85 ASSERT_EQ(thisPid, otherPid.get());
86 ASSERT_EQ(42, result.get());
87}
88
89TEST(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 {
John Reck1bcacfd2017-11-03 10:12:19 -070098 Counter(EventCount* count) : mCount(count) { mCount->construct++; }
John Reckf8441e62017-10-23 13:10:41 -070099
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
140int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) {
John Reck1bcacfd2017-11-03 10:12:19 -0700141 return queue().runSync([t = test]()->int { return t->getStrongCount(); });
John Reckf8441e62017-10-23 13:10:41 -0700142}
143
144TEST(ThreadBase, lifecycle) {
145 sp<VirtualLightRefBase> dummyObject{new VirtualLightRefBase};
146 ASSERT_EQ(1, dummyObject->getStrongCount());
John Reck1bcacfd2017-11-03 10:12:19 -0700147 ASSERT_EQ(2, queue().runSync([dummyObject]() -> int { return dummyObject->getStrongCount(); }));
John Reckf8441e62017-10-23 13:10:41 -0700148 ASSERT_EQ(1, dummyObject->getStrongCount());
149 ASSERT_EQ(2, lifecycleTestHelper(dummyObject));
150 ASSERT_EQ(1, dummyObject->getStrongCount());
151}