// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/crypto/quic_crypto_server_config.h"

#include <stdarg.h>

#include "base/stl_util.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/crypto/crypto_handshake_message.h"
#include "net/quic/crypto/crypto_secret_boxer.h"
#include "net/quic/crypto/crypto_server_config_protobuf.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/crypto/strike_register_client.h"
#include "net/quic/quic_flags.h"
#include "net/quic/quic_time.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::StringPiece;
using std::make_pair;
using std::map;
using std::pair;
using std::string;
using std::vector;

namespace net {
namespace test {

class QuicCryptoServerConfigPeer {
 public:
  explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
      : server_config_(server_config) {}

  scoped_refptr<QuicCryptoServerConfig::Config> GetConfig(string config_id) {
    base::AutoLock locked(server_config_->configs_lock_);
    if (config_id == "<primary>") {
      return scoped_refptr<QuicCryptoServerConfig::Config>(
          server_config_->primary_config_);
    } else {
      return server_config_->GetConfigWithScid(config_id);
    }
  }

  bool ConfigHasDefaultSourceAddressTokenBoxer(string config_id) {
    scoped_refptr<QuicCryptoServerConfig::Config> config = GetConfig(config_id);
    return config->source_address_token_boxer ==
        &(server_config_->default_source_address_token_boxer_);
  }

  string NewSourceAddressToken(
      string config_id,
      const IPEndPoint& ip,
      QuicRandom* rand,
      QuicWallTime now) {
    return NewSourceAddressToken(config_id, ip, rand, now, NULL);
  }

  string NewSourceAddressToken(
      string config_id,
      const IPEndPoint& ip,
      QuicRandom* rand,
      QuicWallTime now,
      CachedNetworkParameters* cached_network_params) {
    return server_config_->NewSourceAddressToken(
        *GetConfig(config_id), ip, rand, now, cached_network_params);
  }

  HandshakeFailureReason ValidateSourceAddressToken(string config_id,
                                                    StringPiece srct,
                                                    const IPEndPoint& ip,
                                                    QuicWallTime now) {
    return ValidateSourceAddressToken(config_id, srct, ip, now, NULL);
  }

  HandshakeFailureReason ValidateSourceAddressToken(
      string config_id,
      StringPiece srct,
      const IPEndPoint& ip,
      QuicWallTime now,
      CachedNetworkParameters* cached_network_params) {
    return server_config_->ValidateSourceAddressToken(
        *GetConfig(config_id), srct, ip, now, cached_network_params);
  }

  string NewServerNonce(QuicRandom* rand, QuicWallTime now) const {
    return server_config_->NewServerNonce(rand, now);
  }

  HandshakeFailureReason ValidateServerNonce(StringPiece token,
                                             QuicWallTime now) {
    return server_config_->ValidateServerNonce(token, now);
  }

  base::Lock* GetStrikeRegisterClientLock() {
    return &server_config_->strike_register_client_lock_;
  }

  // CheckConfigs compares the state of the Configs in |server_config_| to the
  // description given as arguments. The arguments are given as
  // nullptr-terminated pairs. The first of each pair is the server config ID of
  // a Config. The second is a boolean describing whether the config is the
  // primary. For example:
  //   CheckConfigs(nullptr);  // checks that no Configs are loaded.
  //
  //   // Checks that exactly three Configs are loaded with the given IDs and
  //   // status.
  //   CheckConfigs(
  //     "id1", false,
  //     "id2", true,
  //     "id3", false,
  //     nullptr);
  void CheckConfigs(const char* server_config_id1, ...) {
    va_list ap;
    va_start(ap, server_config_id1);

    vector<pair<ServerConfigID, bool> > expected;
    bool first = true;
    for (;;) {
      const char* server_config_id;
      if (first) {
        server_config_id = server_config_id1;
        first = false;
      } else {
        server_config_id = va_arg(ap, const char*);
      }

      if (!server_config_id) {
        break;
      }

      // varargs will promote the value to an int so we have to read that from
      // the stack and cast down.
      const bool is_primary = static_cast<bool>(va_arg(ap, int));
      expected.push_back(make_pair(server_config_id, is_primary));
    }

    va_end(ap);

    base::AutoLock locked(server_config_->configs_lock_);

    ASSERT_EQ(expected.size(), server_config_->configs_.size())
        << ConfigsDebug();

    for (QuicCryptoServerConfig::ConfigMap::const_iterator
             i = server_config_->configs_.begin();
         i != server_config_->configs_.end(); ++i) {
      bool found = false;
      for (vector<pair<ServerConfigID, bool> >::iterator j = expected.begin();
           j != expected.end(); ++j) {
        if (i->first == j->first && i->second->is_primary == j->second) {
          found = true;
          j->first.clear();
          break;
        }
      }

      ASSERT_TRUE(found) << "Failed to find match for " << i->first
                         << " in configs:\n" << ConfigsDebug();
    }
  }

