Home | History | Annotate | Download | only in socket
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/api/socket/udp_socket.h"
      6 
      7 #include <string>
      8 
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/test/test_timeouts.h"
     12 #include "chrome/test/base/browser_with_test_window_test.h"
     13 #include "net/base/io_buffer.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace extensions {
     17 
     18 // UDPSocketUnitTest exists solely to make it easier to pass a specific
     19 // gtest_filter argument during development.
     20 class UDPSocketUnitTest : public BrowserWithTestWindowTest {
     21 };
     22 
     23 static void OnConnected(int result) {
     24   EXPECT_EQ(0, result);
     25 }
     26 
     27 static void OnCompleted(int bytes_read,
     28                         scoped_refptr<net::IOBuffer> io_buffer,
     29                         const std::string& address,
     30                         int port) {
     31   // Do nothing; don't care.
     32 }
     33 
     34 static const char test_message[] = "$$TESTMESSAGETESTMESSAGETESTMESSAGETEST$$";
     35 static const int test_message_length = ARRAYSIZE_UNSAFE(test_message);
     36 
     37 static void OnSendCompleted(int result) {
     38   EXPECT_EQ(test_message_length, result);
     39 }
     40 
     41 TEST(UDPSocketUnitTest, TestUDPSocketRecvFrom) {
     42   base::MessageLoopForIO io_loop;  // For RecvFrom to do its threaded work.
     43   UDPSocket socket("abcdefghijklmnopqrst");
     44 
     45   // Confirm that we can call two RecvFroms in quick succession without
     46   // triggering crbug.com/146606.
     47   socket.Connect("127.0.0.1", 40000, base::Bind(&OnConnected));
     48   socket.RecvFrom(4096, base::Bind(&OnCompleted));
     49   socket.RecvFrom(4096, base::Bind(&OnCompleted));
     50 }
     51 
     52 TEST(UDPSocketUnitTest, TestUDPMulticastJoinGroup) {
     53   const char* kGroup = "237.132.100.17";
     54   UDPSocket src("abcdefghijklmnopqrst");
     55   UDPSocket dest("abcdefghijklmnopqrst");
     56 
     57   EXPECT_EQ(0, dest.Bind("0.0.0.0", 13333));
     58   EXPECT_EQ(0, dest.JoinGroup(kGroup));
     59   std::vector<std::string> groups = dest.GetJoinedGroups();
     60   EXPECT_EQ(static_cast<size_t>(1), groups.size());
     61   EXPECT_EQ(kGroup, *groups.begin());
     62   EXPECT_NE(0, dest.LeaveGroup("237.132.100.13"));
     63   EXPECT_EQ(0, dest.LeaveGroup(kGroup));
     64   groups = dest.GetJoinedGroups();
     65   EXPECT_EQ(static_cast<size_t>(0), groups.size());
     66 }
     67 
     68 TEST(UDPSocketUnitTest, TestUDPMulticastTimeToLive) {
     69   const char* kGroup = "237.132.100.17";
     70   UDPSocket socket("abcdefghijklmnopqrst");
     71   EXPECT_NE(0, socket.SetMulticastTimeToLive(-1));  // Negative TTL shall fail.
     72   EXPECT_EQ(0, socket.SetMulticastTimeToLive(3));
     73   socket.Connect(kGroup, 13333, base::Bind(&OnConnected));
     74 }
     75 
     76 TEST(UDPSocketUnitTest, TestUDPMulticastLoopbackMode) {
     77   const char* kGroup = "237.132.100.17";
     78   UDPSocket socket("abcdefghijklmnopqrst");
     79   EXPECT_EQ(0, socket.SetMulticastLoopbackMode(false));
     80   socket.Connect(kGroup, 13333, base::Bind(&OnConnected));
     81 }
     82 
     83 static void QuitMessageLoop() {
     84   base::MessageLoopForIO::current()->QuitNow();
     85 }
     86 
     87 // Send a test multicast packet every second.
     88 // Once the target socket received the packet, the message loop will exit.
     89 static void SendMulticastPacket(UDPSocket* src, int result) {
     90   if (result == 0) {
     91     scoped_refptr<net::IOBuffer> data = new net::WrappedIOBuffer(test_message);
     92     src->Write(data, test_message_length, base::Bind(&OnSendCompleted));
     93     base::MessageLoopForIO::current()->PostDelayedTask(FROM_HERE,
     94           base::Bind(&SendMulticastPacket, src, result),
     95           base::TimeDelta::FromSeconds(1));
     96   } else {
     97     QuitMessageLoop();
     98     FAIL() << "Failed to connect to multicast address. Error code: " << result;
     99   }
    100 }
    101 
    102 static void OnMulticastReadCompleted(bool *packet_received,
    103                                      int count,
    104                                      scoped_refptr<net::IOBuffer> io_buffer) {
    105   EXPECT_EQ(test_message_length, count);
    106   EXPECT_EQ(0, strncmp(io_buffer->data(), test_message, test_message_length));
    107   *packet_received = true;
    108   QuitMessageLoop();
    109 }
    110 
    111 TEST(UDPSocketUnitTest, TestUDPMulticastRecv) {
    112   const int kPort = 9999;
    113   const char* const kGroup = "237.132.100.17";
    114   bool packet_received = false;
    115   base::MessageLoopForIO io_loop;  // For Read to do its threaded work.
    116   UDPSocket dest("abcdefghijklmnopqrst");
    117   UDPSocket src("abcdefghijklmnopqrst");
    118 
    119   // Receiver
    120   EXPECT_EQ(0, dest.Bind("0.0.0.0", kPort));
    121   EXPECT_EQ(0, dest.JoinGroup(kGroup));
    122   dest.Read(1024, base::Bind(&OnMulticastReadCompleted, &packet_received));
    123 
    124   // Sender
    125   EXPECT_EQ(0, src.SetMulticastTimeToLive(0));
    126   src.Connect(kGroup, kPort, base::Bind(&SendMulticastPacket, &src));
    127 
    128   // If not received within the test action timeout, quit the message loop.
    129   io_loop.PostDelayedTask(FROM_HERE,
    130                           base::Bind(&QuitMessageLoop),
    131                           TestTimeouts::action_timeout());
    132 
    133   io_loop.Run();
    134 
    135   EXPECT_TRUE(packet_received) << "Failed to receive from multicast address";
    136 }
    137 
    138 }  // namespace extensions
    139