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