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 "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_time.h"
17 #include "net/quic/test_tools/mock_clock.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using base::StringPiece;
23 using std::make_pair;
24 using std::map;
25 using std::pair;
26 using std::string;
27 using std::vector;
28
29 namespace net {
30 namespace test {
31
32 class QuicCryptoServerConfigPeer {
33 public:
QuicCryptoServerConfigPeer(QuicCryptoServerConfig * server_config)34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
35 : server_config_(server_config) {}
36
GetConfig(string config_id)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_);
42 } else {
43 return server_config_->GetConfigWithScid(config_id);
44 }
45 }
46
ConfigHasDefaultSourceAddressTokenBoxer(string config_id)47 bool ConfigHasDefaultSourceAddressTokenBoxer(string config_id) {
48 scoped_refptr<QuicCryptoServerConfig::Config> config = GetConfig(config_id);
49 return config->source_address_token_boxer ==
50 &(server_config_->default_source_address_token_boxer_);
51 }
52
NewSourceAddressToken(string config_id,IPEndPoint ip,QuicRandom * rand,QuicWallTime now)53 string NewSourceAddressToken(
54 string config_id,
55 IPEndPoint ip,
56 QuicRandom* rand,
57 QuicWallTime now) {
58 return server_config_->NewSourceAddressToken(
59 *GetConfig(config_id), ip, rand, now, NULL);
60 }
61
ValidateSourceAddressToken(string config_id,StringPiece srct,IPEndPoint ip,QuicWallTime now)62 HandshakeFailureReason ValidateSourceAddressToken(string config_id,
63 StringPiece srct,
64 IPEndPoint ip,
65 QuicWallTime now) {
66 return server_config_->ValidateSourceAddressToken(
67 *GetConfig(config_id), srct, ip, now);
68 }
69
NewServerNonce(QuicRandom * rand,QuicWallTime now) const70 string NewServerNonce(QuicRandom* rand, QuicWallTime now) const {
71 return server_config_->NewServerNonce(rand, now);
72 }
73
ValidateServerNonce(StringPiece token,QuicWallTime now)74 HandshakeFailureReason ValidateServerNonce(StringPiece token,
75 QuicWallTime now) {
76 return server_config_->ValidateServerNonce(token, now);
77 }
78
GetStrikeRegisterClientLock()79 base::Lock* GetStrikeRegisterClientLock() {
80 return &server_config_->strike_register_client_lock_;
81 }
82
83 // CheckConfigs compares the state of the Configs in |server_config_| to the
84 // description given as arguments. The arguments are given as NULL-terminated
85 // pairs. The first of each pair is the server config ID of a Config. The
86 // second is a boolean describing whether the config is the primary. For
87 // example:
88 // CheckConfigs(NULL); // checks that no Configs are loaded.
89 //
90 // // Checks that exactly three Configs are loaded with the given IDs and
91 // // status.
92 // CheckConfigs(
93 // "id1", false,
94 // "id2", true,
95 // "id3", false,
96 // NULL);
CheckConfigs(const char * server_config_id1,...)97 void CheckConfigs(const char* server_config_id1, ...) {
98 va_list ap;
99 va_start(ap, server_config_id1);
100
101 vector<pair<ServerConfigID, bool> > expected;
102 bool first = true;
103 for (;;) {
104 const char* server_config_id;
105 if (first) {
106 server_config_id = server_config_id1;
107 first = false;
108 } else {
109 server_config_id = va_arg(ap, const char*);
110 }
111
112 if (!server_config_id) {
113 break;
114 }
115
116 // varargs will promote the value to an int so we have to read that from
117 // the stack and cast down.
118 const bool is_primary = static_cast<bool>(va_arg(ap, int));
119 expected.push_back(make_pair(server_config_id, is_primary));
120 }
121
122 va_end(ap);
123
124 base::AutoLock locked(server_config_->configs_lock_);
125
126 ASSERT_EQ(expected.size(), server_config_->configs_.size())
127 << ConfigsDebug();
128
129 for (QuicCryptoServerConfig::ConfigMap::const_iterator
130 i = server_config_->configs_.begin();
131 i != server_config_->configs_.end(); ++i) {
132 bool found = false;
133 for (vector<pair<ServerConfigID, bool> >::iterator j = expected.begin();
134 j != expected.end(); ++j) {
135 if (i->first == j->first && i->second->is_primary == j->second) {
136 found = true;
137 j->first.clear();
138 break;
139 }
140 }
141
142 ASSERT_TRUE(found) << "Failed to find match for " << i->first
143 << " in configs:\n" << ConfigsDebug();
144 }
145 }
146
147 // ConfigsDebug returns a string that contains debugging information about
148 // the set of Configs loaded in |server_config_| and their status.
149 // ConfigsDebug() should be called after acquiring
150 // server_config_->configs_lock_.
ConfigsDebug()151 string ConfigsDebug() {
152 if (server_config_->configs_.empty()) {
153 return "No Configs in QuicCryptoServerConfig";
154 }
155
156 string s;
157
158 for (QuicCryptoServerConfig::ConfigMap::const_iterator
159 i = server_config_->configs_.begin();
160 i != server_config_->configs_.end(); ++i) {
161 const scoped_refptr<QuicCryptoServerConfig::Config> config = i->second;
162 if (config->is_primary) {
163 s += "(primary) ";
164 } else {
165 s += " ";
166 }
167 s += config->id;
168 s += "\n";
169 }
170
171 return s;
172 }
173
SelectNewPrimaryConfig(int seconds)174 void SelectNewPrimaryConfig(int seconds) {
175 base::AutoLock locked(server_config_->configs_lock_);
176 server_config_->SelectNewPrimaryConfig(
177 QuicWallTime::FromUNIXSeconds(seconds));
178 }
179
180 private:
181 const QuicCryptoServerConfig* server_config_;
182 };
183
184 class TestStrikeRegisterClient : public StrikeRegisterClient {
185 public:
TestStrikeRegisterClient(QuicCryptoServerConfig * config)186 explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
187 : config_(config),
188 is_known_orbit_called_(false) {
189 }
190
IsKnownOrbit(StringPiece orbit) const191 virtual bool IsKnownOrbit(StringPiece orbit) const OVERRIDE {
192 // Ensure that the strike register client lock is not held.
193 QuicCryptoServerConfigPeer peer(config_);
194 base::Lock* m = peer.GetStrikeRegisterClientLock();
195 // In Chromium, we will dead lock if the lock is held by the current thread.
196 // Chromium doesn't have AssertNotHeld API call.
197 // m->AssertNotHeld();
198 base::AutoLock lock(*m);
199
200 is_known_orbit_called_ = true;
201 return true;
202 }
203
VerifyNonceIsValidAndUnique(StringPiece nonce,QuicWallTime now,ResultCallback * cb)204 virtual void VerifyNonceIsValidAndUnique(
205 StringPiece nonce,
206 QuicWallTime now,
207 ResultCallback* cb) OVERRIDE {
208 LOG(FATAL) << "Not implemented";
209 }
210
is_known_orbit_called()211 bool is_known_orbit_called() { return is_known_orbit_called_; }
212
213 private:
214 QuicCryptoServerConfig* config_;
215 mutable bool is_known_orbit_called_;
216 };
217
TEST(QuicCryptoServerConfigTest,ServerConfig)218 TEST(QuicCryptoServerConfigTest, ServerConfig) {
219 QuicRandom* rand = QuicRandom::GetInstance();
220 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
221 MockClock clock;
222
223 scoped_ptr<CryptoHandshakeMessage>(
224 server.AddDefaultConfig(rand, &clock,
225 QuicCryptoServerConfig::ConfigOptions()));
226 }
227
TEST(QuicCryptoServerConfigTest,GetOrbitIsCalledWithoutTheStrikeRegisterLock)228 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
229 QuicRandom* rand = QuicRandom::GetInstance();
230 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
231 MockClock clock;
232
233 TestStrikeRegisterClient* strike_register =
234 new TestStrikeRegisterClient(&server);
235 server.SetStrikeRegisterClient(strike_register);
236
237 QuicCryptoServerConfig::ConfigOptions options;
238 scoped_ptr<CryptoHandshakeMessage>(
239 server.AddDefaultConfig(rand, &clock, options));
240 EXPECT_TRUE(strike_register->is_known_orbit_called());
241 }
242
TEST(QuicCryptoServerConfigTest,SourceAddressTokens)243 TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
244 const string kPrimary = "<primary>";
245 const string kOverride = "Config with custom source address token key";
246
247 MockClock clock;
248 clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
249
250 QuicWallTime now = clock.WallNow();
251 const QuicWallTime original_time = now;
252
253 QuicRandom* rand = QuicRandom::GetInstance();
254 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
255 QuicCryptoServerConfigPeer peer(&server);
256
257 scoped_ptr<CryptoHandshakeMessage>(
258 server.AddDefaultConfig(rand, &clock,
259 QuicCryptoServerConfig::ConfigOptions()));
260
261 // Add a config that overrides the default boxer.
262 QuicCryptoServerConfig::ConfigOptions options;
263 options.id = kOverride;
264 scoped_ptr<QuicServerConfigProtobuf> protobuf(
265 QuicCryptoServerConfig::GenerateConfig(rand, &clock, options));
266 protobuf->set_source_address_token_secret_override("a secret key");
267 // Lower priority than the default config.
268 protobuf->set_priority(1);
269 scoped_ptr<CryptoHandshakeMessage>(
270 server.AddConfig(protobuf.get(), now));
271
272 EXPECT_TRUE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary));
273 EXPECT_FALSE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kOverride));
274
275 IPEndPoint ip4 = IPEndPoint(Loopback4(), 1);
276 IPEndPoint ip4d = IPEndPoint(ConvertIPv4NumberToIPv6Number(ip4.address()), 1);
277 IPEndPoint ip6 = IPEndPoint(Loopback6(), 2);
278
279 // Primary config generates configs that validate successfully.
280 const string token4 = peer.NewSourceAddressToken(kPrimary, ip4, rand, now);
281 const string token4d = peer.NewSourceAddressToken(kPrimary, ip4d, rand, now);
282 const string token6 = peer.NewSourceAddressToken(kPrimary, ip6, rand, now);
283 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
284 kPrimary, token4, ip4, now));
285 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
286 kPrimary, token4, ip4d, now));
287 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
288 peer.ValidateSourceAddressToken(kPrimary, token4, ip6, now));
289 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
290 kPrimary, token4d, ip4, now));
291 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
292 kPrimary, token4d, ip4d, now));
293 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
294 peer.ValidateSourceAddressToken(kPrimary, token4d, ip6, now));
295 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
296 kPrimary, token6, ip6, now));
297
298 // Override config generates configs that validate successfully.
299 const string override_token4 = peer.NewSourceAddressToken(
300 kOverride, ip4, rand, now);
301 const string override_token6 = peer.NewSourceAddressToken(
302 kOverride, ip6, rand, now);
303 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
304 kOverride, override_token4, ip4, now));
305 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
306 peer.ValidateSourceAddressToken(kOverride, override_token4, ip6,
307 now));
308 DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
309 kOverride, override_token6, ip6, now));
310
311 // Tokens generated by the primary config do not validate
312 // successfully against the override config, and vice versa.
313 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
314 peer.ValidateSourceAddressToken(kOverride, token4, ip4, now));
315 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
316 peer.ValidateSourceAddressToken(kOverride, token6, ip6, now));
317 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
318 peer.ValidateSourceAddressToken(kPrimary, override_token4, ip4,
319 now));
320 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
321 peer.ValidateSourceAddressToken(kPrimary, override_token6, ip6,
322 now));
323
324 // Validation fails after tokens expire.
325 now = original_time.Add(QuicTime::Delta::FromSeconds(86400 * 7));
326 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE,
327 peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
328
329 now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
330 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE,
331 peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
332 }
333
TEST(QuicCryptoServerConfigTest,ValidateServerNonce)334 TEST(QuicCryptoServerConfigTest, ValidateServerNonce) {
335 QuicRandom* rand = QuicRandom::GetInstance();
336 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
337 QuicCryptoServerConfigPeer peer(&server);
338
339 StringPiece message("hello world");
340 const size_t key_size = CryptoSecretBoxer::GetKeySize();
341 scoped_ptr<uint8[]> key(new uint8[key_size]);
342 memset(key.get(), 0x11, key_size);
343
344 CryptoSecretBoxer boxer;
345 boxer.SetKey(StringPiece(reinterpret_cast<char*>(key.get()), key_size));
346 const string box = boxer.Box(rand, message);
347 MockClock clock;
348 QuicWallTime now = clock.WallNow();
349 const QuicWallTime original_time = now;
350 EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE,
351 peer.ValidateServerNonce(box, now));
352
353 string server_nonce = peer.NewServerNonce(rand, now);
354 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
355 EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE,
356 peer.ValidateServerNonce(server_nonce, now));
357
358 now = original_time.Add(QuicTime::Delta::FromSeconds(1000 * 7));
359 server_nonce = peer.NewServerNonce(rand, now);
360 EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
361 }
362
363 class CryptoServerConfigsTest : public ::testing::Test {
364 public:
CryptoServerConfigsTest()365 CryptoServerConfigsTest()
366 : rand_(QuicRandom::GetInstance()),
367 config_(QuicCryptoServerConfig::TESTING, rand_),
368 test_peer_(&config_) {}
369
SetUp()370 virtual void SetUp() {
371 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
372 }
373
374 // SetConfigs constructs suitable config protobufs and calls SetConfigs on
375 // |config_|. The arguments are given as NULL-terminated pairs. The first of
376 // each pair is the server config ID of a Config. The second is the
377 // |primary_time| of that Config, given in epoch seconds. (Although note
378 // that, in these tests, time is set to 1000 seconds since the epoch.) For
379 // example:
380 // SetConfigs(NULL); // calls |config_.SetConfigs| with no protobufs.
381 //
382 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with
383 // // a |primary_time| of 900 and priority 1, and another with
384 // // a |primary_time| of 1000 and priority 2.
385
386 // CheckConfigs(
387 // "id1", 900, 1,
388 // "id2", 1000, 2,
389 // NULL);
390 //
391 // If the server config id starts with "INVALID" then the generated protobuf
392 // will be invalid.
SetConfigs(const char * server_config_id1,...)393 void SetConfigs(const char* server_config_id1, ...) {
394 const char kOrbit[] = "12345678";
395
396 va_list ap;
397 va_start(ap, server_config_id1);
398 bool has_invalid = false;
399 bool is_empty = true;
400
401 vector<QuicServerConfigProtobuf*> protobufs;
402 bool first = true;
403 for (;;) {
404 const char* server_config_id;
405 if (first) {
406 server_config_id = server_config_id1;
407 first = false;
408 } else {
409 server_config_id = va_arg(ap, const char*);
410 }
411
412 if (!server_config_id) {
413 break;
414 }
415
416 is_empty = false;
417 int primary_time = va_arg(ap, int);
418 int priority = va_arg(ap, int);
419
420 QuicCryptoServerConfig::ConfigOptions options;
421 options.id = server_config_id;
422 options.orbit = kOrbit;
423 QuicServerConfigProtobuf* protobuf(
424 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options));
425 protobuf->set_primary_time(primary_time);
426 protobuf->set_priority(priority);
427 if (string(server_config_id).find("INVALID") == 0) {
428 protobuf->clear_key();
429 has_invalid = true;
430 }
431 protobufs.push_back(protobuf);
432 }
433
434 ASSERT_EQ(!has_invalid && !is_empty,
435 config_.SetConfigs(protobufs, clock_.WallNow()));
436 STLDeleteElements(&protobufs);
437 }
438
439 protected:
440 QuicRandom* const rand_;
441 MockClock clock_;
442 QuicCryptoServerConfig config_;
443 QuicCryptoServerConfigPeer test_peer_;
444 };
445
TEST_F(CryptoServerConfigsTest,NoConfigs)446 TEST_F(CryptoServerConfigsTest, NoConfigs) {
447 test_peer_.CheckConfigs(NULL);
448 }
449
TEST_F(CryptoServerConfigsTest,MakePrimaryFirst)450 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
451 // Make sure that "b" is primary even though "a" comes first.
452 SetConfigs("a", 1100, 1,
453 "b", 900, 1,
454 NULL);
455 test_peer_.CheckConfigs(
456 "a", false,
457 "b", true,
458 NULL);
459 }
460
TEST_F(CryptoServerConfigsTest,MakePrimarySecond)461 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
462 // Make sure that a remains primary after b is added.
463 SetConfigs("a", 900, 1,
464 "b", 1100, 1,
465 NULL);
466 test_peer_.CheckConfigs(
467 "a", true,
468 "b", false,
469 NULL);
470 }
471
TEST_F(CryptoServerConfigsTest,Delete)472 TEST_F(CryptoServerConfigsTest, Delete) {
473 // Ensure that configs get deleted when removed.
474 SetConfigs("a", 800, 1,
475 "b", 900, 1,
476 "c", 1100, 1,
477 NULL);
478 test_peer_.CheckConfigs(
479 "a", false,
480 "b", true,
481 "c", false,
482 NULL);
483 SetConfigs("b", 900, 1,
484 "c", 1100, 1,
485 NULL);
486 test_peer_.CheckConfigs(
487 "b", true,
488 "c", false,
489 NULL);
490 }
491
TEST_F(CryptoServerConfigsTest,DeletePrimary)492 TEST_F(CryptoServerConfigsTest, DeletePrimary) {
493 // Ensure that deleting the primary config works.
494 SetConfigs("a", 800, 1,
495 "b", 900, 1,
496 "c", 1100, 1,
497 NULL);
498 test_peer_.CheckConfigs(
499 "a", false,
500 "b", true,
501 "c", false,
502 NULL);
503 SetConfigs("a", 800, 1,
504 "c", 1100, 1,
505 NULL);
506 test_peer_.CheckConfigs(
507 "a", true,
508 "c", false,
509 NULL);
510 }
511
TEST_F(CryptoServerConfigsTest,FailIfDeletingAllConfigs)512 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
513 // Ensure that configs get deleted when removed.
514 SetConfigs("a", 800, 1,
515 "b", 900, 1,
516 NULL);
517 test_peer_.CheckConfigs(
518 "a", false,
519 "b", true,
520 NULL);
521 SetConfigs(NULL);
522 // Config change is rejected, still using old configs.
523 test_peer_.CheckConfigs(
524 "a", false,
525 "b", true,
526 NULL);
527 }
528
TEST_F(CryptoServerConfigsTest,ChangePrimaryTime)529 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
530 // Check that updates to primary time get picked up.
531 SetConfigs("a", 400, 1,
532 "b", 800, 1,
533 "c", 1200, 1,
534 NULL);
535 test_peer_.SelectNewPrimaryConfig(500);
536 test_peer_.CheckConfigs(
537 "a", true,
538 "b", false,
539 "c", false,
540 NULL);
541 SetConfigs("a", 1200, 1,
542 "b", 800, 1,
543 "c", 400, 1,
544 NULL);
545 test_peer_.SelectNewPrimaryConfig(500);
546 test_peer_.CheckConfigs(
547 "a", false,
548 "b", false,
549 "c", true,
550 NULL);
551 }
552
TEST_F(CryptoServerConfigsTest,AllConfigsInThePast)553 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
554 // Check that the most recent config is selected.
555 SetConfigs("a", 400, 1,
556 "b", 800, 1,
557 "c", 1200, 1,
558 NULL);
559 test_peer_.SelectNewPrimaryConfig(1500);
560 test_peer_.CheckConfigs(
561 "a", false,
562 "b", false,
563 "c", true,
564 NULL);
565 }
566
TEST_F(CryptoServerConfigsTest,AllConfigsInTheFuture)567 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
568 // Check that the first config is selected.
569 SetConfigs("a", 400, 1,
570 "b", 800, 1,
571 "c", 1200, 1,
572 NULL);
573 test_peer_.SelectNewPrimaryConfig(100);
574 test_peer_.CheckConfigs(
575 "a", true,
576 "b", false,
577 "c", false,
578 NULL);
579 }
580
TEST_F(CryptoServerConfigsTest,SortByPriority)581 TEST_F(CryptoServerConfigsTest, SortByPriority) {
582 // Check that priority is used to decide on a primary config when
583 // configs have the same primary time.
584 SetConfigs("a", 900, 1,
585 "b", 900, 2,
586 "c", 900, 3,
587 NULL);
588 test_peer_.CheckConfigs(
589 "a", true,
590 "b", false,
591 "c", false,
592 NULL);
593 test_peer_.SelectNewPrimaryConfig(800);
594 test_peer_.CheckConfigs(
595 "a", true,
596 "b", false,
597 "c", false,
598 NULL);
599 test_peer_.SelectNewPrimaryConfig(1000);
600 test_peer_.CheckConfigs(
601 "a", true,
602 "b", false,
603 "c", false,
604 NULL);
605
606 // Change priorities and expect sort order to change.
607 SetConfigs("a", 900, 2,
608 "b", 900, 1,
609 "c", 900, 0,
610 NULL);
611 test_peer_.CheckConfigs(
612 "a", false,
613 "b", false,
614 "c", true,
615 NULL);
616 test_peer_.SelectNewPrimaryConfig(800);
617 test_peer_.CheckConfigs(
618 "a", false,
619 "b", false,
620 "c", true,
621 NULL);
622 test_peer_.SelectNewPrimaryConfig(1000);
623 test_peer_.CheckConfigs(
624 "a", false,
625 "b", false,
626 "c", true,
627 NULL);
628 }
629
TEST_F(CryptoServerConfigsTest,AdvancePrimary)630 TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
631 // Check that a new primary config is enabled at the right time.
632 SetConfigs("a", 900, 1,
633 "b", 1100, 1,
634 NULL);
635 test_peer_.SelectNewPrimaryConfig(1000);
636 test_peer_.CheckConfigs(
637 "a", true,
638 "b", false,
639 NULL);
640 test_peer_.SelectNewPrimaryConfig(1101);
641 test_peer_.CheckConfigs(
642 "a", false,
643 "b", true,
644 NULL);
645 }
646
TEST_F(CryptoServerConfigsTest,InvalidConfigs)647 TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
648 // Ensure that invalid configs don't change anything.
649 SetConfigs("a", 800, 1,
650 "b", 900, 1,
651 "c", 1100, 1,
652 NULL);
653 test_peer_.CheckConfigs(
654 "a", false,
655 "b", true,
656 "c", false,
657 NULL);
658 SetConfigs("a", 800, 1,
659 "c", 1100, 1,
660 "INVALID1", 1000, 1,
661 NULL);
662 test_peer_.CheckConfigs(
663 "a", false,
664 "b", true,
665 "c", false,
666 NULL);
667 }
668
669 } // namespace test
670 } // namespace net
671