async_connection_unittest.cc revision 22f1fbc11b69ee41af8370ec38f1b90577db6c3c
1f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// Use of this source code is governed by a BSD-style license that can be
3f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart// found in the LICENSE file.
4f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
5f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/async_connection.h"
6f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
7f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <netinet/in.h>
8f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
9f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <vector>
10f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
113e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h>
12f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <gtest/gtest.h>
13f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
14f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/ip_address.h"
15f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/mock_event_dispatcher.h"
16f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/mock_sockets.h"
17f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
183e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind;
193e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Callback;
203e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained;
21f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing std::string;
22f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::_;
23f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::Return;
24f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::ReturnNew;
25f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::StrEq;
26f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::StrictMock;
27f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::Test;
28f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
29f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace shill {
30f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
31f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace {
32f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst char kInterfaceName[] = "int0";
33f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiuconst char kIPv4Address[] = "10.11.12.13";
34f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiuconst char kIPv6Address[] = "2001:db8::1";
35f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kConnectPort = 10203;
36f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kErrorNumber = 30405;
37f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kSocketFD = 60708;
388a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko}  // namespace
39f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
40f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass AsyncConnectionTest : public Test {
41f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart public:
42f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  AsyncConnectionTest()
438585b207dc9502256c2a428611e948e105db96b6Paul Stewart      : async_connection_(
448585b207dc9502256c2a428611e948e105db96b6Paul Stewart            new AsyncConnection(kInterfaceName, &dispatcher_, &sockets_,
458585b207dc9502256c2a428611e948e105db96b6Paul Stewart                                callback_target_.callback())),
46f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        ipv4_address_(IPAddress::kFamilyIPv4),
47f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        ipv6_address_(IPAddress::kFamilyIPv6) { }
48f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
49f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  virtual void SetUp() {
50f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(ipv4_address_.SetAddressFromString(kIPv4Address));
51f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(ipv6_address_.SetAddressFromString(kIPv6Address));
52f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
53f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  virtual void TearDown() {
548585b207dc9502256c2a428611e948e105db96b6Paul Stewart    if (async_connection_.get() && async_connection_->fd_ >= 0) {
55f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      EXPECT_CALL(sockets(), Close(kSocketFD))
56f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart          .WillOnce(Return(0));
57f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    }
58f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
598585b207dc9502256c2a428611e948e105db96b6Paul Stewart  void InvokeFreeConnection(bool /*success*/, int /*fd*/) {
608585b207dc9502256c2a428611e948e105db96b6Paul Stewart    async_connection_.reset();
618585b207dc9502256c2a428611e948e105db96b6Paul Stewart  }
62f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
63f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart protected:
64f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  class ConnectCallbackTarget {
65f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart   public:
66f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    ConnectCallbackTarget()
673e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood        : callback_(Bind(&ConnectCallbackTarget::CallTarget,
683e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood                         Unretained(this))) {}
69f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
70f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    MOCK_METHOD2(CallTarget, void(bool success, int fd));
713e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    const Callback<void(bool, int)> &callback() { return callback_; }
72f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
73f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart   private:
743e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    Callback<void(bool, int)> callback_;
75f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  };
76f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
77f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void ExpectReset() {
788585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_STREQ(kInterfaceName, async_connection_->interface_name_.c_str());
798585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(&dispatcher_, async_connection_->dispatcher_);
808585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(&sockets_, async_connection_->sockets_);
813e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_TRUE(callback_target_.callback().
828585b207dc9502256c2a428611e948e105db96b6Paul Stewart                Equals(async_connection_->callback_));
838585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(-1, async_connection_->fd_);
848585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_FALSE(async_connection_->connect_completion_callback_.is_null());
858585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_FALSE(async_connection_->connect_completion_handler_.get());
86f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
87f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
88f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void StartConnection() {
89f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, Socket(_, _, _))
90f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(kSocketFD));
91f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, SetNonBlocking(kSocketFD))
92f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(0));
93f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, BindToDevice(kSocketFD, StrEq(kInterfaceName)))
94f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(0));
953e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
963e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood        .WillOnce(Return(-1));
973e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(sockets_, Error())
98f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(EINPROGRESS));
993e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(dispatcher(),
1003e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood                CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
101f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(ReturnNew<IOHandler>());
102f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(async_connection().Start(ipv4_address_, kConnectPort));
103f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
104f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
105f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void OnConnectCompletion(int fd) {
1068585b207dc9502256c2a428611e948e105db96b6Paul Stewart    async_connection_->OnConnectCompletion(fd);
107f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
1088585b207dc9502256c2a428611e948e105db96b6Paul Stewart  AsyncConnection &async_connection() { return *async_connection_.get(); }
109f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<MockSockets> &sockets() { return sockets_; }
110f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  MockEventDispatcher &dispatcher() { return dispatcher_; }
111f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  const IPAddress &ipv4_address() { return ipv4_address_; }
112f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  const IPAddress &ipv6_address() { return ipv6_address_; }
1138585b207dc9502256c2a428611e948e105db96b6Paul Stewart  int fd() { return async_connection_->fd_; }
1148585b207dc9502256c2a428611e948e105db96b6Paul Stewart  void set_fd(int fd) { async_connection_->fd_ = fd; }
115f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<ConnectCallbackTarget> &callback_target() {
116f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    return callback_target_;
117f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
118f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
119f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart private:
120f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  MockEventDispatcher dispatcher_;
121f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<MockSockets> sockets_;
122f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<ConnectCallbackTarget> callback_target_;
12322f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chan  std::unique_ptr<AsyncConnection> async_connection_;
124f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress ipv4_address_;
125f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress ipv6_address_;
126f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart};
127f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
128f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, InitState) {
129f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
130f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_EQ(string(), async_connection().error());
131f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
132f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
133f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartSocketFailure) {
134f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
135f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
136f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
137f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
138f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
139f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
140f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
141f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
142f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
143f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartNonBlockingFailure) {
144f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
145f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
146f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
147f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
148f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
149f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
150f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
151f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
152f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
153f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
154f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
155f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
156f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
157f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartBindToDeviceFailure) {
158f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
159f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
160f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
161f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
162f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
163f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
164f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
165f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
166f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
167f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
168f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
169f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
170f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
171f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
172f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
173f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousFailure) {
174f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
175f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
176f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
177f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
178f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
179f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
180f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
181f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
182f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
183f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .Times(2)
184f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillRepeatedly(Return(0));
185f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
186f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
187f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
188f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
189f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
190f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
191f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartMATCHER_P2(IsSocketAddress, address, port, "") {
192f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  const struct sockaddr_in *arg_saddr =
193f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      reinterpret_cast<const struct sockaddr_in *>(arg);
194f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  IPAddress arg_addr(IPAddress::kFamilyIPv4,
195f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                     ByteString(reinterpret_cast<const unsigned char *>(
196f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                         &arg_saddr->sin_addr.s_addr),
197f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                sizeof(arg_saddr->sin_addr.s_addr)));
198f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  return address.Equals(arg_addr) && arg_saddr->sin_port == htons(port);
199f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
200f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
201f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuMATCHER_P2(IsSocketIpv6Address, ipv6_address, port, "") {
202f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  const struct sockaddr_in6 *arg_saddr =
203f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      reinterpret_cast<const struct sockaddr_in6 *>(arg);
204f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress arg_addr(IPAddress::kFamilyIPv6,
205f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                     ByteString(reinterpret_cast<const unsigned char *>(
206f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                         &arg_saddr->sin6_addr.s6_addr),
207f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                sizeof(arg_saddr->sin6_addr.s6_addr)));
208f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  return ipv6_address.Equals(arg_addr) && arg_saddr->sin6_port == htons(port);
209f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
210f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
211f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousStart) {
212f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
213f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
214f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
215f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
216f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
217f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
218f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD,
219f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketAddress(ipv4_address(), kConnectPort),
220f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                  sizeof(struct sockaddr_in)))
221f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
222f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(dispatcher(),
2233e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood              CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
224f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(ReturnNew<IOHandler>());
225f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
226f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(EINPROGRESS));
227f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
228f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_EQ(kSocketFD, fd());
229f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
230f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
231f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuTEST_F(AsyncConnectionTest, SynchronousStartIpv6) {
232f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Socket(_, _, _))
233f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(kSocketFD));
234f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
235f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
236f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
237f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
238f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Connect(kSocketFD,
239f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketIpv6Address(ipv6_address(),
240f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                                      kConnectPort),
241f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  sizeof(struct sockaddr_in6)))
242f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(-1));
243f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(dispatcher(),
244f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu              CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
245f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        .WillOnce(ReturnNew<IOHandler>());
246f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Error())
247f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(EINPROGRESS));
248f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
249f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_EQ(kSocketFD, fd());
250f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
251f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
252f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, AsynchronousFailure) {
253f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StartConnection();
254f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
255f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(1));
256f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
257f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
258f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(false, -1));
259f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
260f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
261f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  OnConnectCompletion(kSocketFD);
262f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
263f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
264f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
265f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
266f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, AsynchronousSuccess) {
267f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StartConnection();
268f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
269f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
270f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
271f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  OnConnectCompletion(kSocketFD);
272f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
273f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
274f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
275f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousSuccess) {
276f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
277f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
278f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
279f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
280f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
281f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
282f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD,
283f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketAddress(ipv4_address(), kConnectPort),
284f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                  sizeof(struct sockaddr_in)))
285f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
286f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
287f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
288f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  ExpectReset();
289f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
290f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
291f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuTEST_F(AsyncConnectionTest, SynchronousSuccessIpv6) {
292f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Socket(_, _, _))
293f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(kSocketFD));
294f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
295f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
296f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
297f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
298f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Connect(kSocketFD,
299f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketIpv6Address(ipv6_address(),
300f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                                      kConnectPort),
301f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  sizeof(struct sockaddr_in6)))
302f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
303f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
304f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
305f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
306f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
307f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
3088585b207dc9502256c2a428611e948e105db96b6Paul StewartTEST_F(AsyncConnectionTest, FreeOnSuccessCallback) {
3098585b207dc9502256c2a428611e948e105db96b6Paul Stewart  StartConnection();
3108585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
3118585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(0));
3128585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD))
3138585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
3148585b207dc9502256c2a428611e948e105db96b6Paul Stewart  OnConnectCompletion(kSocketFD);
3158585b207dc9502256c2a428611e948e105db96b6Paul Stewart}
3168585b207dc9502256c2a428611e948e105db96b6Paul Stewart
3178585b207dc9502256c2a428611e948e105db96b6Paul StewartTEST_F(AsyncConnectionTest, FreeOnFailureCallback) {
3188585b207dc9502256c2a428611e948e105db96b6Paul Stewart  StartConnection();
3198585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
3208585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(1));
3218585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(callback_target(), CallTarget(false, -1))
3228585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
3238585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), Error())
3248585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(kErrorNumber));
3258585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
3268585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(0));
3278585b207dc9502256c2a428611e948e105db96b6Paul Stewart  OnConnectCompletion(kSocketFD);
3288585b207dc9502256c2a428611e948e105db96b6Paul Stewart}
3298585b207dc9502256c2a428611e948e105db96b6Paul Stewart
330f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}  // namespace shill
331