• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_slot.h"
6 
7 #include <utility>
8 
9 #include "base/macros.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/threading/sequence_local_storage_map.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 
16 namespace {
17 
18 class SequenceLocalStorageSlotTest : public testing::Test {
19  protected:
SequenceLocalStorageSlotTest()20   SequenceLocalStorageSlotTest()
21       : scoped_sequence_local_storage_(&sequence_local_storage_) {}
22 
23   internal::SequenceLocalStorageMap sequence_local_storage_;
24   internal::ScopedSetSequenceLocalStorageMapForCurrentThread
25       scoped_sequence_local_storage_;
26 
27  private:
28   DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlotTest);
29 };
30 
31 }  // namespace
32 
33 // Verify that a value stored with Set() can be retrieved with Get().
TEST_F(SequenceLocalStorageSlotTest,GetSet)34 TEST_F(SequenceLocalStorageSlotTest, GetSet) {
35   SequenceLocalStorageSlot<int> slot;
36   slot.Set(5);
37   EXPECT_EQ(slot.Get(), 5);
38 }
39 
40 // Verify that setting an object in a SequenceLocalStorageSlot creates a copy
41 // of that object independent of the original one.
TEST_F(SequenceLocalStorageSlotTest,SetObjectIsIndependent)42 TEST_F(SequenceLocalStorageSlotTest, SetObjectIsIndependent) {
43   bool should_be_false = false;
44 
45   SequenceLocalStorageSlot<bool> slot;
46 
47   slot.Set(should_be_false);
48 
49   EXPECT_FALSE(slot.Get());
50   slot.Get() = true;
51   EXPECT_TRUE(slot.Get());
52 
53   EXPECT_NE(should_be_false, slot.Get());
54 }
55 
56 // Verify that multiple slots work and that calling Get after overwriting
57 // a value in a slot yields the new value.
TEST_F(SequenceLocalStorageSlotTest,GetSetMultipleSlots)58 TEST_F(SequenceLocalStorageSlotTest, GetSetMultipleSlots) {
59   SequenceLocalStorageSlot<int> slot1;
60   SequenceLocalStorageSlot<int> slot2;
61   SequenceLocalStorageSlot<int> slot3;
62 
63   slot1.Set(1);
64   slot2.Set(2);
65   slot3.Set(3);
66 
67   EXPECT_EQ(slot1.Get(), 1);
68   EXPECT_EQ(slot2.Get(), 2);
69   EXPECT_EQ(slot3.Get(), 3);
70 
71   slot3.Set(4);
72   slot2.Set(5);
73   slot1.Set(6);
74 
75   EXPECT_EQ(slot3.Get(), 4);
76   EXPECT_EQ(slot2.Get(), 5);
77   EXPECT_EQ(slot1.Get(), 6);
78 }
79 
80 // Verify that changing the the value returned by Get() changes the value
81 // in sequence local storage.
TEST_F(SequenceLocalStorageSlotTest,GetReferenceModifiable)82 TEST_F(SequenceLocalStorageSlotTest, GetReferenceModifiable) {
83   SequenceLocalStorageSlot<bool> slot;
84   slot.Set(false);
85   slot.Get() = true;
86   EXPECT_TRUE(slot.Get());
87 }
88 
89 // Verify that a move-only type can be stored in sequence local storage.
TEST_F(SequenceLocalStorageSlotTest,SetGetWithMoveOnlyType)90 TEST_F(SequenceLocalStorageSlotTest, SetGetWithMoveOnlyType) {
91   std::unique_ptr<int> int_unique_ptr = std::make_unique<int>(5);
92 
93   SequenceLocalStorageSlot<std::unique_ptr<int>> slot;
94   slot.Set(std::move(int_unique_ptr));
95 
96   EXPECT_EQ(*slot.Get(), 5);
97 }
98 
99 // Verify that a Get() without a previous Set() on a slot returns a
100 // default-constructed value.
TEST_F(SequenceLocalStorageSlotTest,GetWithoutSetDefaultConstructs)101 TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructs) {
102   struct DefaultConstructable {
103     int x = 0x12345678;
104   };
105 
106   SequenceLocalStorageSlot<DefaultConstructable> slot;
107 
108   EXPECT_EQ(slot.Get().x, 0x12345678);
109 }
110 
111 // Verify that a Get() without a previous Set() on a slot with a POD-type
112 // returns a default-constructed value.
113 // Note: this test could be flaky and give a false pass. If it's flaky, the test
114 // might've "passed" because the memory for the slot happened to be zeroed.
TEST_F(SequenceLocalStorageSlotTest,GetWithoutSetDefaultConstructsPOD)115 TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructsPOD) {
116   SequenceLocalStorageSlot<void*> slot;
117 
118   EXPECT_EQ(slot.Get(), nullptr);
119 }
120 
121 // Verify that the value of a slot is specific to a SequenceLocalStorageMap
TEST(SequenceLocalStorageSlotMultipleMapTest,SetGetMultipleMapsOneSlot)122 TEST(SequenceLocalStorageSlotMultipleMapTest, SetGetMultipleMapsOneSlot) {
123   SequenceLocalStorageSlot<unsigned int> slot;
124   internal::SequenceLocalStorageMap sequence_local_storage_maps[5];
125 
126   // Set the value of the slot to be the index of the current
127   // SequenceLocalStorageMaps in the vector
128   for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
129     internal::ScopedSetSequenceLocalStorageMapForCurrentThread
130         scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
131 
132     slot.Set(i);
133   }
134 
135   for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
136     internal::ScopedSetSequenceLocalStorageMapForCurrentThread
137         scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
138 
139     EXPECT_EQ(slot.Get(), i);
140   }
141 }
142 
143 }  // namespace base
144