OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "net/quic/crypto/quic_crypto_server_config.h" | |
6 | |
7 #include <stdarg.h> | |
8 | |
9 #include <memory> | |
10 | |
11 #include "base/stl_util.h" | |
12 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" | |
13 #include "net/quic/crypto/cert_compressor.h" | |
14 #include "net/quic/crypto/chacha20_poly1305_encrypter.h" | |
15 #include "net/quic/crypto/crypto_handshake_message.h" | |
16 #include "net/quic/crypto/crypto_secret_boxer.h" | |
17 #include "net/quic/crypto/crypto_server_config_protobuf.h" | |
18 #include "net/quic/crypto/quic_random.h" | |
19 #include "net/quic/crypto/strike_register_client.h" | |
20 #include "net/quic/quic_flags.h" | |
21 #include "net/quic/quic_time.h" | |
22 #include "net/quic/test_tools/crypto_test_utils.h" | |
23 #include "net/quic/test_tools/mock_clock.h" | |
24 #include "net/quic/test_tools/quic_crypto_server_config_peer.h" | |
25 #include "net/quic/test_tools/quic_test_utils.h" | |
26 #include "testing/gmock/include/gmock/gmock.h" | |
27 #include "testing/gtest/include/gtest/gtest.h" | |
28 | |
29 using base::StringPiece; | |
30 using std::map; | |
31 using std::pair; | |
32 using std::string; | |
33 using std::vector; | |
34 | |
35 namespace net { | |
36 namespace test { | |
37 | |
38 class TestStrikeRegisterClient : public StrikeRegisterClient { | |
39 public: | |
40 explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config) | |
41 : config_(config), is_known_orbit_called_(false) {} | |
42 | |
43 bool IsKnownOrbit(StringPiece orbit) const override { | |
44 // Ensure that the strike register client lock is not held. | |
45 QuicCryptoServerConfigPeer peer(config_); | |
46 base::Lock* m = peer.GetStrikeRegisterClientLock(); | |
47 // In Chromium, we will dead lock if the lock is held by the current thread. | |
48 // Chromium doesn't have AssertNotHeld API call. | |
49 // m->AssertNotHeld(); | |
50 base::AutoLock lock(*m); | |
51 | |
52 is_known_orbit_called_ = true; | |
53 return true; | |
54 } | |
55 | |
56 void VerifyNonceIsValidAndUnique(StringPiece nonce, | |
57 QuicWallTime now, | |
58 ResultCallback* cb) override { | |
59 LOG(FATAL) << "Not implemented"; | |
60 } | |
61 | |
62 bool is_known_orbit_called() { return is_known_orbit_called_; } | |
63 | |
64 private: | |
65 QuicCryptoServerConfig* config_; | |
66 mutable bool is_known_orbit_called_; | |
67 }; | |
68 | |
69 TEST(QuicCryptoServerConfigTest, ServerConfig) { | |
70 QuicRandom* rand = QuicRandom::GetInstance(); | |
71 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
72 CryptoTestUtils::ProofSourceForTesting()); | |
73 MockClock clock; | |
74 | |
75 std::unique_ptr<CryptoHandshakeMessage> message(server.AddDefaultConfig( | |
76 rand, &clock, QuicCryptoServerConfig::ConfigOptions())); | |
77 | |
78 // The default configuration should have AES-GCM and at least one ChaCha20 | |
79 // cipher. | |
80 const QuicTag* aead_tags; | |
81 size_t aead_len; | |
82 ASSERT_EQ(QUIC_NO_ERROR, message->GetTaglist(kAEAD, &aead_tags, &aead_len)); | |
83 vector<QuicTag> aead(aead_tags, aead_tags + aead_len); | |
84 EXPECT_THAT(aead, ::testing::Contains(kAESG)); | |
85 EXPECT_LE(1u, aead.size()); | |
86 } | |
87 | |
88 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) { | |
89 QuicRandom* rand = QuicRandom::GetInstance(); | |
90 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
91 CryptoTestUtils::ProofSourceForTesting()); | |
92 MockClock clock; | |
93 | |
94 TestStrikeRegisterClient* strike_register = | |
95 new TestStrikeRegisterClient(&server); | |
96 server.SetStrikeRegisterClient(strike_register); | |
97 | |
98 QuicCryptoServerConfig::ConfigOptions options; | |
99 std::unique_ptr<CryptoHandshakeMessage> message( | |
100 server.AddDefaultConfig(rand, &clock, options)); | |
101 EXPECT_TRUE(strike_register->is_known_orbit_called()); | |
102 } | |
103 | |
104 TEST(QuicCryptoServerConfigTest, CompressCerts) { | |
105 QuicCompressedCertsCache compressed_certs_cache( | |
106 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); | |
107 | |
108 QuicRandom* rand = QuicRandom::GetInstance(); | |
109 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
110 CryptoTestUtils::ProofSourceForTesting()); | |
111 QuicCryptoServerConfigPeer peer(&server); | |
112 | |
113 vector<string> certs = {"testcert"}; | |
114 scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs)); | |
115 | |
116 string compressed = QuicCryptoServerConfigPeer::CompressChain( | |
117 &compressed_certs_cache, chain, "", "", nullptr); | |
118 | |
119 EXPECT_EQ(compressed_certs_cache.Size(), 1u); | |
120 } | |
121 | |
122 TEST(QuicCryptoServerConfigTest, CompressSameCertsTwice) { | |
123 QuicCompressedCertsCache compressed_certs_cache( | |
124 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); | |
125 | |
126 QuicRandom* rand = QuicRandom::GetInstance(); | |
127 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
128 CryptoTestUtils::ProofSourceForTesting()); | |
129 QuicCryptoServerConfigPeer peer(&server); | |
130 | |
131 // Compress the certs for the first time. | |
132 vector<string> certs = {"testcert"}; | |
133 scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs)); | |
134 string common_certs = ""; | |
135 string cached_certs = ""; | |
136 | |
137 string compressed = QuicCryptoServerConfigPeer::CompressChain( | |
138 &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); | |
139 EXPECT_EQ(compressed_certs_cache.Size(), 1u); | |
140 | |
141 // Compress the same certs, should use cache if available. | |
142 string compressed2 = QuicCryptoServerConfigPeer::CompressChain( | |
143 &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); | |
144 EXPECT_EQ(compressed, compressed2); | |
145 EXPECT_EQ(compressed_certs_cache.Size(), 1u); | |
146 } | |
147 | |
148 TEST(QuicCryptoServerConfigTest, CompressDifferentCerts) { | |
149 // This test compresses a set of similar but not identical certs. Cache if | |
150 // used should return cache miss and add all the compressed certs. | |
151 QuicCompressedCertsCache compressed_certs_cache( | |
152 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize); | |
153 | |
154 QuicRandom* rand = QuicRandom::GetInstance(); | |
155 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
156 CryptoTestUtils::ProofSourceForTesting()); | |
157 QuicCryptoServerConfigPeer peer(&server); | |
158 | |
159 vector<string> certs = {"testcert"}; | |
160 scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs)); | |
161 string common_certs = ""; | |
162 string cached_certs = ""; | |
163 | |
164 string compressed = QuicCryptoServerConfigPeer::CompressChain( | |
165 &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); | |
166 EXPECT_EQ(compressed_certs_cache.Size(), 1u); | |
167 | |
168 // Compress a similar certs which only differs in the chain. | |
169 scoped_refptr<ProofSource::Chain> chain2(new ProofSource::Chain(certs)); | |
170 | |
171 string compressed2 = QuicCryptoServerConfigPeer::CompressChain( | |
172 &compressed_certs_cache, chain2, common_certs, cached_certs, nullptr); | |
173 EXPECT_EQ(compressed_certs_cache.Size(), 2u); | |
174 | |
175 // Compress a similar certs which only differs in common certs field. | |
176 static const uint64_t set_hash = 42; | |
177 std::unique_ptr<CommonCertSets> common_sets( | |
178 CryptoTestUtils::MockCommonCertSets(certs[0], set_hash, 1)); | |
179 StringPiece different_common_certs(reinterpret_cast<const char*>(&set_hash), | |
180 sizeof(set_hash)); | |
181 string compressed3 = QuicCryptoServerConfigPeer::CompressChain( | |
182 &compressed_certs_cache, chain, different_common_certs.as_string(), | |
183 cached_certs, common_sets.get()); | |
184 EXPECT_EQ(compressed_certs_cache.Size(), 3u); | |
185 } | |
186 | |
187 class SourceAddressTokenTest : public ::testing::Test { | |
188 public: | |
189 SourceAddressTokenTest() | |
190 : ip4_(Loopback4()), | |
191 ip4_dual_(ConvertIPv4ToIPv4MappedIPv6(ip4_)), | |
192 ip6_(Loopback6()), | |
193 original_time_(QuicWallTime::Zero()), | |
194 rand_(QuicRandom::GetInstance()), | |
195 server_(QuicCryptoServerConfig::TESTING, | |
196 rand_, | |
197 CryptoTestUtils::ProofSourceForTesting()), | |
198 peer_(&server_) { | |
199 // Advance the clock to some non-zero time. | |
200 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); | |
201 original_time_ = clock_.WallNow(); | |
202 | |
203 primary_config_.reset(server_.AddDefaultConfig( | |
204 rand_, &clock_, QuicCryptoServerConfig::ConfigOptions())); | |
205 | |
206 // Add a config that overrides the default boxer. | |
207 QuicCryptoServerConfig::ConfigOptions options; | |
208 options.id = kOverride; | |
209 override_config_protobuf_.reset( | |
210 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options)); | |
211 override_config_protobuf_->set_source_address_token_secret_override( | |
212 "a secret key"); | |
213 // Lower priority than the default config. | |
214 override_config_protobuf_->set_priority(1); | |
215 override_config_.reset( | |
216 server_.AddConfig(override_config_protobuf_.get(), original_time_)); | |
217 } | |
218 | |
219 string NewSourceAddressToken(string config_id, const IPAddress& ip) { | |
220 return NewSourceAddressToken(config_id, ip, nullptr); | |
221 } | |
222 | |
223 string NewSourceAddressToken(string config_id, | |
224 const IPAddress& ip, | |
225 const SourceAddressTokens& previous_tokens) { | |
226 return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_, | |
227 clock_.WallNow(), nullptr); | |
228 } | |
229 | |
230 string NewSourceAddressToken(string config_id, | |
231 const IPAddress& ip, | |
232 CachedNetworkParameters* cached_network_params) { | |
233 SourceAddressTokens previous_tokens; | |
234 return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_, | |
235 clock_.WallNow(), cached_network_params); | |
236 } | |
237 | |
238 HandshakeFailureReason ValidateSourceAddressTokens(string config_id, | |
239 StringPiece srct, | |
240 const IPAddress& ip) { | |
241 return ValidateSourceAddressTokens(config_id, srct, ip, nullptr); | |
242 } | |
243 | |
244 HandshakeFailureReason ValidateSourceAddressTokens( | |
245 string config_id, | |
246 StringPiece srct, | |
247 const IPAddress& ip, | |
248 CachedNetworkParameters* cached_network_params) { | |
249 return peer_.ValidateSourceAddressTokens( | |
250 config_id, srct, ip, clock_.WallNow(), cached_network_params); | |
251 } | |
252 | |
253 const string kPrimary = "<primary>"; | |
254 const string kOverride = "Config with custom source address token key"; | |
255 | |
256 IPAddress ip4_; | |
257 IPAddress ip4_dual_; | |
258 IPAddress ip6_; | |
259 | |
260 MockClock clock_; | |
261 QuicWallTime original_time_; | |
262 QuicRandom* rand_ = QuicRandom::GetInstance(); | |
263 QuicCryptoServerConfig server_; | |
264 QuicCryptoServerConfigPeer peer_; | |
265 // Stores the primary config. | |
266 std::unique_ptr<CryptoHandshakeMessage> primary_config_; | |
267 std::unique_ptr<QuicServerConfigProtobuf> override_config_protobuf_; | |
268 std::unique_ptr<CryptoHandshakeMessage> override_config_; | |
269 }; | |
270 | |
271 // Test basic behavior of source address tokens including being specific | |
272 // to a single IP address and server config. | |
273 TEST_F(SourceAddressTokenTest, NewSourceAddressToken) { | |
274 // Primary config generates configs that validate successfully. | |
275 const string token4 = NewSourceAddressToken(kPrimary, ip4_); | |
276 const string token4d = NewSourceAddressToken(kPrimary, ip4_dual_); | |
277 const string token6 = NewSourceAddressToken(kPrimary, ip6_); | |
278 EXPECT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4, ip4_)); | |
279 ASSERT_EQ(HANDSHAKE_OK, | |
280 ValidateSourceAddressTokens(kPrimary, token4, ip4_dual_)); | |
281 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
282 ValidateSourceAddressTokens(kPrimary, token4, ip6_)); | |
283 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4d, ip4_)); | |
284 ASSERT_EQ(HANDSHAKE_OK, | |
285 ValidateSourceAddressTokens(kPrimary, token4d, ip4_dual_)); | |
286 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
287 ValidateSourceAddressTokens(kPrimary, token4d, ip6_)); | |
288 ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token6, ip6_)); | |
289 | |
290 // Override config generates configs that validate successfully. | |
291 const string override_token4 = NewSourceAddressToken(kOverride, ip4_); | |
292 const string override_token6 = NewSourceAddressToken(kOverride, ip6_); | |
293 ASSERT_EQ(HANDSHAKE_OK, | |
294 ValidateSourceAddressTokens(kOverride, override_token4, ip4_)); | |
295 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, | |
296 ValidateSourceAddressTokens(kOverride, override_token4, ip6_)); | |
297 ASSERT_EQ(HANDSHAKE_OK, | |
298 ValidateSourceAddressTokens(kOverride, override_token6, ip6_)); | |
299 | |
300 // Tokens generated by the primary config do not validate | |
301 // successfully against the override config, and vice versa. | |
302 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
303 ValidateSourceAddressTokens(kOverride, token4, ip4_)); | |
304 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
305 ValidateSourceAddressTokens(kOverride, token6, ip6_)); | |
306 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
307 ValidateSourceAddressTokens(kPrimary, override_token4, ip4_)); | |
308 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, | |
309 ValidateSourceAddressTokens(kPrimary, override_token6, ip6_)); | |
310 } | |
311 | |
312 TEST_F(SourceAddressTokenTest, NewSourceAddressTokenExpiration) { | |
313 const string token = NewSourceAddressToken(kPrimary, ip4_); | |
314 | |
315 // Validation fails if the token is from the future. | |
316 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(-3600 * 2)); | |
317 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE, | |
318 ValidateSourceAddressTokens(kPrimary, token, ip4_)); | |
319 | |
320 // Validation fails after tokens expire. | |
321 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(86400 * 7)); | |
322 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE, | |
323 ValidateSourceAddressTokens(kPrimary, token, ip4_)); | |
324 } | |
325 | |
326 TEST_F(SourceAddressTokenTest, NewSourceAddressTokenWithNetworkParams) { | |
327 // Make sure that if the source address token contains CachedNetworkParameters | |
328 // that this gets written to ValidateSourceAddressToken output argument. | |
329 CachedNetworkParameters cached_network_params_input; | |
330 cached_network_params_input.set_bandwidth_estimate_bytes_per_second(1234); | |
331 const string token4_with_cached_network_params = | |
332 NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input); | |
333 | |
334 CachedNetworkParameters cached_network_params_output; | |
335 EXPECT_NE(cached_network_params_output.SerializeAsString(), | |
336 cached_network_params_input.SerializeAsString()); | |
337 ValidateSourceAddressTokens(kPrimary, token4_with_cached_network_params, ip4_, | |
338 &cached_network_params_output); | |
339 EXPECT_EQ(cached_network_params_output.SerializeAsString(), | |
340 cached_network_params_input.SerializeAsString()); | |
341 } | |
342 | |
343 // Test the ability for a source address token to be valid for multiple | |
344 // addresses. | |
345 TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) { | |
346 QuicWallTime now = clock_.WallNow(); | |
347 | |
348 // Now create a token which is usable for both addresses. | |
349 SourceAddressToken previous_token; | |
350 IPAddress ip_address = ip6_; | |
351 if (ip6_.IsIPv4()) { | |
352 ip_address = ConvertIPv4ToIPv4MappedIPv6(ip_address); | |
353 } | |
354 previous_token.set_ip(IPAddressToPackedString(ip_address)); | |
355 previous_token.set_timestamp(now.ToUNIXSeconds()); | |
356 SourceAddressTokens previous_tokens; | |
357 (*previous_tokens.add_tokens()) = previous_token; | |
358 const string token4or6 = | |
359 NewSourceAddressToken(kPrimary, ip4_, previous_tokens); | |
360 | |
361 EXPECT_EQ(HANDSHAKE_OK, | |
362 ValidateSourceAddressTokens(kPrimary, token4or6, ip4_)); | |
363 ASSERT_EQ(HANDSHAKE_OK, | |
364 ValidateSourceAddressTokens(kPrimary, token4or6, ip6_)); | |
365 } | |
366 | |
367 TEST(QuicCryptoServerConfigTest, ValidateServerNonce) { | |
368 QuicRandom* rand = QuicRandom::GetInstance(); | |
369 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand, | |
370 CryptoTestUtils::ProofSourceForTesting()); | |
371 QuicCryptoServerConfigPeer peer(&server); | |
372 | |
373 StringPiece message("hello world"); | |
374 const size_t key_size = CryptoSecretBoxer::GetKeySize(); | |
375 std::unique_ptr<uint8_t[]> key(new uint8_t[key_size]); | |
376 memset(key.get(), 0x11, key_size); | |
377 | |
378 CryptoSecretBoxer boxer; | |
379 boxer.SetKeys({string(reinterpret_cast<char*>(key.get()), key_size)}); | |
380 const string box = boxer.Box(rand, message); | |
381 MockClock clock; | |
382 QuicWallTime now = clock.WallNow(); | |
383 const QuicWallTime original_time = now; | |
384 EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE, | |
385 peer.ValidateServerNonce(box, now)); | |
386 | |
387 string server_nonce = peer.NewServerNonce(rand, now); | |
388 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now)); | |
389 EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE, | |
390 peer.ValidateServerNonce(server_nonce, now)); | |
391 | |
392 now = original_time.Add(QuicTime::Delta::FromSeconds(1000 * 7)); | |
393 server_nonce = peer.NewServerNonce(rand, now); | |
394 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now)); | |
395 } | |
396 | |
397 class CryptoServerConfigsTest : public ::testing::Test { | |
398 public: | |
399 CryptoServerConfigsTest() | |
400 : rand_(QuicRandom::GetInstance()), | |
401 config_(QuicCryptoServerConfig::TESTING, | |
402 rand_, | |
403 CryptoTestUtils::ProofSourceForTesting()), | |
404 test_peer_(&config_) {} | |
405 | |
406 void SetUp() override { | |
407 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000)); | |
408 } | |
409 | |
410 // SetConfigs constructs suitable config protobufs and calls SetConfigs on | |
411 // |config_|. The arguments are given as nullptr-terminated pairs. The first | |
412 // of each pair is the server config ID of a Config. The second is the | |
413 // |primary_time| of that Config, given in epoch seconds. (Although note that, | |
414 // in these tests, time is set to 1000 seconds since the epoch.) For example: | |
415 // SetConfigs(nullptr); // calls |config_.SetConfigs| with no protobufs. | |
416 // | |
417 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with | |
418 // // a |primary_time| of 900 and priority 1, and another with | |
419 // // a |primary_time| of 1000 and priority 2. | |
420 | |
421 // CheckConfigs( | |
422 // "id1", 900, 1, | |
423 // "id2", 1000, 2, | |
424 // nullptr); | |
425 // | |
426 // If the server config id starts with "INVALID" then the generated protobuf | |
427 // will be invalid. | |
428 void SetConfigs(const char* server_config_id1, ...) { | |
429 const char kOrbit[] = "12345678"; | |
430 | |
431 va_list ap; | |
432 va_start(ap, server_config_id1); | |
433 bool has_invalid = false; | |
434 bool is_empty = true; | |
435 | |
436 vector<QuicServerConfigProtobuf*> protobufs; | |
437 bool first = true; | |
438 for (;;) { | |
439 const char* server_config_id; | |
440 if (first) { | |
441 server_config_id = server_config_id1; | |
442 first = false; | |
443 } else { | |
444 server_config_id = va_arg(ap, const char*); | |
445 } | |
446 | |
447 if (!server_config_id) { | |
448 break; | |
449 } | |
450 | |
451 is_empty = false; | |
452 int primary_time = va_arg(ap, int); | |
453 int priority = va_arg(ap, int); | |
454 | |
455 QuicCryptoServerConfig::ConfigOptions options; | |
456 options.id = server_config_id; | |
457 options.orbit = kOrbit; | |
458 QuicServerConfigProtobuf* protobuf( | |
459 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options)); | |
460 protobuf->set_primary_time(primary_time); | |
461 protobuf->set_priority(priority); | |
462 if (string(server_config_id).find("INVALID") == 0) { | |
463 protobuf->clear_key(); | |
464 has_invalid = true; | |
465 } | |
466 protobufs.push_back(protobuf); | |
467 } | |
468 | |
469 ASSERT_EQ(!has_invalid && !is_empty, | |
470 config_.SetConfigs(protobufs, clock_.WallNow())); | |
471 STLDeleteElements(&protobufs); | |
472 } | |
473 | |
474 protected: | |
475 QuicRandom* const rand_; | |
476 MockClock clock_; | |
477 QuicCryptoServerConfig config_; | |
478 QuicCryptoServerConfigPeer test_peer_; | |
479 }; | |
480 | |
481 TEST_F(CryptoServerConfigsTest, NoConfigs) { | |
482 test_peer_.CheckConfigs(nullptr); | |
483 } | |
484 | |
485 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) { | |
486 // Make sure that "b" is primary even though "a" comes first. | |
487 SetConfigs("a", 1100, 1, "b", 900, 1, nullptr); | |
488 test_peer_.CheckConfigs("a", false, "b", true, nullptr); | |
489 } | |
490 | |
491 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) { | |
492 // Make sure that a remains primary after b is added. | |
493 SetConfigs("a", 900, 1, "b", 1100, 1, nullptr); | |
494 test_peer_.CheckConfigs("a", true, "b", false, nullptr); | |
495 } | |
496 | |
497 TEST_F(CryptoServerConfigsTest, Delete) { | |
498 // Ensure that configs get deleted when removed. | |
499 SetConfigs("a", 800, 1, "b", 900, 1, "c", 1100, 1, nullptr); | |
500 test_peer_.CheckConfigs("a", false, "b", true, "c", false, nullptr); | |
501 SetConfigs("b", 900, 1, "c", 1100, 1, nullptr); | |
502 test_peer_.CheckConfigs("b", true, "c", false, nullptr); | |
503 } | |
504 | |
505 TEST_F(CryptoServerConfigsTest, DeletePrimary) { | |
506 // Ensure that deleting the primary config works. | |
507 SetConfigs("a", 800, 1, "b", 900, 1, "c", 1100, 1, nullptr); | |
508 test_peer_.CheckConfigs("a", false, "b", true, "c", false, nullptr); | |
509 SetConfigs("a", 800, 1, "c", 1100, 1, nullptr); | |
510 test_peer_.CheckConfigs("a", true, "c", false, nullptr); | |
511 } | |
512 | |
513 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) { | |
514 // Ensure that configs get deleted when removed. | |
515 SetConfigs("a", 800, 1, "b", 900, 1, nullptr); | |
516 test_peer_.CheckConfigs("a", false, "b", true, nullptr); | |
517 SetConfigs(nullptr); | |
518 // Config change is rejected, still using old configs. | |
519 test_peer_.CheckConfigs("a", false, "b", true, nullptr); | |
520 } | |
521 | |
522 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) { | |
523 // Check that updates to primary time get picked up. | |
524 SetConfigs("a", 400, 1, "b", 800, 1, "c", 1200, 1, nullptr); | |
525 test_peer_.SelectNewPrimaryConfig(500); | |
526 test_peer_.CheckConfigs("a", true, "b", false, "c", false, nullptr); | |
527 SetConfigs("a", 1200, 1, "b", 800, 1, "c", 400, 1, nullptr); | |
528 test_peer_.SelectNewPrimaryConfig(500); | |
529 test_peer_.CheckConfigs("a", false, "b", false, "c", true, nullptr); | |
530 } | |
531 | |
532 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) { | |
533 // Check that the most recent config is selected. | |
534 SetConfigs("a", 400, 1, "b", 800, 1, "c", 1200, 1, nullptr); | |
535 test_peer_.SelectNewPrimaryConfig(1500); | |
536 test_peer_.CheckConfigs("a", false, "b", false, "c", true, nullptr); | |
537 } | |
538 | |
539 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) { | |
540 // Check that the first config is selected. | |
541 SetConfigs("a", 400, 1, "b", 800, 1, "c", 1200, 1, nullptr); | |
542 test_peer_.SelectNewPrimaryConfig(100); | |
543 test_peer_.CheckConfigs("a", true, "b", false, "c", false, nullptr); | |
544 } | |
545 | |
546 TEST_F(CryptoServerConfigsTest, SortByPriority) { | |
547 // Check that priority is used to decide on a primary config when | |
548 // configs have the same primary time. | |
549 SetConfigs("a", 900, 1, "b", 900, 2, "c", 900, 3, nullptr); | |
550 test_peer_.CheckConfigs("a", true, "b", false, "c", false, nullptr); | |
551 test_peer_.SelectNewPrimaryConfig(800); | |
552 test_peer_.CheckConfigs("a", true, "b", false, "c", false, nullptr); | |
553 test_peer_.SelectNewPrimaryConfig(1000); | |
554 test_peer_.CheckConfigs("a", true, "b", false, "c", false, nullptr); | |
555 | |
556 // Change priorities and expect sort order to change. | |
557 SetConfigs("a", 900, 2, "b", 900, 1, "c", 900, 0, nullptr); | |
558 test_peer_.CheckConfigs("a", false, "b", false, "c", true, nullptr); | |
559 test_peer_.SelectNewPrimaryConfig(800); | |
560 test_peer_.CheckConfigs("a", false, "b", false, "c", true, nullptr); | |
561 test_peer_.SelectNewPrimaryConfig(1000); | |
562 test_peer_.CheckConfigs("a", false, "b", false, "c", true, nullptr); | |
563 } | |
564 | |
565 TEST_F(CryptoServerConfigsTest, AdvancePrimary) { | |
566 // Check that a new primary config is enabled at the right time. | |
567 SetConfigs("a", 900, 1, "b", 1100, 1, nullptr); | |
568 test_peer_.SelectNewPrimaryConfig(1000); | |
569 test_peer_.CheckConfigs("a", true, "b", false, nullptr); | |
570 test_peer_.SelectNewPrimaryConfig(1101); | |
571 test_peer_.CheckConfigs("a", false, "b", true, nullptr); | |
572 } | |
573 | |
574 TEST_F(CryptoServerConfigsTest, InvalidConfigs) { | |
575 // Ensure that invalid configs don't change anything. | |
576 SetConfigs("a", 800, 1, "b", 900, 1, "c", 1100, 1, nullptr); | |
577 test_peer_.CheckConfigs("a", false, "b", true, "c", false, nullptr); | |
578 SetConfigs("a", 800, 1, "c", 1100, 1, "INVALID1", 1000, 1, nullptr); | |
579 test_peer_.CheckConfigs("a", false, "b", true, "c", false, nullptr); | |
580 } | |
581 | |
582 } // namespace test | |
583 } // namespace net | |
OLD | NEW |