[shill] Migrate to RTNLMessage instead of nlmsghdr

Now, RTNLHandler deals with nlmsghdrs internally, and passes parsed RTNLMessage
objects to everyone else.

Also, move some code out of device_info_unittest.cc that was testing
RTNLHandler::ParseRTNL

BUG=chromium-os:18908
TEST=unit
STATUS=Verified

Change-Id: I8e1546ea8e996a0e2302fe5e5937b03c13cb1a61
Reviewed-on: http://gerrit.chromium.org/gerrit/5612
Reviewed-by: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
diff --git a/rtnl_handler_unittest.cc b/rtnl_handler_unittest.cc
index c730423..3530631 100644
--- a/rtnl_handler_unittest.cc
+++ b/rtnl_handler_unittest.cc
@@ -4,15 +4,24 @@
 
 #include <string>
 
+#include <glib.h>
 #include <gtest/gtest.h>
 #include <net/if.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>  // Needs typedefs from sys/socket.h.
+#include <linux/rtnetlink.h>
 #include <sys/ioctl.h>
 
+#include "shill/manager.h"
+#include "shill/mock_control.h"
+#include "shill/mock_glib.h"
 #include "shill/mock_sockets.h"
 #include "shill/rtnl_handler.h"
+#include "shill/rtnl_message.h"
 
 using std::string;
 using testing::_;
+using testing::A;
 using testing::DoAll;
 using testing::Return;
 using testing::StrictMock;
@@ -30,26 +39,101 @@
   }
 }
 
+class TestEventDispatcher : public EventDispatcher {
+ public:
+  virtual IOInputHandler *CreateInputHandler(
+      int fd,
+      Callback1<InputData*>::Type *callback) {
+    return NULL;
+  }
+};
+
 }  // namespace
 
 class RTNLHandlerTest : public Test {
+ public:
+  RTNLHandlerTest()
+      : manager_(&control_interface_, &dispatcher_, &glib_),
+        callback_(NewCallback(this, &RTNLHandlerTest::Callback)),
+        task_factory_(this) {
+  }
+
+  virtual void TearDown() {
+    RTNLHandler::GetInstance()->Stop();
+    SetSockets(NULL);
+  }
+
+  MOCK_METHOD1(Callback, void(const RTNLMessage &));
+
  protected:
+  static const int kTestSocket;
+  static const int kTestDeviceIndex;
+  static const char kTestDeviceName[];
+
+  void AddLink();
+  void StartRTNLHandler();
+  void StopRTNLHandler();
+
   void SetSockets(Sockets *sockets) {
     RTNLHandler::GetInstance()->sockets_ = sockets;
   }
 
-  virtual void SetUp() {
-    SetSockets(&sockets_);
-  }
-
-  virtual void TearDown() {
-    SetSockets(NULL);
-  }
-
   StrictMock<MockSockets> sockets_;
+  MockGLib glib_;
+  MockControl control_interface_;
+  Manager manager_;
+  TestEventDispatcher dispatcher_;
+  scoped_ptr<Callback1<const RTNLMessage &>::Type> callback_;
+  ScopedRunnableMethodFactory<RTNLHandlerTest> task_factory_;
 };
 
+const int RTNLHandlerTest::kTestSocket = 123;
+const int RTNLHandlerTest::kTestDeviceIndex = 123456;
+const char RTNLHandlerTest::kTestDeviceName[] = "test-device";
+
+void RTNLHandlerTest::StartRTNLHandler() {
+  EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
+      .WillOnce(Return(kTestSocket));
+  EXPECT_CALL(sockets_, Bind(kTestSocket, _, sizeof(sockaddr_nl)))
+      .WillOnce(Return(0));
+  RTNLHandler::GetInstance()->Start(&dispatcher_, &sockets_);
+}
+
+void RTNLHandlerTest::StopRTNLHandler() {
+  EXPECT_CALL(sockets_, Close(kTestSocket)).WillOnce(Return(0));
+  RTNLHandler::GetInstance()->Stop();
+}
+
+void RTNLHandlerTest::AddLink() {
+  RTNLMessage message(RTNLMessage::kMessageTypeLink,
+                      RTNLMessage::kMessageModeAdd,
+                      0,
+                      0,
+                      0,
+                      kTestDeviceIndex,
+                      IPAddress::kAddressFamilyIPv4);
+  message.SetAttribute(static_cast<uint16>(IFLA_IFNAME),
+                       ByteString(kTestDeviceName, true));
+  ByteString b(message.Encode());
+  InputData data(b.GetData(), b.GetLength());
+  RTNLHandler::GetInstance()->ParseRTNL(&data);
+}
+
+TEST_F(RTNLHandlerTest, AddLinkTest) {
+  StartRTNLHandler();
+  scoped_ptr<RTNLListener> link_listener(
+      new RTNLListener(RTNLHandler::kRequestLink, callback_.get()));
+
+  EXPECT_CALL(*this, Callback(A<const RTNLMessage &>())).Times(1);
+
+  AddLink();
+
+  StopRTNLHandler();
+}
+
+
 TEST_F(RTNLHandlerTest, GetInterfaceName) {
+  SetSockets(&sockets_);
   EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex(""));
   {
     struct ifreq ifr;
@@ -66,7 +150,7 @@
       .WillOnce(Return(-1))
       .WillOnce(DoAll(SetInterfaceIndex(), Return(0)));
   EXPECT_CALL(sockets_, Close(kTestSocket))
-      .Times(2)
+      .Times(3)
       .WillRepeatedly(Return(0));
   EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("eth0"));
   EXPECT_EQ(-1, RTNLHandler::GetInstance()->GetInterfaceIndex("wlan0"));