1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2011 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
16f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
17f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/async_connection.h"
18f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
19f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <netinet/in.h>
20f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
21f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <vector>
22f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
233e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h>
24f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include <gtest/gtest.h>
25f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
26f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart#include "shill/mock_event_dispatcher.h"
278d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ip_address.h"
288d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/mock_sockets.h"
29f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
303e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind;
313e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Callback;
323e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Unretained;
33f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing std::string;
34f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::_;
35f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::Return;
36f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::ReturnNew;
37f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::StrEq;
38f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::StrictMock;
39f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartusing ::testing::Test;
40f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
41f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace shill {
42f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
43f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartnamespace {
44f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst char kInterfaceName[] = "int0";
45f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiuconst char kIPv4Address[] = "10.11.12.13";
46f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiuconst char kIPv6Address[] = "2001:db8::1";
47f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kConnectPort = 10203;
48f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kErrorNumber = 30405;
49f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartconst int kSocketFD = 60708;
508a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko}  // namespace
51f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
52f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewartclass AsyncConnectionTest : public Test {
53f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart public:
54f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  AsyncConnectionTest()
558585b207dc9502256c2a428611e948e105db96b6Paul Stewart      : async_connection_(
568585b207dc9502256c2a428611e948e105db96b6Paul Stewart            new AsyncConnection(kInterfaceName, &dispatcher_, &sockets_,
578585b207dc9502256c2a428611e948e105db96b6Paul Stewart                                callback_target_.callback())),
58f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        ipv4_address_(IPAddress::kFamilyIPv4),
59f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        ipv6_address_(IPAddress::kFamilyIPv6) { }
60f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
61f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  virtual void SetUp() {
62f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(ipv4_address_.SetAddressFromString(kIPv4Address));
63f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(ipv6_address_.SetAddressFromString(kIPv6Address));
64f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
65f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  virtual void TearDown() {
668585b207dc9502256c2a428611e948e105db96b6Paul Stewart    if (async_connection_.get() && async_connection_->fd_ >= 0) {
67f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      EXPECT_CALL(sockets(), Close(kSocketFD))
68f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart          .WillOnce(Return(0));
69f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    }
70f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
718585b207dc9502256c2a428611e948e105db96b6Paul Stewart  void InvokeFreeConnection(bool /*success*/, int /*fd*/) {
728585b207dc9502256c2a428611e948e105db96b6Paul Stewart    async_connection_.reset();
738585b207dc9502256c2a428611e948e105db96b6Paul Stewart  }
74f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
75f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart protected:
76f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  class ConnectCallbackTarget {
77f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart   public:
78f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    ConnectCallbackTarget()
793e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood        : callback_(Bind(&ConnectCallbackTarget::CallTarget,
803e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood                         Unretained(this))) {}
81f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
82f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    MOCK_METHOD2(CallTarget, void(bool success, int fd));
833b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart    const Callback<void(bool, int)>& callback() { return callback_; }
84f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
85f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart   private:
863e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    Callback<void(bool, int)> callback_;
87f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  };
88f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
89f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void ExpectReset() {
908585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_STREQ(kInterfaceName, async_connection_->interface_name_.c_str());
918585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(&dispatcher_, async_connection_->dispatcher_);
928585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(&sockets_, async_connection_->sockets_);
933e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_TRUE(callback_target_.callback().
948585b207dc9502256c2a428611e948e105db96b6Paul Stewart                Equals(async_connection_->callback_));
958585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_EQ(-1, async_connection_->fd_);
968585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_FALSE(async_connection_->connect_completion_callback_.is_null());
978585b207dc9502256c2a428611e948e105db96b6Paul Stewart    EXPECT_FALSE(async_connection_->connect_completion_handler_.get());
98f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
99f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
100f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void StartConnection() {
101f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, Socket(_, _, _))
102f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(kSocketFD));
103f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, SetNonBlocking(kSocketFD))
104f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(0));
105f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    EXPECT_CALL(sockets_, BindToDevice(kSocketFD, StrEq(kInterfaceName)))
106f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(0));
1073e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
1083e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood        .WillOnce(Return(-1));
1093e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(sockets_, Error())
110f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(Return(EINPROGRESS));
1113e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood    EXPECT_CALL(dispatcher(),
1123e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood                CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
113f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(ReturnNew<IOHandler>());
114f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu    EXPECT_TRUE(async_connection().Start(ipv4_address_, kConnectPort));
115f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
116f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
117f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  void OnConnectCompletion(int fd) {
1188585b207dc9502256c2a428611e948e105db96b6Paul Stewart    async_connection_->OnConnectCompletion(fd);
119f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
1203b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  AsyncConnection& async_connection() { return *async_connection_.get(); }
1213b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  StrictMock<MockSockets>& sockets() { return sockets_; }
1223b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  MockEventDispatcher& dispatcher() { return dispatcher_; }
1233b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  const IPAddress& ipv4_address() { return ipv4_address_; }
1243b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  const IPAddress& ipv6_address() { return ipv6_address_; }
1258585b207dc9502256c2a428611e948e105db96b6Paul Stewart  int fd() { return async_connection_->fd_; }
1268585b207dc9502256c2a428611e948e105db96b6Paul Stewart  void set_fd(int fd) { async_connection_->fd_ = fd; }
1273b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  StrictMock<ConnectCallbackTarget>& callback_target() {
128f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart    return callback_target_;
129f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  }
130f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
131f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart private:
132f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  MockEventDispatcher dispatcher_;
133f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<MockSockets> sockets_;
134f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StrictMock<ConnectCallbackTarget> callback_target_;
13522f1fbc11b69ee41af8370ec38f1b90577db6c3cBen Chan  std::unique_ptr<AsyncConnection> async_connection_;
136f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress ipv4_address_;
137f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress ipv6_address_;
138f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart};
139f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
140f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, InitState) {
141f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
142f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_EQ(string(), async_connection().error());
143f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
144f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
145f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartSocketFailure) {
146f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
147f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
148f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
149f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
150f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
151f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
152f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
153f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
154f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
155f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartNonBlockingFailure) {
156f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
157f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
158f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
159f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
160f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
161f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
162f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
163f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
164f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
165f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
166f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
167f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
168f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
169f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, StartBindToDeviceFailure) {
170f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
171f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
172f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
173f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
174f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
175f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
176f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
177f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
178f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
179f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
180f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
181f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
182f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
183f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
184f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
185f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousFailure) {
186f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
187f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
188f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
189f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
190f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
191f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
192f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD, _, _))
193f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
194f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
195f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .Times(2)
196f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillRepeatedly(Return(0));
197f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
198f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
199f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_FALSE(async_connection().Start(ipv4_address(), kConnectPort));
200f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
201f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
202f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
203f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartMATCHER_P2(IsSocketAddress, address, port, "") {
2043b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  const struct sockaddr_in* arg_saddr =
2053b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart      reinterpret_cast<const struct sockaddr_in*>(arg);
206f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  IPAddress arg_addr(IPAddress::kFamilyIPv4,
2073b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart                     ByteString(reinterpret_cast<const unsigned char*>(
208f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                         &arg_saddr->sin_addr.s_addr),
209f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                sizeof(arg_saddr->sin_addr.s_addr)));
210f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  return address.Equals(arg_addr) && arg_saddr->sin_port == htons(port);
211f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
212f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
213f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuMATCHER_P2(IsSocketIpv6Address, ipv6_address, port, "") {
2143b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart  const struct sockaddr_in6* arg_saddr =
2153b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart      reinterpret_cast<const struct sockaddr_in6*>(arg);
216f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  IPAddress arg_addr(IPAddress::kFamilyIPv6,
2173b30ca58d13cf66b75ba0729b222ddc42ae68b33Paul Stewart                     ByteString(reinterpret_cast<const unsigned char*>(
218f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                         &arg_saddr->sin6_addr.s6_addr),
219f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                sizeof(arg_saddr->sin6_addr.s6_addr)));
220f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  return ipv6_address.Equals(arg_addr) && arg_saddr->sin6_port == htons(port);
221f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
222f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
223f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousStart) {
224f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
225f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
226f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
227f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
228f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
229f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
230f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD,
231f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketAddress(ipv4_address(), kConnectPort),
232f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                  sizeof(struct sockaddr_in)))
233f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(-1));
234f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(dispatcher(),
2353e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood              CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
236f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart        .WillOnce(ReturnNew<IOHandler>());
237f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
238f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(EINPROGRESS));
239f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
240f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_EQ(kSocketFD, fd());
241f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
242f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
243f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuTEST_F(AsyncConnectionTest, SynchronousStartIpv6) {
244f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Socket(_, _, _))
245f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(kSocketFD));
246f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
247f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
248f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
249f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
250f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Connect(kSocketFD,
251f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketIpv6Address(ipv6_address(),
252f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                                      kConnectPort),
253f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  sizeof(struct sockaddr_in6)))
254f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(-1));
255f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(dispatcher(),
256f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu              CreateReadyHandler(kSocketFD, IOHandler::kModeOutput, _))
257f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu        .WillOnce(ReturnNew<IOHandler>());
258f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Error())
259f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(EINPROGRESS));
260f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
261f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_EQ(kSocketFD, fd());
262f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
263f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
264f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, AsynchronousFailure) {
265f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StartConnection();
266f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
267f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(1));
268f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Error())
269f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kErrorNumber));
270f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(false, -1));
271f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
272f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
273f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  OnConnectCompletion(kSocketFD);
274f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
275f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_STREQ(strerror(kErrorNumber), async_connection().error().c_str());
276f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
277f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
278f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, AsynchronousSuccess) {
279f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  StartConnection();
280f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
281f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
282f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
283f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  OnConnectCompletion(kSocketFD);
284f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
285f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
286f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
287f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul StewartTEST_F(AsyncConnectionTest, SynchronousSuccess) {
288f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Socket(_, _, _))
289f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(kSocketFD));
290f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
291f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
292f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
293f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
294f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(sockets(), Connect(kSocketFD,
295f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketAddress(ipv4_address(), kConnectPort),
296f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart                                  sizeof(struct sockaddr_in)))
297f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart      .WillOnce(Return(0));
298f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
299f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv4_address(), kConnectPort));
300f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  ExpectReset();
301f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu}
302f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu
303f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter QiuTEST_F(AsyncConnectionTest, SynchronousSuccessIpv6) {
304f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Socket(_, _, _))
305f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(kSocketFD));
306f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), SetNonBlocking(kSocketFD))
307f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
308f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), BindToDevice(kSocketFD, StrEq(kInterfaceName)))
309f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
310f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(sockets(), Connect(kSocketFD,
311f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  IsSocketIpv6Address(ipv6_address(),
312f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                                      kConnectPort),
313f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu                                  sizeof(struct sockaddr_in6)))
314f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu      .WillOnce(Return(0));
315f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD));
316f3a8f9064976d12c4f8ed3c6a5cc9ea4655c686dPeter Qiu  EXPECT_TRUE(async_connection().Start(ipv6_address(), kConnectPort));
317f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart  ExpectReset();
318f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}
319f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart
3208585b207dc9502256c2a428611e948e105db96b6Paul StewartTEST_F(AsyncConnectionTest, FreeOnSuccessCallback) {
3218585b207dc9502256c2a428611e948e105db96b6Paul Stewart  StartConnection();
3228585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
3238585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(0));
3248585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(callback_target(), CallTarget(true, kSocketFD))
3258585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
3268585b207dc9502256c2a428611e948e105db96b6Paul Stewart  OnConnectCompletion(kSocketFD);
3278585b207dc9502256c2a428611e948e105db96b6Paul Stewart}
3288585b207dc9502256c2a428611e948e105db96b6Paul Stewart
3298585b207dc9502256c2a428611e948e105db96b6Paul StewartTEST_F(AsyncConnectionTest, FreeOnFailureCallback) {
3308585b207dc9502256c2a428611e948e105db96b6Paul Stewart  StartConnection();
3318585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), GetSocketError(kSocketFD))
3328585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(1));
3338585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(callback_target(), CallTarget(false, -1))
3348585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Invoke(this, &AsyncConnectionTest::InvokeFreeConnection));
3358585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), Error())
3368585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(kErrorNumber));
3378585b207dc9502256c2a428611e948e105db96b6Paul Stewart  EXPECT_CALL(sockets(), Close(kSocketFD))
3388585b207dc9502256c2a428611e948e105db96b6Paul Stewart      .WillOnce(Return(0));
3398585b207dc9502256c2a428611e948e105db96b6Paul Stewart  OnConnectCompletion(kSocketFD);
3408585b207dc9502256c2a428611e948e105db96b6Paul Stewart}
3418585b207dc9502256c2a428611e948e105db96b6Paul Stewart
342f65320cc1c04ea9e09cc8656e87fe9912c601e9aPaul Stewart}  // namespace shill
343