  // ConfigsDebug returns a string that contains debugging information about
  // the set of Configs loaded in |server_config_| and their status.
  // ConfigsDebug() should be called after acquiring
  // server_config_->configs_lock_.
  string ConfigsDebug() {
    if (server_config_->configs_.empty()) {
      return "No Configs in QuicCryptoServerConfig";
    }

    string s;

    for (QuicCryptoServerConfig::ConfigMap::const_iterator
             i = server_config_->configs_.begin();
         i != server_config_->configs_.end(); ++i) {
      const scoped_refptr<QuicCryptoServerConfig::Config> config = i->second;
      if (config->is_primary) {
        s += "(primary) ";
      } else {
        s += "          ";
      }
      s += config->id;
      s += "\n";
    }

    return s;
  }

  void SelectNewPrimaryConfig(int seconds) {
    base::AutoLock locked(server_config_->configs_lock_);
    server_config_->SelectNewPrimaryConfig(
        QuicWallTime::FromUNIXSeconds(seconds));
  }

 private:
  const QuicCryptoServerConfig* server_config_;
};

class TestStrikeRegisterClient : public StrikeRegisterClient {
 public:
  explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
      : config_(config),
        is_known_orbit_called_(false) {
  }

  bool IsKnownOrbit(StringPiece orbit) const override {
    // Ensure that the strike register client lock is not held.
    QuicCryptoServerConfigPeer peer(config_);
    base::Lock* m = peer.GetStrikeRegisterClientLock();
    // In Chromium, we will dead lock if the lock is held by the current thread.
    // Chromium doesn't have AssertNotHeld API call.
    // m->AssertNotHeld();
    base::AutoLock lock(*m);

    is_known_orbit_called_ = true;
    return true;
  }

  void VerifyNonceIsValidAndUnique(StringPiece nonce,
                                   QuicWallTime now,
                                   ResultCallback* cb) override {
    LOG(FATAL) << "Not implemented";
  }

  bool is_known_orbit_called() { return is_known_orbit_called_; }

 private:
  QuicCryptoServerConfig* config_;
  mutable bool is_known_orbit_called_;
};

TEST(QuicCryptoServerConfigTest, ServerConfig) {
  QuicRandom* rand = QuicRandom::GetInstance();
  QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
  MockClock clock;

  scoped_ptr<CryptoHandshakeMessage>(
      server.AddDefaultConfig(rand, &clock,
                              QuicCryptoServerConfig::ConfigOptions()));
}

TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
  QuicRandom* rand = QuicRandom::GetInstance();
  QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
  MockClock clock;

  TestStrikeRegisterClient* strike_register =
      new TestStrikeRegisterClient(&server);
  server.SetStrikeRegisterClient(strike_register);

  QuicCryptoServerConfig::ConfigOptions options;
  scoped_ptr<CryptoHandshakeMessage>(
      server.AddDefaultConfig(rand, &clock, options));
  EXPECT_TRUE(strike_register->is_known_orbit_called());
}

TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
  ValueRestore<bool> old_flag(&FLAGS_quic_store_cached_network_params_from_chlo,
                              true);
  const string kPrimary = "<primary>";
  const string kOverride = "Config with custom source address token key";

