OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/crypto/strike_register.h" | 5 #include "net/quic/crypto/strike_register.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/basictypes.h" | |
11 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
13 | 12 |
14 namespace net { | 13 namespace net { |
15 | 14 |
16 namespace { | 15 namespace { |
17 | 16 |
18 using std::min; | 17 using std::min; |
19 using std::pair; | 18 using std::pair; |
20 using std::set; | 19 using std::set; |
21 using std::string; | 20 using std::string; |
22 | 21 |
23 const uint8 kOrbit[8] = {1, 2, 3, 4, 5, 6, 7, 8}; | 22 const uint8_t kOrbit[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
24 | 23 |
25 // StrikeRegisterTests don't look at the random bytes so this function can | 24 // StrikeRegisterTests don't look at the random bytes so this function can |
26 // simply set the random bytes to 0. | 25 // simply set the random bytes to 0. |
27 void SetNonce(uint8 nonce[32], unsigned time, const uint8 orbit[8]) { | 26 void SetNonce(uint8_t nonce[32], unsigned time, const uint8_t orbit[8]) { |
28 nonce[0] = time >> 24; | 27 nonce[0] = time >> 24; |
29 nonce[1] = time >> 16; | 28 nonce[1] = time >> 16; |
30 nonce[2] = time >> 8; | 29 nonce[2] = time >> 8; |
31 nonce[3] = time; | 30 nonce[3] = time; |
32 memcpy(nonce + 4, orbit, 8); | 31 memcpy(nonce + 4, orbit, 8); |
33 memset(nonce + 12, 0, 20); | 32 memset(nonce + 12, 0, 20); |
34 } | 33 } |
35 | 34 |
36 TEST(StrikeRegisterTest, SimpleHorizon) { | 35 TEST(StrikeRegisterTest, SimpleHorizon) { |
37 // The set must reject values created on or before its own creation time. | 36 // The set must reject values created on or before its own creation time. |
38 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 37 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
39 100 /* window secs */, kOrbit, | 38 100 /* window secs */, kOrbit, |
40 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 39 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
41 uint8 nonce[32]; | 40 uint8_t nonce[32]; |
42 SetNonce(nonce, 999, kOrbit); | 41 SetNonce(nonce, 999, kOrbit); |
43 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); | 42 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); |
44 SetNonce(nonce, 1000, kOrbit); | 43 SetNonce(nonce, 1000, kOrbit); |
45 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); | 44 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); |
46 | 45 |
47 EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1000 /* current time */)); | 46 EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1000 /* current time */)); |
48 EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1100 /* current time */)); | 47 EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1100 /* current time */)); |
49 EXPECT_EQ(1u, set.GetCurrentValidWindowSecs(1101 /* current time */)); | 48 EXPECT_EQ(1u, set.GetCurrentValidWindowSecs(1101 /* current time */)); |
50 EXPECT_EQ(50u, set.GetCurrentValidWindowSecs(1150 /* current time */)); | 49 EXPECT_EQ(50u, set.GetCurrentValidWindowSecs(1150 /* current time */)); |
51 EXPECT_EQ(100u, set.GetCurrentValidWindowSecs(1200 /* current time */)); | 50 EXPECT_EQ(100u, set.GetCurrentValidWindowSecs(1200 /* current time */)); |
52 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); | 51 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); |
53 } | 52 } |
54 | 53 |
55 TEST(StrikeRegisterTest, NoStartupMode) { | 54 TEST(StrikeRegisterTest, NoStartupMode) { |
56 // Check that a strike register works immediately if NO_STARTUP_PERIOD_NEEDED | 55 // Check that a strike register works immediately if NO_STARTUP_PERIOD_NEEDED |
57 // is specified. | 56 // is specified. |
58 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 57 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
59 100 /* window secs */, kOrbit, | 58 100 /* window secs */, kOrbit, |
60 StrikeRegister::NO_STARTUP_PERIOD_NEEDED); | 59 StrikeRegister::NO_STARTUP_PERIOD_NEEDED); |
61 uint8 nonce[32]; | 60 uint8_t nonce[32]; |
62 SetNonce(nonce, 1000, kOrbit); | 61 SetNonce(nonce, 1000, kOrbit); |
63 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1000)); | 62 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1000)); |
64 EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1000)); | 63 EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1000)); |
65 | 64 |
66 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1000 /* current time */)); | 65 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1000 /* current time */)); |
67 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1050 /* current time */)); | 66 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1050 /* current time */)); |
68 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1100 /* current time */)); | 67 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1100 /* current time */)); |
69 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1200 /* current time */)); | 68 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1200 /* current time */)); |
70 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); | 69 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1300 /* current time */)); |
71 } | 70 } |
72 | 71 |
73 TEST(StrikeRegisterTest, WindowFuture) { | 72 TEST(StrikeRegisterTest, WindowFuture) { |
74 // The set must reject values outside the window. | 73 // The set must reject values outside the window. |
75 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 74 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
76 100 /* window secs */, kOrbit, | 75 100 /* window secs */, kOrbit, |
77 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 76 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
78 uint8 nonce[32]; | 77 uint8_t nonce[32]; |
79 SetNonce(nonce, 1101, kOrbit); | 78 SetNonce(nonce, 1101, kOrbit); |
80 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); | 79 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); |
81 SetNonce(nonce, 999, kOrbit); | 80 SetNonce(nonce, 999, kOrbit); |
82 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); | 81 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); |
83 } | 82 } |
84 | 83 |
85 TEST(StrikeRegisterTest, BadOrbit) { | 84 TEST(StrikeRegisterTest, BadOrbit) { |
86 // The set must reject values with the wrong orbit | 85 // The set must reject values with the wrong orbit |
87 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 86 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
88 100 /* window secs */, kOrbit, | 87 100 /* window secs */, kOrbit, |
89 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 88 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
90 uint8 nonce[32]; | 89 uint8_t nonce[32]; |
91 static const uint8 kBadOrbit[8] = {0, 0, 0, 0, 1, 1, 1, 1}; | 90 static const uint8_t kBadOrbit[8] = {0, 0, 0, 0, 1, 1, 1, 1}; |
92 SetNonce(nonce, 1101, kBadOrbit); | 91 SetNonce(nonce, 1101, kBadOrbit); |
93 EXPECT_EQ(NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100)); | 92 EXPECT_EQ(NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100)); |
94 } | 93 } |
95 | 94 |
96 TEST(StrikeRegisterTest, OneValue) { | 95 TEST(StrikeRegisterTest, OneValue) { |
97 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 96 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
98 100 /* window secs */, kOrbit, | 97 100 /* window secs */, kOrbit, |
99 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 98 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
100 uint8 nonce[32]; | 99 uint8_t nonce[32]; |
101 SetNonce(nonce, 1101, kOrbit); | 100 SetNonce(nonce, 1101, kOrbit); |
102 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); | 101 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); |
103 } | 102 } |
104 | 103 |
105 TEST(StrikeRegisterTest, RejectDuplicate) { | 104 TEST(StrikeRegisterTest, RejectDuplicate) { |
106 // The set must reject values with the wrong orbit | 105 // The set must reject values with the wrong orbit |
107 StrikeRegister set(10 /* max size */, 1000 /* current time */, | 106 StrikeRegister set(10 /* max size */, 1000 /* current time */, |
108 100 /* window secs */, kOrbit, | 107 100 /* window secs */, kOrbit, |
109 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 108 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
110 uint8 nonce[32]; | 109 uint8_t nonce[32]; |
111 SetNonce(nonce, 1101, kOrbit); | 110 SetNonce(nonce, 1101, kOrbit); |
112 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); | 111 EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); |
113 EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101)); | 112 EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101)); |
114 } | 113 } |
115 | 114 |
116 TEST(StrikeRegisterTest, HorizonUpdating) { | 115 TEST(StrikeRegisterTest, HorizonUpdating) { |
117 StrikeRegister::StartupType startup_types[] = { | 116 StrikeRegister::StartupType startup_types[] = { |
118 StrikeRegister::DENY_REQUESTS_AT_STARTUP, | 117 StrikeRegister::DENY_REQUESTS_AT_STARTUP, |
119 StrikeRegister::NO_STARTUP_PERIOD_NEEDED}; | 118 StrikeRegister::NO_STARTUP_PERIOD_NEEDED}; |
120 | 119 |
121 for (size_t type_idx = 0; type_idx < arraysize(startup_types); ++type_idx) { | 120 for (size_t type_idx = 0; type_idx < arraysize(startup_types); ++type_idx) { |
122 StrikeRegister set(5 /* max size */, 500 /* current time */, | 121 StrikeRegister set(5 /* max size */, 500 /* current time */, |
123 100 /* window secs */, kOrbit, startup_types[type_idx]); | 122 100 /* window secs */, kOrbit, startup_types[type_idx]); |
124 uint8 nonce[6][32]; | 123 uint8_t nonce[6][32]; |
125 for (unsigned i = 0; i < 5; i++) { | 124 for (unsigned i = 0; i < 5; i++) { |
126 SetNonce(nonce[i], 1101 + i, kOrbit); | 125 SetNonce(nonce[i], 1101 + i, kOrbit); |
127 nonce[i][31] = i; | 126 nonce[i][31] = i; |
128 EXPECT_EQ(NONCE_OK, set.Insert(nonce[i], 1100)); | 127 EXPECT_EQ(NONCE_OK, set.Insert(nonce[i], 1100)); |
129 } | 128 } |
130 | 129 |
131 // Valid window is still equal to |window_secs + 1|. | 130 // Valid window is still equal to |window_secs + 1|. |
132 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1100)); | 131 EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1100)); |
133 | 132 |
134 // This should push the oldest value out and force the horizon to | 133 // This should push the oldest value out and force the horizon to |
(...skipping 28 matching lines...) Expand all Loading... |
163 nonce[5][31] = 2; | 162 nonce[5][31] = 2; |
164 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); | 163 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); |
165 } | 164 } |
166 } | 165 } |
167 | 166 |
168 TEST(StrikeRegisterTest, InsertMany) { | 167 TEST(StrikeRegisterTest, InsertMany) { |
169 StrikeRegister set(5000 /* max size */, 1000 /* current time */, | 168 StrikeRegister set(5000 /* max size */, 1000 /* current time */, |
170 500 /* window secs */, kOrbit, | 169 500 /* window secs */, kOrbit, |
171 StrikeRegister::DENY_REQUESTS_AT_STARTUP); | 170 StrikeRegister::DENY_REQUESTS_AT_STARTUP); |
172 | 171 |
173 uint8 nonce[32]; | 172 uint8_t nonce[32]; |
174 SetNonce(nonce, 1101, kOrbit); | 173 SetNonce(nonce, 1101, kOrbit); |
175 for (unsigned i = 0; i < 100000; i++) { | 174 for (unsigned i = 0; i < 100000; i++) { |
176 SetNonce(nonce, 1101 + i / 500, kOrbit); | 175 SetNonce(nonce, 1101 + i / 500, kOrbit); |
177 memcpy(nonce + 12, &i, sizeof(i)); | 176 memcpy(nonce + 12, &i, sizeof(i)); |
178 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); | 177 EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); |
179 } | 178 } |
180 } | 179 } |
181 | 180 |
182 // For the following test we create a slow, but simple, version of a | 181 // For the following test we create a slow, but simple, version of a |
183 // StrikeRegister. The behaviour of this object is much easier to understand | 182 // StrikeRegister. The behaviour of this object is much easier to understand |
184 // than the fully fledged version. We then create a test to show, empirically, | 183 // than the fully fledged version. We then create a test to show, empirically, |
185 // that the two objects have identical behaviour. | 184 // that the two objects have identical behaviour. |
186 | 185 |
187 // A SlowStrikeRegister has the same public interface as a StrikeRegister, but | 186 // A SlowStrikeRegister has the same public interface as a StrikeRegister, but |
188 // is much slower. Hopefully it is also more obviously correct and we can | 187 // is much slower. Hopefully it is also more obviously correct and we can |
189 // empirically test that their behaviours are identical. | 188 // empirically test that their behaviours are identical. |
190 class SlowStrikeRegister { | 189 class SlowStrikeRegister { |
191 public: | 190 public: |
192 SlowStrikeRegister(unsigned max_entries, | 191 SlowStrikeRegister(unsigned max_entries, |
193 uint32 current_time, | 192 uint32_t current_time, |
194 uint32 window_secs, | 193 uint32_t window_secs, |
195 const uint8 orbit[8]) | 194 const uint8_t orbit[8]) |
196 : max_entries_(max_entries), | 195 : max_entries_(max_entries), |
197 window_secs_(window_secs), | 196 window_secs_(window_secs), |
198 creation_time_(current_time), | 197 creation_time_(current_time), |
199 horizon_(ExternalTimeToInternal(current_time + window_secs) + 1) { | 198 horizon_(ExternalTimeToInternal(current_time + window_secs) + 1) { |
200 memcpy(orbit_, orbit, sizeof(orbit_)); | 199 memcpy(orbit_, orbit, sizeof(orbit_)); |
201 } | 200 } |
202 | 201 |
203 InsertStatus Insert(const uint8 nonce_bytes[32], | 202 InsertStatus Insert(const uint8_t nonce_bytes[32], |
204 const uint32 nonce_time_external, | 203 const uint32_t nonce_time_external, |
205 const uint32 current_time_external) { | 204 const uint32_t current_time_external) { |
206 if (nonces_.size() == max_entries_) { | 205 if (nonces_.size() == max_entries_) { |
207 DropOldestEntry(); | 206 DropOldestEntry(); |
208 } | 207 } |
209 | 208 |
210 const uint32 current_time = ExternalTimeToInternal(current_time_external); | 209 const uint32_t current_time = ExternalTimeToInternal(current_time_external); |
211 | 210 |
212 // Check to see if the orbit is correct. | 211 // Check to see if the orbit is correct. |
213 if (memcmp(nonce_bytes + 4, orbit_, sizeof(orbit_))) { | 212 if (memcmp(nonce_bytes + 4, orbit_, sizeof(orbit_))) { |
214 return NONCE_INVALID_ORBIT_FAILURE; | 213 return NONCE_INVALID_ORBIT_FAILURE; |
215 } | 214 } |
216 const uint32 nonce_time = | 215 const uint32_t nonce_time = |
217 ExternalTimeToInternal(TimeFromBytes(nonce_bytes)); | 216 ExternalTimeToInternal(TimeFromBytes(nonce_bytes)); |
218 EXPECT_EQ(ExternalTimeToInternal(nonce_time_external), nonce_time); | 217 EXPECT_EQ(ExternalTimeToInternal(nonce_time_external), nonce_time); |
219 // We have dropped one or more nonces with a time value of |horizon_ - 1|, | 218 // We have dropped one or more nonces with a time value of |horizon_ - 1|, |
220 // so we have to reject anything with a timestamp less than or | 219 // so we have to reject anything with a timestamp less than or |
221 // equal to that. | 220 // equal to that. |
222 if (nonce_time < horizon_) { | 221 if (nonce_time < horizon_) { |
223 return NONCE_INVALID_TIME_FAILURE; | 222 return NONCE_INVALID_TIME_FAILURE; |
224 } | 223 } |
225 | 224 |
226 // Check that the timestamp is in the current window. | 225 // Check that the timestamp is in the current window. |
227 if ((current_time > window_secs_ && | 226 if ((current_time > window_secs_ && |
228 nonce_time < (current_time - window_secs_)) || | 227 nonce_time < (current_time - window_secs_)) || |
229 nonce_time > (current_time + window_secs_)) { | 228 nonce_time > (current_time + window_secs_)) { |
230 return NONCE_INVALID_TIME_FAILURE; | 229 return NONCE_INVALID_TIME_FAILURE; |
231 } | 230 } |
232 | 231 |
233 pair<uint32, string> nonce = std::make_pair( | 232 pair<uint32_t, string> nonce = std::make_pair( |
234 nonce_time, string(reinterpret_cast<const char*>(nonce_bytes), 32)); | 233 nonce_time, string(reinterpret_cast<const char*>(nonce_bytes), 32)); |
235 | 234 |
236 set<pair<uint32, string>>::const_iterator it = nonces_.find(nonce); | 235 set<pair<uint32_t, string>>::const_iterator it = nonces_.find(nonce); |
237 if (it != nonces_.end()) { | 236 if (it != nonces_.end()) { |
238 return NONCE_NOT_UNIQUE_FAILURE; | 237 return NONCE_NOT_UNIQUE_FAILURE; |
239 } | 238 } |
240 | 239 |
241 nonces_.insert(nonce); | 240 nonces_.insert(nonce); |
242 return NONCE_OK; | 241 return NONCE_OK; |
243 } | 242 } |
244 | 243 |
245 uint32 GetCurrentValidWindowSecs(const uint32 current_time_external) const { | 244 uint32_t GetCurrentValidWindowSecs( |
246 const uint32 current_time = ExternalTimeToInternal(current_time_external); | 245 const uint32_t current_time_external) const { |
| 246 const uint32_t current_time = ExternalTimeToInternal(current_time_external); |
247 if (horizon_ > current_time) { | 247 if (horizon_ > current_time) { |
248 return 0; | 248 return 0; |
249 } | 249 } |
250 return 1 + min(current_time - horizon_, window_secs_); | 250 return 1 + min(current_time - horizon_, window_secs_); |
251 } | 251 } |
252 | 252 |
253 private: | 253 private: |
254 // TimeFromBytes returns a big-endian uint32 from |d|. | 254 // TimeFromBytes returns a big-endian uint32_t from |d|. |
255 static uint32 TimeFromBytes(const uint8 d[4]) { | 255 static uint32_t TimeFromBytes(const uint8_t d[4]) { |
256 return static_cast<uint32>(d[0]) << 24 | static_cast<uint32>(d[1]) << 16 | | 256 return static_cast<uint32_t>(d[0]) << 24 | |
257 static_cast<uint32>(d[2]) << 8 | static_cast<uint32>(d[3]); | 257 static_cast<uint32_t>(d[1]) << 16 | |
| 258 static_cast<uint32_t>(d[2]) << 8 | static_cast<uint32_t>(d[3]); |
258 } | 259 } |
259 | 260 |
260 uint32 ExternalTimeToInternal(uint32 external_time) const { | 261 uint32_t ExternalTimeToInternal(uint32_t external_time) const { |
261 static const uint32 kCreationTimeFromInternalEpoch = 63115200.0; | 262 static const uint32_t kCreationTimeFromInternalEpoch = 63115200.0; |
262 uint32 internal_epoch = 0; | 263 uint32_t internal_epoch = 0; |
263 if (creation_time_ > kCreationTimeFromInternalEpoch) { | 264 if (creation_time_ > kCreationTimeFromInternalEpoch) { |
264 internal_epoch = creation_time_ - kCreationTimeFromInternalEpoch; | 265 internal_epoch = creation_time_ - kCreationTimeFromInternalEpoch; |
265 } | 266 } |
266 | 267 |
267 return external_time - internal_epoch; | 268 return external_time - internal_epoch; |
268 } | 269 } |
269 | 270 |
270 void DropOldestEntry() { | 271 void DropOldestEntry() { |
271 set<pair<uint32, string>>::iterator oldest = nonces_.begin(); | 272 set<pair<uint32_t, string>>::iterator oldest = nonces_.begin(); |
272 horizon_ = oldest->first + 1; | 273 horizon_ = oldest->first + 1; |
273 nonces_.erase(oldest); | 274 nonces_.erase(oldest); |
274 } | 275 } |
275 | 276 |
276 const unsigned max_entries_; | 277 const unsigned max_entries_; |
277 const unsigned window_secs_; | 278 const unsigned window_secs_; |
278 const uint32 creation_time_; | 279 const uint32_t creation_time_; |
279 uint8 orbit_[8]; | 280 uint8_t orbit_[8]; |
280 uint32 horizon_; | 281 uint32_t horizon_; |
281 | 282 |
282 set<pair<uint32, string>> nonces_; | 283 set<pair<uint32_t, string>> nonces_; |
283 }; | 284 }; |
284 | 285 |
285 class StrikeRegisterStressTest : public ::testing::Test {}; | 286 class StrikeRegisterStressTest : public ::testing::Test {}; |
286 | 287 |
287 TEST_F(StrikeRegisterStressTest, InOrderInsertion) { | 288 TEST_F(StrikeRegisterStressTest, InOrderInsertion) { |
288 // Fixed seed gives reproducibility for this test. | 289 // Fixed seed gives reproducibility for this test. |
289 srand(42); | 290 srand(42); |
290 | 291 |
291 unsigned max_entries = 64; | 292 unsigned max_entries = 64; |
292 uint32 current_time = 10000, window = 200; | 293 uint32_t current_time = 10000, window = 200; |
293 scoped_ptr<StrikeRegister> s1( | 294 scoped_ptr<StrikeRegister> s1( |
294 new StrikeRegister(max_entries, current_time, window, kOrbit, | 295 new StrikeRegister(max_entries, current_time, window, kOrbit, |
295 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); | 296 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); |
296 scoped_ptr<SlowStrikeRegister> s2( | 297 scoped_ptr<SlowStrikeRegister> s2( |
297 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); | 298 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); |
298 | 299 |
299 uint64 i; | 300 uint64_t i; |
300 const uint64 kMaxIterations = 10000; | 301 const uint64_t kMaxIterations = 10000; |
301 for (i = 0; i < kMaxIterations; i++) { | 302 for (i = 0; i < kMaxIterations; i++) { |
302 const uint32 time = current_time + i; | 303 const uint32_t time = current_time + i; |
303 | 304 |
304 uint8 nonce[32]; | 305 uint8_t nonce[32]; |
305 SetNonce(nonce, time, kOrbit); | 306 SetNonce(nonce, time, kOrbit); |
306 | 307 |
307 // There are 2048 possible nonce values: | 308 // There are 2048 possible nonce values: |
308 const uint32 v = rand() % 2048; | 309 const uint32_t v = rand() % 2048; |
309 nonce[30] = v >> 8; | 310 nonce[30] = v >> 8; |
310 nonce[31] = v; | 311 nonce[31] = v; |
311 | 312 |
312 const InsertStatus nonce_error2 = s2->Insert(nonce, time, time); | 313 const InsertStatus nonce_error2 = s2->Insert(nonce, time, time); |
313 const InsertStatus nonce_error1 = s1->Insert(nonce, time); | 314 const InsertStatus nonce_error1 = s1->Insert(nonce, time); |
314 EXPECT_EQ(nonce_error1, nonce_error2); | 315 EXPECT_EQ(nonce_error1, nonce_error2); |
315 | 316 |
316 // Inserts succeed after the startup period. | 317 // Inserts succeed after the startup period. |
317 if (time > current_time + window) { | 318 if (time > current_time + window) { |
318 EXPECT_EQ(NONCE_OK, nonce_error1); | 319 EXPECT_EQ(NONCE_OK, nonce_error1); |
(...skipping 14 matching lines...) Expand all Loading... |
333 | 334 |
334 if (i != kMaxIterations) { | 335 if (i != kMaxIterations) { |
335 FAIL() << "Failed after " << i << " iterations"; | 336 FAIL() << "Failed after " << i << " iterations"; |
336 } | 337 } |
337 } | 338 } |
338 | 339 |
339 TEST_F(StrikeRegisterStressTest, Stress) { | 340 TEST_F(StrikeRegisterStressTest, Stress) { |
340 // Fixed seed gives reproducibility for this test. | 341 // Fixed seed gives reproducibility for this test. |
341 srand(42); | 342 srand(42); |
342 unsigned max_entries = 64; | 343 unsigned max_entries = 64; |
343 uint32 current_time = 10000, window = 200; | 344 uint32_t current_time = 10000, window = 200; |
344 scoped_ptr<StrikeRegister> s1( | 345 scoped_ptr<StrikeRegister> s1( |
345 new StrikeRegister(max_entries, current_time, window, kOrbit, | 346 new StrikeRegister(max_entries, current_time, window, kOrbit, |
346 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); | 347 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); |
347 scoped_ptr<SlowStrikeRegister> s2( | 348 scoped_ptr<SlowStrikeRegister> s2( |
348 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); | 349 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); |
349 uint64 i; | 350 uint64_t i; |
350 | 351 |
351 // When making changes it's worth removing the limit on this test and running | 352 // When making changes it's worth removing the limit on this test and running |
352 // it for a while. For the initial development an opt binary was left running | 353 // it for a while. For the initial development an opt binary was left running |
353 // for 10 minutes. | 354 // for 10 minutes. |
354 const uint64 kMaxIterations = 10000; | 355 const uint64_t kMaxIterations = 10000; |
355 for (i = 0; i < kMaxIterations; i++) { | 356 for (i = 0; i < kMaxIterations; i++) { |
356 if (rand() % 1000 == 0) { | 357 if (rand() % 1000 == 0) { |
357 // 0.1% chance of resetting the sets. | 358 // 0.1% chance of resetting the sets. |
358 max_entries = rand() % 300 + 2; | 359 max_entries = rand() % 300 + 2; |
359 current_time = rand() % 10000; | 360 current_time = rand() % 10000; |
360 window = rand() % 500; | 361 window = rand() % 500; |
361 s1.reset(new StrikeRegister(max_entries, current_time, window, kOrbit, | 362 s1.reset(new StrikeRegister(max_entries, current_time, window, kOrbit, |
362 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); | 363 StrikeRegister::DENY_REQUESTS_AT_STARTUP)); |
363 s2.reset( | 364 s2.reset( |
364 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); | 365 new SlowStrikeRegister(max_entries, current_time, window, kOrbit)); |
365 } | 366 } |
366 | 367 |
367 int32 time_delta = rand() % (window * 4); | 368 int32_t time_delta = rand() % (window * 4); |
368 time_delta -= window * 2; | 369 time_delta -= window * 2; |
369 const uint32 time = current_time + time_delta; | 370 const uint32_t time = current_time + time_delta; |
370 if (time_delta < 0 && time > current_time) { | 371 if (time_delta < 0 && time > current_time) { |
371 continue; // overflow | 372 continue; // overflow |
372 } | 373 } |
373 | 374 |
374 uint8 nonce[32]; | 375 uint8_t nonce[32]; |
375 SetNonce(nonce, time, kOrbit); | 376 SetNonce(nonce, time, kOrbit); |
376 | 377 |
377 // There are 2048 possible nonce values: | 378 // There are 2048 possible nonce values: |
378 const uint32 v = rand() % 2048; | 379 const uint32_t v = rand() % 2048; |
379 nonce[30] = v >> 8; | 380 nonce[30] = v >> 8; |
380 nonce[31] = v; | 381 nonce[31] = v; |
381 | 382 |
382 const InsertStatus nonce_error2 = s2->Insert(nonce, time, time); | 383 const InsertStatus nonce_error2 = s2->Insert(nonce, time, time); |
383 const InsertStatus nonce_error1 = s1->Insert(nonce, time); | 384 const InsertStatus nonce_error1 = s1->Insert(nonce, time); |
384 EXPECT_EQ(nonce_error1, nonce_error2); | 385 EXPECT_EQ(nonce_error1, nonce_error2); |
385 EXPECT_EQ(s1->GetCurrentValidWindowSecs(time), | 386 EXPECT_EQ(s1->GetCurrentValidWindowSecs(time), |
386 s2->GetCurrentValidWindowSecs(time)); | 387 s2->GetCurrentValidWindowSecs(time)); |
387 | 388 |
388 if (i % 10 == 0) { | 389 if (i % 10 == 0) { |
389 s1->Validate(); | 390 s1->Validate(); |
390 } | 391 } |
391 | 392 |
392 if (HasFailure()) { | 393 if (HasFailure()) { |
393 break; | 394 break; |
394 } | 395 } |
395 } | 396 } |
396 | 397 |
397 if (i != kMaxIterations) { | 398 if (i != kMaxIterations) { |
398 FAIL() << "Failed after " << i << " iterations"; | 399 FAIL() << "Failed after " << i << " iterations"; |
399 } | 400 } |
400 } | 401 } |
401 | 402 |
402 } // namespace | 403 } // namespace |
403 | 404 |
404 } // namespace net | 405 } // namespace net |
OLD | NEW |