Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2011 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/async_connection.h"
     18 
     19 #include <netinet/in.h>
     20 
     21 #include <vector>
     22 
     23 #include <base/bind.h>
     24 #include <gtest/gtest.h>
     25 
     26 #include "shill/mock_event_dispatcher.h"
     27 #include "shill/net/ip_address.h"
     28 #include "shill/net/mock_sockets.h"
     29 
     30 using base::Bind;
     31 using base::Callback;
     32 using base::Unretained;
     33 using std::string;
     34 using ::testing::_;
     35 using ::testing::Return;
     36 using ::testing::ReturnNew;
     37 using ::testing::StrEq;
     38 using ::testing::StrictMock;
     39 using ::testing::Test;
     40 
     41 namespace shill {
     42 
     43 namespace {
     44 const char kInterfaceName[] = "int0";
     45 const char kIPv4Address[] = "10.11.12.13";
     46 const char kIPv6Address[] = "2001:db8::1";
     47 const int kConnectPort = 10203;
     48 const int kErrorNumber = 30405;
     49 const int kSocketFD = 60708;
     50 }  // namespace
     51 
     52 class AsyncConnectionTest : public Test {
     53  public:
     54   AsyncConnectionTest()
     55       : async_connection_(
     56             new AsyncConnection(kInterfaceName, &dispatcher_, &sockets_,
     57                                 callback_target_.callback())),
     58         ipv4_address_(IPAddress::kFamilyIPv4),
     59         ipv6_address_(IPAddress::kFamilyIPv6) { }
     60 
     61   virtual void SetUp() {
     62     EXPECT_TRUE(ipv4_address_.SetAddressFromString(kIPv4Address));
     63     EXPECT_TRUE(ipv6_address_.SetAddressFromString(kIPv6Address));
     64   }
     65   virtual void TearDown() {
     66     if (async_connection_.get() && async_connection_->fd_ >= 0) {
     67       EXPECT_CALL(sockets(), Close(kSocketFD))
     68           .WillOnce(Return(0));
     69     }
     70   }
     71   void InvokeFreeConnection(bool /*success*/, int /*fd*/) {
     72     async_connection_.reset();
     73   }
     74 
     75  protected:
     76   class ConnectCallbackTarget {
     77    public:
     78     ConnectCallbackTarget()
     79         : callback_(Bind(&ConnectCallbackTarget::CallTarget,
     80                          Unretained(this))) {}
     81 
     82     MOCK_METHOD2(CallTarget, void(bool success, int fd));
     83     const Callback<void(bool, int)>& callback() { return callback_; }
     84 
     85    private:
     86     Callback<void(bool, int)> callback_;
     87   };
     88 
     89   void ExpectReset() {
     90     EXPECT_STREQ(kInterfaceName, async_connection_->interface_name_.c_str());
     91     EXPECT_EQ(&dispatcher_, async_connection_->dispatcher_);
     92     EXPECT_EQ(&sockets_, async_connection_->sockets_);
     93     EXPECT_TRUE(callback_target_.callback().
     94                 Equals(async_connection_->callback_));
     95     EXPECT_EQ(-1, async_connection_->fd_);
     96     EXPECT_FALSE(async_connection_->connect_completion_callback_.is_null());
     97     EXPECT_FALSE(async_connection_->connect_completion_handler_.get());
     98   }
     99 
    100   void StartConnection() {
    101     EXPECT_CALL(sockets_, Socket(_, _, _))
    102         .WillOnce(Return(kSocketFD));
    103     EXPECT_CALL(sockets_, SetNonBlocking(kSocketFD))
    104         .WillOnce(Return(0));
    105     EXPECT_CALL(sockets_, BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    106         .WillOnce(Return(0));
    107     EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
    108         .WillOnce(Return(-1));
    109     EXPECT_CALL(sockets_, Error())
    110         .WillOnce(Return(EINPROGRESS));
    111     EXPECT_CALL(dispatcher(),
    112                 CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
    113         .WillOnce(ReturnNew<IOHandler>());
    114     EXPECT_TRUE(async_connection().Start(ipv4_address_, kConnectPort));
    115   }
    116 
    117   void OnConnectCompletion(int fd) {
    118     async_connection_->OnConnectCompletion(fd);
    119   }
    120   AsyncConnection& async_connection() { return *async_connection_.get(); }
    121   StrictMock<MockSockets>& sockets() { return sockets_; }
    122   MockEventDispatcher& dispatcher() { return dispatcher_; }
    123   const IPAddress& ipv4_address() { return ipv4_address_; }
    124   const IPAddress& ipv6_address() { return ipv6_address_; }
    125   int fd() { return async_connection_->fd_; }
    126   void set_fd(int fd) { async_connection_->fd_ = fd; }
    127   StrictMock<ConnectCallbackTarget>& callback_target() {
    128     return callback_target_;
    129   }
    130 
    131  private:
    132   MockEventDispatcher dispatcher_;
    133   StrictMock<MockSockets> sockets_;
    134   StrictMock<ConnectCallbackTarget> callback_target_;
    135   std::unique_ptr<AsyncConnection> async_connection_;
    136   IPAddress ipv4_address_;
    137   IPAddress ipv6_address_;
    138 };
    139 
    140 TEST_F(AsyncConnectionTest, InitState) {
    141   ExpectReset();
    142   EXPECT_EQ(string(), async_connection().error());
    143 }
    144 
    145 TEST_F(AsyncConnectionTest, StartSocketFailure) {
    146   EXPECT_CALL(sockets(), Socket(_, _, _))
    147       .WillOnce(Return(-1));
    148   EXPECT_CALL(sockets(), Error())
    149       .WillOnce(Return(kErrorNumber));
    150   EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
    151   ExpectReset();
    152   EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
    153 }
    154 
    155 TEST_F(AsyncConnectionTest, StartNonBlockingFailure) {
    156   EXPECT_CALL(sockets(), Socket(_, _, _))
    157       .WillOnce(Return(kSocketFD));
    158   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    159       .WillOnce(Return(-1));
    160   EXPECT_CALL(sockets(), Error())
    161       .WillOnce(Return(kErrorNumber));
    162   EXPECT_CALL(sockets(), Close(kSocketFD))
    163       .WillOnce(Return(0));
    164   EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
    165   ExpectReset();
    166   EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
    167 }
    168 
    169 TEST_F(AsyncConnectionTest, StartBindToDeviceFailure) {
    170   EXPECT_CALL(sockets(), Socket(_, _, _))
    171       .WillOnce(Return(kSocketFD));
    172   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    173       .WillOnce(Return(0));
    174   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    175       .WillOnce(Return(-1));
    176   EXPECT_CALL(sockets(), Error())
    177       .WillOnce(Return(kErrorNumber));
    178   EXPECT_CALL(sockets(), Close(kSocketFD))
    179       .WillOnce(Return(0));
    180   EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
    181   ExpectReset();
    182   EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
    183 }
    184 
    185 TEST_F(AsyncConnectionTest, SynchronousFailure) {
    186   EXPECT_CALL(sockets(), Socket(_, _, _))
    187       .WillOnce(Return(kSocketFD));
    188   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    189       .WillOnce(Return(0));
    190   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    191       .WillOnce(Return(0));
    192   EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
    193       .WillOnce(Return(-1));
    194   EXPECT_CALL(sockets(), Error())
    195       .Times(2)
    196       .WillRepeatedly(Return(0));
    197   EXPECT_CALL(sockets(), Close(kSocketFD))
    198       .WillOnce(Return(0));
    199   EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
    200   ExpectReset();
    201 }
    202 
    203 MATCHER_P2(IsSocketAddress, address, port, "") {
    204   const struct sockaddr_in* arg_saddr =
    205       reinterpret_cast<const struct sockaddr_in*>(arg);
    206   IPAddress arg_addr(IPAddress::kFamilyIPv4,
    207                      ByteString(reinterpret_cast<const unsigned char*>(
    208                          &arg_saddr->sin_addr.s_addr),
    209                                 sizeof(arg_saddr->sin_addr.s_addr)));
    210   return address.Equals(arg_addr) && arg_saddr->sin_port == htons(port);
    211 }
    212 
    213 MATCHER_P2(IsSocketIpv6Address, ipv6_address, port, "") {
    214   const struct sockaddr_in6* arg_saddr =
    215       reinterpret_cast<const struct sockaddr_in6*>(arg);
    216   IPAddress arg_addr(IPAddress::kFamilyIPv6,
    217                      ByteString(reinterpret_cast<const unsigned char*>(
    218                          &arg_saddr->sin6_addr.s6_addr),
    219                                 sizeof(arg_saddr->sin6_addr.s6_addr)));
    220   return ipv6_address.Equals(arg_addr) && arg_saddr->sin6_port == htons(port);
    221 }
    222 
    223 TEST_F(AsyncConnectionTest, SynchronousStart) {
    224   EXPECT_CALL(sockets(), Socket(_, _, _))
    225       .WillOnce(Return(kSocketFD));
    226   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    227       .WillOnce(Return(0));
    228   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    229       .WillOnce(Return(0));
    230   EXPECT_CALL(sockets(), Connect(kSocketFD,
    231                                   IsSocketAddress(ipv4_address(), kConnectPort),
    232                                   sizeof(struct sockaddr_in)))
    233       .WillOnce(Return(-1));
    234   EXPECT_CALL(dispatcher(),
    235               CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
    236         .WillOnce(ReturnNew<IOHandler>());
    237   EXPECT_CALL(sockets(), Error())
    238       .WillOnce(Return(EINPROGRESS));
    239   EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
    240   EXPECT_EQ(kSocketFD, fd());
    241 }
    242 
    243 TEST_F(AsyncConnectionTest, SynchronousStartIpv6) {
    244   EXPECT_CALL(sockets(), Socket(_, _, _))
    245       .WillOnce(Return(kSocketFD));
    246   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    247       .WillOnce(Return(0));
    248   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    249       .WillOnce(Return(0));
    250   EXPECT_CALL(sockets(), Connect(kSocketFD,
    251                                   IsSocketIpv6Address(ipv6_address(),
    252                                                       kConnectPort),
    253                                   sizeof(struct sockaddr_in6)))
    254       .WillOnce(Return(-1));
    255   EXPECT_CALL(dispatcher(),
    256               CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
    257         .WillOnce(ReturnNew<IOHandler>());
    258   EXPECT_CALL(sockets(), Error())
    259       .WillOnce(Return(EINPROGRESS));
    260   EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
    261   EXPECT_EQ(kSocketFD, fd());
    262 }
    263 
    264 TEST_F(AsyncConnectionTest, AsynchronousFailure) {
    265   StartConnection();
    266   EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
    267       .WillOnce(Return(1));
    268   EXPECT_CALL(sockets(), Error())
    269       .WillOnce(Return(kErrorNumber));
    270   EXPECT_CALL(callback_target(), CallTarget(false, -1));
    271   EXPECT_CALL(sockets(), Close(kSocketFD))
    272       .WillOnce(Return(0));
    273   OnConnectCompletion(kSocketFD);
    274   ExpectReset();
    275   EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
    276 }
    277 
    278 TEST_F(AsyncConnectionTest, AsynchronousSuccess) {
    279   StartConnection();
    280   EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
    281       .WillOnce(Return(0));
    282   EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
    283   OnConnectCompletion(kSocketFD);
    284   ExpectReset();
    285 }
    286 
    287 TEST_F(AsyncConnectionTest, SynchronousSuccess) {
    288   EXPECT_CALL(sockets(), Socket(_, _, _))
    289       .WillOnce(Return(kSocketFD));
    290   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    291       .WillOnce(Return(0));
    292   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    293       .WillOnce(Return(0));
    294   EXPECT_CALL(sockets(), Connect(kSocketFD,
    295                                   IsSocketAddress(ipv4_address(), kConnectPort),
    296                                   sizeof(struct sockaddr_in)))
    297       .WillOnce(Return(0));
    298   EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
    299   EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
    300   ExpectReset();
    301 }
    302 
    303 TEST_F(AsyncConnectionTest, SynchronousSuccessIpv6) {
    304   EXPECT_CALL(sockets(), Socket(_, _, _))
    305       .WillOnce(Return(kSocketFD));
    306   EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
    307       .WillOnce(Return(0));
    308   EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
    309       .WillOnce(Return(0));
    310   EXPECT_CALL(sockets(), Connect(kSocketFD,
    311                                   IsSocketIpv6Address(ipv6_address(),
    312                                                       kConnectPort),
    313                                   sizeof(struct sockaddr_in6)))
    314       .WillOnce(Return(0));
    315   EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
    316   EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
    317   ExpectReset();
    318 }
    319 
    320 TEST_F(AsyncConnectionTest, FreeOnSuccessCallback) {
    321   StartConnection();
    322   EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
    323       .WillOnce(Return(0));
    324   EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD))
    325       .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
    326   OnConnectCompletion(kSocketFD);
    327 }
    328 
    329 TEST_F(AsyncConnectionTest, FreeOnFailureCallback) {
    330   StartConnection();
    331   EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
    332       .WillOnce(Return(1));
    333   EXPECT_CALL(callback_target(), CallTarget(false, -1))
    334       .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
    335   EXPECT_CALL(sockets(), Error())
    336       .WillOnce(Return(kErrorNumber));
    337   EXPECT_CALL(sockets(), Close(kSocketFD))
    338       .WillOnce(Return(0));
    339   OnConnectCompletion(kSocketFD);
    340 }
    341 
    342 }  // namespace shill
    343