// // Copyright (C) 2012 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // 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/net/netlink_manager.h" #include <errno.h> #include <map> #include <string> #include <vector> #include <base/strings/stringprintf.h> #include <base/message_loop/message_loop.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include "shill/net/io_handler.h" #include "shill/net/mock_io_handler_factory.h" #include "shill/net/mock_netlink_socket.h" #include "shill/net/mock_sockets.h" #include "shill/net/mock_time.h" #include "shill/net/netlink_attribute.h" #include "shill/net/netlink_packet.h" #include "shill/net/nl80211_message.h" using base::Bind; using base::StringPrintf; using base::Unretained; using std::map; using std::string; using std::vector; using testing::_; using testing::AnyNumber; using testing::EndsWith; using testing::Invoke; using testing::Mock; using testing::Return; using testing::SetArgPointee; using testing::StrictMock; 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 unsigned char kNLMSG_ACK[] = { 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Error code 1. const unsigned char kNLMSG_Error[] = { 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; const char kGetFamilyCommandString[] = "CTRL_CMD_GETFAMILY"; } // namespace class NetlinkManagerTest : public Test { public: NetlinkManagerTest() : netlink_manager_(NetlinkManager::GetInstance()), netlink_socket_(new MockNetlinkSocket()), sockets_(new MockSockets), saved_sequence_number_(0) { EXPECT_NE(nullptr, netlink_manager_); 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); netlink_socket_->sockets_.reset(sockets_); // Passes ownership. netlink_manager_->sock_.reset(netlink_socket_); // Passes ownership. netlink_manager_->io_handler_factory_ = &io_handler_factory_; EXPECT_TRUE(netlink_manager_->Init()); } ~NetlinkManagerTest() { // NetlinkManager is a singleton, so reset its state for the next test. netlink_manager_->Reset(true); } // |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); }; class MockHandlerNetlinkAck { public: MockHandlerNetlinkAck() : on_netlink_message_(base::Bind(&MockHandlerNetlinkAck::OnAckHandler, base::Unretained(this))) {} MOCK_METHOD1(OnAckHandler, void(bool* remove_callbacks)); const NetlinkManager::NetlinkAckHandler& on_netlink_message() const { return on_netlink_message_; } private: NetlinkManager::NetlinkAckHandler on_netlink_message_; DISALLOW_COPY_AND_ASSIGN(MockHandlerNetlinkAck); }; void Reset() { netlink_manager_->Reset(false); } NetlinkManager* netlink_manager_; MockNetlinkSocket* netlink_socket_; // Owned by |netlink_manager_|. MockSockets* sockets_; // Owned by |netlink_socket_|. StrictMock<MockIOHandlerFactory> io_handler_factory_; ByteString saved_message_; uint32_t saved_sequence_number_; base::MessageLoop message_loop_; }; 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) { EXPECT_CALL(io_handler_factory_, CreateIOInputHandler(_, _, _)); netlink_manager_->Start(); } TEST_F(NetlinkManagerTest, SubscribeToEvents) { // Family not registered. EXPECT_CALL(*netlink_socket_, SubscribeToEvents(_)).Times(0); EXPECT_FALSE(netlink_manager_->SubscribeToEvents(kFamilyStoogesString, kGroupMoeString)); // Group not part of 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()->CreateControlAttribute( CTRL_ATTR_FAMILY_ID); new_family_message.attributes()->SetU16AttributeValue( CTRL_ATTR_FAMILY_ID, kSampleMessageType); new_family_message.attributes()->CreateControlAttribute( CTRL_ATTR_FAMILY_NAME); 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()->CreateControlAttribute( CTRL_ATTR_FAMILY_ID); new_family_message.attributes()->SetU16AttributeValue( CTRL_ATTR_FAMILY_ID, kSampleMessageType); new_family_message.attributes()->CreateControlAttribute( CTRL_ATTR_FAMILY_NAME); 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(); MutableNetlinkPacket packet( kNL80211_CMD_DISCONNECT, sizeof(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(&packet); packet.ResetConsumedBytes(); // 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(&packet); packet.ResetConsumedBytes(); // 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(&packet); packet.ResetConsumedBytes(); // 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(&packet); packet.ResetConsumedBytes(); // 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(&packet); packet.ResetConsumedBytes(); // Check that ClearBroadcastHandlers works. netlink_manager_->ClearBroadcastHandlers(); EXPECT_CALL(handler1, OnNetlinkMessage(_)).Times(0); EXPECT_CALL(handler2, OnNetlinkMessage(_)).Times(0); netlink_manager_->OnNlMessageReceived(&packet); } 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. MutableNetlinkPacket received_message( kNL80211_CMD_DISCONNECT, sizeof(kNL80211_CMD_DISCONNECT)); // 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); received_message.ResetConsumedBytes(); // Send the message and give our handler. Verify that we get called back. NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler; NetlinkManager::NetlinkAckHandler null_ack_handler; EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillRepeatedly(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &sent_message_1, handler_sent_1.on_netlink_message(), null_ack_handler, null_error_handler)); // Make it appear that this message is in response to our sent message. received_message.SetMessageSequence(netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_message); received_message.ResetConsumedBytes(); // 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); received_message.ResetConsumedBytes(); // 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_ack_handler, null_error_handler)); received_message.SetMessageSequence(netlink_socket_->GetLastSequenceNumber()); EXPECT_TRUE(netlink_manager_->RemoveMessageHandler(sent_message_1)); EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_message); received_message.ResetConsumedBytes(); // 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_ack_handler, null_error_handler)); EXPECT_CALL(handler_broadcast, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_message); received_message.ResetConsumedBytes(); // Change the ID for the message to that of the second handler; verify that // the appropriate handler is called for _that_ message. received_message.SetMessageSequence(netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_2, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_message); } TEST_F(NetlinkManagerTest, AckHandler) { Reset(); Nl80211Message sent_message(CTRL_CMD_GETFAMILY, kGetFamilyCommandString); MockHandler80211 handler_sent_1; MockHandlerNetlinkAck handler_sent_2; // Send the message and give a Nl80211 response handlerand an Ack // handler that does not remove other callbacks after execution. // Receive an Ack message and verify that the Ack handler is invoked. NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler; EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillRepeatedly(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &sent_message, handler_sent_1.on_netlink_message(), handler_sent_2.on_netlink_message(), null_error_handler)); // Set up message as an ack in response to sent_message. MutableNetlinkPacket received_ack_message(kNLMSG_ACK, sizeof(kNLMSG_ACK)); // Make it appear that this message is in response to our sent message. received_ack_message.SetMessageSequence( netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_2, OnAckHandler(_)) .Times(1) .WillOnce(SetArgPointee<0>(false)); // Do not remove callbacks netlink_manager_->OnNlMessageReceived(&received_ack_message); // Receive an Nl80211 response message after handling the Ack and verify // that the Nl80211 response handler is invoked to ensure that it was not // deleted after the Ack handler was executed. MutableNetlinkPacket received_response_message( kNL80211_CMD_DISCONNECT, sizeof(kNL80211_CMD_DISCONNECT)); // Make it appear that this message is in response to our sent message. received_response_message.SetMessageSequence( netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_response_message); received_response_message.ResetConsumedBytes(); // Send the message and give a Nl80211 response handler and Ack handler again, // but remove other callbacks after executing the Ack handler. // Receive an Ack message and verify the Ack handler is invoked. EXPECT_TRUE(netlink_manager_->SendNl80211Message( &sent_message, handler_sent_1.on_netlink_message(), handler_sent_2.on_netlink_message(), null_error_handler)); received_ack_message.ResetConsumedBytes(); received_ack_message.SetMessageSequence( netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_2, OnAckHandler(_)) .Times(1) .WillOnce(SetArgPointee<0>(true)); // Remove callbacks netlink_manager_->OnNlMessageReceived(&received_ack_message); // Receive an Nl80211 response message after handling the Ack and verify // that the Nl80211 response handler is not invoked this time, since it should // have been deleted after calling the Ack handler. received_response_message.SetMessageSequence( received_ack_message.GetNlMsgHeader().nlmsg_seq); EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(0); netlink_manager_->OnNlMessageReceived(&received_response_message); } TEST_F(NetlinkManagerTest, ErrorHandler) { Nl80211Message sent_message(CTRL_CMD_GETFAMILY, kGetFamilyCommandString); MockHandler80211 handler_sent_1; MockHandlerNetlinkAck handler_sent_2; MockHandlerNetlinkAuxilliary handler_sent_3; // Send the message and receive a netlink reply. EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillRepeatedly(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &sent_message, handler_sent_1.on_netlink_message(), handler_sent_2.on_netlink_message(), handler_sent_3.on_netlink_message())); MutableNetlinkPacket received_response_message( kNL80211_CMD_DISCONNECT, sizeof(kNL80211_CMD_DISCONNECT)); received_response_message.SetMessageSequence( netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_1, OnNetlinkMessage(_)).Times(1); netlink_manager_->OnNlMessageReceived(&received_response_message); // Send the message again, but receive an error response. EXPECT_TRUE(netlink_manager_->SendNl80211Message( &sent_message, handler_sent_1.on_netlink_message(), handler_sent_2.on_netlink_message(), handler_sent_3.on_netlink_message())); MutableNetlinkPacket received_error_message( kNLMSG_Error, sizeof(kNLMSG_Error)); received_error_message.SetMessageSequence( netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL(handler_sent_3, OnErrorHandler(NetlinkManager::kErrorFromKernel, _)) .Times(1); netlink_manager_->OnNlMessageReceived(&received_error_message); // Put the state of the singleton back where it was. Reset(); } 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; MockHandlerNetlinkAck ack_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(), ack_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)); MutableNetlinkPacket received_message( new_scan_results_bytes.GetData(), new_scan_results_bytes.GetLength()); received_message.SetMessageSequence(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(_)); received_message.ResetConsumedBytes(); netlink_manager_->OnNlMessageReceived(&received_message); // Build a Done message with the sent-message sequence number. DoneMessage done_message; done_message.AddFlag(NLM_F_MULTI); ByteString done_message_bytes( done_message.Encode(netlink_socket_->GetLastSequenceNumber())); NetlinkPacket done_packet( done_message_bytes.GetData(), done_message_bytes.GetLength()); // Verify that the message-specific auxilliary handler is called for the done // message, with the correct message type. EXPECT_CALL(auxilliary_handler, OnErrorHandler(NetlinkManager::kDone, _)); netlink_manager_->OnNlMessageReceived(&done_packet); // 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(ack_handler, OnAckHandler(_)).Times(0); EXPECT_CALL(broadcast_handler, OnNetlinkMessage(_)).Times(1); received_message.ResetConsumedBytes(); 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_wiphy_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); MutableNetlinkPacket received_message( new_wiphy_message_bytes.GetData(), new_wiphy_message_bytes.GetLength()); // 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_wiphy_message; MockHandler80211 response_handler; MockHandlerNetlinkAuxilliary auxilliary_handler; MockHandlerNetlinkAck ack_handler; GetRegMessage get_reg_message; // Just a message to trigger timeout. NetlinkManager::Nl80211MessageHandler null_message_handler; NetlinkManager::NetlinkAuxilliaryMessageHandler null_error_handler; NetlinkManager::NetlinkAckHandler null_ack_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_wiphy_message, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); received_message.SetMessageSequence(netlink_socket_->GetLastSequenceNumber()); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_reg_message, null_message_handler, null_ack_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_wiphy_message, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); received_message.ResetConsumedBytes(); received_message.SetMessageSequence(netlink_socket_->GetLastSequenceNumber()); EXPECT_CALL( auxilliary_handler, OnErrorHandler(NetlinkManager::kTimeoutWaitingForResponse, nullptr)); EXPECT_TRUE(netlink_manager_->SendNl80211Message(&get_reg_message, null_message_handler, null_ack_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; } TEST_F(NetlinkManagerTest, PendingDump) { // Set up the responses to the two get station messages we're going to send. // The response to then first message is a 2-message multi-part response, // while the response to the second is a single response. NewStationMessage new_station_message_1_pt1; NewStationMessage new_station_message_1_pt2; NewStationMessage new_station_message_2; const uint32_t kRandomSequenceNumber = 3; new_station_message_1_pt1.AddFlag(NLM_F_MULTI); new_station_message_1_pt2.AddFlag(NLM_F_MULTI); ByteString new_station_message_1_pt1_bytes = new_station_message_1_pt1.Encode(kRandomSequenceNumber); ByteString new_station_message_1_pt2_bytes = new_station_message_1_pt2.Encode(kRandomSequenceNumber); ByteString new_station_message_2_bytes = new_station_message_2.Encode(kRandomSequenceNumber); MutableNetlinkPacket received_message_1_pt1( new_station_message_1_pt1_bytes.GetData(), new_station_message_1_pt1_bytes.GetLength()); MutableNetlinkPacket received_message_1_pt2( new_station_message_1_pt2_bytes.GetData(), new_station_message_1_pt2_bytes.GetLength()); received_message_1_pt2.SetMessageType(NLMSG_DONE); MutableNetlinkPacket received_message_2( new_station_message_2_bytes.GetData(), new_station_message_2_bytes.GetLength()); // The two get station messages (with the dump flag set) will be sent one // after another. The second message can only be sent once all replies to the // first have been received. The get wiphy message will be sent while waiting // for replies from the first get station message. GetStationMessage get_station_message_1; get_station_message_1.AddFlag(NLM_F_DUMP); GetStationMessage get_station_message_2; get_station_message_2.AddFlag(NLM_F_DUMP); GetWiphyMessage get_wiphy_message; MockHandler80211 response_handler; MockHandlerNetlinkAuxilliary auxilliary_handler; MockHandlerNetlinkAck ack_handler; // Send the first get station message, which should be sent immediately and // trigger a pending dump. EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_1, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_1_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Send the second get station message before the replies to the first // get station message have been received. This should cause the message // to be enqueued for later sending. EXPECT_CALL(*netlink_socket_, SendMessage(_)).Times(0); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_2, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_2_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Send the get wiphy message before the replies to the first // get station message have been received. Since this message does not have // the NLM_F_DUMP flag set, it will not be enqueued and sent immediately. EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_wiphy_message, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Now we receive the two-part response to the first message. // On receiving the first part, keep waiting for second part. received_message_1_pt1.SetMessageSequence(get_station_message_1_seq_num); EXPECT_CALL(response_handler, OnNetlinkMessage(_)); netlink_manager_->OnNlMessageReceived(&received_message_1_pt1); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // On receiving second part of the message, report done to the error handler, // and dispatch the next message in the queue. received_message_1_pt2.SetMessageSequence(get_station_message_1_seq_num); EXPECT_CALL(auxilliary_handler, OnErrorHandler(NetlinkManager::kDone, _)); EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); netlink_manager_->OnNlMessageReceived(&received_message_1_pt2); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_2_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Receive response to second dump message, and stop waiting for dump replies. received_message_2.SetMessageSequence(get_station_message_2_seq_num); EXPECT_CALL(response_handler, OnNetlinkMessage(_)); EXPECT_CALL(*netlink_socket_, SendMessage(_)).Times(0); netlink_manager_->OnNlMessageReceived(&received_message_2); EXPECT_FALSE(netlink_manager_->IsDumpPending()); EXPECT_TRUE(netlink_manager_->pending_messages_.empty()); EXPECT_EQ(0, netlink_manager_->PendingDumpSequenceNumber()); // Put the state of the singleton back where it was. Reset(); } TEST_F(NetlinkManagerTest, PendingDump_Timeout) { // These two messages will be sent one after another. GetStationMessage get_station_message_1; get_station_message_1.AddFlag(NLM_F_DUMP); GetStationMessage get_station_message_2; get_station_message_2.AddFlag(NLM_F_DUMP); MockHandler80211 response_handler; MockHandlerNetlinkAuxilliary auxilliary_handler; MockHandlerNetlinkAck ack_handler; // Send the first get station message, which should be sent immediately and // trigger a pending dump. EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_1, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_1_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Send the second get station message before the replies to the first // get station message have been received. This should cause the message // to be enqueued for later sending. EXPECT_CALL(*netlink_socket_, SendMessage(_)).Times(0); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_2, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_2_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Timeout waiting for responses to the first get station message. This // should cause the second get station message to be sent. EXPECT_CALL(auxilliary_handler, OnErrorHandler(NetlinkManager::kTimeoutWaitingForResponse, _)); EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); netlink_manager_->OnPendingDumpTimeout(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_2_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Put the state of the singleton back where it was. Reset(); } TEST_F(NetlinkManagerTest, PendingDump_Retry) { const int kNumRetries = 1; // Create EBUSY netlink error response. Do this manually because // ErrorAckMessage does not implement NetlinkMessage::Encode. MutableNetlinkPacket received_ebusy_message(kNLMSG_ACK, sizeof(kNLMSG_ACK)); *received_ebusy_message.GetMutablePayload() = ByteString::CreateFromCPUUInt32(EBUSY); // The two get station messages (with the dump flag set) will be sent one // after another. The second message can only be sent once all replies to the // first have been received. GetStationMessage get_station_message_1; get_station_message_1.AddFlag(NLM_F_DUMP); GetStationMessage get_station_message_2; get_station_message_2.AddFlag(NLM_F_DUMP); MockHandler80211 response_handler; MockHandlerNetlinkAuxilliary auxilliary_handler; MockHandlerNetlinkAck ack_handler; // Send the first get station message, which should be sent immediately and // trigger a pending dump. EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_1, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_1_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Send the second get station message before the replies to the first // get station message have been received. This should cause the message // to be enqueued for later sending. EXPECT_CALL(*netlink_socket_, SendMessage(_)).Times(0); EXPECT_TRUE(netlink_manager_->SendNl80211Message( &get_station_message_2, response_handler.on_netlink_message(), ack_handler.on_netlink_message(), auxilliary_handler.on_netlink_message())); uint16_t get_station_message_2_seq_num = netlink_socket_->GetLastSequenceNumber(); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Now we receive an EBUSY error response, which should trigger a retry and // not invoke the error handler. netlink_manager_->pending_messages_.front().retries_left = kNumRetries; received_ebusy_message.SetMessageSequence(get_station_message_1_seq_num); EXPECT_EQ(kNumRetries, netlink_manager_->pending_messages_.front().retries_left); EXPECT_CALL(auxilliary_handler, OnErrorHandler(_, _)).Times(0); EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); netlink_manager_->OnNlMessageReceived(&received_ebusy_message); // Cancel timeout callback before attempting resend. EXPECT_TRUE(netlink_manager_->pending_dump_timeout_callback_.IsCancelled()); EXPECT_FALSE(netlink_manager_->resend_dump_message_callback_.IsCancelled()); // Trigger this manually instead of via message loop since it is posted as a // delayed task, which base::RunLoop().RunUntilIdle() will not dispatch. netlink_manager_->ResendPendingDumpMessage(); EXPECT_EQ(kNumRetries - 1, netlink_manager_->pending_messages_.front().retries_left); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(2, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_1_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // We receive an EBUSY error response again. Since we have no retries left for // this message, the error handler should be invoked, and the next pending // message sent. received_ebusy_message.ResetConsumedBytes(); received_ebusy_message.SetMessageSequence(get_station_message_1_seq_num); EXPECT_EQ(0, netlink_manager_->pending_messages_.front().retries_left); EXPECT_CALL(auxilliary_handler, OnErrorHandler(NetlinkManager::kErrorFromKernel, _)); EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(true)); netlink_manager_->OnNlMessageReceived(&received_ebusy_message); EXPECT_TRUE(netlink_manager_->IsDumpPending()); EXPECT_EQ(1, netlink_manager_->pending_messages_.size()); EXPECT_EQ(get_station_message_2_seq_num, netlink_manager_->PendingDumpSequenceNumber()); // Now we receive an EBUSY error response to the second get station message, // which should trigger a retry. However, we fail on sending this second retry // out on the netlink socket. Since we expended our one retry on this attempt, // we should invoke the error handler and declare the dump complete. received_ebusy_message.ResetConsumedBytes(); received_ebusy_message.SetMessageSequence(get_station_message_2_seq_num); EXPECT_EQ(1, netlink_manager_->pending_messages_.front().retries_left); EXPECT_CALL(auxilliary_handler, OnErrorHandler(NetlinkManager::kErrorFromKernel, _)); EXPECT_CALL(*netlink_socket_, SendMessage(_)).WillOnce(Return(false)); netlink_manager_->OnNlMessageReceived(&received_ebusy_message); // Cancel timeout callback before attempting resend. EXPECT_TRUE(netlink_manager_->pending_dump_timeout_callback_.IsCancelled()); EXPECT_FALSE(netlink_manager_->resend_dump_message_callback_.IsCancelled()); // Trigger this manually instead of via message loop since it is posted as a // delayed task, which base::RunLoop().RunUntilIdle() will not dispatch. netlink_manager_->ResendPendingDumpMessage(); EXPECT_FALSE(netlink_manager_->IsDumpPending()); EXPECT_TRUE(netlink_manager_->pending_dump_timeout_callback_.IsCancelled()); EXPECT_TRUE(netlink_manager_->resend_dump_message_callback_.IsCancelled()); EXPECT_TRUE(netlink_manager_->pending_messages_.empty()); // Put the state of the singleton back where it was. Reset(); } // Not strictly part of the "public" interface, but part of the // external interface. TEST_F(NetlinkManagerTest, OnInvalidRawNlMessageReceived) { MockHandlerNetlink message_handler; netlink_manager_->AddBroadcastHandler(message_handler.on_netlink_message()); vector<unsigned char> bad_len_message{ 0x01 }; // len should be 32-bits vector<unsigned char> bad_hdr_message{ 0x04, 0x00, 0x00, 0x00 }; // only len vector<unsigned char> bad_body_message{ 0x30, 0x00, 0x00, 0x00, // length 0x00, 0x00, // type 0x00, 0x00, // flags 0x00, 0x00, 0x00, 0x00, // sequence number 0x00, 0x00, 0x00, 0x00, // sender port // Body is empty, but should be 32 bytes. }; for (auto message : {bad_len_message, bad_hdr_message, bad_body_message}) { EXPECT_CALL(message_handler, OnNetlinkMessage(_)).Times(0); InputData data(message.data(), message.size()); netlink_manager_->OnRawNlMessageReceived(&data); Mock::VerifyAndClearExpectations(&message_handler); } vector<unsigned char> good_message{ 0x14, 0x00, 0x00, 0x00, // length 0x00, 0x00, // type 0x00, 0x00, // flags 0x00, 0x00, 0x00, 0x00, // sequence number 0x00, 0x00, 0x00, 0x00, // sender port 0x00, 0x00, 0x00, 0x00, // body }; for (auto bad_msg : {bad_len_message, bad_hdr_message, bad_body_message}) { // A good message followed by a bad message. This should yield one call // to |message_handler|, and one error message. vector<unsigned char> two_messages( good_message.begin(), good_message.end()); two_messages.insert(two_messages.end(), bad_msg.begin(), bad_msg.end()); EXPECT_CALL(message_handler, OnNetlinkMessage(_)).Times(1); InputData data(two_messages.data(), two_messages.size()); netlink_manager_->OnRawNlMessageReceived(&data); Mock::VerifyAndClearExpectations(&message_handler); } EXPECT_CALL(message_handler, OnNetlinkMessage(_)).Times(0); netlink_manager_->OnRawNlMessageReceived(nullptr); } } // namespace shill