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 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 39 static WorkQueue& queue() { 40 return thread().queue(); 41 } 42 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 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 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 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 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 140 int lifecycleTestHelper(const sp<VirtualLightRefBase>& test) { 141 return queue().runSync([t = test]()->int { return t->getStrongCount(); }); 142 } 143 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