  MockClock clock;
  clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));

  QuicWallTime now = clock.WallNow();
  const QuicWallTime original_time = now;

  QuicRandom* rand = QuicRandom::GetInstance();
  QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
  QuicCryptoServerConfigPeer peer(&server);

  scoped_ptr<CryptoHandshakeMessage>(
      server.AddDefaultConfig(rand, &clock,
                              QuicCryptoServerConfig::ConfigOptions()));

  // Add a config that overrides the default boxer.
  QuicCryptoServerConfig::ConfigOptions options;
  options.id = kOverride;
  scoped_ptr<QuicServerConfigProtobuf> protobuf(
      QuicCryptoServerConfig::GenerateConfig(rand, &clock, options));
  protobuf->set_source_address_token_secret_override("a secret key");
  // Lower priority than the default config.
  protobuf->set_priority(1);
  scoped_ptr<CryptoHandshakeMessage>(
      server.AddConfig(protobuf.get(), now));

  EXPECT_TRUE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary));
  EXPECT_FALSE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kOverride));

  IPEndPoint ip4 = IPEndPoint(Loopback4(), 1);
  IPEndPoint ip4d = IPEndPoint(ConvertIPv4NumberToIPv6Number(ip4.address()), 1);
  IPEndPoint ip6 = IPEndPoint(Loopback6(), 2);

  // Primary config generates configs that validate successfully.
  const string token4 = peer.NewSourceAddressToken(kPrimary, ip4, rand, now);
  const string token4d = peer.NewSourceAddressToken(kPrimary, ip4d, rand, now);
  const string token6 = peer.NewSourceAddressToken(kPrimary, ip6, rand, now);
  EXPECT_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kPrimary, token4, ip4, now));
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kPrimary, token4, ip4d, now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, token4, ip6, now));
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kPrimary, token4d, ip4, now));
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kPrimary, token4d, ip4d, now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, token4d, ip6, now));
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kPrimary, token6, ip6, now));

  // Override config generates configs that validate successfully.
  const string override_token4 = peer.NewSourceAddressToken(
      kOverride, ip4, rand, now);
  const string override_token6 = peer.NewSourceAddressToken(
      kOverride, ip6, rand, now);
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kOverride, override_token4, ip4, now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
            peer.ValidateSourceAddressToken(kOverride, override_token4, ip6,
                                            now));
  DCHECK_EQ(HANDSHAKE_OK, peer.ValidateSourceAddressToken(
      kOverride, override_token6, ip6, now));

  // Tokens generated by the primary config do not validate
  // successfully against the override config, and vice versa.
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
            peer.ValidateSourceAddressToken(kOverride, token4, ip4, now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
            peer.ValidateSourceAddressToken(kOverride, token6, ip6, now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, override_token4, ip4,
                                            now));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, override_token6, ip6,
                                            now));

  // Validation fails after tokens expire.
  now = original_time.Add(QuicTime::Delta::FromSeconds(86400 * 7));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));

  now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
  DCHECK_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE,
            peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));

  // Make sure that if the source address token contains CachedNetworkParameters
  // that this gets written to ValidateSourceAddressToken output argument.
  CachedNetworkParameters cached_network_params_input;
  cached_network_params_input.set_bandwidth_estimate_bytes_per_second(1234);
  const string token4_with_cached_network_params = peer.NewSourceAddressToken(
      kPrimary, ip4, rand, now, &cached_network_params_input);

  CachedNetworkParameters cached_network_params_output;
  EXPECT_NE(cached_network_params_output, cached_network_params_input);
  peer.ValidateSourceAddressToken(kPrimary, token4_with_cached_network_params,
                                  ip4, now, &cached_network_params_output);
  // TODO(rtenneti): For server, enable the following check after serialization
  // of optional CachedNetworkParameters is implemented.
  // EXPECT_EQ(cached_network_params_output, cached_network_params_input);
}

