• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
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/allocator/dispatcher/tls.h"
6 
7 #if USE_LOCAL_TLS_EMULATION()
8 #include <algorithm>
9 #include <array>
10 #include <cstddef>
11 #include <functional>
12 #include <mutex>
13 #include <thread>
14 #include <unordered_set>
15 #include <utility>
16 
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 using ::testing::_;
21 using ::testing::InSequence;
22 using ::testing::NiceMock;
23 using ::testing::NotNull;
24 using ::testing::Return;
25 using ::testing::ReturnNull;
26 
27 namespace base::allocator::dispatcher {
28 namespace {
29 struct DataToStore {
30   int data_int = 0;
31   float data_float = 0.0;
32   size_t data_size_t = 0;
33   double data_double = 0.0;
34 };
35 
36 struct AllocatorMockBase {
AllocatorMockBasebase::allocator::dispatcher::__anon4b6f41660111::AllocatorMockBase37   AllocatorMockBase() {
38     ON_CALL(*this, AllocateMemory(_)).WillByDefault([](size_t size_in_bytes) {
39       return malloc(size_in_bytes);
40     });
41     ON_CALL(*this, FreeMemoryForTesting(_, _))
42         .WillByDefault([](void* pointer_to_allocated, size_t size_in_bytes) {
43           free(pointer_to_allocated);
44           return true;
45         });
46   }
47 
48   MOCK_METHOD(void*, AllocateMemory, (size_t size_in_bytes), ());
49   MOCK_METHOD(bool,
50               FreeMemoryForTesting,
51               (void* pointer_to_allocated, size_t size_in_bytes),
52               ());
53 };
54 
55 struct TLSSystemMockBase {
TLSSystemMockBasebase::allocator::dispatcher::__anon4b6f41660111::TLSSystemMockBase56   TLSSystemMockBase() {
57     ON_CALL(*this, Setup(_)).WillByDefault(Return(true));
58     ON_CALL(*this, TearDownForTesting()).WillByDefault(Return(true));
59     ON_CALL(*this, SetThreadSpecificData(_)).WillByDefault(Return(true));
60   }
61 
62   MOCK_METHOD(
63       bool,
64       Setup,
65       (internal::OnThreadTerminationFunction thread_termination_function),
66       ());
67   MOCK_METHOD(bool, TearDownForTesting, (), ());
68   MOCK_METHOD(void*, GetThreadSpecificData, (), ());
69   MOCK_METHOD(bool, SetThreadSpecificData, (void* data), ());
70 };
71 
72 using AllocatorMock = NiceMock<AllocatorMockBase>;
73 using TLSSystemMock = NiceMock<TLSSystemMockBase>;
74 
75 template <typename T, typename Allocator, typename TLSSystem>
76 ThreadLocalStorage<T,
77                    std::reference_wrapper<Allocator>,
78                    std::reference_wrapper<TLSSystem>,
79                    0,
80                    true>
CreateThreadLocalStorage(Allocator & allocator,TLSSystem & tlsSystem)81 CreateThreadLocalStorage(Allocator& allocator, TLSSystem& tlsSystem) {
82   return {std::ref(allocator), std::ref(tlsSystem)};
83 }
84 
85 template <typename T>
86 ThreadLocalStorage<T,
87                    internal::DefaultAllocator,
88                    internal::DefaultTLSSystem,
89                    0,
90                    true>
CreateThreadLocalStorage()91 CreateThreadLocalStorage() {
92   return {};
93 }
94 
95 }  // namespace
96 
97 struct BaseThreadLocalStorageTest : public ::testing::Test {};
98 
TEST_F(BaseThreadLocalStorageTest,VerifyDataIsIndependentBetweenDifferentSUTs)99 TEST_F(BaseThreadLocalStorageTest,
100        VerifyDataIsIndependentBetweenDifferentSUTs) {
101   auto sut_1 = CreateThreadLocalStorage<DataToStore>();
102   auto sut_2 = CreateThreadLocalStorage<DataToStore>();
103 
104   EXPECT_NE(sut_1.GetThreadLocalData(), sut_2.GetThreadLocalData());
105 }
106 
TEST_F(BaseThreadLocalStorageTest,VerifyDistinctEntriesForEachThread)107 TEST_F(BaseThreadLocalStorageTest, VerifyDistinctEntriesForEachThread) {
108   auto sut = CreateThreadLocalStorage<DataToStore>();
109   using TLSType = decltype(sut);
110 
111   std::array<std::thread, 2 * TLSType::ItemsPerChunk> threads;
112   std::mutex thread_worker_mutex;
113   std::condition_variable thread_counter_cv;
114   std::atomic_uint32_t thread_counter{0};
115   std::unordered_set<void*> stored_object_addresses;
116 
117   std::mutex threads_can_finish_mutex;
118   std::condition_variable threads_can_finish_cv;
119   std::atomic_bool threads_can_finish{false};
120 
121   for (auto& t : threads) {
122     t = std::thread{[&] {
123       {
124         std::lock_guard<std::mutex> lock(thread_worker_mutex);
125         stored_object_addresses.insert(sut.GetThreadLocalData());
126         ++thread_counter;
127         thread_counter_cv.notify_one();
128       }
129 
130       {
131         std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
132         threads_can_finish_cv.wait(lock,
133                                    [&] { return threads_can_finish.load(); });
134       }
135     }};
136   }
137 
138   {
139     std::unique_lock<std::mutex> lock(thread_worker_mutex);
140     thread_counter_cv.wait(
141         lock, [&] { return thread_counter.load() == threads.size(); });
142   }
143 
144   {
145     std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
146     threads_can_finish = true;
147     threads_can_finish_cv.notify_all();
148   }
149 
150   for (auto& t : threads) {
151     t.join();
152   }
153 
154   EXPECT_EQ(stored_object_addresses.size(), threads.size());
155 }
156 
TEST_F(BaseThreadLocalStorageTest,VerifyEntriesAreReusedForNewThreads)157 TEST_F(BaseThreadLocalStorageTest, VerifyEntriesAreReusedForNewThreads) {
158   auto sut = CreateThreadLocalStorage<DataToStore>();
159   using TLSType = decltype(sut);
160 
161   std::unordered_set<void*> stored_object_addresses;
162 
163   for (size_t thread_count = 0; thread_count < (2 * TLSType::ItemsPerChunk);
164        ++thread_count) {
165     auto thread = std::thread{
166         [&] { stored_object_addresses.insert(sut.GetThreadLocalData()); }};
167 
168     thread.join();
169   }
170 
171   EXPECT_EQ(stored_object_addresses.size(), 1ul);
172 }
173 
TEST_F(BaseThreadLocalStorageTest,VerifyDataIsSameWithinEachThread)174 TEST_F(BaseThreadLocalStorageTest, VerifyDataIsSameWithinEachThread) {
175   auto sut = CreateThreadLocalStorage<DataToStore>();
176   using TLSType = decltype(sut);
177 
178   std::array<std::thread, 2 * TLSType::ItemsPerChunk> threads;
179 
180   for (auto& t : threads) {
181     t = std::thread{[&] {
182       EXPECT_EQ(sut.GetThreadLocalData(), sut.GetThreadLocalData());
183       std::this_thread::sleep_for(std::chrono::milliseconds(100));
184       // Check once again to verify the data doesn't change in the course of a
185       // thread's lifetime.
186       EXPECT_EQ(sut.GetThreadLocalData(), sut.GetThreadLocalData());
187     }};
188   }
189 
190   for (auto& t : threads) {
191     t.join();
192   }
193 }
194 
TEST_F(BaseThreadLocalStorageTest,VerifySetupTeardownSequence)195 TEST_F(BaseThreadLocalStorageTest, VerifySetupTeardownSequence) {
196   AllocatorMock allocator_mock;
197   TLSSystemMock tlsSystem_mock;
198 
199   InSequence execution_sequence;
200 
201   EXPECT_CALL(allocator_mock, AllocateMemory(_))
202       .WillOnce([](size_t size_in_bytes) { return malloc(size_in_bytes); });
203   EXPECT_CALL(tlsSystem_mock, Setup(NotNull())).WillOnce(Return(true));
204   EXPECT_CALL(tlsSystem_mock, TearDownForTesting()).WillOnce(Return(true));
205   EXPECT_CALL(allocator_mock, FreeMemoryForTesting(_, _))
206       .WillOnce([](void* pointer_to_allocated, size_t size_in_bytes) {
207         free(pointer_to_allocated);
208         return true;
209       });
210 
211   auto sut =
212       CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
213 }
214 
TEST_F(BaseThreadLocalStorageTest,VerifyAllocatorIsUsed)215 TEST_F(BaseThreadLocalStorageTest, VerifyAllocatorIsUsed) {
216   AllocatorMock allocator_mock;
217   TLSSystemMock tlsSystem_mock;
218 
219   EXPECT_CALL(allocator_mock, AllocateMemory(_))
220       .WillOnce([](size_t size_in_bytes) { return malloc(size_in_bytes); });
221 
222   EXPECT_CALL(allocator_mock, FreeMemoryForTesting(_, _))
223       .WillOnce([](void* pointer_to_allocated, size_t size_in_bytes) {
224         free(pointer_to_allocated);
225         return true;
226       });
227 
228   auto sut =
229       CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
230 }
231 
TEST_F(BaseThreadLocalStorageTest,VerifyAllocatorIsUsedForMultipleChunks)232 TEST_F(BaseThreadLocalStorageTest, VerifyAllocatorIsUsedForMultipleChunks) {
233   AllocatorMock allocator_mock;
234   TLSSystemMock tlsSystem_mock;
235 
236   constexpr auto number_of_chunks = 3;
237 
238   EXPECT_CALL(allocator_mock, AllocateMemory(_))
239       .Times(number_of_chunks)
240       .WillRepeatedly(
241           [](size_t size_in_bytes) { return malloc(size_in_bytes); });
242 
243   EXPECT_CALL(allocator_mock, FreeMemoryForTesting(_, _))
244       .Times(number_of_chunks)
245       .WillRepeatedly([](void* pointer_to_allocated, size_t size_in_bytes) {
246         free(pointer_to_allocated);
247         return true;
248       });
249 
250   auto sut =
251       CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
252 
253   std::array<std::thread,
254              (number_of_chunks - 1) * decltype(sut)::ItemsPerChunk + 1>
255       threads;
256   std::mutex thread_worker_mutex;
257   std::condition_variable thread_counter_cv;
258   std::atomic_uint32_t thread_counter{0};
259   std::unordered_set<void*> stored_object_addresses;
260 
261   std::mutex threads_can_finish_mutex;
262   std::condition_variable threads_can_finish_cv;
263   std::atomic_bool threads_can_finish{false};
264 
265   for (auto& t : threads) {
266     t = std::thread{[&] {
267       sut.GetThreadLocalData();
268 
269       {
270         std::lock_guard<std::mutex> lock(thread_worker_mutex);
271         ++thread_counter;
272         thread_counter_cv.notify_one();
273       }
274 
275       {
276         std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
277         threads_can_finish_cv.wait(lock,
278                                    [&] { return threads_can_finish.load(); });
279       }
280     }};
281   }
282 
283   {
284     std::unique_lock<std::mutex> lock(thread_worker_mutex);
285     thread_counter_cv.wait(
286         lock, [&] { return thread_counter.load() == threads.size(); });
287   }
288 
289   {
290     std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
291     threads_can_finish = true;
292     threads_can_finish_cv.notify_all();
293   }
294 
295   for (auto& t : threads) {
296     t.join();
297   }
298 }
299 
TEST_F(BaseThreadLocalStorageTest,VerifyTLSSystemIsUsed)300 TEST_F(BaseThreadLocalStorageTest, VerifyTLSSystemIsUsed) {
301   AllocatorMock allocator_mock;
302   TLSSystemMock tlsSystem_mock;
303 
304   InSequence execution_sequence;
305 
306   EXPECT_CALL(tlsSystem_mock, Setup(NotNull())).WillOnce(Return(true));
307   EXPECT_CALL(tlsSystem_mock, GetThreadSpecificData())
308       .WillOnce(Return(nullptr));
309   EXPECT_CALL(tlsSystem_mock, SetThreadSpecificData(NotNull()));
310   EXPECT_CALL(tlsSystem_mock, TearDownForTesting())
311       .Times(1)
312       .WillOnce(Return(true));
313 
314   auto sut =
315       CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
316 
317   sut.GetThreadLocalData();
318 }
319 
320 #if defined(GTEST_HAS_DEATH_TEST)
321 struct BaseThreadLocalStorageDeathTest : public ::testing::Test {};
322 
TEST_F(BaseThreadLocalStorageDeathTest,VerifyDeathIfAllocationFails)323 TEST_F(BaseThreadLocalStorageDeathTest, VerifyDeathIfAllocationFails) {
324   auto f = [] {
325     AllocatorMock allocator_mock;
326     TLSSystemMock tlsSystem_mock;
327 
328     // Setup all expectations here. If we're setting them up in the parent
329     // process, they will fail because the parent doesn't execute any test.
330     EXPECT_CALL(allocator_mock, AllocateMemory(_)).WillOnce(ReturnNull());
331 
332     CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
333   };
334 
335   EXPECT_DEATH(f(), "");
336 }
337 
TEST_F(BaseThreadLocalStorageDeathTest,VerifyDeathIfFreeFails)338 TEST_F(BaseThreadLocalStorageDeathTest, VerifyDeathIfFreeFails) {
339   auto f = [] {
340     AllocatorMock allocator_mock;
341     TLSSystemMock tlsSystem_mock;
342 
343     // Setup all expectations here. If we're setting them up in the parent
344     // process, they will fail because the parent doesn't execute any test.
345     EXPECT_CALL(allocator_mock, FreeMemoryForTesting(_, _))
346         .WillOnce([](void* allocated_memory, size_t size_in_bytes) {
347           free(allocated_memory);
348           return false;
349         });
350 
351     CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
352   };
353 
354   EXPECT_DEATH(f(), "");
355 }
356 
TEST_F(BaseThreadLocalStorageDeathTest,VerifyDeathIfTLSSetupFails)357 TEST_F(BaseThreadLocalStorageDeathTest, VerifyDeathIfTLSSetupFails) {
358   auto f = [] {
359     AllocatorMock allocator_mock;
360     TLSSystemMock tlsSystem_mock;
361 
362     // Setup all expectations here. If we're setting them up in the parent
363     // process, they will fail because the parent doesn't execute any test.
364     EXPECT_CALL(tlsSystem_mock, Setup(_)).WillOnce(Return(false));
365     EXPECT_CALL(tlsSystem_mock, GetThreadSpecificData()).Times(0);
366     EXPECT_CALL(tlsSystem_mock, SetThreadSpecificData(_)).Times(0);
367     EXPECT_CALL(tlsSystem_mock, TearDownForTesting()).Times(0);
368 
369     CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
370   };
371 
372   EXPECT_DEATH(f(), "");
373 }
374 
TEST_F(BaseThreadLocalStorageDeathTest,VerifyDeathIfStoringTLSDataFails)375 TEST_F(BaseThreadLocalStorageDeathTest, VerifyDeathIfStoringTLSDataFails) {
376   auto f = [] {
377     AllocatorMock allocator_mock;
378     TLSSystemMock tlsSystem_mock;
379 
380     // Setup all expectations here. If we're setting them up in the parent
381     // process, they will fail because the parent doesn't execute any test.
382     EXPECT_CALL(tlsSystem_mock, SetThreadSpecificData(_))
383         .Times(1)
384         .WillOnce(Return(false));
385     EXPECT_CALL(tlsSystem_mock, TearDownForTesting()).Times(0);
386 
387     CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock)
388         .GetThreadLocalData();
389   };
390 
391   EXPECT_DEATH(f(), "");
392 }
393 
TEST_F(BaseThreadLocalStorageDeathTest,VerifyDeathIfTLSTeardownFails)394 TEST_F(BaseThreadLocalStorageDeathTest, VerifyDeathIfTLSTeardownFails) {
395   auto f = [] {
396     AllocatorMock allocator_mock;
397     TLSSystemMock tlsSystem_mock;
398 
399     // Setup all expectations here. If we're setting them up in the parent
400     // process, they will fail because the parent doesn't execute any test.
401     EXPECT_CALL(tlsSystem_mock, Setup(_)).WillOnce(Return(true));
402     EXPECT_CALL(tlsSystem_mock, TearDownForTesting()).WillOnce(Return(false));
403 
404     CreateThreadLocalStorage<DataToStore>(allocator_mock, tlsSystem_mock);
405   };
406 
407   EXPECT_DEATH(f(), "");
408 }
409 #endif  // GTEST_HAS_DEATH_TEST
410 
411 struct BasePThreadTLSSystemTest : public ::testing::Test {
SetUpbase::allocator::dispatcher::BasePThreadTLSSystemTest412   void SetUp() override { thread_termination_counter = 0; }
413 
414  protected:
ThreadTerminationFunctionbase::allocator::dispatcher::BasePThreadTLSSystemTest415   static void ThreadTerminationFunction(void*) { ++thread_termination_counter; }
416 
417   static std::atomic<size_t> thread_termination_counter;
418 };
419 
420 std::atomic<size_t> BasePThreadTLSSystemTest::thread_termination_counter{0};
421 
TEST_F(BasePThreadTLSSystemTest,VerifySetupNTeardownSequence)422 TEST_F(BasePThreadTLSSystemTest, VerifySetupNTeardownSequence) {
423   internal::PThreadTLSSystem sut;
424 
425   for (size_t idx = 0; idx < 5; ++idx) {
426     EXPECT_TRUE(sut.Setup(nullptr));
427     EXPECT_TRUE(sut.TearDownForTesting());
428   }
429 }
430 
TEST_F(BasePThreadTLSSystemTest,VerifyThreadTerminationFunctionIsCalled)431 TEST_F(BasePThreadTLSSystemTest, VerifyThreadTerminationFunctionIsCalled) {
432   std::array<std::thread, 10> threads;
433 
434   internal::PThreadTLSSystem sut;
435   sut.Setup(&ThreadTerminationFunction);
436 
437   for (auto& t : threads) {
438     t = std::thread{[&] {
439       int x = 0;
440       ASSERT_TRUE(sut.SetThreadSpecificData(&x));
441     }};
442   }
443 
444   for (auto& t : threads) {
445     t.join();
446   }
447 
448   sut.TearDownForTesting();
449 
450   EXPECT_EQ(threads.size(), thread_termination_counter);
451 }
452 
TEST_F(BasePThreadTLSSystemTest,VerifyGetWithoutSetReturnsNull)453 TEST_F(BasePThreadTLSSystemTest, VerifyGetWithoutSetReturnsNull) {
454   internal::PThreadTLSSystem sut;
455   sut.Setup(nullptr);
456 
457   EXPECT_EQ(nullptr, sut.GetThreadSpecificData());
458 
459   sut.TearDownForTesting();
460 }
461 
TEST_F(BasePThreadTLSSystemTest,VerifyGetAfterTeardownReturnsNull)462 TEST_F(BasePThreadTLSSystemTest, VerifyGetAfterTeardownReturnsNull) {
463   internal::PThreadTLSSystem sut;
464   sut.Setup(nullptr);
465   sut.SetThreadSpecificData(this);
466   sut.TearDownForTesting();
467 
468   EXPECT_EQ(sut.GetThreadSpecificData(), nullptr);
469 }
470 
TEST_F(BasePThreadTLSSystemTest,VerifyGetAfterTeardownReturnsNullThreaded)471 TEST_F(BasePThreadTLSSystemTest, VerifyGetAfterTeardownReturnsNullThreaded) {
472   std::array<std::thread, 50> threads;
473 
474   std::mutex thread_worker_mutex;
475   std::condition_variable thread_counter_cv;
476   std::atomic_uint32_t thread_counter{0};
477 
478   std::mutex threads_can_finish_mutex;
479   std::condition_variable threads_can_finish_cv;
480   std::atomic_bool threads_can_finish{false};
481 
482   internal::PThreadTLSSystem sut;
483   ASSERT_TRUE(sut.Setup(nullptr));
484 
485   for (auto& t : threads) {
486     t = std::thread{[&] {
487       // Set some thread specific data. At this stage retrieving the data must
488       // return the pointer that was originally set.
489       int x = 0;
490       ASSERT_TRUE(sut.SetThreadSpecificData(&x));
491       ASSERT_EQ(sut.GetThreadSpecificData(), &x);
492 
493       // Notify the main thread that one more test thread has started.
494       {
495         std::lock_guard<std::mutex> lock(thread_worker_mutex);
496         ++thread_counter;
497         thread_counter_cv.notify_one();
498       }
499 
500       // Wait for the main thread to notify about teardown of the sut.
501       {
502         std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
503         threads_can_finish_cv.wait(lock,
504                                    [&] { return threads_can_finish.load(); });
505       }
506 
507       // After teardown, thread local data must be nullptr for all threads.
508       EXPECT_EQ(sut.GetThreadSpecificData(), nullptr);
509     }};
510   }
511 
512   // Wait for notification from threads that they started and passed the initial
513   // check.
514   {
515     std::unique_lock<std::mutex> lock(thread_worker_mutex);
516     thread_counter_cv.wait(
517         lock, [&] { return thread_counter.load() == threads.size(); });
518   }
519 
520   ASSERT_TRUE(sut.TearDownForTesting());
521 
522   // Notify all threads that the subject under test was torn down and they can
523   // proceed.
524   {
525     std::unique_lock<std::mutex> lock(threads_can_finish_mutex);
526     threads_can_finish = true;
527     threads_can_finish_cv.notify_all();
528   }
529 
530   for (auto& t : threads) {
531     t.join();
532   }
533 }
534 
TEST_F(BasePThreadTLSSystemTest,VerifyGetSetSequence)535 TEST_F(BasePThreadTLSSystemTest, VerifyGetSetSequence) {
536   std::array<std::thread, 50> threads;
537 
538   internal::PThreadTLSSystem sut;
539   sut.Setup(nullptr);
540 
541   for (auto& t : threads) {
542     t = std::thread{[&] {
543       int x = 0;
544       EXPECT_TRUE(sut.SetThreadSpecificData(&x));
545       EXPECT_EQ(&x, sut.GetThreadSpecificData());
546     }};
547   }
548 
549   for (auto& t : threads) {
550     t.join();
551   }
552 
553   sut.TearDownForTesting();
554 }
555 
556 #if DCHECK_IS_ON()
TEST_F(BasePThreadTLSSystemTest,VerifyGetWithoutSetupReturnsNull)557 TEST_F(BasePThreadTLSSystemTest, VerifyGetWithoutSetupReturnsNull) {
558   internal::PThreadTLSSystem sut;
559 
560   EXPECT_EQ(sut.GetThreadSpecificData(), nullptr);
561 }
562 
TEST_F(BasePThreadTLSSystemTest,VerifyStoreWithoutSetupFails)563 TEST_F(BasePThreadTLSSystemTest, VerifyStoreWithoutSetupFails) {
564   internal::PThreadTLSSystem sut;
565 
566   EXPECT_FALSE(sut.SetThreadSpecificData(this));
567 }
568 #endif
569 
570 #if defined(GTEST_HAS_DEATH_TEST) && DCHECK_IS_ON()
571 struct BasePThreadTLSSystemDeathTest : public ::testing::Test {};
572 
TEST_F(BasePThreadTLSSystemDeathTest,VerifyDeathIfSetupTwice)573 TEST_F(BasePThreadTLSSystemDeathTest, VerifyDeathIfSetupTwice) {
574   internal::PThreadTLSSystem sut;
575 
576   EXPECT_TRUE(sut.Setup(nullptr));
577   EXPECT_DEATH(sut.Setup(nullptr), "");
578 }
579 
TEST_F(BasePThreadTLSSystemDeathTest,VerifyDeathIfTearDownWithoutSetup)580 TEST_F(BasePThreadTLSSystemDeathTest, VerifyDeathIfTearDownWithoutSetup) {
581   internal::PThreadTLSSystem sut;
582 
583   EXPECT_DEATH(sut.TearDownForTesting(), "");
584 }
585 #endif
586 }  // namespace base::allocator::dispatcher
587 
588 #endif  // USE_LOCAL_TLS_EMULATION()