Home | History | Annotate | Download | only in unit
      1 /*
      2  * Copyright (C) 2019 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/CommonPool.h"
     20 
     21 #include <array>
     22 #include <condition_variable>
     23 #include <set>
     24 #include <thread>
     25 #include "unistd.h"
     26 
     27 using namespace android;
     28 using namespace android::uirenderer;
     29 
     30 TEST(CommonPool, post) {
     31     std::atomic_bool ran(false);
     32     CommonPool::post([&ran] { ran = true; });
     33     for (int i = 0; !ran && i < 1000; i++) {
     34         usleep(1);
     35     }
     36     EXPECT_TRUE(ran) << "Failed to flip atomic after 1 second";
     37 }
     38 
     39 // test currently relies on timings, which
     40 // makes it flaky. Disable for now
     41 TEST(DISABLED_CommonPool, threadCount) {
     42     std::set<pid_t> threads;
     43     std::array<std::future<pid_t>, 64> futures;
     44     for (int i = 0; i < futures.size(); i++) {
     45         futures[i] = CommonPool::async([] {
     46             usleep(10);
     47             return gettid();
     48         });
     49     }
     50     for (auto& f : futures) {
     51         threads.insert(f.get());
     52     }
     53     EXPECT_EQ(threads.size(), CommonPool::THREAD_COUNT);
     54     EXPECT_EQ(0, threads.count(gettid()));
     55 }
     56 
     57 TEST(CommonPool, singleThread) {
     58     std::mutex mutex;
     59     std::condition_variable fence;
     60     bool isProcessing = false;
     61     bool queuedSecond = false;
     62 
     63     auto f1 = CommonPool::async([&] {
     64         {
     65             std::unique_lock lock{mutex};
     66             isProcessing = true;
     67             fence.notify_all();
     68             while (!queuedSecond) {
     69                 fence.wait(lock);
     70             }
     71         }
     72         return gettid();
     73     });
     74 
     75     {
     76         std::unique_lock lock{mutex};
     77         while (!isProcessing) {
     78             fence.wait(lock);
     79         }
     80     }
     81 
     82     auto f2 = CommonPool::async([] {
     83         return gettid();
     84     });
     85 
     86     {
     87         std::unique_lock lock{mutex};
     88         queuedSecond = true;
     89         fence.notify_all();
     90     }
     91 
     92     auto tid1 = f1.get();
     93     auto tid2 = f2.get();
     94     EXPECT_EQ(tid1, tid2);
     95     EXPECT_NE(gettid(), tid1);
     96 }
     97 
     98 // Test currently relies on timings
     99 // which makes it flaky, disable for now
    100 TEST(DISABLED_CommonPool, fullQueue) {
    101     std::mutex lock;
    102     std::condition_variable fence;
    103     bool signaled = false;
    104     static constexpr auto QUEUE_COUNT = CommonPool::THREAD_COUNT + CommonPool::QUEUE_SIZE + 10;
    105     std::atomic_int queuedCount{0};
    106     std::array<std::future<void>, QUEUE_COUNT> futures;
    107 
    108     std::thread queueThread{[&] {
    109         for (int i = 0; i < QUEUE_COUNT; i++) {
    110             futures[i] = CommonPool::async([&] {
    111                 std::unique_lock _lock{lock};
    112                 while (!signaled) {
    113                     fence.wait(_lock);
    114                 }
    115             });
    116             queuedCount++;
    117         }
    118     }};
    119 
    120     int previous;
    121     do {
    122         previous = queuedCount.load();
    123         usleep(10000);
    124     } while (previous != queuedCount.load());
    125 
    126     EXPECT_GT(queuedCount.load(), CommonPool::QUEUE_SIZE);
    127     EXPECT_LT(queuedCount.load(), QUEUE_COUNT);
    128 
    129     {
    130         std::unique_lock _lock{lock};
    131         signaled = true;
    132         fence.notify_all();
    133     }
    134 
    135     queueThread.join();
    136     EXPECT_EQ(queuedCount.load(), QUEUE_COUNT);
    137 
    138     // Ensure all our tasks are finished before return as they have references to the stack
    139     for (auto& f : futures) {
    140         f.get();
    141     }
    142 }
    143 
    144 class ObjectTracker {
    145     static std::atomic_int sGlobalCount;
    146 
    147 public:
    148     ObjectTracker() {
    149         sGlobalCount++;
    150     }
    151     ObjectTracker(const ObjectTracker&) {
    152         sGlobalCount++;
    153     }
    154     ObjectTracker(ObjectTracker&&) {
    155         sGlobalCount++;
    156     }
    157     ~ObjectTracker() {
    158         sGlobalCount--;
    159     }
    160 
    161     static int count() { return sGlobalCount.load(); }
    162 };
    163 
    164 std::atomic_int ObjectTracker::sGlobalCount{0};
    165 
    166 TEST(CommonPool, asyncLifecycleCheck) {
    167     ASSERT_EQ(0, ObjectTracker::count());
    168     {
    169         ObjectTracker obj;
    170         ASSERT_EQ(1, ObjectTracker::count());
    171         EXPECT_LT(1, CommonPool::async([obj] { return ObjectTracker::count(); }).get());
    172     }
    173     CommonPool::waitForIdle();
    174     ASSERT_EQ(0, ObjectTracker::count());
    175 }
    176 
    177 TEST(CommonPool, syncLifecycleCheck) {
    178     ASSERT_EQ(0, ObjectTracker::count());
    179     {
    180         ObjectTracker obj;
    181         ASSERT_EQ(1, ObjectTracker::count());
    182         EXPECT_LT(1, CommonPool::runSync([obj] { return ObjectTracker::count(); }));
    183     }
    184     CommonPool::waitForIdle();
    185     ASSERT_EQ(0, ObjectTracker::count());
    186 }
    187