TEST(QuicCryptoServerConfigTest, ValidateServerNonce) {
  QuicRandom* rand = QuicRandom::GetInstance();
  QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
  QuicCryptoServerConfigPeer peer(&server);

  StringPiece message("hello world");
  const size_t key_size = CryptoSecretBoxer::GetKeySize();
  scoped_ptr<uint8[]> key(new uint8[key_size]);
  memset(key.get(), 0x11, key_size);

  CryptoSecretBoxer boxer;
  boxer.SetKey(StringPiece(reinterpret_cast<char*>(key.get()), key_size));
  const string box = boxer.Box(rand, message);
  MockClock clock;
  QuicWallTime now = clock.WallNow();
  const QuicWallTime original_time = now;
  EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE,
            peer.ValidateServerNonce(box, now));

  string server_nonce = peer.NewServerNonce(rand, now);
  EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
  EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE,
            peer.ValidateServerNonce(server_nonce, now));

  now = original_time.Add(QuicTime::Delta::FromSeconds(1000 * 7));
  server_nonce = peer.NewServerNonce(rand, now);
  EXPECT_EQ(HANDSHAKE_OK, peer.ValidateServerNonce(server_nonce, now));
}

class CryptoServerConfigsTest : public ::testing::Test {
 public:
  CryptoServerConfigsTest()
      : rand_(QuicRandom::GetInstance()),
        config_(QuicCryptoServerConfig::TESTING, rand_),
        test_peer_(&config_) {}

  void SetUp() override {
    clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
  }

  // SetConfigs constructs suitable config protobufs and calls SetConfigs on
  // |config_|. The arguments are given as nullptr-terminated pairs. The first
  // of each pair is the server config ID of a Config. The second is the
  // |primary_time| of that Config, given in epoch seconds. (Although note that,
  // in these tests, time is set to 1000 seconds since the epoch.) For example:
  //   SetConfigs(nullptr);  // calls |config_.SetConfigs| with no protobufs.
  //
  //   // Calls |config_.SetConfigs| with two protobufs: one for a Config with
  //   // a |primary_time| of 900 and priority 1, and another with
  //   // a |primary_time| of 1000 and priority 2.

  //   CheckConfigs(
  //     "id1", 900, 1,
  //     "id2", 1000, 2,
  //     nullptr);
  //
  // If the server config id starts with "INVALID" then the generated protobuf
  // will be invalid.
  void SetConfigs(const char* server_config_id1, ...) {
    const char kOrbit[] = "12345678";

    va_list ap;
    va_start(ap, server_config_id1);
    bool has_invalid = false;
    bool is_empty = true;

    vector<QuicServerConfigProtobuf*> protobufs;
    bool first = true;
    for (;;) {
      const char* server_config_id;
      if (first) {
        server_config_id = server_config_id1;
        first = false;
      } else {
        server_config_id = va_arg(ap, const char*);
      }

      if (!server_config_id) {
        break;
      }

      is_empty = false;
      int primary_time = va_arg(ap, int);
      int priority = va_arg(ap, int);

      QuicCryptoServerConfig::ConfigOptions options;
      options.id = server_config_id;
      options.orbit = kOrbit;
      QuicServerConfigProtobuf* protobuf(
          QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options));
      protobuf->set_primary_time(primary_time);
      protobuf->set_priority(priority);
      if (string(server_config_id).find("INVALID") == 0) {
        protobuf->clear_key();
        has_invalid = true;
      }
      protobufs.push_back(protobuf);
    }

    ASSERT_EQ(!has_invalid && !is_empty,
              config_.SetConfigs(protobufs, clock_.WallNow()));
    STLDeleteElements(&protobufs);
  }

 protected:
  QuicRandom* const rand_;
  MockClock clock_;
  QuicCryptoServerConfig config_;
  QuicCryptoServerConfigPeer test_peer_;
};

