| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/udp/udp_listen_socket.h" |
| |
| #if !defined(OS_STARBOARD) |
| #include <netinet/in.h> |
| #endif |
| |
| #include "base/message_loop.h" |
| #include "net/base/test_completion_callback.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| namespace net { |
| namespace { |
| |
| using ::testing::_; |
| using ::testing::StrEq; |
| using ::testing::InvokeWithoutArgs; |
| |
| class MockDelegate : public UDPListenSocket::Delegate { |
| public: |
| MockDelegate() { |
| ON_CALL(*this, DidRead(_, _, _, _)) |
| .WillByDefault(InvokeWithoutArgs(this, &MockDelegate::DoDidRead)); |
| } |
| |
| MOCK_METHOD1(DidClose, void(UDPListenSocket*)); |
| MOCK_METHOD4(DidRead, void(UDPListenSocket*, const char*, int, |
| const IPEndPoint*)); |
| |
| void DoDidRead() { callback.callback().Run(OK); } |
| |
| TestCompletionCallback callback; |
| }; |
| |
| // Create a DGRAM socket and bound to random port. |
| SocketDescriptor GetSocketBoundToRandomPort() { |
| #if defined(OS_STARBOARD) |
| SocketDescriptor s = |
| SbSocketCreate(kSbSocketAddressTypeIpv4, kSbSocketProtocolUdp); |
| SbSocketAddress sb_address = {0}; |
| sb_address.type = kSbSocketAddressTypeIpv4; |
| |
| SbSocketBind(s, &sb_address); |
| return s; |
| #else // defined(OS_STARBOARD) |
| SocketDescriptor s = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
| SockaddrStorage src_addr; |
| struct sockaddr_in *in = (struct sockaddr_in *)src_addr.addr; |
| in->sin_family = AF_INET; |
| in->sin_port = htons(0); |
| in->sin_addr.s_addr = INADDR_ANY; |
| ::bind(s, src_addr.addr, src_addr.addr_len); |
| SetNonBlocking(s); |
| return s; |
| #endif // defined(OS_STARBOARD) |
| } |
| |
| // Get the address from |s| and send data to that address |
| // using another DGRAM socket. |
| void SendDataToListeningSocket(SocketDescriptor s, |
| const char* data, int size) { |
| #if defined(OS_STARBOARD) |
| // Get the watching address |
| SbSocketAddress sb_address = {0}; |
| SbSocketGetLocalAddress(s, &sb_address); |
| |
| // Create another socket. |
| SocketDescriptor cs = SbSocketCreate(sb_address.type, kSbSocketProtocolUdp); |
| SbSocketSendTo(cs, data, size, &sb_address); |
| SbSocketDestroy(cs); |
| #else // defined(OS_STARBOARD) |
| // Get the watching address |
| SockaddrStorage bind_addr; |
| ::getsockname(s, bind_addr.addr, &bind_addr.addr_len); |
| |
| // Create another socket. |
| SocketDescriptor cs = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
| ::sendto(cs, data, size, 0, bind_addr.addr, bind_addr.addr_len); |
| #endif // defined(OS_STARBOARD) |
| } |
| |
| const std::string& kSampleData = "Hello World."; |
| |
| TEST(UDPListenSocketTest, DoRead) { |
| SocketDescriptor s = GetSocketBoundToRandomPort(); |
| MockDelegate del; |
| scoped_refptr<UDPListenSocket> sock = new UDPListenSocket(s, &del); |
| |
| // send the extra null character. |
| SendDataToListeningSocket(s, kSampleData.c_str(), kSampleData.size() + 1); |
| EXPECT_CALL(del, DidRead(sock.get(), StrEq(kSampleData.c_str()), |
| kSampleData.size() + 1, _)); |
| del.callback.WaitForResult(); |
| } |
| |
| TEST(UDPListenSocketTest, DoReadReturnsNullAtEnd) { |
| SocketDescriptor s = GetSocketBoundToRandomPort(); |
| MockDelegate del; |
| scoped_refptr<UDPListenSocket> sock = new UDPListenSocket(s, &del); |
| |
| SendDataToListeningSocket(s, kSampleData.data(), kSampleData.size()); |
| |
| // still expect kSampleData, since that has been padded with '\0'. |
| EXPECT_CALL(del, DidRead(sock.get(), StrEq(kSampleData.c_str()), |
| kSampleData.size(), _)); |
| del.callback.WaitForResult(); |
| } |
| |
| // Create 2 UDPListenSockets. Use one to send message to another. |
| TEST(UDPListenSocketTest, SendTo) { |
| SocketDescriptor s1 = GetSocketBoundToRandomPort(); |
| MockDelegate del1; |
| scoped_refptr<UDPListenSocket> sock1 = new UDPListenSocket(s1, &del1); |
| |
| SocketDescriptor s2 = GetSocketBoundToRandomPort(); |
| MockDelegate del2; |
| scoped_refptr<UDPListenSocket> sock2 = new UDPListenSocket(s2, &del2); |
| |
| #if defined(OS_STARBOARD) |
| // Get the port of s1 |
| SbSocketAddress sb_address = {0}; |
| SbSocketGetLocalAddress(s1, &sb_address); |
| IPEndPoint s1_addr; |
| ignore_result(s1_addr.FromSbSocketAddress(&sb_address)); |
| #else // defined(OS_STARBOARD) |
| // Get the port of s1 |
| SockaddrStorage bind_addr; |
| ::getsockname(s1, bind_addr.addr, &bind_addr.addr_len); |
| IPEndPoint s1_addr; |
| ignore_result(s1_addr.FromSockAddr(bind_addr.addr, bind_addr.addr_len)); |
| #endif // defined(OS_STARBOARD) |
| |
| // Send message to s1 using s2 |
| sock2->SendTo(s1_addr, kSampleData); |
| |
| EXPECT_CALL(del1, DidRead(sock1.get(), StrEq(kSampleData.c_str()), |
| kSampleData.size(), _)); |
| del1.callback.WaitForResult(); |
| } |
| |
| } // namespace |
| } // namespace net |