1f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko// Copyright 2014 The Chromium OS Authors. All rights reserved.
2f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko// Use of this source code is governed by a BSD-style license that can be
3f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko// found in the LICENSE file.
4f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_transport_curl.h>
6f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
7aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko#include <base/at_exit.h>
8aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko#include <base/message_loop/message_loop.h>
9aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko#include <base/run_loop.h>
109ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/bind_lambda.h>
119ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_connection_curl.h>
129ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/http_request.h>
139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/http/mock_curl_api.h>
14f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko#include <gmock/gmock.h>
15f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko#include <gtest/gtest.h>
16f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
17aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::DoAll;
18aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::Invoke;
19f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkousing testing::Return;
20aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::SaveArg;
21aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::SetArgPointee;
22aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::WithoutArgs;
23aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkousing testing::_;
24f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
259ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
26f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkonamespace http {
27f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkonamespace curl {
28f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
29f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenkoclass HttpCurlTransportTest : public testing::Test {
30f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko public:
31f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  void SetUp() override {
32f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko    curl_api_ = std::make_shared<MockCurlInterface>();
33f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko    transport_ = std::make_shared<Transport>(curl_api_);
34f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko    handle_ = reinterpret_cast<CURL*>(100);  // Mock handle value.
35c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasyInit()).WillOnce(Return(handle_));
36c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptStr(handle_, CURLOPT_CAPATH, _))
37c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
38c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_SSL_VERIFYPEER, 1))
39c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
40c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_SSL_VERIFYHOST, 2))
41c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
42c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptPtr(handle_, CURLOPT_PRIVATE, _))
43c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillRepeatedly(Return(CURLE_OK));
44f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  }
45f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
46f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  void TearDown() override {
47f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko    transport_.reset();
48f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko    curl_api_.reset();
49f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  }
50f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
51f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko protected:
52f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  std::shared_ptr<MockCurlInterface> curl_api_;
53f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  std::shared_ptr<Transport> transport_;
54f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  CURL* handle_{nullptr};
55f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko};
56f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
57f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, RequestGet) {
58f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
59f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/get"))
60f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
61f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
62f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_USERAGENT, "User Agent"))
63f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
64f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
65f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_REFERER, "http://foo.bar/baz"))
66f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
67f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_HTTPGET, 1))
68f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
6905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko  auto connection = transport_->CreateConnection("http://foo.bar/get",
7005d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                                                 request_type::kGet,
7105d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                                                 {},
7205d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                                                 "User Agent",
7305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                                                 "http://foo.bar/baz",
7405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko                                                 nullptr);
75f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_NE(nullptr, connection.get());
76f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
77f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
78f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  connection.reset();
79f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
80f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
81f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, RequestHead) {
82f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
83f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/head"))
84f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
85f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_NOBODY, 1))
86f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
87f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  auto connection = transport_->CreateConnection(
88f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      "http://foo.bar/head", request_type::kHead, {}, "", "", nullptr);
89f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_NE(nullptr, connection.get());
90f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
91f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
92f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  connection.reset();
93f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
94f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
95f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, RequestPut) {
96f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
97f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/put"))
98f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
99f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_UPLOAD, 1))
100f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
101f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  auto connection = transport_->CreateConnection(
102f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      "http://foo.bar/put", request_type::kPut, {}, "", "", nullptr);
103f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_NE(nullptr, connection.get());
104f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
105f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
106f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  connection.reset();
107f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
108f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
109f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, RequestPost) {
110f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
111f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://www.foo.bar/post"))
112f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
113f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_POST, 1))
114f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
115f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptPtr(handle_, CURLOPT_POSTFIELDS, nullptr))
116f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
117f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  auto connection = transport_->CreateConnection(
118f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      "http://www.foo.bar/post", request_type::kPost, {}, "", "", nullptr);
119f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_NE(nullptr, connection.get());
120f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
121f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
122f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  connection.reset();
123f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
124f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
125f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, RequestPatch) {
126f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
127f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://www.foo.bar/patch"))
128f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
129f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_POST, 1))
130f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
131f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptPtr(handle_, CURLOPT_POSTFIELDS, nullptr))
132f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
13305d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko  EXPECT_CALL(
13405d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      *curl_api_,
13505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko      EasySetOptStr(handle_, CURLOPT_CUSTOMREQUEST, request_type::kPatch))
136f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
137f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  auto connection = transport_->CreateConnection(
138f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      "http://www.foo.bar/patch", request_type::kPatch, {}, "", "", nullptr);
139f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_NE(nullptr, connection.get());
140f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
141f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
142f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  connection.reset();
143f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
144f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
145f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex VakulenkoTEST_F(HttpCurlTransportTest, CurlFailure) {
146f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_,
147f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/get"))
148f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OK));
149f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_HTTPGET, 1))
150f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return(CURLE_OUT_OF_MEMORY));
151f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyStrError(CURLE_OUT_OF_MEMORY))
152f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      .WillOnce(Return("Out of Memory"));
153f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
154f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  ErrorPtr error;
155f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  auto connection = transport_->CreateConnection(
156f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko      "http://foo.bar/get", request_type::kGet, {}, "", "", &error);
157f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
158f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_EQ(nullptr, connection.get());
159aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_EQ("curl_easy_error", error->GetDomain());
160f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_EQ(std::to_string(CURLE_OUT_OF_MEMORY), error->GetCode());
161f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko  EXPECT_EQ("Out of Memory", error->GetMessage());
162f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}
163f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko
164aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenkoclass HttpCurlTransportAsyncTest : public testing::Test {
165aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko public:
166aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  void SetUp() override {
167aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    curl_api_ = std::make_shared<MockCurlInterface>();
168aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    transport_ = std::make_shared<Transport>(curl_api_);
169c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasyInit()).WillOnce(Return(handle_));
170c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptStr(handle_, CURLOPT_CAPATH, _))
171c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
172c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_SSL_VERIFYPEER, 1))
173c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
174c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_SSL_VERIFYHOST, 2))
175c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
176c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko    EXPECT_CALL(*curl_api_, EasySetOptPtr(handle_, CURLOPT_PRIVATE, _))
177c85d17cbfa7cceb2a9a643ae0fcba082ee796d85Alex Vakulenko        .WillOnce(Return(CURLE_OK));
178aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  }
179aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
180aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko protected:
181aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  std::shared_ptr<MockCurlInterface> curl_api_;
182aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  std::shared_ptr<Transport> transport_;
183aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  CURL* handle_{reinterpret_cast<CURL*>(123)};          // Mock handle value.
184aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  CURLM* multi_handle_{reinterpret_cast<CURLM*>(456)};  // Mock handle value.
185aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  curl_socket_t dummy_socket_{789};
186aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko};
187aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
188aa7d677661213b4116adc5fac88b8c37a1490010Alex VakulenkoTEST_F(HttpCurlTransportAsyncTest, StartAsyncTransfer) {
189aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // This test is a bit tricky because it deals with asynchronous I/O which
190aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // relies on a message loop to run all the async tasks.
191aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // For this, create a temporary I/O message loop and run it ourselves for the
192aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // duration of the test.
193aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  base::MessageLoopForIO message_loop;
194aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  base::RunLoop run_loop;
195aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
196aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // Initial expectations for creating a CURL connection.
197aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_,
198aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/get"))
199aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(Return(CURLE_OK));
200aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_HTTPGET, 1))
201aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(Return(CURLE_OK));
202aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  auto connection = transport_->CreateConnection(
203aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      "http://foo.bar/get", request_type::kGet, {}, "", "", nullptr);
204aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  ASSERT_NE(nullptr, connection.get());
205aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
206aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // Success/error callback needed to report the result of an async operation.
207aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  int success_call_count = 0;
208aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  auto success_callback = [&success_call_count, &run_loop](
2092fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley      RequestID /* request_id */, std::unique_ptr<http::Response> /* resp */) {
210aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
211aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    success_call_count++;
212aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  };
213aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
2142fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley  auto error_callback = [](RequestID /* request_id */,
2152fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley                           const Error* /* error */) {
216aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    FAIL() << "This callback shouldn't have been called";
217aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  };
218aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
219aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, MultiInit()).WillOnce(Return(multi_handle_));
220736346392699216622881933f3260c67c6f6f9a1Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyGetInfoInt(handle_, CURLINFO_RESPONSE_CODE, _))
221736346392699216622881933f3260c67c6f6f9a1Alex Vakulenko      .WillRepeatedly(DoAll(SetArgPointee<2>(200), Return(CURLE_OK)));
222aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
223aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  curl_socket_callback socket_callback = nullptr;
224aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_,
225aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko              MultiSetSocketCallback(multi_handle_, _, transport_.get()))
226aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(DoAll(SaveArg<1>(&socket_callback), Return(CURLM_OK)));
227aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
228aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  curl_multi_timer_callback timer_callback = nullptr;
229aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_,
230aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko              MultiSetTimerCallback(multi_handle_, _, transport_.get()))
231aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(DoAll(SaveArg<1>(&timer_callback), Return(CURLM_OK)));
232aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
233aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, MultiAddHandle(multi_handle_, handle_))
234aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(Return(CURLM_OK));
235aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
236aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_EQ(1, transport_->StartAsyncTransfer(connection.get(),
237aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                                              base::Bind(success_callback),
238aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                                              base::Bind(error_callback)));
239aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_EQ(0, success_call_count);
240aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
241aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  timer_callback(multi_handle_, 1, transport_.get());
242aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
243aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  auto do_socket_action = [&socket_callback, this] {
244aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    EXPECT_CALL(*curl_api_, MultiAssign(multi_handle_, dummy_socket_, _))
245aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko        .Times(2).WillRepeatedly(Return(CURLM_OK));
246aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko    EXPECT_EQ(0, socket_callback(handle_, dummy_socket_, CURL_POLL_REMOVE,
247aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                                 transport_.get(), nullptr));
248aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  };
249aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
250aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_,
251aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko              MultiSocketAction(multi_handle_, CURL_SOCKET_TIMEOUT, 0, _))
252aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(DoAll(SetArgPointee<3>(1),
253aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                      WithoutArgs(Invoke(do_socket_action)),
254aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                      Return(CURLM_OK)))
255aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillRepeatedly(DoAll(SetArgPointee<3>(0), Return(CURLM_OK)));
256aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
257aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  CURLMsg msg = {};
258aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  msg.msg = CURLMSG_DONE;
259aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  msg.easy_handle = handle_;
260aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  msg.data.result = CURLE_OK;
261aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
262aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, MultiInfoRead(multi_handle_, _))
263aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(DoAll(SetArgPointee<1>(0), Return(&msg)))
264aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(nullptr)));
265aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyGetInfoPtr(handle_, CURLINFO_PRIVATE, _))
266aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillRepeatedly(DoAll(SetArgPointee<2>(connection.get()),
267aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko                            Return(CURLE_OK)));
268aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
269aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, MultiRemoveHandle(multi_handle_, handle_))
270aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(Return(CURLM_OK));
271aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
272aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // Just in case something goes wrong and |success_callback| isn't called,
273aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  // post a time-out quit closure to abort the message loop after 1 second.
274aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  message_loop.PostDelayedTask(
275aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
276aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  run_loop.Run();
277aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_EQ(1, success_call_count);
278aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
279aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
280aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  connection.reset();
281aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
282aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  EXPECT_CALL(*curl_api_, MultiCleanup(multi_handle_))
283aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko      .WillOnce(Return(CURLM_OK));
284aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko  transport_.reset();
285aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko}
286aa7d677661213b4116adc5fac88b8c37a1490010Alex Vakulenko
28739a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave TapuskaTEST_F(HttpCurlTransportTest, RequestGetTimeout) {
28839a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  transport_->SetDefaultTimeout(base::TimeDelta::FromMilliseconds(2000));
28939a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  EXPECT_CALL(*curl_api_,
29039a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska              EasySetOptStr(handle_, CURLOPT_URL, "http://foo.bar/get"))
29139a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska      .WillOnce(Return(CURLE_OK));
29239a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_TIMEOUT_MS, 2000))
29339a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska      .WillOnce(Return(CURLE_OK));
29439a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  EXPECT_CALL(*curl_api_, EasySetOptInt(handle_, CURLOPT_HTTPGET, 1))
29539a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska      .WillOnce(Return(CURLE_OK));
29639a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  auto connection = transport_->CreateConnection(
29739a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska      "http://foo.bar/get", request_type::kGet, {}, "", "", nullptr);
29839a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  EXPECT_NE(nullptr, connection.get());
29939a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska
30039a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  EXPECT_CALL(*curl_api_, EasyCleanup(handle_)).Times(1);
30139a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska  connection.reset();
30239a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska}
30339a28f2d429c8e73f3d2b6f7daf7b0bfaca7fcf0Dave Tapuska
304f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}  // namespace curl
305f5effe9e46e479e6fdc4f6928da545d48dcd3997Alex Vakulenko}  // namespace http
3069ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
307