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