TEST_F(CryptoServerConfigsTest, NoConfigs) {
  test_peer_.CheckConfigs(nullptr);
}

TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
  // Make sure that "b" is primary even though "a" comes first.
  SetConfigs("a", 1100, 1,
             "b", 900, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
  // Make sure that a remains primary after b is added.
  SetConfigs("a", 900, 1,
             "b", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, Delete) {
  // Ensure that configs get deleted when removed.
  SetConfigs("a", 800, 1,
             "b", 900, 1,
             "c", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      "c", false,
      nullptr);
  SetConfigs("b", 900, 1,
             "c", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "b", true,
      "c", false,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, DeletePrimary) {
  // Ensure that deleting the primary config works.
  SetConfigs("a", 800, 1,
             "b", 900, 1,
             "c", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      "c", false,
      nullptr);
  SetConfigs("a", 800, 1,
             "c", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", true,
      "c", false,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
  // Ensure that configs get deleted when removed.
  SetConfigs("a", 800, 1,
             "b", 900, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      nullptr);
  SetConfigs(nullptr);
  // Config change is rejected, still using old configs.
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
  // Check that updates to primary time get picked up.
  SetConfigs("a", 400, 1,
             "b", 800, 1,
             "c", 1200, 1,
             nullptr);
  test_peer_.SelectNewPrimaryConfig(500);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      "c", false,
      nullptr);
  SetConfigs("a", 1200, 1,
             "b", 800, 1,
             "c", 400, 1,
             nullptr);
  test_peer_.SelectNewPrimaryConfig(500);
  test_peer_.CheckConfigs(
      "a", false,
      "b", false,
      "c", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
  // Check that the most recent config is selected.
  SetConfigs("a", 400, 1,
             "b", 800, 1,
             "c", 1200, 1,
             nullptr);
  test_peer_.SelectNewPrimaryConfig(1500);
  test_peer_.CheckConfigs(
      "a", false,
      "b", false,
      "c", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
  // Check that the first config is selected.
  SetConfigs("a", 400, 1,
             "b", 800, 1,
             "c", 1200, 1,
             nullptr);
  test_peer_.SelectNewPrimaryConfig(100);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      "c", false,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, SortByPriority) {
  // Check that priority is used to decide on a primary config when
  // configs have the same primary time.
  SetConfigs("a", 900, 1,
             "b", 900, 2,
             "c", 900, 3,
             nullptr);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      "c", false,
      nullptr);
  test_peer_.SelectNewPrimaryConfig(800);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      "c", false,
      nullptr);
  test_peer_.SelectNewPrimaryConfig(1000);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      "c", false,
      nullptr);

  // Change priorities and expect sort order to change.
  SetConfigs("a", 900, 2,
             "b", 900, 1,
             "c", 900, 0,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", false,
      "c", true,
      nullptr);
  test_peer_.SelectNewPrimaryConfig(800);
  test_peer_.CheckConfigs(
      "a", false,
      "b", false,
      "c", true,
      nullptr);
  test_peer_.SelectNewPrimaryConfig(1000);
  test_peer_.CheckConfigs(
      "a", false,
      "b", false,
      "c", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
  // Check that a new primary config is enabled at the right time.
  SetConfigs("a", 900, 1,
             "b", 1100, 1,
             nullptr);
  test_peer_.SelectNewPrimaryConfig(1000);
  test_peer_.CheckConfigs(
      "a", true,
      "b", false,
      nullptr);
  test_peer_.SelectNewPrimaryConfig(1101);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      nullptr);
}

TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
  // Ensure that invalid configs don't change anything.
  SetConfigs("a", 800, 1,
             "b", 900, 1,
             "c", 1100, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      "c", false,
      nullptr);
  SetConfigs("a", 800, 1,
             "c", 1100, 1,
             "INVALID1", 1000, 1,
             nullptr);
  test_peer_.CheckConfigs(
      "a", false,
      "b", true,
      "c", false,
      nullptr);
}

}  // namespace test
}  // namespace net
