blob: 26f7dcb92fc5a73e104ac0853789cd9eb716e3d3 [file] [log] [blame] [edit]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net-base/rtnl_handler.h"
#include <net/if.h>
#include <sys/socket.h>
// NOLINTNEXTLINE(build/include_alpha)
#include <linux/netlink.h> // Needs typedefs from sys/socket.h.
#include <linux/rtnetlink.h>
#include <sys/ioctl.h>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <base/functional/bind.h>
#include <base/test/test_future.h>
#include <base/test/task_environment.h>
#include <gtest/gtest.h>
#include "net-base/byte_utils.h"
#include "net-base/mac_address.h"
#include "net-base/mock_socket.h"
#include "net-base/rtnl_message.h"
using testing::_;
using testing::A;
using testing::AtLeast;
using testing::DoAll;
using testing::ElementsAre;
using testing::HasSubstr;
using testing::Invoke;
using testing::Return;
using testing::ReturnArg;
using testing::StrictMock;
using testing::Test;
namespace net_base {
namespace {
const int kTestInterfaceIndex = 4;
ACTION(SetInterfaceIndex) {
if (arg1) {
reinterpret_cast<struct ifreq*>(arg1)->ifr_ifindex = kTestInterfaceIndex;
}
}
MATCHER_P(MessageType, message_type, "") {
return std::get<0>(arg).type() == message_type;
}
std::unique_ptr<RTNLMessage> CreateFakeMessage() {
return std::make_unique<RTNLMessage>(
RTNLMessage::kTypeLink, RTNLMessage::kModeGet, 0, 0, 0, 0, AF_UNSPEC);
}
std::optional<size_t> SimulateSend(base::span<const uint8_t> buf, int flags) {
return buf.size();
}
} // namespace
class RTNLHandlerTest : public Test {
public:
RTNLHandlerTest()
: callback_(base::BindRepeating(&RTNLHandlerTest::HandlerCallback,
base::Unretained(this))) {}
void SetUp() override {
auto socket_factory = std::make_unique<MockSocketFactory>();
socket_factory_ = socket_factory.get();
RTNLHandler::GetInstance()->socket_factory_ = std::move(socket_factory);
}
void TearDown() override { RTNLHandler::GetInstance()->Stop(); }
MockSocket* GetMockSocket() {
return reinterpret_cast<MockSocket*>(
RTNLHandler::GetInstance()->rtnl_socket_.get());
}
uint32_t GetRequestSequence() {
return RTNLHandler::GetInstance()->request_sequence_;
}
void SetRequestSequence(uint32_t sequence) {
RTNLHandler::GetInstance()->request_sequence_ = sequence;
}
bool SendMessageWithErrorMask(std::unique_ptr<RTNLMessage> message,
const RTNLHandler::ErrorMask& error_mask,
uint32_t* msg_seq) {
return RTNLHandler::GetInstance()->SendMessageWithErrorMask(
std::move(message), error_mask, msg_seq);
}
bool IsSequenceInErrorMaskWindow(uint32_t sequence) {
return RTNLHandler::GetInstance()->IsSequenceInErrorMaskWindow(sequence);
}
void SetErrorMask(uint32_t sequence,
const RTNLHandler::ErrorMask& error_mask) {
return RTNLHandler::GetInstance()->SetErrorMask(sequence, error_mask);
}
RTNLHandler::ErrorMask GetAndClearErrorMask(uint32_t sequence) {
return RTNLHandler::GetInstance()->GetAndClearErrorMask(sequence);
}
uint32_t GetErrorWindowSize() { return RTNLHandler::kErrorWindowSize; }
void StoreRequest(std::unique_ptr<RTNLMessage> request) {
RTNLHandler::GetInstance()->StoreRequest(std::move(request));
}
std::unique_ptr<RTNLMessage> PopStoredRequest(uint32_t seq) {
return RTNLHandler::GetInstance()->PopStoredRequest(seq);
}
uint32_t CalculateStoredRequestWindowSize() {
return RTNLHandler::GetInstance()->CalculateStoredRequestWindowSize();
}
uint32_t stored_request_window_size() {
return RTNLHandler::GetInstance()->kStoredRequestWindowSize;
}
uint32_t oldest_request_sequence() {
return RTNLHandler::GetInstance()->oldest_request_sequence_;
}
MOCK_METHOD(void, HandlerCallback, (const RTNLMessage&));
protected:
static const int kTestSocket;
static const int kTestDeviceIndex;
static const char kTestDeviceName[];
void AddLink();
void AddNeighbor();
void StartRTNLHandler();
void StopRTNLHandler();
void ReturnError(uint32_t sequence, int error_number);
MockSocketFactory* socket_factory_; // Owned by RTNLHandler
base::RepeatingCallback<void(const RTNLMessage&)> callback_;
private:
base::test::TaskEnvironment task_environment_{
// required by base::FileDescriptorWatcher.
base::test::TaskEnvironment::MainThreadType::IO,
base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY};
};
const int RTNLHandlerTest::kTestSocket = 123;
const int RTNLHandlerTest::kTestDeviceIndex = 123456;
const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
void RTNLHandlerTest::StartRTNLHandler() {
EXPECT_CALL(*socket_factory_, CreateNetlink(NETLINK_ROUTE, _, _))
.WillOnce(Return(std::make_unique<MockSocket>()));
RTNLHandler::GetInstance()->Start(0);
}
void RTNLHandlerTest::StopRTNLHandler() {
RTNLHandler::GetInstance()->Stop();
EXPECT_EQ(GetMockSocket(), nullptr);
}
void RTNLHandlerTest::AddLink() {
RTNLMessage message(RTNLMessage::kTypeLink, RTNLMessage::kModeAdd, 0, 0, 0,
kTestDeviceIndex, AF_INET);
message.SetAttribute(static_cast<uint16_t>(IFLA_IFNAME),
byte_utils::StringToCStringBytes(kTestDeviceName));
const auto encoded = message.Encode();
RTNLHandler::GetInstance()->ParseRTNL(encoded);
}
void RTNLHandlerTest::AddNeighbor() {
RTNLMessage message(RTNLMessage::kTypeNeighbor, RTNLMessage::kModeAdd, 0, 0,
0, kTestDeviceIndex, AF_INET);
const auto encoded = message.Encode();
RTNLHandler::GetInstance()->ParseRTNL(encoded);
}
void RTNLHandlerTest::ReturnError(uint32_t sequence, int error_number) {
struct {
struct nlmsghdr hdr;
struct nlmsgerr err;
} errmsg;
memset(&errmsg, 0, sizeof(errmsg));
errmsg.hdr.nlmsg_type = NLMSG_ERROR;
errmsg.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(errmsg.err));
errmsg.hdr.nlmsg_seq = sequence;
errmsg.err.error = -error_number;
RTNLHandler::GetInstance()->ParseRTNL(byte_utils::AsBytes(errmsg));
}
TEST_F(RTNLHandlerTest, ListenersInvoked) {
StartRTNLHandler();
std::unique_ptr<RTNLListener> link_listener(
new RTNLListener(RTNLHandler::kRequestLink, callback_));
std::unique_ptr<RTNLListener> neighbor_listener(
new RTNLListener(RTNLHandler::kRequestNeighbor, callback_));
EXPECT_CALL(*this, HandlerCallback(A<const RTNLMessage&>()))
.With(MessageType(RTNLMessage::kTypeLink));
EXPECT_CALL(*this, HandlerCallback(A<const RTNLMessage&>()))
.With(MessageType(RTNLMessage::kTypeNeighbor));
AddLink();
AddNeighbor();
StopRTNLHandler();
}
TEST_F(RTNLHandlerTest, GetInterfaceName) {
EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
{
struct ifreq ifr;
std::string name(sizeof(ifr.ifr_name), 'x');
EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(name));
}
}
TEST_F(RTNLHandlerTest, GetInterfaceNameFailToCreateSocket) {
EXPECT_CALL(*socket_factory_, Create(PF_INET, _, 0))
.WillOnce(Return(nullptr));
EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
}
TEST_F(RTNLHandlerTest, GetInterfaceNameFailToIoctl) {
EXPECT_CALL(*socket_factory_, Create(PF_INET, _, 0)).WillOnce([]() {
auto socket = std::make_unique<MockSocket>();
EXPECT_CALL(*socket, Ioctl(SIOCGIFINDEX, _)).WillOnce(Return(std::nullopt));
return socket;
});
EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));
}
TEST_F(RTNLHandlerTest, GetInterfaceNameSuccess) {
EXPECT_CALL(*socket_factory_, Create(PF_INET, _, 0)).WillOnce([]() {
auto socket = std::make_unique<MockSocket>();
EXPECT_CALL(*socket, Ioctl(SIOCGIFINDEX, _))
.WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
return socket;
});
EXPECT_EQ(kTestInterfaceIndex,
RTNLHandler::GetInstance()->GetInterfaceIndex("usb0"));
}
TEST_F(RTNLHandlerTest, IsSequenceInErrorMaskWindow) {
const uint32_t kRequestSequence = 1234;
SetRequestSequence(kRequestSequence);
EXPECT_FALSE(IsSequenceInErrorMaskWindow(kRequestSequence + 1));
EXPECT_TRUE(IsSequenceInErrorMaskWindow(kRequestSequence));
EXPECT_TRUE(IsSequenceInErrorMaskWindow(kRequestSequence - 1));
EXPECT_TRUE(
IsSequenceInErrorMaskWindow(kRequestSequence - GetErrorWindowSize() + 1));
EXPECT_FALSE(
IsSequenceInErrorMaskWindow(kRequestSequence - GetErrorWindowSize()));
EXPECT_FALSE(
IsSequenceInErrorMaskWindow(kRequestSequence - GetErrorWindowSize() - 1));
}
TEST_F(RTNLHandlerTest, SendMessageReturnsErrorAndAdvancesSequenceNumber) {
StartRTNLHandler();
const uint32_t kSequenceNumber = 123;
SetRequestSequence(kSequenceNumber);
EXPECT_CALL(*GetMockSocket(), Send(_, 0)).WillOnce(Return(std::nullopt));
uint32_t seq = 0;
EXPECT_FALSE(
RTNLHandler::GetInstance()->SendMessage(CreateFakeMessage(), &seq));
// |seq| should not be set if there was a failure.
EXPECT_EQ(seq, 0);
// Sequence number should still increment even if there was a failure.
EXPECT_EQ(kSequenceNumber + 1, GetRequestSequence());
StopRTNLHandler();
}
TEST_F(RTNLHandlerTest, SendMessageWithEmptyMask) {
StartRTNLHandler();
const uint32_t kSequenceNumber = 123;
SetRequestSequence(kSequenceNumber);
SetErrorMask(kSequenceNumber, {1, 2, 3});
EXPECT_CALL(*GetMockSocket(), Send(_, 0))
.WillOnce(testing::Invoke(SimulateSend));
uint32_t seq;
EXPECT_TRUE(SendMessageWithErrorMask(CreateFakeMessage(), {}, &seq));
EXPECT_EQ(seq, kSequenceNumber);
EXPECT_EQ(kSequenceNumber + 1, GetRequestSequence());
EXPECT_TRUE(GetAndClearErrorMask(kSequenceNumber).empty());
StopRTNLHandler();
}
TEST_F(RTNLHandlerTest, SendMessageWithErrorMask) {
StartRTNLHandler();
const uint32_t kSequenceNumber = 123;
SetRequestSequence(kSequenceNumber);
EXPECT_CALL(*GetMockSocket(), Send(_, 0))
.WillOnce(testing::Invoke(SimulateSend));
uint32_t seq;
EXPECT_TRUE(SendMessageWithErrorMask(CreateFakeMessage(), {1, 2, 3}, &seq));
EXPECT_EQ(seq, kSequenceNumber);
EXPECT_EQ(kSequenceNumber + 1, GetRequestSequence());
EXPECT_TRUE(GetAndClearErrorMask(kSequenceNumber + 1).empty());
EXPECT_THAT(GetAndClearErrorMask(kSequenceNumber), ElementsAre(1, 2, 3));
// A second call to GetAndClearErrorMask() returns an empty vector.
EXPECT_TRUE(GetAndClearErrorMask(kSequenceNumber).empty());
StopRTNLHandler();
}
TEST_F(RTNLHandlerTest, SendMessageInferredErrorMasks) {
StartRTNLHandler();
EXPECT_CALL(*GetMockSocket(), Send(_, 0))
.WillRepeatedly(testing::Invoke(SimulateSend));
struct {
RTNLMessage::Type type;
RTNLMessage::Mode mode;
RTNLHandler::ErrorMask mask;
} expectations[] = {
{RTNLMessage::kTypeLink, RTNLMessage::kModeGet, {}},
{RTNLMessage::kTypeLink, RTNLMessage::kModeAdd, {EEXIST}},
{RTNLMessage::kTypeLink, RTNLMessage::kModeDelete, {ESRCH, ENODEV}},
{RTNLMessage::kTypeAddress,
RTNLMessage::kModeDelete,
{ESRCH, ENODEV, EADDRNOTAVAIL}}};
const uint32_t kSequenceNumber = 123;
for (const auto& expectation : expectations) {
SetRequestSequence(kSequenceNumber);
auto message = std::make_unique<RTNLMessage>(
expectation.type, expectation.mode, 0, 0, 0, 0, AF_UNSPEC);
EXPECT_TRUE(
RTNLHandler::GetInstance()->SendMessage(std::move(message), nullptr));
EXPECT_EQ(expectation.mask, GetAndClearErrorMask(kSequenceNumber));
}
}
TEST_F(RTNLHandlerTest, BasicStoreRequest) {
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
const uint32_t kSequenceNumber1 = 123;
auto request = CreateFakeMessage();
request->set_seq(kSequenceNumber1);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber2 = 124;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber2);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber3 =
kSequenceNumber1 + stored_request_window_size() - 1;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber3);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), stored_request_window_size());
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
EXPECT_NE(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(),
stored_request_window_size() - 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber2);
EXPECT_NE(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber3);
EXPECT_NE(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
}
TEST_F(RTNLHandlerTest, StoreRequestLargerThanWindow) {
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
const uint32_t kSequenceNumber1 = 123;
auto request = CreateFakeMessage();
request->set_seq(kSequenceNumber1);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber2 = 124;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber2);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber3 =
kSequenceNumber1 + stored_request_window_size();
request = CreateFakeMessage();
request->set_seq(kSequenceNumber3);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), stored_request_window_size());
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber2);
const uint32_t kSequenceNumber4 =
kSequenceNumber2 + stored_request_window_size();
request = CreateFakeMessage();
request->set_seq(kSequenceNumber4);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber3);
EXPECT_EQ(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_NE(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_NE(PopStoredRequest(kSequenceNumber4), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber4), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
}
TEST_F(RTNLHandlerTest, OverflowStoreRequest) {
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
const uint32_t kSequenceNumber1 = std::numeric_limits<uint32_t>::max();
auto request = CreateFakeMessage();
request->set_seq(kSequenceNumber1);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber2 = kSequenceNumber1 + 1;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber2);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber3 =
kSequenceNumber1 + stored_request_window_size() - 1;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber3);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), stored_request_window_size());
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
EXPECT_NE(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(),
stored_request_window_size() - 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber2);
EXPECT_NE(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber3);
EXPECT_NE(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
}
TEST_F(RTNLHandlerTest, OverflowStoreRequestLargerThanWindow) {
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
const uint32_t kSequenceNumber1 = std::numeric_limits<uint32_t>::max();
auto request = CreateFakeMessage();
request->set_seq(kSequenceNumber1);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber2 = kSequenceNumber1 + 1;
request = CreateFakeMessage();
request->set_seq(kSequenceNumber2);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber1);
const uint32_t kSequenceNumber3 =
kSequenceNumber1 + stored_request_window_size();
request = CreateFakeMessage();
request->set_seq(kSequenceNumber3);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), stored_request_window_size());
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber2);
const uint32_t kSequenceNumber4 =
kSequenceNumber2 + stored_request_window_size();
request = CreateFakeMessage();
request->set_seq(kSequenceNumber4);
StoreRequest(std::move(request));
EXPECT_EQ(CalculateStoredRequestWindowSize(), 2);
EXPECT_EQ(oldest_request_sequence(), kSequenceNumber3);
EXPECT_EQ(PopStoredRequest(kSequenceNumber1), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber2), nullptr);
EXPECT_NE(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber3), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 1);
EXPECT_NE(PopStoredRequest(kSequenceNumber4), nullptr);
EXPECT_EQ(PopStoredRequest(kSequenceNumber4), nullptr);
EXPECT_EQ(CalculateStoredRequestWindowSize(), 0);
}
TEST_F(RTNLHandlerTest, SetInterfaceMac) {
StartRTNLHandler();
constexpr uint32_t kSequenceNumber = 123456;
constexpr int32_t kErrorNumber = 115;
SetRequestSequence(kSequenceNumber);
EXPECT_CALL(*GetMockSocket(), Send(_, 0))
.WillOnce(testing::Invoke(SimulateSend));
base::test::TestFuture<int32_t> error_future;
RTNLHandler::GetInstance()->SetInterfaceMac(
3, *MacAddress::CreateFromString("ab:cd:ef:12:34:56"),
error_future.GetCallback());
ReturnError(kSequenceNumber, kErrorNumber);
EXPECT_EQ(error_future.Get(), kErrorNumber);
StopRTNLHandler();
}
TEST_F(RTNLHandlerTest, AddInterfaceTest) {
StartRTNLHandler();
constexpr uint32_t kSequenceNumber = 123456;
constexpr int32_t kErrorNumber = 115;
const std::string kIfName = "wg0";
const std::string kIfType = "wireguard";
SetRequestSequence(kSequenceNumber);
std::vector<uint8_t> msg_bytes;
EXPECT_CALL(*GetMockSocket(), Send(_, 0))
.WillOnce([&](base::span<const uint8_t> buf, int flags) {
msg_bytes = {std::begin(buf), std::end(buf)};
return buf.size();
});
base::test::TestFuture<int32_t> error_future;
RTNLHandler::GetInstance()->AddInterface(kIfName, kIfType, {},
error_future.GetCallback());
const auto sent_msg = RTNLMessage::Decode(msg_bytes);
EXPECT_EQ(sent_msg->flags(),
NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
EXPECT_EQ(sent_msg->GetIflaIfname(), kIfName);
ASSERT_TRUE(sent_msg->link_status().kind.has_value());
EXPECT_EQ(sent_msg->link_status().kind.value(), kIfType);
ReturnError(kSequenceNumber, kErrorNumber);
EXPECT_EQ(error_future.Get(), kErrorNumber);
StopRTNLHandler();
}
} // namespace net_base