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