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 <broadcastradio-utils/WorkerThread.h> 18#include <gtest/gtest.h> 19 20namespace { 21 22using namespace std::chrono_literals; 23 24using android::WorkerThread; 25 26using std::atomic; 27using std::chrono::time_point; 28using std::chrono::steady_clock; 29using std::is_sorted; 30using std::lock_guard; 31using std::mutex; 32using std::this_thread::sleep_for; 33using std::vector; 34 35#define ASSERT_EQ_WITH_TOLERANCE(val1, val2, tolerance) \ 36 ASSERT_LE((val1) - (tolerance), (val2)); \ 37 ASSERT_GE((val1) + (tolerance), (val2)); 38 39TEST(WorkerThreadTest, oneTask) { 40 atomic<bool> executed(false); 41 atomic<time_point<steady_clock>> stop; 42 WorkerThread thread; 43 44 auto start = steady_clock::now(); 45 thread.schedule( 46 [&]() { 47 stop = steady_clock::now(); 48 executed = true; 49 }, 50 100ms); 51 52 sleep_for(150ms); 53 54 ASSERT_TRUE(executed); 55 auto delta = stop.load() - start; 56 ASSERT_EQ_WITH_TOLERANCE(delta, 100ms, 50ms); 57} 58 59TEST(WorkerThreadTest, cancelSecond) { 60 atomic<bool> executed1(false); 61 atomic<bool> executed2(false); 62 WorkerThread thread; 63 64 thread.schedule([&]() { executed2 = true; }, 100ms); 65 thread.schedule([&]() { executed1 = true; }, 25ms); 66 67 sleep_for(50ms); 68 thread.cancelAll(); 69 sleep_for(100ms); 70 71 ASSERT_TRUE(executed1); 72 ASSERT_FALSE(executed2); 73} 74 75TEST(WorkerThreadTest, executeInOrder) { 76 mutex mut; 77 vector<int> order; 78 WorkerThread thread; 79 80 thread.schedule( 81 [&]() { 82 lock_guard<mutex> lk(mut); 83 order.push_back(0); 84 }, 85 50ms); 86 87 thread.schedule( 88 [&]() { 89 lock_guard<mutex> lk(mut); 90 order.push_back(4); 91 }, 92 400ms); 93 94 thread.schedule( 95 [&]() { 96 lock_guard<mutex> lk(mut); 97 order.push_back(1); 98 }, 99 100ms); 100 101 thread.schedule( 102 [&]() { 103 lock_guard<mutex> lk(mut); 104 order.push_back(3); 105 }, 106 300ms); 107 108 thread.schedule( 109 [&]() { 110 lock_guard<mutex> lk(mut); 111 order.push_back(2); 112 }, 113 200ms); 114 115 sleep_for(500ms); 116 117 ASSERT_EQ(5u, order.size()); 118 ASSERT_TRUE(is_sorted(order.begin(), order.end())); 119} 120 121TEST(WorkerThreadTest, dontExecuteAfterDestruction) { 122 atomic<bool> executed1(false); 123 atomic<bool> executed2(false); 124 { 125 WorkerThread thread; 126 127 thread.schedule([&]() { executed2 = true; }, 100ms); 128 thread.schedule([&]() { executed1 = true; }, 25ms); 129 130 sleep_for(50ms); 131 } 132 sleep_for(100ms); 133 134 ASSERT_TRUE(executed1); 135 ASSERT_FALSE(executed2); 136} 137 138} // anonymous namespace 139