Home | History | Annotate | Download | only in unit
      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         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 }