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