OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/threading/non_thread_safe.h" | |
6 | |
7 #include <memory> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/macros.h" | |
11 #include "base/test/gtest_util.h" | |
12 #include "base/threading/simple_thread.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace base { | |
16 | |
17 namespace { | |
18 | |
19 // Simple class to exersice the basics of NonThreadSafe. | |
20 // Both the destructor and DoStuff should verify that they were | |
21 // called on the same thread as the constructor. | |
22 class NonThreadSafeClass : public NonThreadSafe { | |
23 public: | |
24 NonThreadSafeClass() {} | |
25 | |
26 // Verifies that it was called on the same thread as the constructor. | |
27 void DoStuff() { | |
28 DCHECK(CalledOnValidThread()); | |
29 } | |
30 | |
31 void DetachFromThread() { | |
32 NonThreadSafe::DetachFromThread(); | |
33 } | |
34 | |
35 static void MethodOnDifferentThreadImpl(); | |
36 static void DestructorOnDifferentThreadImpl(); | |
37 | |
38 private: | |
39 DISALLOW_COPY_AND_ASSIGN(NonThreadSafeClass); | |
40 }; | |
41 | |
42 // Calls NonThreadSafeClass::DoStuff on another thread. | |
43 class CallDoStuffOnThread : public SimpleThread { | |
44 public: | |
45 explicit CallDoStuffOnThread(NonThreadSafeClass* non_thread_safe_class) | |
46 : SimpleThread("call_do_stuff_on_thread"), | |
47 non_thread_safe_class_(non_thread_safe_class) { | |
48 } | |
49 | |
50 void Run() override { non_thread_safe_class_->DoStuff(); } | |
51 | |
52 private: | |
53 NonThreadSafeClass* non_thread_safe_class_; | |
54 | |
55 DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread); | |
56 }; | |
57 | |
58 // Deletes NonThreadSafeClass on a different thread. | |
59 class DeleteNonThreadSafeClassOnThread : public SimpleThread { | |
60 public: | |
61 explicit DeleteNonThreadSafeClassOnThread( | |
62 NonThreadSafeClass* non_thread_safe_class) | |
63 : SimpleThread("delete_non_thread_safe_class_on_thread"), | |
64 non_thread_safe_class_(non_thread_safe_class) { | |
65 } | |
66 | |
67 void Run() override { non_thread_safe_class_.reset(); } | |
68 | |
69 private: | |
70 std::unique_ptr<NonThreadSafeClass> non_thread_safe_class_; | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(DeleteNonThreadSafeClassOnThread); | |
73 }; | |
74 | |
75 } // namespace | |
76 | |
77 TEST(NonThreadSafeTest, CallsAllowedOnSameThread) { | |
78 std::unique_ptr<NonThreadSafeClass> non_thread_safe_class( | |
79 new NonThreadSafeClass); | |
80 | |
81 // Verify that DoStuff doesn't assert. | |
82 non_thread_safe_class->DoStuff(); | |
83 | |
84 // Verify that the destructor doesn't assert. | |
85 non_thread_safe_class.reset(); | |
86 } | |
87 | |
88 TEST(NonThreadSafeTest, DetachThenDestructOnDifferentThread) { | |
89 std::unique_ptr<NonThreadSafeClass> non_thread_safe_class( | |
90 new NonThreadSafeClass); | |
91 | |
92 // Verify that the destructor doesn't assert when called on a different thread | |
93 // after a detach. | |
94 non_thread_safe_class->DetachFromThread(); | |
95 DeleteNonThreadSafeClassOnThread delete_on_thread( | |
96 non_thread_safe_class.release()); | |
97 | |
98 delete_on_thread.Start(); | |
99 delete_on_thread.Join(); | |
100 } | |
101 | |
102 void NonThreadSafeClass::MethodOnDifferentThreadImpl() { | |
103 std::unique_ptr<NonThreadSafeClass> non_thread_safe_class( | |
104 new NonThreadSafeClass); | |
105 | |
106 // Verify that DoStuff asserts in debug builds only when called | |
107 // on a different thread. | |
108 CallDoStuffOnThread call_on_thread(non_thread_safe_class.get()); | |
109 | |
110 call_on_thread.Start(); | |
111 call_on_thread.Join(); | |
112 } | |
113 | |
114 #if DCHECK_IS_ON() | |
115 TEST(NonThreadSafeDeathTest, MethodNotAllowedOnDifferentThreadInDebug) { | |
116 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
117 ASSERT_DCHECK_DEATH({ NonThreadSafeClass::MethodOnDifferentThreadImpl(); }); | |
118 } | |
119 #else | |
120 TEST(NonThreadSafeTest, MethodAllowedOnDifferentThreadInRelease) { | |
121 NonThreadSafeClass::MethodOnDifferentThreadImpl(); | |
122 } | |
123 #endif // DCHECK_IS_ON() | |
124 | |
125 void NonThreadSafeClass::DestructorOnDifferentThreadImpl() { | |
126 std::unique_ptr<NonThreadSafeClass> non_thread_safe_class( | |
127 new NonThreadSafeClass); | |
128 | |
129 // Verify that the destructor asserts in debug builds only | |
130 // when called on a different thread. | |
131 DeleteNonThreadSafeClassOnThread delete_on_thread( | |
132 non_thread_safe_class.release()); | |
133 | |
134 delete_on_thread.Start(); | |
135 delete_on_thread.Join(); | |
136 } | |
137 | |
138 #if DCHECK_IS_ON() | |
139 TEST(NonThreadSafeDeathTest, DestructorNotAllowedOnDifferentThreadInDebug) { | |
140 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | |
141 ASSERT_DCHECK_DEATH( | |
142 { NonThreadSafeClass::DestructorOnDifferentThreadImpl(); }); | |
143 } | |
144 #else | |
145 TEST(NonThreadSafeTest, DestructorAllowedOnDifferentThreadInRelease) { | |
146 NonThreadSafeClass::DestructorOnDifferentThreadImpl(); | |
147 } | |
148 #endif // DCHECK_IS_ON() | |
149 | |
150 } // namespace base | |
OLD | NEW |