Upstream version 10.39.225.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       IPEndPoint ip,
56       QuicRandom* rand,
57       QuicWallTime now) {
58     return server_config_->NewSourceAddressToken(
59         *GetConfig(config_id), ip, rand, now, NULL);
60   }
61
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
70   string NewServerNonce(QuicRandom* rand, QuicWallTime now) const {
71     return server_config_->NewServerNonce(rand, now);
72   }
73
74   HandshakeFailureReason ValidateServerNonce(StringPiece token,
75                                              QuicWallTime now) {
76     return server_config_->ValidateServerNonce(token, now);
77   }
78
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);
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_.
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
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:
186   explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
187       : config_(config),
188         is_known_orbit_called_(false) {
189   }
190
191   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
204   virtual void VerifyNonceIsValidAndUnique(
205       StringPiece nonce,
206       QuicWallTime now,
207       ResultCallback* cb) OVERRIDE {
208     LOG(FATAL) << "Not implemented";
209   }
210
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
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
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
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
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:
365   CryptoServerConfigsTest()
366       : rand_(QuicRandom::GetInstance()),
367         config_(QuicCryptoServerConfig::TESTING, rand_),
368         test_peer_(&config_) {}
369
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.
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
446 TEST_F(CryptoServerConfigsTest, NoConfigs) {
447   test_peer_.CheckConfigs(NULL);
448 }
449
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
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
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
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
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
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
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
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
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
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
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