From b46a544a7b7ca04915085a8369939e7ff2bd0f53 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 28 Aug 2020 23:17:16 +0000 Subject: [PATCH] fix for unit tests for cleanner (#558) * fix for unit tests for cleanner --- sdk/core/azure-core/test/ut/main.cpp | 6 +- .../azure-core/test/ut/transport_adapter.cpp | 173 ++++++++---------- 2 files changed, 86 insertions(+), 93 deletions(-) diff --git a/sdk/core/azure-core/test/ut/main.cpp b/sdk/core/azure-core/test/ut/main.cpp index 19e7500cb..d63ef744b 100644 --- a/sdk/core/azure-core/test/ut/main.cpp +++ b/sdk/core/azure-core/test/ut/main.cpp @@ -2,9 +2,13 @@ // SPDX-License-Identifier: MIT #include "gtest/gtest.h" +#include "curl/curl.h" int main(int argc, char** argv) { + curl_global_init(CURL_GLOBAL_ALL); testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + auto r = RUN_ALL_TESTS(); + curl_global_cleanup(); + return r; } diff --git a/sdk/core/azure-core/test/ut/transport_adapter.cpp b/sdk/core/azure-core/test/ut/transport_adapter.cpp index 64daa4d13..37811e430 100644 --- a/sdk/core/azure-core/test/ut/transport_adapter.cpp +++ b/sdk/core/azure-core/test/ut/transport_adapter.cpp @@ -26,6 +26,87 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::HttpPipeline TransportAdapter::pipeline(policies); Azure::Core::Context TransportAdapter::context = Azure::Core::GetApplicationContext(); + // multiThread test requires `ConnectionsOnPool` hook which is only available when building + // TESTING_BUILD. This test is only built when that case is true. + TEST_F(TransportAdapter, getMultiThread) + { + std::string host("http://httpbin.org/get"); + Azure::Core::Http::CurlConnectionPool::ClearIndex(); + + auto threadRoutine = [host]() { + auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host); + auto response = pipeline.Send(context, request); + checkResponseCode(response->GetStatusCode()); + auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); + CheckBodyFromBuffer(*response, expectedResponseBodySize); + }; + + std::thread t1(threadRoutine); + std::thread t2(threadRoutine); + t1.join(); + t2.join(); + + // 2 connections must be available at this point + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 2); + + std::thread t3(threadRoutine); + std::thread t4(threadRoutine); + std::thread t5(threadRoutine); + t3.join(); + t4.join(); + t5.join(); + + // Two connections re-used plus one connection created + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 3); + } + +#ifdef RUN_LONG_UNIT_TESTS + TEST_F(TransportAdapter, ConnectionPoolCleaner) + { + std::string host("http://httpbin.org/get"); + + auto threadRoutine = [host]() { + auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host); + auto response = pipeline.Send(context, request); + checkResponseCode(response->GetStatusCode()); + auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); + CheckBodyFromBuffer(*response, expectedResponseBodySize); + }; + + // 3 connections from previous test. Make sure cleaner remove them + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 3); + + std::cout + << "Running Connection Pool Cleaner Test. This test takes more than 3 minutes to complete." + << std::endl + << "Add compiler option -DRUN_LONG_UNIT_TESTS=OFF when building if you want to skip this " + "test." + << std::endl; + + // Wait for 180 secs to make sure any previous connection is removed by the cleaner + std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 180)); + + std::cout << "First wait time done. Validating state." << std::endl; + + // index is not affected by cleaner. It does not remove index + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsIndexOnPool(), 1); + // cleaner should have remove connections + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 0); + + std::thread t1(threadRoutine); + std::thread t2(threadRoutine); + t1.join(); + t2.join(); + + // wait for connection to be moved back to pool + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + // 2 connections must be available at this point and one index + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsIndexOnPool(), 1); + EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 2); + } +#endif + TEST_F(TransportAdapter, get) { std::string host("http://httpbin.org/get"); @@ -169,98 +250,6 @@ namespace Azure { namespace Core { namespace Test { } } - // multiThread test requires `ConnectionsOnPool` hook which is only available when building - // TESTING_BUILD. This test cases are only built when that case is true.` - TEST_F(TransportAdapter, getMultiThread) - { - std::string host("http://httpbin.org/get"); - Azure::Core::Http::CurlConnectionPool::ClearIndex(); - - auto threadRoutine = [host]() { - auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host); - auto response = pipeline.Send(context, request); - checkResponseCode(response->GetStatusCode()); - auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); - CheckBodyFromBuffer(*response, expectedResponseBodySize); - }; - - std::thread t1(threadRoutine); - std::thread t2(threadRoutine); - t1.join(); - t2.join(); - // wait a few ms for connections to go back to pool. - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - // 2 connections must be available at this point - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 2); - - std::thread t3(threadRoutine); - std::thread t4(threadRoutine); - std::thread t5(threadRoutine); - t3.join(); - t4.join(); - t5.join(); - // wait a few ms for connections to go back to pool. - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - // Two connections re-used plus one connection created - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 3); - } - -#ifdef RUN_LONG_UNIT_TESTS - TEST_F(TransportAdapter, ConnectionPoolCleaner) - { - std::string host("http://httpbin.org/get"); - - auto threadRoutine = [host]() { - auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, host); - auto response = pipeline.Send(context, request); - checkResponseCode(response->GetStatusCode()); - auto expectedResponseBodySize = std::stoull(response->GetHeaders().at("content-length")); - CheckBodyFromBuffer(*response, expectedResponseBodySize); - }; - - // one index expected from previous tests - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsIndexOnPool(), 1); - - std::cout - << "Running Connection Pool Cleaner Test. This test takes more than 3 minutes to complete." - << std::endl - << "Add compiler option -DRUN_LONG_UNIT_TESTS=OFF when building if you want to skip this " - "test." - << std::endl; - - // Wait for 100 secs to make sure any previous connection is removed by the cleaner - std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 100)); - - std::cout << "First wait time done. Validating state." << std::endl; - - // index is not affected by cleaner. It does not remove index - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsIndexOnPool(), 1); - // cleaner should have remove connections - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 0); - - // Let cleaner finish - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - - std::thread t1(threadRoutine); - std::thread t2(threadRoutine); - t1.join(); - t2.join(); - - // 2 connections must be available at this point and one index - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsIndexOnPool(), 1); - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 2); - - // At this point, cleaner should be ON and will clean connections after on second. - // After 5 seconds connection pool should have been cleaned - std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 100)); - - std::cout << "Second wait time done. Validating state." << std::endl; - - // EXPECT_EQ(Http::CurlSession::ConnectionsIndexOnPool(), 0); - EXPECT_EQ(Http::CurlConnectionPool::ConnectionsOnPool("httpbin.org"), 0); - } -#endif - // ********************** // ***Same tests but getting stream to pull from socket, simulating the Download Op // **********************