Fix for Azure Core with libcurl. clean up and global clean up (#1500)

make SDK to call global_init and global_cleanup
This commit is contained in:
Victor Vazquez 2021-04-08 15:55:26 -07:00 committed by GitHub
parent ff0d5a18cd
commit 5de76e7a21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 214 additions and 91 deletions

View File

@ -29,7 +29,7 @@ The Azure SDK for C++ provides two HTTP transport adapters as part of the azure-
Users can create and use their own transport adapter [by following the guidance below](#building-a-custom-http-transport-adapter).
For the simplest case, when no specific configuration is set, the default transport adapter will be selected based on the OS. The WinHTTP transport adapter will be used for Windows-based systems (making libcurl an optional dependency). The libcurl transport adapter will be selected for any non-Windows-based system.
For the simplest case, when no specific configuration is set, the default transport adapter will be selected based on the OS. The WinHTTP transport adapter will be used for Windows-based systems (making libcurl an optional dependency). The libcurl transport adapter will be selected for any non-Windows-based system. Read more about using the libcurl transport adapter here.
## Building the HTTP Transport Adapter

View File

@ -0,0 +1,37 @@
# Libcurl Transport Adapter
The Azure SDK for C++ provides an http transport adapter implementation using the well known libcurl library. There are some general guidelines that you should know if you decide to use this implementation.
## Global init and clean up
Libcurl provides the functions [curl_global_init](https://curl.se/libcurl/c/curl_global_init.html) and [curl_global_cleanup](https://curl.se/libcurl/c/curl_global_cleanup.html) which are expected to be called at the start and before exiting the application. However, for a modular part of the application, like a library, it is expected that each library using libcurl will call the `curl_global_init` and `curl_global_cleanup`. From [libcurl global constants documentation](https://curl.se/libcurl/c/libcurl.html):
> Note that if multiple modules in the program use libcurl, they all will separately call the libcurl functions, and that's OK because only the first curl_global_init and the last curl_global_cleanup in a program change anything. (libcurl uses a reference count in static memory).
Consider the next example:
```cpp
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file Demonstrate how to use libcurl and the Azure SDK for C++.
*
*/
#include <curl/curl.h>
#include <azure/storage/blob/blobs.hpp>
int main(int argc, char** argv)
{
curl_global_init(CURL_GLOBAL_ALL);
// Use the Azure SDK clients.
curl_global_cleanup();
return 0;
}
```
If the application is not using libcurl at all, only the Azure SDK library will call `curl_global_init` and `curl_global_cleanup`. If the application is calling the global functions and using libcurl, then the calls to these functions from the Azure SDK library won't change anything. So, as an application or library owner, you only need to worry about calling the global libcurl functions if you will be using libcurl directly.

View File

@ -184,7 +184,6 @@ static inline std::string GetHTTPMessagePreBody(Azure::Core::Http::Request const
using Azure::Core::Context;
using Azure::Core::Http::CurlConnection;
using Azure::Core::Http::CurlConnectionPool;
using Azure::Core::Http::CurlNetworkConnection;
using Azure::Core::Http::CurlSession;
using Azure::Core::Http::CurlTransport;
@ -193,6 +192,7 @@ using Azure::Core::Http::HttpStatusCode;
using Azure::Core::Http::RawResponse;
using Azure::Core::Http::Request;
using Azure::Core::Http::TransportException;
using Azure::Core::Http::_detail::CurlConnectionPool;
std::unique_ptr<RawResponse> CurlTransport::Send(Request& request, Context const& context)
{
@ -1109,8 +1109,8 @@ int64_t CurlSession::ResponseBufferParser::BuildHeader(
std::mutex CurlConnectionPool::ConnectionPoolMutex;
std::map<std::string, std::list<std::unique_ptr<CurlNetworkConnection>>>
CurlConnectionPool::ConnectionPoolIndex;
uint64_t CurlConnectionPool::s_connectionCounter = 0;
bool CurlConnectionPool::s_isCleanConnectionsRunning = false;
uint64_t CurlConnectionPool::g_connectionCounter = 0;
std::atomic<bool> CurlConnectionPool::g_isCleanConnectionsRunning(false);
namespace {
inline std::string GetConnectionKey(std::string const& host, CurlTransportOptions const& options)
@ -1174,7 +1174,7 @@ std::unique_ptr<CurlNetworkConnection> CurlConnectionPool::ExtractOrCreateCurlCo
if (resetPool)
{
// Remove all connections for the connection Key and move to spawn new connection below
CurlConnectionPool::s_connectionCounter -= hostPoolIndex->second.size();
CurlConnectionPool::g_connectionCounter -= hostPoolIndex->second.size();
hostPoolIndex->second.clear();
}
else
@ -1186,7 +1186,7 @@ std::unique_ptr<CurlNetworkConnection> CurlConnectionPool::ExtractOrCreateCurlCo
// Remove the connection ref from list
hostPoolIndex->second.erase(fistConnectionIterator);
// reduce number of connections on the pool
CurlConnectionPool::s_connectionCounter -= 1;
CurlConnectionPool::g_connectionCounter -= 1;
// Remove index if there are no more connections
if (hostPoolIndex->second.size() == 0)
@ -1330,11 +1330,11 @@ void CurlConnectionPool::MoveConnectionBackToPool(
// update the time when connection was moved back to pool
connection->updateLastUsageTime();
hostPool.push_front(std::move(connection));
CurlConnectionPool::s_connectionCounter += 1;
CurlConnectionPool::g_connectionCounter += 1;
// Check if there's no cleaner running and started
if (!CurlConnectionPool::s_isCleanConnectionsRunning)
if (!CurlConnectionPool::g_isCleanConnectionsRunning)
{
CurlConnectionPool::s_isCleanConnectionsRunning = true;
CurlConnectionPool::g_isCleanConnectionsRunning = true;
CurlConnectionPool::CleanUp();
}
}
@ -1350,14 +1350,22 @@ void CurlConnectionPool::CleanUp()
std::this_thread::sleep_for(
std::chrono::milliseconds(_detail::DefaultCleanerIntervalMilliseconds));
// while sleeping, it is allowed to explicitly prevent the cleaner to run and stop it, for
// example, when the application exits, and the cleaner is sleeping, we don't want it to wake
// up and try to access de-allocated memory.
if (!CurlConnectionPool::g_isCleanConnectionsRunning)
{
return;
}
{
// take mutex for reading the pool
std::lock_guard<std::mutex> lock(CurlConnectionPool::ConnectionPoolMutex);
if (CurlConnectionPool::s_connectionCounter == 0)
if (CurlConnectionPool::g_connectionCounter == 0)
{
// stop the cleaner since there are no connections
CurlConnectionPool::s_isCleanConnectionsRunning = false;
CurlConnectionPool::g_isCleanConnectionsRunning = false;
return;
}
@ -1385,7 +1393,7 @@ void CurlConnectionPool::CleanUp()
// remove connection from the pool and update the connection to the next one
// which is going to be list.end()
connection = index->second.erase(connection);
CurlConnectionPool::s_connectionCounter -= 1;
CurlConnectionPool::g_connectionCounter -= 1;
// Connection removed, break if there are no more connections to check
if (index->second.size() == 0)

View File

@ -14,6 +14,7 @@
#include "curl_connection_private.hpp"
#include <atomic>
#include <curl/curl.h>
#include <list>
#include <map>
@ -27,7 +28,10 @@ namespace Azure { namespace Core { namespace Test {
}}} // namespace Azure::Core::Test
#endif
namespace Azure { namespace Core { namespace Http {
namespace Azure { namespace Core { namespace Http { namespace _detail {
// In charge of calling the libcurl global functions for the Azure SDK
struct CurlGlobalStateForAzureSdk;
/**
* @brief CURL HTTP connection pool makes it possible to re-use one curl connection to perform
@ -41,6 +45,10 @@ namespace Azure { namespace Core { namespace Http {
// Give access to private to this tests class
friend class Azure::Core::Test::CurlConnectionPool_connectionPoolTest_Test;
#endif
private:
// The cttor and dttor of this member makes sure of calling the libcurl global init and cleanup
AZ_CORE_DLLEXPORT static CurlGlobalStateForAzureSdk CurlGlobalState;
public:
/**
* @brief Mutex for accessing connection pool for thread-safe reading and writing.
@ -66,8 +74,8 @@ namespace Azure { namespace Core { namespace Http {
* @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.
* @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.
*/
@ -89,6 +97,8 @@ namespace Azure { namespace Core { namespace Http {
// Class can't have instances.
CurlConnectionPool() = delete;
static void StopCleaner() { g_isCleanConnectionsRunning = false; }
private:
/**
* Review all connections in the pool and removes old connections that might be already
@ -96,8 +106,8 @@ namespace Azure { namespace Core { namespace Http {
*/
static void CleanUp();
AZ_CORE_DLLEXPORT static uint64_t s_connectionCounter;
AZ_CORE_DLLEXPORT static bool s_isCleanConnectionsRunning;
AZ_CORE_DLLEXPORT static uint64_t g_connectionCounter;
AZ_CORE_DLLEXPORT static std::atomic<bool> g_isCleanConnectionsRunning;
// Removes all connections and indexes
static void ClearIndex() { CurlConnectionPool::ConnectionPoolIndex.clear(); }
@ -115,4 +125,16 @@ namespace Azure { namespace Core { namespace Http {
return CurlConnectionPool::ConnectionPoolIndex.size();
};
};
}}} // namespace Azure::Core::Http
struct CurlGlobalStateForAzureSdk
{
CurlGlobalStateForAzureSdk() { curl_global_init(CURL_GLOBAL_ALL); }
~CurlGlobalStateForAzureSdk()
{
CurlConnectionPool::StopCleaner();
curl_global_cleanup();
}
};
}}}} // namespace Azure::Core::Http::_detail

View File

@ -385,7 +385,8 @@ namespace Azure { namespace Core { namespace Http {
// IsEOF will also handle a connection that fail to complete an upload request.
if (IsEOF() && m_keepAlive)
{
CurlConnectionPool::MoveConnectionBackToPool(std::move(m_connection), m_lastStatusCode);
_detail::CurlConnectionPool::MoveConnectionBackToPool(
std::move(m_connection), m_lastStatusCode);
}
}

View File

@ -105,7 +105,32 @@ gtest_discover_tests(azure-core-test
NO_PRETTY_TYPES
NO_PRETTY_VALUES)
if(BUILD_TRANSPORT_CURL)
################## Azure Libcurl Core Test #################################
# Creating one exe file alone for this test since it requires the full control over the connection pool.
# This test will check that end-user can call `curl_global_cleanup()` with active handlers in the connection pool
# without getting errors.
add_executable (
azure-core-libcurl-test
azure_libcurl_core_main.cpp
)
if (MSVC)
# warning C4389: '==': signed/unsigned mismatch
target_compile_options(azure-core-libcurl-test PUBLIC /wd4389)
endif()
# Adding private headers from CORE to the tests so we can test the private APIs with no relative paths include.
target_include_directories (azure-core-libcurl-test PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../src>)
target_link_libraries(azure-core-libcurl-test PRIVATE azure-core gtest gmock)
# Use the same prefix to run this test
gtest_discover_tests(azure-core-libcurl-test
TEST_PREFIX azure-core.)
endif()
gtest_discover_tests(azure-core-global-context-test
TEST_PREFIX azure-core-global-context.
TEST_PREFIX azure-core.
NO_PRETTY_TYPES
NO_PRETTY_VALUES)

View File

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file This test assumes the application is already using libcurl.
*
*/
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#if !defined(NOMINMAX)
#define NOMINMAX
#endif
#include <gtest/gtest.h>
#include <curl/curl.h>
#include <azure/core/context.hpp>
#include <azure/core/http/curl_transport.hpp>
#include <azure/core/http/http.hpp>
#include <azure/core/http/policies/policy.hpp>
#include <azure/core/io/body_stream.hpp>
#include <azure/core/response.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>
namespace Azure { namespace Core { namespace Test {
TEST(SdkWithLibcurl, globalCleanUp)
{
Azure::Core::Http::Request req(
Azure::Core::Http::HttpMethod::Get, Azure::Core::Url("https://httpbin.org/get"));
{
// Creating a new connection with default options
Azure::Core::Http::CurlTransportOptions options;
auto connection
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
auto session = std::make_unique<Azure::Core::Http::CurlSession>(
req, std::move(connection), options.HttpKeepAlive);
session->Perform(Azure::Core::Context::GetApplicationContext());
// Reading all the response
session->ReadToEnd(Azure::Core::Context::GetApplicationContext());
}
// Check that after the connection is gone, it is moved back to the pool
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
}
}}} // namespace Azure::Core::Test
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
auto r = RUN_ALL_TESTS();
return r;
}

View File

@ -30,9 +30,9 @@ namespace Azure { namespace Core { namespace Test {
TEST(CurlConnectionPool, connectionPoolTest)
{
Azure::Core::Http::CurlConnectionPool::ClearIndex();
Azure::Core::Http::_detail::CurlConnectionPool::ClearIndex();
// Make sure there are nothing in the pool
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
// Use the same request for all connections.
Azure::Core::Http::Request req(
@ -43,7 +43,8 @@ namespace Azure { namespace Core { namespace Test {
// Creating a new connection with default options
Azure::Core::Http::CurlTransportOptions options;
auto connection
= Azure::Core::Http::CurlConnectionPool::ExtractOrCreateCurlConnection(req, options);
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
EXPECT_EQ(connection->GetConnectionKey(), expectedConnectionKey);
@ -54,10 +55,11 @@ namespace Azure { namespace Core { namespace Test {
session->m_sessionState = Azure::Core::Http::CurlSession::SessionState::STREAMING;
}
// Check that after the connection is gone, it is moved back to the pool
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
auto connectionFromPool = Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin()
->second.begin()
->get();
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
auto connectionFromPool
= Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin()
->second.begin()
->get();
EXPECT_EQ(connectionFromPool->GetConnectionKey(), expectedConnectionKey);
// Test that asking a connection with same config will re-use the same connection
@ -65,10 +67,11 @@ namespace Azure { namespace Core { namespace Test {
// Creating a new connection with default options
Azure::Core::Http::CurlTransportOptions options;
auto connection
= Azure::Core::Http::CurlConnectionPool::ExtractOrCreateCurlConnection(req, options);
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
// There was just one connection in the pool, it should be empty now
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
// And the connection key for the connection we got is the expected
EXPECT_EQ(connection->GetConnectionKey(), expectedConnectionKey);
@ -79,8 +82,8 @@ namespace Azure { namespace Core { namespace Test {
session->m_sessionState = Azure::Core::Http::CurlSession::SessionState::STREAMING;
}
// Check that after the connection is gone, it is moved back to the pool
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
auto values = Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
auto values = Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(values->second.size(), 1);
EXPECT_EQ(values->second.begin()->get()->GetConnectionKey(), expectedConnectionKey);
@ -91,13 +94,14 @@ namespace Azure { namespace Core { namespace Test {
Azure::Core::Http::CurlTransportOptions options;
options.SslVerifyPeer = false;
auto connection
= Azure::Core::Http::CurlConnectionPool::ExtractOrCreateCurlConnection(req, options);
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
EXPECT_EQ(connection->GetConnectionKey(), secondExpectedKey);
// One connection still in the pool after getting a new connection and with first expected
// key
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
EXPECT_EQ(
Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin()
Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin()
->second.begin()
->get()
->GetConnectionKey(),
@ -111,8 +115,8 @@ namespace Azure { namespace Core { namespace Test {
}
// Now there should be 2 index wit one connection each
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(values->second.size(), 1);
EXPECT_EQ(values->second.begin()->get()->GetConnectionKey(), secondExpectedKey);
values++;
@ -124,13 +128,14 @@ namespace Azure { namespace Core { namespace Test {
// Creating a new connection with default options
Azure::Core::Http::CurlTransportOptions options;
auto connection
= Azure::Core::Http::CurlConnectionPool::ExtractOrCreateCurlConnection(req, options);
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
EXPECT_EQ(connection->GetConnectionKey(), expectedConnectionKey);
// One connection still in the pool after getting a new connection and with first expected
// key
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 1);
EXPECT_EQ(
Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin()
Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin()
->second.begin()
->get()
->GetConnectionKey(),
@ -143,8 +148,8 @@ namespace Azure { namespace Core { namespace Test {
session->m_sessionState = Azure::Core::Http::CurlSession::SessionState::STREAMING;
}
// Now there should be 2 index wit one connection each
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(values->second.size(), 1);
EXPECT_EQ(values->second.begin()->get()->GetConnectionKey(), secondExpectedKey);
values++;
@ -167,8 +172,8 @@ namespace Azure { namespace Core { namespace Test {
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 100));
// Ensure connections are removed but indexes are still there
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 2);
values = Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.begin();
EXPECT_EQ(values->second.size(), 0);
values++;
EXPECT_EQ(values->second.size(), 0);
@ -183,7 +188,8 @@ namespace Azure { namespace Core { namespace Test {
Azure::Core::Http::CurlTransportOptions options;
auto connection
= Azure::Core::Http::CurlConnectionPool::ExtractOrCreateCurlConnection(req, options);
= Azure::Core::Http::_detail::CurlConnectionPool::ExtractOrCreateCurlConnection(
req, options);
// Simulate connection lost (like server disconnection).
connection->Shutdown();

View File

@ -90,7 +90,7 @@ namespace Azure { namespace Core { namespace Test {
// Clean the connection from the pool *Windows fails to clean if we leave to be clean uppon
// app-destruction
EXPECT_NO_THROW(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear());
EXPECT_NO_THROW(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear());
}
/*
@ -208,7 +208,7 @@ namespace Azure { namespace Core { namespace Test {
// Clean the connection from the pool *Windows fails to clean if we leave to be clean uppon
// app-destruction
EXPECT_NO_THROW(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear());
EXPECT_NO_THROW(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear());
}
TEST(CurlTransportOptions, httpsDefault)
@ -240,7 +240,7 @@ namespace Azure { namespace Core { namespace Test {
// Clean the connection from the pool *Windows fails to clean if we leave to be clean uppon
// app-destruction
EXPECT_NO_THROW(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear());
EXPECT_NO_THROW(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear());
}
TEST(CurlTransportOptions, disableKeepAlive)
@ -276,7 +276,7 @@ namespace Azure { namespace Core { namespace Test {
responseCode));
}
// Make sure there are no connections in the pool
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
}
}}} // namespace Azure::Core::Test

View File

@ -79,7 +79,7 @@ namespace Azure { namespace Core { namespace Test {
EXPECT_NO_THROW(session->Perform(Azure::Core::Context::GetApplicationContext()));
}
// Clear the connections from the pool to invoke clean routine
Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear();
Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear();
}
TEST_F(CurlSession, chunkBadFormatResponse)
@ -127,7 +127,7 @@ namespace Azure { namespace Core { namespace Test {
Azure::Core::Http::TransportException);
}
// Clear the connections from the pool to invoke clean routine
Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear();
Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear();
}
TEST_F(CurlSession, chunkSegmentedResponse)
@ -202,7 +202,7 @@ namespace Azure { namespace Core { namespace Test {
EXPECT_NO_THROW(bodyS->ReadToEnd(Azure::Core::Context::GetApplicationContext()));
}
// Clear the connections from the pool to invoke clean routine
Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.clear();
Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.clear();
}
TEST_F(CurlSession, DoNotReuseConnectionIfDownloadFail)
@ -231,6 +231,6 @@ namespace Azure { namespace Core { namespace Test {
EXPECT_EQ(CURLE_SEND_ERROR, returnCode);
}
// Check connection pool is empty (connection was not moved to the pool)
EXPECT_EQ(Azure::Core::Http::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
EXPECT_EQ(Azure::Core::Http::_detail::CurlConnectionPool::ConnectionPoolIndex.size(), 0);
}
}}} // namespace Azure::Core::Test

View File

@ -11,24 +11,14 @@
int main(int argc, char** argv)
{
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
curl_global_init(CURL_GLOBAL_ALL);
#if defined(AZ_PLATFORM_POSIX)
// OpenSSL signals SIGPIPE when trying to clean an HTTPS closed connection.
// End users need to decide if SIGPIPE should be ignored or not.
signal(SIGPIPE, SIG_IGN);
#endif
#endif
testing::InitGoogleTest(&argc, argv);
auto r = RUN_ALL_TESTS();
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
#if defined(AZ_PLATFORM_POSIX)
// Cleaning ssl connections on Windows is broken until
// https://github.com/Azure/azure-sdk-for-cpp/pull/1500 is merged.
curl_global_cleanup();
#endif
#endif
return r;
}

View File

@ -38,12 +38,9 @@ namespace Azure { namespace Perf { namespace Test {
*/
void GlobalSetup() override
{
curl_global_init(CURL_GLOBAL_ALL);
_detail::HttpClient = std::make_unique<Azure::Core::Http::CurlTransport>();
}
void GlobalCleanup() override { curl_global_cleanup(); }
/**
* @brief Get the static Test Metadata for the test.
*

View File

@ -11,24 +11,7 @@
int main(int argc, char** argv)
{
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
curl_global_init(CURL_GLOBAL_ALL);
#if defined(AZ_PLATFORM_POSIX)
// OpenSSL signals SIGPIPE when trying to clean an HTTPS closed connection.
// End users need to decide if SIGPIPE should be ignored or not.
signal(SIGPIPE, SIG_IGN);
#endif
#endif
testing::InitGoogleTest(&argc, argv);
auto r = RUN_ALL_TESTS();
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
#if defined(AZ_PLATFORM_POSIX)
// Cleaning ssl connections on Windows is broken until
// https://github.com/Azure/azure-sdk-for-cpp/pull/1500 is merged.
curl_global_cleanup();
#endif
#endif
return r;
}

View File

@ -9,16 +9,7 @@
int main(int argc, char** argv)
{
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
curl_global_init(CURL_GLOBAL_ALL);
#endif
testing::InitGoogleTest(&argc, argv);
auto r = RUN_ALL_TESTS();
#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER)
// Can't call global cleanup due to: https://github.com/Azure/azure-sdk-for-cpp/issues/1499
// curl_global_cleanup();
#endif
return r;
}