• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RunOnThread(std::function<void * (void)> closure)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 
TEST(ThreadCheckerTest,Basic)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 
TEST(ThreadCheckerTest,Detach)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 
TEST(ThreadCheckerTest,CopyConstructor)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