1 // Copyright 2017 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/sequence_local_storage_map.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "testing/gtest/include/gtest/gtest.h"
11 
12 namespace base {
13 namespace internal {
14 
15 namespace {
16 
17 constexpr int kSlotId = 1;
18 
19 class SetOnDestroy {
20  public:
SetOnDestroy(bool * was_destroyed_ptr)21   SetOnDestroy(bool* was_destroyed_ptr)
22       : was_destroyed_ptr_(was_destroyed_ptr) {
23     DCHECK(was_destroyed_ptr_);
24     DCHECK(!(*was_destroyed_ptr_));
25   }
~SetOnDestroy()26   ~SetOnDestroy() {
27     DCHECK(!(*was_destroyed_ptr_));
28     *was_destroyed_ptr_ = true;
29   }
30 
31  private:
32   bool* const was_destroyed_ptr_;
33 
34   DISALLOW_COPY_AND_ASSIGN(SetOnDestroy);
35 };
36 
37 template <typename T, typename... Args>
CreateValueDestructorPair(Args...args)38 SequenceLocalStorageMap::ValueDestructorPair CreateValueDestructorPair(
39     Args... args) {
40   T* value = new T(args...);
41   SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc* destructor =
42       [](void* ptr) { std::default_delete<T>()(static_cast<T*>(ptr)); };
43 
44   SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair{
45       value, destructor};
46 
47   return value_destructor_pair;
48 }
49 
50 }  // namespace
51 
52 // Verify that setting a value in the SequenceLocalStorageMap, then getting
53 // it will yield the same value.
TEST(SequenceLocalStorageMapTest,SetGet)54 TEST(SequenceLocalStorageMapTest, SetGet) {
55   SequenceLocalStorageMap sequence_local_storage_map;
56   ScopedSetSequenceLocalStorageMapForCurrentThread
57       scoped_sequence_local_storage_map(&sequence_local_storage_map);
58 
59   SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
60       CreateValueDestructorPair<int>(5);
61 
62   sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
63 
64   EXPECT_EQ(*static_cast<int*>(sequence_local_storage_map.Get(kSlotId)), 5);
65 }
66 
67 // Verify that the destructor is called on a value stored in the
68 // SequenceLocalStorageMap when SequenceLocalStorageMap is destroyed.
TEST(SequenceLocalStorageMapTest,Destructor)69 TEST(SequenceLocalStorageMapTest, Destructor) {
70   bool set_on_destruction = false;
71 
72   {
73     SequenceLocalStorageMap sequence_local_storage_map;
74     ScopedSetSequenceLocalStorageMapForCurrentThread
75         scoped_sequence_local_storage_map(&sequence_local_storage_map);
76 
77     SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
78         CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
79 
80     sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
81   }
82 
83   EXPECT_TRUE(set_on_destruction);
84 }
85 
86 // Verify that overwriting a value already in the SequenceLocalStorageMap
87 // calls value's destructor.
TEST(SequenceLocalStorageMapTest,DestructorCalledOnSetOverwrite)88 TEST(SequenceLocalStorageMapTest, DestructorCalledOnSetOverwrite) {
89   bool set_on_destruction = false;
90   bool set_on_destruction2 = false;
91   {
92     SequenceLocalStorageMap sequence_local_storage_map;
93     ScopedSetSequenceLocalStorageMapForCurrentThread
94         scoped_sequence_local_storage_map(&sequence_local_storage_map);
95 
96     SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
97         CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
98     SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair2 =
99         CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction2);
100 
101     sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
102 
103     ASSERT_FALSE(set_on_destruction);
104 
105     // Overwrites the old value in the slot.
106     sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair2));
107 
108     // Destructor should've been called for the old value in the slot, and not
109     // yet called for the new value.
110     EXPECT_TRUE(set_on_destruction);
111     EXPECT_FALSE(set_on_destruction2);
112   }
113   EXPECT_TRUE(set_on_destruction2);
114 }
115 
116 }  // namespace internal
117 }  // namespace base
118