blob: d5bf2e95eb7fb25364d971a37cf89eddbe54080e [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file provides tests for individual messages. It tests
// NetlinkMessageFactory's ability to create specific message types and it
// tests the various NetlinkMessage types' ability to parse those
// messages.
// This file tests the public interface to NetlinkManager.
#include "shill/netlink_manager.h"
#include <map>
#include <string>
#include <base/stringprintf.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_log.h"
#include "shill/mock_netlink_socket.h"
#include "shill/mock_sockets.h"
#include "shill/mock_time.h"
#include "shill/netlink_attribute.h"
#include "shill/nl80211_message.h"
#include "shill/scope_logger.h"
using base::Bind;
using base::StringPrintf;
using base::Unretained;
using std::map;
using std::string;
using testing::_;
using testing::AnyNumber;
using testing::EndsWith;
using testing::Invoke;
using testing::Return;
using testing::Test;
namespace shill {
namespace {
// These data blocks have been collected by shill using NetlinkManager while,
// simultaneously (and manually) comparing shill output with that of the 'iw'
// code from which it was derived. The test strings represent the raw packet
// data coming from the kernel. The comments above each of these strings is
// the markup that "iw" outputs for ech of these packets.
// These constants are consistent throughout the packets, below.
const uint16_t kNl80211FamilyId = 0x13;
// Family and group Ids.
const char kFamilyStoogesString[] = "stooges"; // Not saved as a legal family.
const char kGroupMoeString[] = "moe"; // Not saved as a legal group.
const char kFamilyMarxString[] = "marx";
const uint16_t kFamilyMarxNumber = 20;
const char kGroupGrouchoString[] = "groucho";
const uint32_t kGroupGrouchoNumber = 21;
const char kGroupHarpoString[] = "harpo";
const uint32_t kGroupHarpoNumber = 22;
const char kGroupChicoString[] = "chico";
const uint32_t kGroupChicoNumber = 23;
const char kGroupZeppoString[] = "zeppo";
const uint32_t kGroupZeppoNumber = 24;
const char kGroupGummoString[] = "gummo";
const uint32_t kGroupGummoNumber = 25;
// wlan0 (phy #0): disconnected (by AP) reason: 2: Previous authentication no
// longer valid
const unsigned char kNL80211_CMD_DISCONNECT[] = {
0x30, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x36, 0x00,
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x47, 0x00,
};
const char kGetFamilyCommandString[] = "CTRL_CMD_GETFAMILY";
} // namespace
class NetlinkManagerTest : public Test {
public:
NetlinkManagerTest()
: netlink_manager_(NetlinkManager::GetInstance()),
sockets_(new MockSockets),
saved_sequence_number_(0) {
netlink_manager_->message_types_[Nl80211Message::kMessageTypeString].
family_id = kNl80211FamilyId;
netlink_manager_->message_types_[kFamilyMarxString].family_id =
kFamilyMarxNumber;
netlink_manager_->message_types_[kFamilyMarxString].groups =
map<string, uint32_t> {{kGroupGrouchoString, kGroupGrouchoNumber},
{kGroupHarpoString, kGroupHarpoNumber},
{kGroupChicoString, kGroupChicoNumber},
{kGroupZeppoString, kGroupZeppoNumber},
{kGroupGummoString, kGroupGummoNumber}};
netlink_manager_->message_factory_.AddFactoryMethod(
kNl80211FamilyId, Bind(&Nl80211Message::CreateMessage));
Nl80211Message::SetMessageType(kNl80211FamilyId);
// Passes ownership.
netlink_socket_.sockets_.reset(sockets_);
EXPECT_NE(reinterpret_cast<NetlinkManager *>(NULL), netlink_manager_);
netlink_manager_->sock_ = &netlink_socket_;
EXPECT_TRUE(netlink_manager_->Init());
}
~NetlinkManagerTest() {
// NetlinkManager is a singleton, the sock_ field *MUST* be cleared
// before "NetlinkManagerTest::socket_" gets invalidated, otherwise
// later tests will refer to a corrupted memory.
netlink_manager_->sock_ = NULL;
}
// |SaveReply|, |SendMessage|, and |ReplyToSentMessage| work together to
// enable a test to get a response to a sent message. They must be called
// in the order, above, so that a) a reply message is available to b) have
// its sequence number replaced, and then c) sent back to the code.
void SaveReply(const ByteString &message) {
saved_message_ = message;
}
// Replaces the |saved_message_|'s sequence number with the sent value.
bool SendMessage(const ByteString &outgoing_message) {
if (outgoing_message.GetLength() < sizeof(nlmsghdr)) {
LOG(ERROR) << "Outgoing message is too short";
return false;
}
const nlmsghdr *outgoing_header =
reinterpret_cast<const nlmsghdr *>(outgoing_message.GetConstData());
if (saved_message_.GetLength() < sizeof(nlmsghdr)) {
LOG(ERROR) << "Saved message is too short; have you called |SaveReply|?";
return false;
}
nlmsghdr *reply_header =
reinterpret_cast<nlmsghdr *>(saved_message_.GetData());
reply_header->nlmsg_seq = outgoing_header->nlmsg_seq;
saved_sequence_number_ = reply_header->nlmsg_seq;
return true;
}
bool ReplyToSentMessage(ByteString *message) {
if (!message) {
return false;
}
*message = saved_message_;
return true;
}
bool ReplyWithRandomMessage(ByteString *message) {
GetFamilyMessage get_family_message;
// Any number that's not 0 or 1 is acceptable, here. Zero is bad because
// we want to make sure that this message is different than the main
// send/receive pair. One is bad because the default for
// |saved_sequence_number_| is zero and the likely default value for the
// first sequence number generated from the code is 1.
const uint32_t kRandomOffset = 1003;
if (!message) {
return false;
}
*message = get_family_message.Encode(saved_sequence_number_ +
kRandomOffset);
return true;
}
protected:
class MockHandlerNetlink {
public:
MockHandlerNetlink() :
on_netlink_message_(base::Bind(&MockHandlerNetlink::OnNetlinkMessage,
base::Unretained(this))) {}
MOCK_METHOD1(OnNetlinkMessage, void(const NetlinkMessage &msg));
const NetlinkManager::NetlinkMessageHandler &on_netlink_message() const {
return on_netlink_message_;
}
private:
NetlinkManager::NetlinkMessageHandler on_netlink_message_;
DISALLOW_COPY_AND_ASSIGN(MockHandlerNetlink);
};
class MockHandlerNetlinkAuxilliary {
public:
MockHandlerNetlinkAuxilliary() :
on_netlink_message_(
base::Bind(&MockHandlerNetlinkAuxilliary::OnErrorHandler,
base::Unretained(this))) {}
MOCK_METHOD2(OnErrorHandler,
void(NetlinkManager::AuxilliaryMessageType type,
const NetlinkMessage *msg));
const NetlinkManager::NetlinkAuxilliaryMessageHandler &on_netlink_message()
const {
return on_netlink_message_;
}
private:
NetlinkManager::NetlinkAuxilliaryMessageHandler on_netlink_message_;
DISALLOW_COPY_AND_ASSIGN(MockHandlerNetlinkAuxilliary);
};
class MockHandler80211 {
public:
MockHandler80211() :
on_netlink_message_(base::Bind(&MockHandler80211::OnNetlinkMessage,
base::Unretained(this))) {}
MOCK_METHOD1(OnNetlinkMessage, void(const Nl80211Message &msg));
const NetlinkManager::Nl80211MessageHandler &on_netlink_message() const {
return on_netlink_message_;
}
private:
NetlinkManager::Nl80211MessageHandler on_netlink_message_;
DISALLOW_COPY_AND_ASSIGN(MockHandler80211);
};
void Reset() {
netlink_manager_->Reset(false);
}
NetlinkManager *netlink_manager_;
MockNetlinkSocket netlink_socket_;
MockSockets *sockets_; // Owned by |netlink_socket_|.
ByteString saved_message_;
uint32_t saved_sequence_number_;
};
namespace {
class TimeFunctor {
public:
TimeFunctor(time_t tv_sec, suseconds_t tv_usec) {
return_value_.tv_sec = tv_sec;
return_value_.tv_usec = tv_usec;
}
TimeFunctor() {
return_value_.tv_sec = 0;
return_value_.tv_usec = 0;
}
TimeFunctor(const TimeFunctor &other) {
return_value_.tv_sec = other.return_value_.tv_sec;
return_value_.tv_usec = other.return_value_.tv_usec;
}
TimeFunctor &operator=(const TimeFunctor &rhs) {
return_value_.tv_sec = rhs.return_value_.tv_sec;
return_value_.tv_usec = rhs.return_value_.tv_usec;
return *this;
}
// Replaces GetTimeMonotonic.
int operator()(struct timeval *answer) {
if (answer) {
*answer = return_value_;
}
return 0;
}
private:
struct timeval return_value_;
// No DISALLOW_COPY_AND_ASSIGN since testing::Invoke uses copy.
};
} // namespace
TEST_F(NetlinkManagerTest, Start) {
MockEventDispatcher dispatcher;
EXPECT_CALL(dispatcher, CreateInputHandler(_, _, _));
netlink_manager_->Start(&dispatcher);
}
TEST_F(NetlinkManagerTest, SubscribeToEvents) {
ScopedMockLog log;
EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
// Family not registered.
EXPECT_CALL(log, Log(logging::LOG_ERROR, _,
EndsWith("doesn't exist")));
EXPECT_CALL(netlink_socket_, SubscribeToEvents(_)).Times(0);
EXPECT_FALSE(netlink_manager_->SubscribeToEvents(kFamilyStoogesString,
kGroupMoeString));
// Group not part of family
string in_family = StringPrintf("doesn't exist in family '%s'",
kFamilyMarxString);
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith(in_family)));
EXPECT_CALL(netlink_socket_, SubscribeToEvents(_)).Times(0);
EXPECT_FALSE(netlink_manager_->SubscribeToEvents(kFamilyMarxString,
kGroupMoeString));
// Family registered and group part of family.
EXPECT_CALL(netlink_socket_, SubscribeToEvents(kGroupHarpoNumber)).
WillOnce(Return(true));
EXPECT_TRUE(netlink_manager_->SubscribeToEvents(kFamilyMarxString,
kGroupHarpoString));
}
TEST_F(NetlinkManagerTest, GetFamily) {
const uint16_t kSampleMessageType = 42;
const string kSampleMessageName("SampleMessageName");
const uint32_t kRandomSequenceNumber = 3;
NewFamilyMessage new_family_message;
new_family_message.attributes()->CreateAttribute(
CTRL_ATTR_FAMILY_ID,
base::Bind(&NetlinkAttribute::NewControlAttributeFromId));
new_family_message.attributes()->SetU16AttributeValue(
CTRL_ATTR_FAMILY_ID, kSampleMessageType);
new_family_message.attributes()->CreateAttribute(
CTRL_ATTR_FAMILY_NAME,
base::Bind(&NetlinkAttribute::NewControlAttributeFromId));
new_family_message.attributes()->SetStringAttributeValue(
CTRL_ATTR_FAMILY_NAME, kSampleMessageName);
// The sequence number is immaterial since it'll be overwritten.
SaveReply(new_family_message.Encode(kRandomSequenceNumber));
EXPECT_CALL(netlink_socket_, SendMessage(_)).
WillOnce(Invoke(this, &NetlinkManagerTest::SendMessage));
EXPECT_CALL(netlink_socket_, file_descriptor()).WillRepeatedly(Return(0));
EXPECT_CALL(*sockets_, Select(_, _, _, _, _)).WillOnce(Return(1));
EXPECT_CALL(netlink_socket_, RecvMessage(_)).
WillOnce(Invoke(this, &NetlinkManagerTest::ReplyToSentMessage));
NetlinkMessageFactory::FactoryMethod null_factory;
EXPECT_EQ(kSampleMessageType, netlink_manager_->GetFamily(kSampleMessageName,
null_factory));
}
TEST_F(NetlinkManagerTest, GetFamilyOneInterstitialMessage) {
Reset();
const uint16_t kSampleMessageType = 42;
const string kSampleMessageName("SampleMessageName");
const uint32_t kRandomSequenceNumber = 3;
NewFamilyMessage new_family_message;
new_family_message.attributes()->CreateAttribute(
CTRL_ATTR_FAMILY_ID,
base::Bind(&NetlinkAttribute::NewControlAttributeFromId));
new_family_message.attributes()->SetU16AttributeValue(
CTRL_ATTR_FAMILY_ID, kSampleMessageType);
new_family_message.attributes()->CreateAttribute(
CTRL_ATTR_FAMILY_NAME,
base::Bind(&NetlinkAttribute::NewControlAttributeFromId));
new_family_message.attributes()->SetStringAttributeValue(
CTRL_ATTR_FAMILY_NAME, kSampleMessageName);
// The sequence number is immaterial since it'll be overwritten.
SaveReply(new_family_message.Encode(kRandomSequenceNumber));
EXPECT_CALL(netlink_socket_, SendMessage(_)).
WillOnce(Invoke(this, &NetlinkManagerTest::SendMessage));
EXPECT_CALL(netlink_socket_, file_descriptor()).WillRepeatedly(Return(0));
EXPECT_CALL(*sockets_, Select(_, _, _, _, _)).WillRepeatedly(Return(1));
EXPECT_CALL(netlink_socket_, RecvMessage(_)).
WillOnce(Invoke(this, &NetlinkManagerTest::ReplyWithRandomMessage)).
WillOnce(Invoke(this, &NetlinkManagerTest::ReplyToSentMessage));
NetlinkMessageFactory::FactoryMethod null_factory;
EXPECT_EQ(kSampleMessageType, netlink_manager_->GetFamily(kSampleMessageName,
null_factory));
}
TEST_F(NetlinkManagerTest, GetFamilyTimeout) {
Reset();
MockTime time;
Time *old_time = netlink_manager_->time_;
netlink_manager_->time_ = &time;
EXPECT_CALL(netlink_socket_, SendMessage(_)).WillOnce(Return(true));
time_t kStartSeconds = 1234; // Arbitrary.
suseconds_t kSmallUsec = 100;
EXPECT_CALL(time, GetTimeMonotonic(_)).
WillOnce(Invoke(TimeFunctor(kStartSeconds, 0))). // Initial time.
WillOnce(Invoke(TimeFunctor(kStartSeconds, kSmallUsec))).
WillOnce(Invoke(TimeFunctor(kStartSeconds, 2 * kSmallUsec))).
WillOnce(Invoke(TimeFunctor(
kStartSeconds + NetlinkManager::kMaximumNewFamilyWaitSeconds + 1,
NetlinkManager::kMaximumNewFamilyWaitMicroSeconds)));
EXPECT_CALL(netlink_socket_, file_descriptor()).WillRepeatedly(Return(0));
EXPECT_CALL(*sockets_, Select(_, _, _, _, _)).WillRepeatedly(Return(1));
EXPECT_CALL(netlink_socket_, RecvMessage(_)).
WillRepeatedly(Invoke(this, &NetlinkManagerTest::ReplyWithRandomMessage));
NetlinkMessageFactory::FactoryMethod null_factory;
const string kSampleMessageName("SampleMessageName");
EXPECT_EQ(NetlinkMessage::kIllegalMessageType,
netlink_manager_->GetFamily(kSampleMessageName, null_factory));
netlink_manager_->time_ = old_time;
}
TEST_F(NetlinkManagerTest, BroadcastHandler) {
Reset();
nlmsghdr *message = const_cast<nlmsghdr *>(
reinterpret_cast<const nlmsghdr *>(kNL80211_CMD_DISCONNECT));
MockHandlerNetlink handler1;
MockHandlerNetlink handler2;
// Simple, 1 handler, case.
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(1);
EXPECT_FALSE(
netlink_manager_->FindBroadcastHandler(handler1.on_netlink_message()));
netlink_manager_->AddBroadcastHandler(handler1.on_netlink_message());
EXPECT_TRUE(
netlink_manager_->FindBroadcastHandler(handler1.on_netlink_message()));
netlink_manager_->OnNlMessageReceived(message);
// Add a second handler.
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(1);
EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(1);
netlink_manager_->AddBroadcastHandler(handler2.on_netlink_message());
netlink_manager_->OnNlMessageReceived(message);
// Verify that a handler can't be added twice.
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(1);
EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(1);
netlink_manager_->AddBroadcastHandler(handler1.on_netlink_message());
netlink_manager_->OnNlMessageReceived(message);
// Check that we can remove a handler.
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(0);
EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(1);
EXPECT_TRUE(netlink_manager_->RemoveBroadcastHandler(
handler1.on_netlink_message()));
netlink_manager_->OnNlMessageReceived(message);
// Check that re-adding the handler goes smoothly.
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(1);
EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(1);
netlink_manager_->AddBroadcastHandler(handler1.on_netlink_message());
netlink_manager_->OnNlMessageReceived(message);
// Check that ClearBroadcastHandlers works.
netlink_manager_->ClearBroadcastHandlers();
EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(0);
EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(0);
netlink_manager_->OnNlMessageReceived(message);
}
TEST_F(NetlinkManagerTest, MessageHandler) {
Reset();
MockHandlerNetlink handler_broadcast;
EXPECT_TRUE(netlink_manager_->AddBroadcastHandler(
handler_broadcast.on_netlink_message()));
Nl80211Message sent_message_1(CTRL_CMD_GETFAMILY, kGetFamilyCommandString);
MockHandler80211 handler_sent_1;
Nl80211Message sent_message_2(CTRL_CMD_GETFAMILY, kGetFamilyCommandString);
MockHandler80211 handler_sent_2;
// Set up the received message as a response to sent_message_1.
scoped_array<unsigned char> message_memory(
new unsigned char[sizeof(kNL80211_CMD_DISCONNECT)]);
memcpy(message_memory.get(), kNL80211_CMD_DISCONNECT,
sizeof(kNL80211_CMD_DISCONNECT));
nlmsghdr *received_message =
reinterpret_cast<nlmsghdr *>(message_memory.get());
// Now, we can start the actual test...
// Verify that generic handler gets called for a message when no
// message-specific handler has been installed.
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
// Send the message and give our handler. Verify that we get called back.
NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler;
EXPECT_CALL(netlink_socket_, SendMessage(_)).WillRepeatedly(Return(true));
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&sent_message_1, handler_sent_1.on_netlink_message(),
null_error_handler));
// Make it appear that this message is in response to our sent message.
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
// Verify that broadcast handler is called for the message after the
// message-specific handler is called once.
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
// Install and then uninstall message-specific handler; verify broadcast
// handler is called on message receipt.
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&sent_message_1, handler_sent_1.on_netlink_message(),
null_error_handler));
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
EXPECT_TRUE(netlink_manager_->RemoveMessageHandler(sent_message_1));
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
// Install handler for different message; verify that broadcast handler is
// called for _this_ message.
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&sent_message_2, handler_sent_2.on_netlink_message(),
null_error_handler));
EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
// Change the ID for the message to that of the second handler; verify that
// the appropriate handler is called for _that_ message.
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
EXPECT_CALL(handler_sent_2, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
}
TEST_F(NetlinkManagerTest, MultipartMessageHandler) {
Reset();
// Install a broadcast handler.
MockHandlerNetlink broadcast_handler;
EXPECT_TRUE(netlink_manager_->AddBroadcastHandler(
broadcast_handler.on_netlink_message()));
// Build a message and send it in order to install a response handler.
TriggerScanMessage trigger_scan_message;
MockHandler80211 response_handler;
MockHandlerNetlinkAuxilliary auxilliary_handler;
EXPECT_CALL(netlink_socket_, SendMessage(_)).WillOnce(Return(true));
NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler;
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&trigger_scan_message, response_handler.on_netlink_message(),
auxilliary_handler.on_netlink_message()));
// Build a multi-part response (well, it's just one message but it'll be
// received multiple times).
const uint32_t kSequenceNumber = 32; // Arbitrary (replaced, later).
NewScanResultsMessage new_scan_results;
new_scan_results.AddFlag(NLM_F_MULTI);
ByteString new_scan_results_bytes(new_scan_results.Encode(kSequenceNumber));
nlmsghdr *received_message =
reinterpret_cast<nlmsghdr *>(new_scan_results_bytes.GetData());
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
// Verify that the message-specific handler is called.
EXPECT_CALL(response_handler, OnNetlinkMessage(_));
netlink_manager_->OnNlMessageReceived(received_message);
// Verify that the message-specific handler is still called.
EXPECT_CALL(response_handler, OnNetlinkMessage(_));
netlink_manager_->OnNlMessageReceived(received_message);
// Build a Done message with the sent-message sequence number.
DoneMessage done_message;
ByteString done_message_bytes(
done_message.Encode(netlink_socket_.GetLastSequenceNumber()));
// Verify that the message-specific handler is called for the done message.
EXPECT_CALL(auxilliary_handler, OnErrorHandler(_, _));
netlink_manager_->OnNlMessageReceived(
reinterpret_cast<nlmsghdr *>(done_message_bytes.GetData()));
// Verify that broadcast handler is called now that the done message has
// been seen.
EXPECT_CALL(response_handler, OnNetlinkMessage(_)).Times(0);
EXPECT_CALL(auxilliary_handler, OnErrorHandler(_, _)).Times(0);
EXPECT_CALL(broadcast_handler, OnNetlinkMessage(_)).Times(1);
netlink_manager_->OnNlMessageReceived(received_message);
}
TEST_F(NetlinkManagerTest, TimeoutResponseHandlers) {
Reset();
MockHandlerNetlink broadcast_handler;
EXPECT_TRUE(netlink_manager_->AddBroadcastHandler(
broadcast_handler.on_netlink_message()));
// Set up the received message as a response to the get_wiphi_message
// we're going to send.
NewWiphyMessage new_wiphy_message;
const uint32_t kRandomSequenceNumber = 3;
ByteString new_wiphy_message_bytes =
new_wiphy_message.Encode(kRandomSequenceNumber);
nlmsghdr *received_message =
reinterpret_cast<nlmsghdr *>(new_wiphy_message_bytes.GetData());
// Setup a random received message to trigger wiping out old messages.
NewScanResultsMessage new_scan_results;
ByteString new_scan_results_bytes =
new_scan_results.Encode(kRandomSequenceNumber);
// Setup the timestamps of various messages
MockTime time;
Time *old_time = netlink_manager_->time_;
netlink_manager_->time_ = &time;
time_t kStartSeconds = 1234; // Arbitrary.
suseconds_t kSmallUsec = 100;
EXPECT_CALL(time, GetTimeMonotonic(_)).
WillOnce(Invoke(TimeFunctor(kStartSeconds, 0))). // Initial time.
WillOnce(Invoke(TimeFunctor(kStartSeconds, kSmallUsec))).
WillOnce(Invoke(TimeFunctor(kStartSeconds, 0))). // Initial time.
WillOnce(Invoke(TimeFunctor(
kStartSeconds + NetlinkManager::kResponseTimeoutSeconds + 1,
NetlinkManager::kResponseTimeoutMicroSeconds)));
EXPECT_CALL(netlink_socket_, SendMessage(_)).WillRepeatedly(Return(true));
GetWiphyMessage get_wiphi_message;
MockHandler80211 response_handler;
MockHandlerNetlinkAuxilliary auxilliary_handler;
GetRegMessage get_reg_message; // Just a message to trigger timeout.
NetlinkManager::Nl80211MessageHandler null_message_handler;
NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler;
// Send two messages within the message handler timeout; verify that we
// get called back (i.e., that the first handler isn't discarded).
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&get_wiphi_message, response_handler.on_netlink_message(),
auxilliary_handler.on_netlink_message()));
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&get_reg_message, null_message_handler, null_error_handler));
EXPECT_CALL(response_handler, OnNetlinkMessage(_));
netlink_manager_->OnNlMessageReceived(received_message);
// Send two messages at an interval greater than the message handler timeout
// before the response to the first arrives. Verify that the error handler
// for the first message is called (with a timeout flag) and that the
// broadcast handler gets called, instead of the message's handler.
EXPECT_TRUE(netlink_manager_->SendNl80211Message(
&get_wiphi_message, response_handler.on_netlink_message(),
auxilliary_handler.on_netlink_message()));
received_message->nlmsg_seq = netlink_socket_.GetLastSequenceNumber();
EXPECT_CALL(auxilliary_handler,
OnErrorHandler(NetlinkManager::kTimeoutWaitingForResponse, NULL));
EXPECT_TRUE(netlink_manager_->SendNl80211Message(&get_reg_message,
null_message_handler,
null_error_handler));
EXPECT_CALL(response_handler, OnNetlinkMessage(_)).Times(0);
EXPECT_CALL(broadcast_handler, OnNetlinkMessage(_));
netlink_manager_->OnNlMessageReceived(received_message);
// Put the state of the singleton back where it was.
netlink_manager_->time_ = old_time;
}
} // namespace shill