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