remove duplicated headers and update tests (#2369)

This commit is contained in:
Victor Vazquez 2021-06-01 10:02:55 -07:00 committed by GitHub
parent 38bd273d23
commit da252f76f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 17 additions and 765 deletions

View File

@ -33,7 +33,12 @@ if(BUILD_TRANSPORT_CURL)
endif()
if(BUILD_TRANSPORT_CURL)
SET(CURL_TRANSPORT_ADAPTER_SRC src/http/curl/curl.cpp)
SET(CURL_TRANSPORT_ADAPTER_SRC
src/http/curl/curl_connection_pool_private.hpp
src/http/curl/curl_connection_private.hpp
src/http/curl/curl_session_private.hpp
src/http/curl/curl.cpp
)
SET(CURL_TRANSPORT_ADAPTER_INC inc/azure/core/http/curl_transport.hpp)
endif()
if(BUILD_TRANSPORT_WINHTTP)
@ -102,9 +107,6 @@ set(
src/http/url.cpp
src/io/body_stream.cpp
src/io/random_access_file_body_stream.cpp
src/private/curl_connection.hpp
src/private/curl_connection_pool.hpp
src/private/curl_session.hpp
src/private/environment_log_level_listener.hpp
src/private/package_version.hpp
src/base64.cpp

View File

@ -1,204 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief The libcurl connection keeps the curl handle and performs the data transfer to the
* network.
*/
#pragma once
#include "azure/core/http/http.hpp"
#include <chrono>
#include <curl/curl.h>
#include <string>
namespace Azure { namespace Core { namespace Http {
namespace _detail {
// libcurl CURL_MAX_WRITE_SIZE is 64k. Using same value for default uploading chunk size.
// This can be customizable in the HttpRequest
constexpr static int64_t DefaultUploadChunkSize = 1024 * 64;
constexpr static auto DefaultLibcurlReaderSize = 1024;
// Run time error template
constexpr static const char* DefaultFailedToGetNewConnectionTemplate
= "Fail to get a new connection for: ";
constexpr static int32_t DefaultMaxOpenNewConnectionIntentsAllowed = 10;
// After 3 connections are received from the pool and failed to send a request, the next
// connections would ask the pool to be clean and spawn new connection.
constexpr static int32_t RequestPoolResetAfterConnectionFailed = 3;
// 90 sec -> cleaner wait time before next clean routine
constexpr static int32_t DefaultCleanerIntervalMilliseconds = 1000 * 90;
// 60 sec -> expired connection is when it waits for 60 sec or more and it's not re-used
constexpr static int32_t DefaultConnectionExpiredMilliseconds = 1000 * 60;
// Define the maximun allowed connections per host-index in the pool. If this number is reached
// for the host-index, next connections trying to be added to the pool will be ignored.
constexpr static size_t MaxConnectionsPerIndex = 1024;
} // namespace _detail
/**
* @brief Interface for the connection to the network with Curl.
*
* @remark This interface enables to mock the communication to the network with any behavior for
* testing.
*
*/
class CurlNetworkConnection {
protected:
bool m_isShutDown = false;
public:
/**
* @brief Allow derived classes calling a destructor.
*
*/
virtual ~CurlNetworkConnection() = default;
/**
* @brief Get the Connection Properties Key object
*
*/
virtual std::string const& GetConnectionKey() const = 0;
/**
* @brief Update last usage time for the connection.
*
*/
virtual void UpdateLastUsageTime() = 0;
/**
* @brief Checks whether this CURL connection is expired.
*
*/
virtual bool IsExpired() = 0;
/**
* @brief This function is used when working with streams to pull more data from the wire.
* Function will try to keep pulling data from socket until the buffer is all written or until
* there is no more data to get from the socket.
*
*/
virtual size_t ReadFromSocket(uint8_t* buffer, size_t bufferSize, Context const& context) = 0;
/**
* @brief This method will use libcurl socket to write all the bytes from buffer.
*
*/
virtual CURLcode SendBuffer(uint8_t const* buffer, size_t bufferSize, Context const& context)
= 0;
/**
* @brief Set the connection into an invalid and unusable state.
*
* @remark A connection won't be returned to the connection pool if it was shut it down.
*
*/
virtual void Shutdown() { m_isShutDown = true; };
/**
* @brief Check if the the connection was shut it down.
*
* @return `true` is the connection was shut it down.
*/
bool IsShutdown() const { return m_isShutDown; };
};
/**
* @brief CURL HTTP connection.
*
*/
class CurlConnection final : public CurlNetworkConnection {
private:
CURL* m_handle;
curl_socket_t m_curlSocket;
std::chrono::steady_clock::time_point m_lastUseTime;
std::string m_connectionKey;
public:
/**
* @Brief Construct CURL HTTP connection.
*
* @param host HTTP connection host name.
*/
CurlConnection(CURL* handle, std::string connectionPropertiesKey)
: m_handle(handle), m_connectionKey(std::move(connectionPropertiesKey))
{
// Get the socket that libcurl is using from handle. Will use this to wait while
// reading/writing
// into wire
#if defined(_MSC_VER)
#pragma warning(push)
// C26812: The enum type 'CURLcode' is un-scoped. Prefer 'enum class' over 'enum' (Enum.3)
#pragma warning(disable : 26812)
#endif
auto result = curl_easy_getinfo(m_handle, CURLINFO_ACTIVESOCKET, &m_curlSocket);
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if (result != CURLE_OK)
{
throw Http::TransportException(
"Broken connection. Couldn't get the active sockect for it."
+ std::string(curl_easy_strerror(result)));
}
}
/**
* @brief Destructor.
* @details Cleans up CURL (invokes `curl_easy_cleanup()`).
*/
~CurlConnection() override { curl_easy_cleanup(this->m_handle); }
std::string const& GetConnectionKey() const override { return this->m_connectionKey; }
/**
* @brief Update last usage time for the connection.
*
*/
void UpdateLastUsageTime() override
{
this->m_lastUseTime = std::chrono::steady_clock::now();
}
/**
* @brief Checks whether this CURL connection is expired.
* @return `true` if this connection is considered expired, `false` otherwise.
*/
bool IsExpired() override
{
auto connectionOnWaitingTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - this->m_lastUseTime);
return connectionOnWaitingTimeMs.count() >= _detail::DefaultConnectionExpiredMilliseconds;
}
/**
* @brief This function is used when working with streams to pull more data from the wire.
* Function will try to keep pulling data from socket until the buffer is all written or until
* there is no more data to get from the socket.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
* @param buffer ptr to buffer where to copy bytes from socket.
* @param bufferSize size of the buffer and the requested bytes to be pulled from wire.
* @return return the numbers of bytes pulled from socket. It can be less than what it was
* requested.
*/
size_t ReadFromSocket(uint8_t* buffer, size_t bufferSize, Context const& context) override;
/**
* @brief This method will use libcurl socket to write all the bytes from buffer.
*
* @remarks Hardcoded timeout is used in case a socket stop responding.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
* @param buffer ptr to the data to be sent to wire.
* @param bufferSize size of the buffer to send.
* @return CURL_OK when response is sent successfully.
*/
CURLcode SendBuffer(uint8_t const* buffer, size_t bufferSize, Context const& context)
override;
void Shutdown() override;
};
}}} // namespace Azure::Core::Http

View File

@ -1,127 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief The curl connection pool provides the utilities for creating a new curl connection and to
* keep a pool of connections to be re-used.
*/
#pragma once
#include "azure/core/dll_import_export.hpp"
#include "azure/core/http/http.hpp"
#include "private/curl_connection.hpp"
#include <atomic>
#include <condition_variable>
#include <curl/curl.h>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <thread>
#if defined(TESTING_BUILD)
// Define the class name that reads from ConnectionPool private members
namespace Azure { namespace Core { namespace Test {
class CurlConnectionPool_connectionPoolTest_Test;
class CurlConnectionPool_uniquePort_Test;
}}} // namespace Azure::Core::Test
#endif
namespace Azure { namespace Core { namespace Http { namespace _detail {
/**
* @brief CURL HTTP connection pool makes it possible to re-use one curl connection to perform
* more than one request. Use this component when connections are not re-used by default.
*
* This pool offers static methods and it is allocated statically. There can be only one
* connection pool per application.
*/
class CurlConnectionPool final {
#if defined(TESTING_BUILD)
// Give access to private to this tests class
friend class Azure::Core::Test::CurlConnectionPool_connectionPoolTest_Test;
friend class Azure::Core::Test::CurlConnectionPool_uniquePort_Test;
#endif
public:
~CurlConnectionPool()
{
using namespace Azure::Core::Http::_detail;
if (m_cleanThread.joinable())
{
{
std::unique_lock<std::mutex> lock(ConnectionPoolMutex);
// Remove all connections
g_curlConnectionPool.ConnectionPoolIndex.clear();
}
// Signal clean thread to wake up
ConditionalVariableForCleanThread.notify_one();
// join thread
m_cleanThread.join();
}
curl_global_cleanup();
}
/**
* @brief Finds a connection to be re-used from the connection pool.
* @remark If there is not any available connection, a new connection is created.
*
* @param request HTTP request to get #Azure::Core::Http::CurlNetworkConnection for.
* @param options The connection settings which includes host name and libcurl handle specific
* configuration.
* @param resetPool Request the pool to remove all current connections for the provided
* options to force the creation of a new connection.
*
* @return #Azure::Core::Http::CurlNetworkConnection to use.
*/
std::unique_ptr<CurlNetworkConnection> ExtractOrCreateCurlConnection(
Request& request,
CurlTransportOptions const& options,
bool resetPool = false);
/**
* @brief Moves a connection back to the pool to be re-used.
*
* @param connection CURL HTTP connection to add to the pool.
* @param lastStatusCode The most recent HTTP status code received from the \p connection.
*/
void MoveConnectionBackToPool(
std::unique_ptr<CurlNetworkConnection> connection,
HttpStatusCode lastStatusCode);
/**
* @brief Keeps a unique key for each host and creates a connection pool for each key.
*
* @details This way getting a connection for a specific host can be done in O(1) instead of
* looping a single connection list to find the first connection for the required host.
*
* @remark There might be multiple connections for each host.
*/
std::map<std::string, std::list<std::unique_ptr<CurlNetworkConnection>>> ConnectionPoolIndex;
std::mutex ConnectionPoolMutex;
// This is used to put the cleaning pool thread to sleep and yet to be able to wake it if the
// application finishes.
std::condition_variable ConditionalVariableForCleanThread;
AZ_CORE_DLLEXPORT static Azure::Core::Http::_detail::CurlConnectionPool g_curlConnectionPool;
bool IsCleanThreadRunning = false;
private:
// private constructor to keep this as singleton.
CurlConnectionPool() { curl_global_init(CURL_GLOBAL_ALL); }
// Makes possible to know the number of current connections in the connection pool for an
// index
int64_t ConnectionsOnPool(std::string const& host) { return ConnectionPoolIndex[host].size(); };
std::thread m_cleanThread;
};
}}}} // namespace Azure::Core::Http::_detail

View File

@ -1,418 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief The curl session consumes a curl connection to perform a request with it and start
* streaming the response.
*
* @remark The curl session is a body stream derived class.
*/
#pragma once
#include "azure/core/http/http.hpp"
#include "private/curl_connection.hpp"
#include "private/curl_connection_pool.hpp"
#include <memory>
#include <string>
#ifdef TESTING_BUILD
// Define the class name that reads from ConnectionPool private members
namespace Azure { namespace Core { namespace Test {
class CurlConnectionPool_connectionPoolTest_Test;
}}} // namespace Azure::Core::Test
#endif
namespace Azure { namespace Core { namespace Http {
/**
* @brief Stateful component that controls sending an HTTP Request with libcurl over the wire.
*
* @remark This component does not use the classic libcurl easy interface to send and receive
* bytes from the network using callbacks. Instead, `CurlSession` supports working with the custom
* HTTP protocol option from libcurl to manually upload and download bytes from the network socket
* using curl_easy_send() and curl_easy_recv().
*
* @remarks This component is expected to be used by an HTTP Transporter to ensure that
* transporter to be reusable in multiple pipelines while every call to network is unique.
*/
class CurlSession final : public Azure::Core::IO::BodyStream {
#ifdef TESTING_BUILD
// Give access to private to this tests class
friend class Azure::Core::Test::CurlConnectionPool_connectionPoolTest_Test;
#endif
private:
/**
* @brief Read one expected byte and throw if it is different than the \p expected
*
*/
void ReadExpected(uint8_t expected, Context const& context);
/**
* @brief Read `\\r\\n` from internal buffer or from the wire.
*
* @remark throw if `\\r\\n` are not the next data read.
*/
void ReadCRLF(Context const& context);
/**
* @brief This is used to set the current state of a session.
*
* @remark The session needs to know what's the state on it when an exception occurs so the
* connection is not moved back to the connection pool. When a new request is going to be sent,
* the session will be in `PERFORM` until the request has been uploaded and a response code is
* received from the server. At that point the state will change to `STREAMING`.
* If there is any error before changing the state, the connection need to be cleaned up.
*
*/
enum class SessionState
{
PERFORM,
STREAMING
};
/*
* Enum used by ResponseBufferParser to control the parsing internal state while building
* the HTTP RawResponse
*
*/
enum class ResponseParserState
{
StatusLine,
Headers,
EndOfHeaders,
};
/**
* @brief stateful component used to read and parse a buffer to construct a valid HTTP
* RawResponse.
*
* @remark It uses an internal string as a buffer to accumulate a response token (version, code,
* header, etc.) until the next delimiter is found. Then it uses this string to keep building
* the HTTP RawResponse.
*
* @remark Only status line and headers are parsed and built. Body is ignored by this
* component. A libcurl session will use this component to build and return the HTTP
* RawResponse with a body stream to the pipeline.
*/
class ResponseBufferParser final {
private:
/**
* @brief Controls what the parser is expecting during the reading process
*
*/
ResponseParserState state = ResponseParserState::StatusLine;
/**
* @brief Unique ptr to a response. Parser will create an Initial-valid HTTP RawResponse and
* then it will append headers to it. This response is moved to a different owner once
* parsing is completed.
*
*/
std::unique_ptr<RawResponse> m_response;
/**
* @brief Indicates if parser has found the end of the headers and there is nothing left for
* the HTTP RawResponse.
*
*/
bool m_parseCompleted = false;
bool m_delimiterStartInPrevPosition = false;
/**
* @brief This buffer is used when the parsed buffer doesn't contain a completed token. The
* content from the buffer will be appended to this buffer. Once that a delimiter is found,
* the token for the HTTP RawResponse is taken from this internal sting if it contains data.
*
* @remark This buffer allows a libcurl session to use any size of buffer to read from a
* socket while constructing an initial valid HTTP RawResponse. No matter if the response
* from wire contains hundreds of headers, we can use only one fixed size buffer to parse it
* all.
*
*/
std::string m_internalBuffer;
/**
* @brief This method is invoked by the Parsing process if the internal state is set to
* status code. Function will get the status-line expected tokens until finding the end of
* status line delimiter.
*
* @remark When the end of status line delimiter is found, this method will create the HTTP
* RawResponse. The HTTP RawResponse is constructed by default with body type as Stream.
*
* @param buffer Points to a memory address with all or some part of a HTTP status line.
* @param bufferSize Indicates the size of the buffer.
* @return Returns the index of the last parsed position from buffer.
*/
int64_t BuildStatusCode(uint8_t const* const buffer, int64_t const bufferSize);
/**
* @brief This method is invoked by the Parsing process if the internal state is set to
* headers. Function will keep adding headers to the HTTP RawResponse created before while
* parsing an status line.
*
* @param buffer Points to a memory address with all or some part of a HTTP header.
* @param bufferSize Indicates the size of the buffer.
* @return Returns the index of the last parsed position from buffer. When the returned
* value is smaller than the body size, means there is part of the body response in the
* buffer.
*/
int64_t BuildHeader(uint8_t const* const buffer, int64_t const bufferSize);
public:
/**
* @brief Construct a new RawResponse Buffer Parser object.
*
*/
ResponseBufferParser() {}
/**
* @brief Parses the content of a buffer to construct a valid HTTP RawResponse. This method
* is expected to be called over and over until it returns 0, indicating there is nothing
* more to parse to build the HTTP RawResponse.
*
* @param buffer points to a memory area that contains, all or some part of an HTTP
* response.
* @param bufferSize Indicates the size of the buffer.
* @return Returns the index of the last parsed position. Returning a 0 means nothing was
* parsed and it is likely that the HTTP RawResponse is completed. Returning the same value
* as the buffer size means all buffer was parsed and the HTTP might be completed or not.
* Returning a value smaller than the buffer size will likely indicate that the HTTP
* RawResponse is completed and that the rest of the buffer contains part of the response
* body.
*/
int64_t Parse(uint8_t const* const buffer, int64_t const bufferSize);
/**
* @brief Indicates when the parser has completed parsing and building the HTTP RawResponse.
*
* @return `true` if parsing is completed. Otherwise `false`.
*/
bool IsParseCompleted() const { return m_parseCompleted; }
/**
* @brief Moves the internal response to a different owner.
*
* @return Will move the response only if parsing is completed and if the HTTP RawResponse
* was not moved before.
*/
std::unique_ptr<RawResponse> ExtractResponse()
{
if (m_parseCompleted && m_response != nullptr)
{
return std::move(m_response);
}
return nullptr; // parse is not completed or response has been moved already.
}
};
/**
* @brief The current state of the session.
*
* @remark The state of the session is used to determine if a connection can be moved back to
* the connection pool or not. A connection can be re-used only when the session state is
* `STREAMING` and the response has been read completely.
*
*/
SessionState m_sessionState = SessionState::PERFORM;
std::unique_ptr<CurlNetworkConnection> m_connection;
/**
* @brief unique ptr for the HTTP RawResponse. The session is responsable for creating the
* response once that an HTTP status line is received.
*
*/
std::unique_ptr<RawResponse> m_response;
/**
* @brief The HTTP Request for to be used by the session.
*
*/
Request& m_request;
/**
* @brief Control field to handle the case when part of HTTP response body was copied to the
* inner buffer. When a libcurl stream tries to read part of the body, this field will help to
* decide how much data to take from the inner buffer before pulling more data from network.
*
*/
int64_t m_bodyStartInBuffer = -1;
/**
* @brief Control field to handle the number of bytes containing relevant data within the
* internal buffer. This is because internal buffer can be set to be size N but after writing
* from wire into it, it can be holding less then N bytes.
*
*/
int64_t m_innerBufferSize = _detail::DefaultLibcurlReaderSize;
bool m_isChunkedResponseType = false;
/**
* @brief This is a copy of the value of an HTTP response header `content-length`. The value
* is received as string and parsed to size_t. This field avoid parsing the string header
* every time from HTTP RawResponse.
*
* @remark This value is also used to avoid trying to read more data from network than what we
* are expecting to.
*
*/
int64_t m_contentLength = 0;
/**
* @brief For chunked responses, this field knows the size of the current chuck size server
* will de sending
*
*/
int64_t m_chunkSize = 0;
int64_t m_sessionTotalRead = 0;
/**
* @brief Internal buffer from a session used to read bytes from a socket. This buffer is only
* used while constructing an HTTP RawResponse without adding a body to it. Customers would
* provide their own buffer to copy from socket when reading the HTTP body using streams.
*
*/
uint8_t m_readBuffer[_detail::DefaultLibcurlReaderSize]
= {0}; // to work with libcurl custom read.
/**
* @brief Function used when working with Streams to manually write from the HTTP Request to
* the wire.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
*
* @return CURL_OK when response is sent successfully.
*/
CURLcode SendRawHttp(Context const& context);
/**
* @brief Upload body.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
*
* @return Curl code.
*/
CURLcode UploadBody(Context const& context);
/**
* @brief This function is used after sending an HTTP request to the server to read the HTTP
* RawResponse from wire until the end of headers only.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
* @param reuseInternalBuffer Indicates whether the internal buffer should be reused.
*/
void ReadStatusLineAndHeadersFromRawResponse(
Context const& context,
bool reuseInternalBuffer = false);
/**
* @brief Reads from inner buffer or from Wire until chunkSize is parsed and converted to
* unsigned long long
*
* @param context #Azure::Core::Context so that operation can be cancelled.
*/
void ParseChunkSize(Context const& context);
/**
* @brief Last HTTP status code read.
*
* @remark The last status is initialized as a bad request just as a way to know that there's
* not a good request performed by the session. The status will be updated as soon as the
* session sent a request and it is used to decide if a connection can be re-used or not.
*/
Http::HttpStatusCode m_lastStatusCode = Http::HttpStatusCode::BadRequest;
/**
* @brief check whether an end of file has been reached.
* @return `true` if end of file has been reached, `false` otherwise.
*/
bool IsEOF()
{
auto eof = m_isChunkedResponseType ? m_chunkSize == 0 : m_contentLength == m_sessionTotalRead;
// `IsEOF` is called before trying to move a connection back to the connection pool.
// If the session state is `PERFORM` it means the request could not complete an upload
// operation (might have throw while uploading).
// Connection should not be moved back to the connection pool on this scenario.
return eof && m_sessionState != SessionState::PERFORM;
}
/**
* @brief All connections will request to keep the channel open to re-use the
* connection.
*
* @remark This option can be disabled from the transport adapter options. When disabled, the
* session won't return connections to the connection pool. Connection will be closed as soon as
* the request is completed.
*
*/
bool m_keepAlive = true;
/**
* @brief Implement #Azure::Core::IO::BodyStream::OnRead(). Calling this function pulls data
* from the wire.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
* @param buffer Buffer where data from wire is written to.
* @param count The number of bytes to read from the network.
* @return The actual number of bytes read from the network.
*/
size_t OnRead(uint8_t* buffer, size_t count, Azure::Core::Context const& context) override;
public:
/**
* @brief Construct a new Curl Session object. Init internal libcurl handler.
*
* @param request reference to an HTTP Request.
*/
CurlSession(Request& request, std::unique_ptr<CurlNetworkConnection> connection, bool keepAlive)
: m_connection(std::move(connection)), m_request(request), m_keepAlive(keepAlive)
{
}
~CurlSession() override
{
// mark connection as reusable only if entire response was read
// If not, connection can't be reused because next Read will start from what it is currently
// in the wire.
// By not moving the connection back to the pool, it gets destroyed calling the connection
// destructor to clean libcurl handle and close the connection.
// IsEOF will also handle a connection that fail to complete an upload request.
if (IsEOF() && m_keepAlive)
{
_detail::CurlConnectionPool::g_curlConnectionPool.MoveConnectionBackToPool(
std::move(m_connection), m_lastStatusCode);
}
}
/**
* @brief Function will use the HTTP request received in constructor to perform a network call
* based on the HTTP request configuration.
*
* @param context #Azure::Core::Context so that operation can be cancelled.
* @return CURLE_OK when the network call is completed successfully.
*/
CURLcode Perform(Context const& context);
/**
* @brief Moved the ownership of the HTTP RawResponse out of the session.
*
* @return the unique ptr to the HTTP RawResponse or null if the HTTP RawResponse is not yet
* created or was moved before.
*/
std::unique_ptr<Azure::Core::Http::RawResponse> ExtractResponse();
/**
* @brief Implement #Azure::Core::IO::BodyStream length.
*
* @return The size of the payload.
*/
int64_t Length() const override { return m_contentLength; }
};
}}} // namespace Azure::Core::Http

View File

@ -25,9 +25,9 @@
#include <azure/core/io/body_stream.hpp>
#include <azure/core/response.hpp>
#include <private/curl_connection.hpp>
#include <private/curl_connection_pool.hpp>
#include <private/curl_session.hpp>
#include <http/curl/curl_connection_pool_private.hpp>
#include <http/curl/curl_connection_private.hpp>
#include <http/curl/curl_session_private.hpp>
#include <cstdlib>

View File

@ -15,11 +15,10 @@
#include <thread>
// The next includes are from Azure Core private headers.
// That's why the path starts from `private/`
// They are included to test the connection pool from the libcurl transport adapter implementation.
#include <private/curl_connection.hpp>
#include <private/curl_connection_pool.hpp>
#include <private/curl_session.hpp>
#include <http/curl/curl_connection_pool_private.hpp>
#include <http/curl/curl_connection_private.hpp>
#include <http/curl/curl_session_private.hpp>
#include "curl_session_test.hpp"

View File

@ -14,8 +14,8 @@
#include "azure/core/http/curl_transport.hpp"
#endif
#include <private/curl_connection.hpp>
#include <private/curl_session.hpp>
#include <http/curl/curl_connection_pool_private.hpp>
#include <http/curl/curl_session_private.hpp>
#include "transport_adapter_base_test.hpp"

View File

@ -24,7 +24,7 @@
#include <gtest/gtest.h>
#include <string>
#include <private/curl_connection_pool.hpp>
#include <http/curl/curl_connection_pool_private.hpp>
namespace Azure { namespace Core { namespace Test {

View File

@ -6,8 +6,8 @@
#include <azure/core/http/curl_transport.hpp>
#include <azure/core/http/http.hpp>
#include <private/curl_connection.hpp>
#include <private/curl_session.hpp>
#include <http/curl/curl_connection_private.hpp>
#include <http/curl/curl_session_private.hpp>
using ::testing::_;
using ::testing::DoAll;