• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Abseil Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/strings/internal/cordz_update_tracker.h"
16 
17 #include <array>
18 #include <thread>  // NOLINT
19 
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "absl/base/attributes.h"
23 #include "absl/base/config.h"
24 #include "absl/synchronization/notification.h"
25 
26 namespace absl {
27 ABSL_NAMESPACE_BEGIN
28 namespace cord_internal {
29 namespace {
30 
31 using ::testing::AnyOf;
32 using ::testing::Eq;
33 
34 using Method = CordzUpdateTracker::MethodIdentifier;
35 using Methods = std::array<Method, Method::kNumMethods>;
36 
37 // Returns an array of all methods defined in `MethodIdentifier`
AllMethods()38 Methods AllMethods() {
39   return Methods{Method::kUnknown,
40                  Method::kAppendCord,
41                  Method::kAppendExternalMemory,
42                  Method::kAppendString,
43                  Method::kAssignCord,
44                  Method::kAssignString,
45                  Method::kClear,
46                  Method::kConstructorCord,
47                  Method::kConstructorString,
48                  Method::kCordReader,
49                  Method::kFlatten,
50                  Method::kGetAppendRegion,
51                  Method::kMakeCordFromExternal,
52                  Method::kMoveAppendCord,
53                  Method::kMoveAssignCord,
54                  Method::kMovePrependCord,
55                  Method::kPrependCord,
56                  Method::kPrependString,
57                  Method::kRemovePrefix,
58                  Method::kRemoveSuffix,
59                  Method::kSubCord};
60 }
61 
TEST(CordzUpdateTracker,IsConstExprAndInitializesToZero)62 TEST(CordzUpdateTracker, IsConstExprAndInitializesToZero) {
63   constexpr CordzUpdateTracker tracker;
64   for (Method method : AllMethods()) {
65     ASSERT_THAT(tracker.Value(method), Eq(0));
66   }
67 }
68 
TEST(CordzUpdateTracker,LossyAdd)69 TEST(CordzUpdateTracker, LossyAdd) {
70   int64_t n = 1;
71   CordzUpdateTracker tracker;
72   for (Method method : AllMethods()) {
73     tracker.LossyAdd(method, n);
74     EXPECT_THAT(tracker.Value(method), Eq(n));
75     n += 2;
76   }
77 }
78 
TEST(CordzUpdateTracker,CopyConstructor)79 TEST(CordzUpdateTracker, CopyConstructor) {
80   int64_t n = 1;
81   CordzUpdateTracker src;
82   for (Method method : AllMethods()) {
83     src.LossyAdd(method, n);
84     n += 2;
85   }
86 
87   n = 1;
88   CordzUpdateTracker tracker(src);
89   for (Method method : AllMethods()) {
90     EXPECT_THAT(tracker.Value(method), Eq(n));
91     n += 2;
92   }
93 }
94 
TEST(CordzUpdateTracker,OperatorAssign)95 TEST(CordzUpdateTracker, OperatorAssign) {
96   int64_t n = 1;
97   CordzUpdateTracker src;
98   CordzUpdateTracker tracker;
99   for (Method method : AllMethods()) {
100     src.LossyAdd(method, n);
101     n += 2;
102   }
103 
104   n = 1;
105   tracker = src;
106   for (Method method : AllMethods()) {
107     EXPECT_THAT(tracker.Value(method), Eq(n));
108     n += 2;
109   }
110 }
111 
TEST(CordzUpdateTracker,ThreadSanitizedValueCheck)112 TEST(CordzUpdateTracker, ThreadSanitizedValueCheck) {
113   absl::Notification done;
114   CordzUpdateTracker tracker;
115 
116   std::thread reader([&done, &tracker] {
117     while (!done.HasBeenNotified()) {
118       int n = 1;
119       for (Method method : AllMethods()) {
120         EXPECT_THAT(tracker.Value(method), AnyOf(Eq(n), Eq(0)));
121         n += 2;
122       }
123     }
124     int n = 1;
125     for (Method method : AllMethods()) {
126       EXPECT_THAT(tracker.Value(method), Eq(n));
127       n += 2;
128     }
129   });
130 
131   int64_t n = 1;
132   for (Method method : AllMethods()) {
133     tracker.LossyAdd(method, n);
134     n += 2;
135   }
136   done.Notify();
137   reader.join();
138 }
139 
140 }  // namespace
141 }  // namespace cord_internal
142 ABSL_NAMESPACE_END
143 }  // namespace absl
144