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 "perfetto/base/thread_checker.h" 18 19 #include <pthread.h> 20 21 #include <functional> 22 #include <memory> 23 24 #include "gtest/gtest.h" 25 26 namespace perfetto { 27 namespace base { 28 namespace { 29 30 // We just need two distinct pointers to return to pthread_join(). 31 void* const kTrue = reinterpret_cast<void*>(1); 32 void* const kFalse = nullptr; 33 34 void* RunOnThread(std::function<void*(void)> closure) { 35 pthread_t thread; 36 auto thread_main = [](void* arg) -> void* { 37 pthread_exit((*reinterpret_cast<std::function<void*(void)>*>(arg))()); 38 }; 39 EXPECT_EQ(0, pthread_create(&thread, nullptr, thread_main, &closure)); 40 void* retval = nullptr; 41 EXPECT_EQ(0, pthread_join(thread, &retval)); 42 return retval; 43 } 44 45 TEST(ThreadCheckerTest, Basic) { 46 ThreadChecker thread_checker; 47 ASSERT_TRUE(thread_checker.CalledOnValidThread()); 48 void* res = RunOnThread([&thread_checker]() -> void* { 49 return thread_checker.CalledOnValidThread() ? kTrue : kFalse; 50 }); 51 ASSERT_TRUE(thread_checker.CalledOnValidThread()); 52 ASSERT_EQ(kFalse, res); 53 } 54 55 TEST(ThreadCheckerTest, Detach) { 56 ThreadChecker thread_checker; 57 ASSERT_TRUE(thread_checker.CalledOnValidThread()); 58 thread_checker.DetachFromThread(); 59 void* res = RunOnThread([&thread_checker]() -> void* { 60 return thread_checker.CalledOnValidThread() ? kTrue : kFalse; 61 }); 62 ASSERT_EQ(kTrue, res); 63 ASSERT_FALSE(thread_checker.CalledOnValidThread()); 64 } 65 66 TEST(ThreadCheckerTest, CopyConstructor) { 67 ThreadChecker thread_checker; 68 ThreadChecker copied_thread_checker = thread_checker; 69 ASSERT_TRUE(thread_checker.CalledOnValidThread()); 70 ASSERT_TRUE(copied_thread_checker.CalledOnValidThread()); 71 void* res = RunOnThread([&copied_thread_checker]() -> void* { 72 return copied_thread_checker.CalledOnValidThread() ? kTrue : kFalse; 73 }); 74 ASSERT_EQ(kFalse, res); 75 76 copied_thread_checker.DetachFromThread(); 77 res = RunOnThread([&thread_checker, &copied_thread_checker]() -> void* { 78 return (copied_thread_checker.CalledOnValidThread() && 79 !thread_checker.CalledOnValidThread()) 80 ? kTrue 81 : kFalse; 82 }); 83 ASSERT_EQ(kTrue, res); 84 } 85 86 } // namespace 87 } // namespace base 88 } // namespace perfetto 89