1 // Copyright 2014 the V8 project 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 <limits.h>
6 
7 #include "src/atomic-utils.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace v8 {
11 namespace internal {
12 
TEST(AtomicNumber,Constructor)13 TEST(AtomicNumber, Constructor) {
14   // Test some common types.
15   AtomicNumber<int> zero_int;
16   AtomicNumber<size_t> zero_size_t;
17   AtomicNumber<intptr_t> zero_intptr_t;
18   EXPECT_EQ(0, zero_int.Value());
19   EXPECT_EQ(0U, zero_size_t.Value());
20   EXPECT_EQ(0, zero_intptr_t.Value());
21 }
22 
23 
TEST(AtomicNumber,Value)24 TEST(AtomicNumber, Value) {
25   AtomicNumber<int> a(1);
26   EXPECT_EQ(1, a.Value());
27   AtomicNumber<int> b(-1);
28   EXPECT_EQ(-1, b.Value());
29   AtomicNumber<size_t> c(1);
30   EXPECT_EQ(1U, c.Value());
31   AtomicNumber<size_t> d(static_cast<size_t>(-1));
32   EXPECT_EQ(std::numeric_limits<size_t>::max(), d.Value());
33 }
34 
35 
TEST(AtomicNumber,SetValue)36 TEST(AtomicNumber, SetValue) {
37   AtomicNumber<int> a(1);
38   a.SetValue(-1);
39   EXPECT_EQ(-1, a.Value());
40 }
41 
42 
TEST(AtomicNumber,Increment)43 TEST(AtomicNumber, Increment) {
44   AtomicNumber<int> a(std::numeric_limits<int>::max());
45   a.Increment(1);
46   EXPECT_EQ(std::numeric_limits<int>::min(), a.Value());
47   // Check that potential signed-ness of the underlying storage has no impact
48   // on unsigned types.
49   AtomicNumber<size_t> b(std::numeric_limits<intptr_t>::max());
50   b.Increment(1);
51   EXPECT_EQ(static_cast<size_t>(std::numeric_limits<intptr_t>::max()) + 1,
52             b.Value());
53   // Should work as decrement as well.
54   AtomicNumber<size_t> c(1);
55   c.Increment(-1);
56   EXPECT_EQ(0U, c.Value());
57   c.Increment(-1);
58   EXPECT_EQ(std::numeric_limits<size_t>::max(), c.Value());
59 }
60 
61 
62 namespace {
63 
64 enum TestFlag {
65   kA,
66   kB,
67   kC,
68 };
69 
70 }  // namespace
71 
72 
TEST(AtomicValue,Initial)73 TEST(AtomicValue, Initial) {
74   AtomicValue<TestFlag> a(kA);
75   EXPECT_EQ(TestFlag::kA, a.Value());
76 }
77 
78 
TEST(AtomicValue,TrySetValue)79 TEST(AtomicValue, TrySetValue) {
80   AtomicValue<TestFlag> a(kA);
81   EXPECT_FALSE(a.TrySetValue(kB, kC));
82   EXPECT_TRUE(a.TrySetValue(kA, kC));
83   EXPECT_EQ(TestFlag::kC, a.Value());
84 }
85 
86 
TEST(AtomicValue,SetValue)87 TEST(AtomicValue, SetValue) {
88   AtomicValue<TestFlag> a(kB);
89   a.SetValue(kC);
90   EXPECT_EQ(TestFlag::kC, a.Value());
91 }
92 
93 
TEST(AtomicValue,WithVoidStar)94 TEST(AtomicValue, WithVoidStar) {
95   AtomicValue<void*> a(nullptr);
96   AtomicValue<void*> dummy(nullptr);
97   EXPECT_EQ(nullptr, a.Value());
98   a.SetValue(&a);
99   EXPECT_EQ(&a, a.Value());
100   EXPECT_FALSE(a.TrySetValue(nullptr, &dummy));
101   EXPECT_TRUE(a.TrySetValue(&a, &dummy));
102   EXPECT_EQ(&dummy, a.Value());
103 }
104 
105 
106 namespace {
107 
108 enum TestSetValue { kAA, kBB, kCC, kLastValue = kCC };
109 
110 }  // namespace
111 
112 
TEST(AtomicEnumSet,Constructor)113 TEST(AtomicEnumSet, Constructor) {
114   AtomicEnumSet<TestSetValue> a;
115   EXPECT_TRUE(a.IsEmpty());
116   EXPECT_FALSE(a.Contains(kAA));
117 }
118 
119 
TEST(AtomicEnumSet,AddSingle)120 TEST(AtomicEnumSet, AddSingle) {
121   AtomicEnumSet<TestSetValue> a;
122   a.Add(kAA);
123   EXPECT_FALSE(a.IsEmpty());
124   EXPECT_TRUE(a.Contains(kAA));
125   EXPECT_FALSE(a.Contains(kBB));
126   EXPECT_FALSE(a.Contains(kCC));
127 }
128 
129 
TEST(AtomicEnumSet,AddOtherSet)130 TEST(AtomicEnumSet, AddOtherSet) {
131   AtomicEnumSet<TestSetValue> a;
132   AtomicEnumSet<TestSetValue> b;
133   a.Add(kAA);
134   EXPECT_FALSE(a.IsEmpty());
135   EXPECT_TRUE(b.IsEmpty());
136   b.Add(a);
137   EXPECT_FALSE(b.IsEmpty());
138   EXPECT_TRUE(a.Contains(kAA));
139   EXPECT_TRUE(b.Contains(kAA));
140 }
141 
142 
TEST(AtomicEnumSet,RemoveSingle)143 TEST(AtomicEnumSet, RemoveSingle) {
144   AtomicEnumSet<TestSetValue> a;
145   a.Add(kAA);
146   a.Add(kBB);
147   EXPECT_TRUE(a.Contains(kAA));
148   EXPECT_TRUE(a.Contains(kBB));
149   a.Remove(kAA);
150   EXPECT_FALSE(a.Contains(kAA));
151   EXPECT_TRUE(a.Contains(kBB));
152 }
153 
154 
TEST(AtomicEnumSet,RemoveOtherSet)155 TEST(AtomicEnumSet, RemoveOtherSet) {
156   AtomicEnumSet<TestSetValue> a;
157   AtomicEnumSet<TestSetValue> b;
158   a.Add(kAA);
159   a.Add(kBB);
160   b.Add(kBB);
161   a.Remove(b);
162   EXPECT_TRUE(a.Contains(kAA));
163   EXPECT_FALSE(a.Contains(kBB));
164   EXPECT_FALSE(a.Contains(kCC));
165 }
166 
167 
TEST(AtomicEnumSet,RemoveEmptySet)168 TEST(AtomicEnumSet, RemoveEmptySet) {
169   AtomicEnumSet<TestSetValue> a;
170   AtomicEnumSet<TestSetValue> b;
171   a.Add(kAA);
172   a.Add(kBB);
173   EXPECT_TRUE(a.Contains(kAA));
174   EXPECT_TRUE(a.Contains(kBB));
175   EXPECT_FALSE(a.Contains(kCC));
176   EXPECT_TRUE(b.IsEmpty());
177   a.Remove(b);
178   EXPECT_TRUE(a.Contains(kAA));
179   EXPECT_TRUE(a.Contains(kBB));
180   EXPECT_FALSE(a.Contains(kCC));
181 }
182 
183 
TEST(AtomicEnumSet,Intersect)184 TEST(AtomicEnumSet, Intersect) {
185   AtomicEnumSet<TestSetValue> a;
186   AtomicEnumSet<TestSetValue> b;
187   a.Add(kAA);
188   b.Add(kCC);
189   a.Intersect(b);
190   EXPECT_TRUE(a.IsEmpty());
191 }
192 
193 
TEST(AtomicEnumSet,ContainsAnyOf)194 TEST(AtomicEnumSet, ContainsAnyOf) {
195   AtomicEnumSet<TestSetValue> a;
196   AtomicEnumSet<TestSetValue> b;
197   a.Add(kAA);
198   b.Add(kCC);
199   EXPECT_FALSE(a.ContainsAnyOf(b));
200   b.Add(kAA);
201   EXPECT_TRUE(a.ContainsAnyOf(b));
202 }
203 
204 
TEST(AtomicEnumSet,Equality)205 TEST(AtomicEnumSet, Equality) {
206   AtomicEnumSet<TestSetValue> a;
207   AtomicEnumSet<TestSetValue> b;
208   a.Add(kAA);
209   EXPECT_FALSE(a == b);
210   EXPECT_TRUE(a != b);
211   b.Add(kAA);
212   EXPECT_TRUE(a == b);
213   EXPECT_FALSE(a != b);
214 }
215 
216 }  // namespace internal
217 }  // namespace v8
218