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.
5 #include "net/quic/crypto/quic_crypto_server_config.h"
9 #include "base/stl_util.h"
10 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
11 #include "net/quic/crypto/crypto_handshake_message.h"
12 #include "net/quic/crypto/crypto_secret_boxer.h"
13 #include "net/quic/crypto/crypto_server_config_protobuf.h"
14 #include "net/quic/crypto/quic_random.h"
15 #include "net/quic/crypto/strike_register_client.h"
16 #include "net/quic/quic_flags.h"
17 #include "net/quic/quic_time.h"
18 #include "net/quic/test_tools/mock_clock.h"
19 #include "net/quic/test_tools/quic_test_utils.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using base::StringPiece
;
32 class QuicCryptoServerConfigPeer
{
34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig
* server_config
)
35 : server_config_(server_config
) {}
37 scoped_refptr
<QuicCryptoServerConfig::Config
> GetConfig(string config_id
) {
38 base::AutoLock
locked(server_config_
->configs_lock_
);
39 if (config_id
== "<primary>") {
40 return scoped_refptr
<QuicCryptoServerConfig::Config
>(
41 server_config_
->primary_config_
);
43 return server_config_
->GetConfigWithScid(config_id
);
47 string
NewSourceAddressToken(string config_id
,
48 SourceAddressTokens previous_tokens
,
49 const IPAddressNumber
& ip
,
52 CachedNetworkParameters
* cached_network_params
) {
53 return server_config_
->NewSourceAddressToken(*GetConfig(config_id
),
54 previous_tokens
, ip
, rand
, now
,
55 cached_network_params
);
58 HandshakeFailureReason
ValidateSourceAddressTokens(
61 const IPAddressNumber
& ip
,
63 CachedNetworkParameters
* cached_network_params
) {
64 SourceAddressTokens tokens
;
65 HandshakeFailureReason reason
= server_config_
->ParseSourceAddressToken(
66 *GetConfig(config_id
), srct
, &tokens
);
67 if (reason
!= HANDSHAKE_OK
) {
71 return server_config_
->ValidateSourceAddressTokens(tokens
, ip
, now
,
72 cached_network_params
);
75 string
NewServerNonce(QuicRandom
* rand
, QuicWallTime now
) const {
76 return server_config_
->NewServerNonce(rand
, now
);
79 HandshakeFailureReason
ValidateServerNonce(StringPiece token
,
81 return server_config_
->ValidateServerNonce(token
, now
);
84 base::Lock
* GetStrikeRegisterClientLock() {
85 return &server_config_
->strike_register_client_lock_
;
88 // CheckConfigs compares the state of the Configs in |server_config_| to the
89 // description given as arguments. The arguments are given as
90 // nullptr-terminated pairs. The first of each pair is the server config ID of
91 // a Config. The second is a boolean describing whether the config is the
92 // primary. For example:
93 // CheckConfigs(nullptr); // checks that no Configs are loaded.
95 // // Checks that exactly three Configs are loaded with the given IDs and
102 void CheckConfigs(const char* server_config_id1
, ...) {
104 va_start(ap
, server_config_id1
);
106 vector
<pair
<ServerConfigID
, bool> > expected
;
109 const char* server_config_id
;
111 server_config_id
= server_config_id1
;
114 server_config_id
= va_arg(ap
, const char*);
117 if (!server_config_id
) {
121 // varargs will promote the value to an int so we have to read that from
122 // the stack and cast down.
123 const bool is_primary
= static_cast<bool>(va_arg(ap
, int));
124 expected
.push_back(std::make_pair(server_config_id
, is_primary
));
129 base::AutoLock
locked(server_config_
->configs_lock_
);
131 ASSERT_EQ(expected
.size(), server_config_
->configs_
.size())
134 for (QuicCryptoServerConfig::ConfigMap::const_iterator
135 i
= server_config_
->configs_
.begin();
136 i
!= server_config_
->configs_
.end(); ++i
) {
138 for (vector
<pair
<ServerConfigID
, bool> >::iterator j
= expected
.begin();
139 j
!= expected
.end(); ++j
) {
140 if (i
->first
== j
->first
&& i
->second
->is_primary
== j
->second
) {
147 ASSERT_TRUE(found
) << "Failed to find match for " << i
->first
148 << " in configs:\n" << ConfigsDebug();
152 // ConfigsDebug returns a string that contains debugging information about
153 // the set of Configs loaded in |server_config_| and their status.
154 // ConfigsDebug() should be called after acquiring
155 // server_config_->configs_lock_.
156 string
ConfigsDebug() {
157 if (server_config_
->configs_
.empty()) {
158 return "No Configs in QuicCryptoServerConfig";
163 for (QuicCryptoServerConfig::ConfigMap::const_iterator
164 i
= server_config_
->configs_
.begin();
165 i
!= server_config_
->configs_
.end(); ++i
) {
166 const scoped_refptr
<QuicCryptoServerConfig::Config
> config
= i
->second
;
167 if (config
->is_primary
) {
179 void SelectNewPrimaryConfig(int seconds
) {
180 base::AutoLock
locked(server_config_
->configs_lock_
);
181 server_config_
->SelectNewPrimaryConfig(
182 QuicWallTime::FromUNIXSeconds(seconds
));
186 const QuicCryptoServerConfig
* server_config_
;
189 class TestStrikeRegisterClient
: public StrikeRegisterClient
{
191 explicit TestStrikeRegisterClient(QuicCryptoServerConfig
* config
)
193 is_known_orbit_called_(false) {
196 bool IsKnownOrbit(StringPiece orbit
) const override
{
197 // Ensure that the strike register client lock is not held.
198 QuicCryptoServerConfigPeer
peer(config_
);
199 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
200 // In Chromium, we will dead lock if the lock is held by the current thread.
201 // Chromium doesn't have AssertNotHeld API call.
202 // m->AssertNotHeld();
203 base::AutoLock
lock(*m
);
205 is_known_orbit_called_
= true;
209 void VerifyNonceIsValidAndUnique(StringPiece nonce
,
211 ResultCallback
* cb
) override
{
212 LOG(FATAL
) << "Not implemented";
215 bool is_known_orbit_called() { return is_known_orbit_called_
; }
218 QuicCryptoServerConfig
* config_
;
219 mutable bool is_known_orbit_called_
;
222 TEST(QuicCryptoServerConfigTest
, ServerConfig
) {
223 QuicRandom
* rand
= QuicRandom::GetInstance();
224 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
227 scoped_ptr
<CryptoHandshakeMessage
>(
228 server
.AddDefaultConfig(rand
, &clock
,
229 QuicCryptoServerConfig::ConfigOptions()));
232 TEST(QuicCryptoServerConfigTest
, GetOrbitIsCalledWithoutTheStrikeRegisterLock
) {
233 QuicRandom
* rand
= QuicRandom::GetInstance();
234 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
237 TestStrikeRegisterClient
* strike_register
=
238 new TestStrikeRegisterClient(&server
);
239 server
.SetStrikeRegisterClient(strike_register
);
241 QuicCryptoServerConfig::ConfigOptions options
;
242 scoped_ptr
<CryptoHandshakeMessage
>(
243 server
.AddDefaultConfig(rand
, &clock
, options
));
244 EXPECT_TRUE(strike_register
->is_known_orbit_called());
247 class SourceAddressTokenTest
: public ::testing::Test
{
249 SourceAddressTokenTest()
251 ip4_dual_(ConvertIPv4NumberToIPv6Number(ip4_
)),
253 original_time_(QuicWallTime::Zero()),
254 rand_(QuicRandom::GetInstance()),
255 server_(QuicCryptoServerConfig::TESTING
, rand_
),
257 // Advance the clock to some non-zero time.
258 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
259 original_time_
= clock_
.WallNow();
261 primary_config_
.reset(server_
.AddDefaultConfig(
262 rand_
, &clock_
, QuicCryptoServerConfig::ConfigOptions()));
264 // Add a config that overrides the default boxer.
265 QuicCryptoServerConfig::ConfigOptions options
;
266 options
.id
= kOverride
;
267 override_config_protobuf_
.reset(
268 QuicCryptoServerConfig::GenerateConfig(rand_
, &clock_
, options
));
269 override_config_protobuf_
->set_source_address_token_secret_override(
271 // Lower priority than the default config.
272 override_config_protobuf_
->set_priority(1);
273 override_config_
.reset(
274 server_
.AddConfig(override_config_protobuf_
.get(), original_time_
));
277 string
NewSourceAddressToken(string config_id
, const IPAddressNumber
& ip
) {
278 return NewSourceAddressToken(config_id
, ip
, NULL
);
281 string
NewSourceAddressToken(string config_id
,
282 const IPAddressNumber
& ip
,
283 const SourceAddressTokens
& previous_tokens
) {
284 return peer_
.NewSourceAddressToken(config_id
, previous_tokens
, ip
, rand_
,
285 clock_
.WallNow(), NULL
);
288 string
NewSourceAddressToken(string config_id
,
289 const IPAddressNumber
& ip
,
290 CachedNetworkParameters
* cached_network_params
) {
291 SourceAddressTokens previous_tokens
;
292 return peer_
.NewSourceAddressToken(config_id
, previous_tokens
, ip
, rand_
,
293 clock_
.WallNow(), cached_network_params
);
296 HandshakeFailureReason
ValidateSourceAddressTokens(
299 const IPAddressNumber
& ip
) {
300 return ValidateSourceAddressTokens(config_id
, srct
, ip
, NULL
);
303 HandshakeFailureReason
ValidateSourceAddressTokens(
306 const IPAddressNumber
& ip
,
307 CachedNetworkParameters
* cached_network_params
) {
308 return peer_
.ValidateSourceAddressTokens(
309 config_id
, srct
, ip
, clock_
.WallNow(), cached_network_params
);
312 const string kPrimary
= "<primary>";
313 const string kOverride
= "Config with custom source address token key";
315 IPAddressNumber ip4_
;
316 IPAddressNumber ip4_dual_
;
317 IPAddressNumber ip6_
;
320 QuicWallTime original_time_
;
321 QuicRandom
* rand_
= QuicRandom::GetInstance();
322 QuicCryptoServerConfig server_
;
323 QuicCryptoServerConfigPeer peer_
;
324 // Stores the primary config.
325 scoped_ptr
<CryptoHandshakeMessage
> primary_config_
;
326 scoped_ptr
<QuicServerConfigProtobuf
> override_config_protobuf_
;
327 scoped_ptr
<CryptoHandshakeMessage
> override_config_
;
330 // Test basic behavior of source address tokens including being specific
331 // to a single IP address and server config.
332 TEST_F(SourceAddressTokenTest
, NewSourceAddressToken
) {
333 // Primary config generates configs that validate successfully.
334 const string token4
= NewSourceAddressToken(kPrimary
, ip4_
);
335 const string token4d
= NewSourceAddressToken(kPrimary
, ip4_dual_
);
336 const string token6
= NewSourceAddressToken(kPrimary
, ip6_
);
337 EXPECT_EQ(HANDSHAKE_OK
, ValidateSourceAddressTokens(kPrimary
, token4
, ip4_
));
338 ASSERT_EQ(HANDSHAKE_OK
,
339 ValidateSourceAddressTokens(kPrimary
, token4
, ip4_dual_
));
340 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
341 ValidateSourceAddressTokens(kPrimary
, token4
, ip6_
));
342 ASSERT_EQ(HANDSHAKE_OK
, ValidateSourceAddressTokens(kPrimary
, token4d
, ip4_
));
343 ASSERT_EQ(HANDSHAKE_OK
,
344 ValidateSourceAddressTokens(kPrimary
, token4d
, ip4_dual_
));
345 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
346 ValidateSourceAddressTokens(kPrimary
, token4d
, ip6_
));
347 ASSERT_EQ(HANDSHAKE_OK
, ValidateSourceAddressTokens(kPrimary
, token6
, ip6_
));
349 // Override config generates configs that validate successfully.
350 const string override_token4
= NewSourceAddressToken(kOverride
, ip4_
);
351 const string override_token6
= NewSourceAddressToken(kOverride
, ip6_
);
352 ASSERT_EQ(HANDSHAKE_OK
,
353 ValidateSourceAddressTokens(kOverride
, override_token4
, ip4_
));
354 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
355 ValidateSourceAddressTokens(kOverride
, override_token4
, ip6_
));
356 ASSERT_EQ(HANDSHAKE_OK
,
357 ValidateSourceAddressTokens(kOverride
, override_token6
, ip6_
));
359 // Tokens generated by the primary config do not validate
360 // successfully against the override config, and vice versa.
361 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
362 ValidateSourceAddressTokens(kOverride
, token4
, ip4_
));
363 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
364 ValidateSourceAddressTokens(kOverride
, token6
, ip6_
));
365 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
366 ValidateSourceAddressTokens(kPrimary
, override_token4
, ip4_
));
367 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
368 ValidateSourceAddressTokens(kPrimary
, override_token6
, ip6_
));
371 TEST_F(SourceAddressTokenTest
, NewSourceAddressTokenExpiration
) {
372 const string token
= NewSourceAddressToken(kPrimary
, ip4_
);
374 // Validation fails if the token is from the future.
375 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(-3600 * 2));
376 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE
,
377 ValidateSourceAddressTokens(kPrimary
, token
, ip4_
));
379 // Validation fails after tokens expire.
380 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(86400 * 7));
381 ASSERT_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE
,
382 ValidateSourceAddressTokens(kPrimary
, token
, ip4_
));
385 TEST_F(SourceAddressTokenTest
, NewSourceAddressTokenWithNetworkParams
) {
386 // Make sure that if the source address token contains CachedNetworkParameters
387 // that this gets written to ValidateSourceAddressToken output argument.
388 CachedNetworkParameters cached_network_params_input
;
389 cached_network_params_input
.set_bandwidth_estimate_bytes_per_second(1234);
390 const string token4_with_cached_network_params
=
391 NewSourceAddressToken(kPrimary
, ip4_
, &cached_network_params_input
);
393 CachedNetworkParameters cached_network_params_output
;
394 EXPECT_NE(cached_network_params_output
.SerializeAsString(),
395 cached_network_params_input
.SerializeAsString());
396 ValidateSourceAddressTokens(kPrimary
, token4_with_cached_network_params
, ip4_
,
397 &cached_network_params_output
);
398 EXPECT_EQ(cached_network_params_output
.SerializeAsString(),
399 cached_network_params_input
.SerializeAsString());
402 // Test the ability for a source address token to be valid for multiple
404 TEST_F(SourceAddressTokenTest
, SourceAddressTokenMultipleAddresses
) {
405 QuicWallTime now
= clock_
.WallNow();
407 // Now create a token which is usable for both addresses.
408 SourceAddressToken previous_token
;
409 IPAddressNumber ip_address
= ip6_
;
410 if (ip6_
.size() == kIPv4AddressSize
) {
411 ip_address
= ConvertIPv4NumberToIPv6Number(ip_address
);
413 previous_token
.set_ip(IPAddressToPackedString(ip_address
));
414 previous_token
.set_timestamp(now
.ToUNIXSeconds());
415 SourceAddressTokens previous_tokens
;
416 (*previous_tokens
.add_tokens()) = previous_token
;
417 const string token4or6
=
418 NewSourceAddressToken(kPrimary
, ip4_
, previous_tokens
);
420 EXPECT_EQ(HANDSHAKE_OK
,
421 ValidateSourceAddressTokens(kPrimary
, token4or6
, ip4_
));
422 ASSERT_EQ(HANDSHAKE_OK
,
423 ValidateSourceAddressTokens(kPrimary
, token4or6
, ip6_
));
426 TEST(QuicCryptoServerConfigTest
, ValidateServerNonce
) {
427 QuicRandom
* rand
= QuicRandom::GetInstance();
428 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
429 QuicCryptoServerConfigPeer
peer(&server
);
431 StringPiece
message("hello world");
432 const size_t key_size
= CryptoSecretBoxer::GetKeySize();
433 scoped_ptr
<uint8
[]> key(new uint8
[key_size
]);
434 memset(key
.get(), 0x11, key_size
);
436 CryptoSecretBoxer boxer
;
437 boxer
.SetKey(StringPiece(reinterpret_cast<char*>(key
.get()), key_size
));
438 const string box
= boxer
.Box(rand
, message
);
440 QuicWallTime now
= clock
.WallNow();
441 const QuicWallTime original_time
= now
;
442 EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE
,
443 peer
.ValidateServerNonce(box
, now
));
445 string server_nonce
= peer
.NewServerNonce(rand
, now
);
446 EXPECT_EQ(HANDSHAKE_OK
, peer
.ValidateServerNonce(server_nonce
, now
));
447 EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE
,
448 peer
.ValidateServerNonce(server_nonce
, now
));
450 now
= original_time
.Add(QuicTime::Delta::FromSeconds(1000 * 7));
451 server_nonce
= peer
.NewServerNonce(rand
, now
);
452 EXPECT_EQ(HANDSHAKE_OK
, peer
.ValidateServerNonce(server_nonce
, now
));
455 class CryptoServerConfigsTest
: public ::testing::Test
{
457 CryptoServerConfigsTest()
458 : rand_(QuicRandom::GetInstance()),
459 config_(QuicCryptoServerConfig::TESTING
, rand_
),
460 test_peer_(&config_
) {}
462 void SetUp() override
{
463 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
466 // SetConfigs constructs suitable config protobufs and calls SetConfigs on
467 // |config_|. The arguments are given as nullptr-terminated pairs. The first
468 // of each pair is the server config ID of a Config. The second is the
469 // |primary_time| of that Config, given in epoch seconds. (Although note that,
470 // in these tests, time is set to 1000 seconds since the epoch.) For example:
471 // SetConfigs(nullptr); // calls |config_.SetConfigs| with no protobufs.
473 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with
474 // // a |primary_time| of 900 and priority 1, and another with
475 // // a |primary_time| of 1000 and priority 2.
482 // If the server config id starts with "INVALID" then the generated protobuf
484 void SetConfigs(const char* server_config_id1
, ...) {
485 const char kOrbit
[] = "12345678";
488 va_start(ap
, server_config_id1
);
489 bool has_invalid
= false;
490 bool is_empty
= true;
492 vector
<QuicServerConfigProtobuf
*> protobufs
;
495 const char* server_config_id
;
497 server_config_id
= server_config_id1
;
500 server_config_id
= va_arg(ap
, const char*);
503 if (!server_config_id
) {
508 int primary_time
= va_arg(ap
, int);
509 int priority
= va_arg(ap
, int);
511 QuicCryptoServerConfig::ConfigOptions options
;
512 options
.id
= server_config_id
;
513 options
.orbit
= kOrbit
;
514 QuicServerConfigProtobuf
* protobuf(
515 QuicCryptoServerConfig::GenerateConfig(rand_
, &clock_
, options
));
516 protobuf
->set_primary_time(primary_time
);
517 protobuf
->set_priority(priority
);
518 if (string(server_config_id
).find("INVALID") == 0) {
519 protobuf
->clear_key();
522 protobufs
.push_back(protobuf
);
525 ASSERT_EQ(!has_invalid
&& !is_empty
,
526 config_
.SetConfigs(protobufs
, clock_
.WallNow()));
527 STLDeleteElements(&protobufs
);
531 QuicRandom
* const rand_
;
533 QuicCryptoServerConfig config_
;
534 QuicCryptoServerConfigPeer test_peer_
;
537 TEST_F(CryptoServerConfigsTest
, NoConfigs
) {
538 test_peer_
.CheckConfigs(nullptr);
541 TEST_F(CryptoServerConfigsTest
, MakePrimaryFirst
) {
542 // Make sure that "b" is primary even though "a" comes first.
543 SetConfigs("a", 1100, 1,
546 test_peer_
.CheckConfigs(
552 TEST_F(CryptoServerConfigsTest
, MakePrimarySecond
) {
553 // Make sure that a remains primary after b is added.
554 SetConfigs("a", 900, 1,
557 test_peer_
.CheckConfigs(
563 TEST_F(CryptoServerConfigsTest
, Delete
) {
564 // Ensure that configs get deleted when removed.
565 SetConfigs("a", 800, 1,
569 test_peer_
.CheckConfigs(
574 SetConfigs("b", 900, 1,
577 test_peer_
.CheckConfigs(
583 TEST_F(CryptoServerConfigsTest
, DeletePrimary
) {
584 // Ensure that deleting the primary config works.
585 SetConfigs("a", 800, 1,
589 test_peer_
.CheckConfigs(
594 SetConfigs("a", 800, 1,
597 test_peer_
.CheckConfigs(
603 TEST_F(CryptoServerConfigsTest
, FailIfDeletingAllConfigs
) {
604 // Ensure that configs get deleted when removed.
605 SetConfigs("a", 800, 1,
608 test_peer_
.CheckConfigs(
613 // Config change is rejected, still using old configs.
614 test_peer_
.CheckConfigs(
620 TEST_F(CryptoServerConfigsTest
, ChangePrimaryTime
) {
621 // Check that updates to primary time get picked up.
622 SetConfigs("a", 400, 1,
626 test_peer_
.SelectNewPrimaryConfig(500);
627 test_peer_
.CheckConfigs(
632 SetConfigs("a", 1200, 1,
636 test_peer_
.SelectNewPrimaryConfig(500);
637 test_peer_
.CheckConfigs(
644 TEST_F(CryptoServerConfigsTest
, AllConfigsInThePast
) {
645 // Check that the most recent config is selected.
646 SetConfigs("a", 400, 1,
650 test_peer_
.SelectNewPrimaryConfig(1500);
651 test_peer_
.CheckConfigs(
658 TEST_F(CryptoServerConfigsTest
, AllConfigsInTheFuture
) {
659 // Check that the first config is selected.
660 SetConfigs("a", 400, 1,
664 test_peer_
.SelectNewPrimaryConfig(100);
665 test_peer_
.CheckConfigs(
672 TEST_F(CryptoServerConfigsTest
, SortByPriority
) {
673 // Check that priority is used to decide on a primary config when
674 // configs have the same primary time.
675 SetConfigs("a", 900, 1,
679 test_peer_
.CheckConfigs(
684 test_peer_
.SelectNewPrimaryConfig(800);
685 test_peer_
.CheckConfigs(
690 test_peer_
.SelectNewPrimaryConfig(1000);
691 test_peer_
.CheckConfigs(
697 // Change priorities and expect sort order to change.
698 SetConfigs("a", 900, 2,
702 test_peer_
.CheckConfigs(
707 test_peer_
.SelectNewPrimaryConfig(800);
708 test_peer_
.CheckConfigs(
713 test_peer_
.SelectNewPrimaryConfig(1000);
714 test_peer_
.CheckConfigs(
721 TEST_F(CryptoServerConfigsTest
, AdvancePrimary
) {
722 // Check that a new primary config is enabled at the right time.
723 SetConfigs("a", 900, 1,
726 test_peer_
.SelectNewPrimaryConfig(1000);
727 test_peer_
.CheckConfigs(
731 test_peer_
.SelectNewPrimaryConfig(1101);
732 test_peer_
.CheckConfigs(
738 TEST_F(CryptoServerConfigsTest
, InvalidConfigs
) {
739 // Ensure that invalid configs don't change anything.
740 SetConfigs("a", 800, 1,
744 test_peer_
.CheckConfigs(
749 SetConfigs("a", 800, 1,
753 test_peer_
.CheckConfigs(