blob: 69b65aa8b67e215a9c7b692715d19fd948431ced [file] [log] [blame]
Primiano Tucci575af772017-11-08 18:14:17 +00001/*
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
Oystein Eftevaagdd727e42017-12-05 08:49:55 -080017#include "perfetto_base/thread_checker.h"
Primiano Tucci575af772017-11-08 18:14:17 +000018
19#include <pthread.h>
20
Primiano Tucci22c84172017-11-09 13:54:45 +000021#include <functional>
Primiano Tucci575af772017-11-08 18:14:17 +000022#include <memory>
23
24#include "gtest/gtest.h"
25
26namespace perfetto {
27namespace base {
28namespace {
29
30// We just need two distinct pointers to return to pthread_join().
31void* const kTrue = reinterpret_cast<void*>(1);
32void* const kFalse = nullptr;
33
34void* 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
45TEST(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
55TEST(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
66TEST(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