diff --git a/.cspell.json b/.cspell.json index 46ecb400fb1..c24d14b1715 100644 --- a/.cspell.json +++ b/.cspell.json @@ -13,7 +13,7 @@ "Presigner", "xindex", "errortype", "waveout", "WAVEOUTCAPSA", "ALLOWSYNC", "WAVEHDR", "MMSYSERR", "WAVEFORMATEX", "Unprepare", "DDISABLE_IMDSV1", "SENDREQUEST", "threadpool", // AWS general - "Arns", "AMZN", "amzn", "Paulo", "Ningxia", "ISOB", "isob", "AWSXML", "IMDSV", + "Arns", "AMZN", "amzn", "Paulo", "Ningxia", "ISOB", "isob", "AWSXML", "IMDSV", "AWSSTL", // AWS Signature "SIGV", "AUTHV", // CMake diff --git a/generated/tests/s3-gen-tests/S3EndpointProviderTests.cpp b/generated/tests/s3-gen-tests/S3EndpointProviderTests.cpp index d16fc2a06f4..756ce41c41b 100644 --- a/generated/tests/s3-gen-tests/S3EndpointProviderTests.cpp +++ b/generated/tests/s3-gen-tests/S3EndpointProviderTests.cpp @@ -20,8 +20,6 @@ using ExpEpProps = Aws::UnorderedMap; using ExpEpHeaders = Aws::UnorderedMap>; -class S3EndpointProviderTests : public ::testing::TestWithParam {}; - struct S3EndpointProviderEndpointTestCase { using OperationParamsFromTest = EndpointParameters; @@ -55,7 +53,32 @@ struct S3EndpointProviderEndpointTestCase // Aws::Vector operationInput; }; -static const Aws::Vector TEST_CASES = { +class S3EndpointProviderTests : public ::testing::TestWithParam +{ +public: + static const size_t TEST_CASES_SZ; +protected: + static Aws::Vector getTestCase(); + static Aws::UniquePtrSafeDeleted> TEST_CASES; + static void SetUpTestSuite() + { + TEST_CASES = Aws::MakeUniqueSafeDeleted>(ALLOCATION_TAG, getTestCase()); + ASSERT_TRUE(TEST_CASES) << "Failed to allocate TEST_CASES table"; + assert(TEST_CASES->size() == TEST_CASES_SZ); + } + + static void TearDownTestSuite() + { + TEST_CASES.reset(); + } +}; + +Aws::UniquePtrSafeDeleted> S3EndpointProviderTests::TEST_CASES; +const size_t S3EndpointProviderTests::TEST_CASES_SZ = 297; + +Aws::Vector S3EndpointProviderTests::getTestCase() { + + Aws::Vector test_cases = { /*TEST CASE 0*/ {"region is not a valid DNS-suffix", // documentation {EpParam("UseFIPS", false), EpParam("Region", "a b"), EpParam("Accelerate", false), EpParam("UseDualStack", false)}, // params @@ -2585,7 +2608,9 @@ static const Aws::Vector TEST_CASES = { {}, // tags {{/*No endpoint expected*/}, /*error*/"S3Express bucket name is not a valid virtual hostable name."} // expect } -}; + }; + return test_cases; +} Aws::String RulesToSdkSignerName(const Aws::String& rulesSignerName) { @@ -2680,9 +2705,10 @@ void ValidateOutcome(const ResolveEndpointOutcome& outcome, const S3EndpointProv TEST_P(S3EndpointProviderTests, EndpointProviderTest) { const size_t TEST_CASE_IDX = GetParam(); - ASSERT_LT(TEST_CASE_IDX, TEST_CASES.size()) << "Something is wrong with the test fixture itself."; - const S3EndpointProviderEndpointTestCase& TEST_CASE = TEST_CASES.at(TEST_CASE_IDX); + ASSERT_LT(TEST_CASE_IDX, TEST_CASES->size()) << "Something is wrong with the test fixture itself."; + const S3EndpointProviderEndpointTestCase& TEST_CASE = TEST_CASES->at(TEST_CASE_IDX); SCOPED_TRACE(Aws::String("\nTEST CASE # ") + Aws::Utils::StringUtils::to_string(TEST_CASE_IDX) + ": " + TEST_CASE.documentation); + SCOPED_TRACE(Aws::String("\n--gtest_filter=EndpointTestsFromModel/S3EndpointProviderTests.EndpointProviderTest/") + Aws::Utils::StringUtils::to_string(TEST_CASE_IDX)); std::shared_ptr endpointProvider = Aws::MakeShared(ALLOCATION_TAG); ASSERT_TRUE(endpointProvider) << "Failed to allocate/initialize S3EndpointProvider"; @@ -2724,4 +2750,4 @@ TEST_P(S3EndpointProviderTests, EndpointProviderTest) INSTANTIATE_TEST_SUITE_P(EndpointTestsFromModel, S3EndpointProviderTests, - ::testing::Range((size_t) 0u, TEST_CASES.size())); + ::testing::Range((size_t) 0u, S3EndpointProviderTests::TEST_CASES_SZ)); diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/memory/stl/AWSAllocator.h b/src/aws-cpp-sdk-core/include/aws/core/utils/memory/stl/AWSAllocator.h index 0e680cb9b11..90b61ccb0f1 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/memory/stl/AWSAllocator.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/memory/stl/AWSAllocator.h @@ -18,8 +18,65 @@ namespace Aws { #ifdef USE_AWS_MEMORY_MANAGEMENT + /** + * Std allocator interface that is used for all STL types in CRT library + * in the event that Custom Memory Management is being used. + * + * Both SDK and CRT STL allocators are going to call the same SDK memory allocation methods. + * However, we should keep them separated + * to allow SDK to use the allocator when CRT is not initialized or already terminated. + */ + template< typename T > using CrtAllocator = Aws::Crt::StlAllocator; + + /** + * Std allocator interface that is used for all STL types in the SDK + * in the event that Custom Memory Management is being used. + */ + template + class Allocator : public std::allocator + { + public: + + typedef std::allocator Base; + + Allocator() throw() : + Base() + {} + + Allocator(const Allocator& a) throw() : + Base(a) + {} + + template + Allocator(const Allocator& a) throw() : + Base(a) + {} - template< typename T > using Allocator = Aws::Crt::StlAllocator; + ~Allocator() throw() {} + + typedef std::size_t size_type; + + template + struct rebind + { + typedef Allocator other; + }; + + typename Base::pointer allocate(size_type n, const void *hint = nullptr) + { + AWS_UNREFERENCED_PARAM(hint); + + return reinterpret_cast(Malloc("AWSSTL", n * sizeof(T))); + } + + void deallocate(typename Base::pointer p, size_type n) + { + AWS_UNREFERENCED_PARAM(n); + + Free(p); + } + + }; #ifdef __ANDROID__ #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0 @@ -46,6 +103,13 @@ namespace Aws template std::shared_ptr MakeShared(const char* allocationTag, ArgTypes&&... args) { +#ifdef USE_AWS_MEMORY_MANAGEMENT + Aws::Utils::Memory::MemorySystemInterface* memorySystem = Aws::Utils::Memory::GetMemorySystem(); + // Was InitAPI forgotten or ShutdownAPI already called or Aws:: class used as static? + // TODO: enforce to non-conditional assert + AWS_ASSERT(memorySystem && "Memory system is not initialized."); + AWS_UNREFERENCED_PARAM(memorySystem); +#endif AWS_UNREFERENCED_PARAM(allocationTag); return std::allocate_shared>(Aws::Allocator(), std::forward(args)...); diff --git a/src/aws-cpp-sdk-core/source/Aws.cpp b/src/aws-cpp-sdk-core/source/Aws.cpp index 720f26bfb1d..686d67d4e6f 100644 --- a/src/aws-cpp-sdk-core/source/Aws.cpp +++ b/src/aws-cpp-sdk-core/source/Aws.cpp @@ -46,7 +46,6 @@ namespace Aws Aws::Utils::Memory::InitializeAWSMemorySystem(*options.memoryManagementOptions.memoryManager); } #endif // USE_AWS_MEMORY_MANAGEMENT - Aws::InitializeCrt(); Aws::Client::CoreErrorsMapper::InitCoreErrorsMapper(); if(options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) { @@ -72,6 +71,7 @@ namespace Aws AWS_LOGSTREAM_INFO(ALLOCATION_TAG, "Initiate AWS SDK for C++ with Version:" << Aws::String(Aws::Version::GetVersionString())); } + Aws::InitializeCrt(); Aws::Config::InitConfigAndCredentialsCacheManager(); if (options.ioOptions.clientBootstrap_create_fn) @@ -210,14 +210,14 @@ namespace Aws Aws::Config::CleanupConfigAndCredentialsCacheManager(); + Aws::Client::CoreErrorsMapper::CleanupCoreErrorsMapper(); + Aws::CleanupCrt(); + if (options.loggingOptions.logLevel != Aws::Utils::Logging::LogLevel::Off) { Aws::Utils::Logging::ShutdownCRTLogging(); Aws::Utils::Logging::PushLogger(nullptr); // stops further logging but keeps old logger object alive } - Aws::Client::CoreErrorsMapper::CleanupCoreErrorsMapper(); - Aws::CleanupCrt(); - Aws::Utils::Logging::ShutdownAWSLogging(); #ifdef USE_AWS_MEMORY_MANAGEMENT if(options.memoryManagementOptions.memoryManager) diff --git a/src/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp b/src/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp index 1fdcc2c072f..21f6139ad7e 100644 --- a/src/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp +++ b/src/aws-cpp-sdk-core/source/utils/logging/DefaultLogSystem.cpp @@ -27,6 +27,8 @@ static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, std::s { // localtime requires access to env. variables to get Timezone, which is not thread-safe int32_t lastRolledHour = DateTime::Now().GetHour(false /*localtime*/); + Aws::Vector messages; + messages.reserve(BUFFERED_MSG_COUNT); for(;;) { @@ -38,9 +40,7 @@ static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, std::s break; } - Aws::Vector messages(std::move(syncData->m_queuedLogMessages)); - syncData->m_queuedLogMessages.reserve(BUFFERED_MSG_COUNT); - + std::swap(messages, syncData->m_queuedLogMessages); locker.unlock(); if (messages.size() > 0) @@ -48,7 +48,7 @@ static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, std::s if (rollLog) { // localtime requires access to env. variables to get Timezone, which is not thread-safe - int32_t currentHour = DateTime::Now().GetHour(false /*localtime*/); + int32_t currentHour = DateTime::Now().GetHour(false /*localtime*/); if (currentHour != lastRolledHour) { logFile = MakeDefaultLogFile(filenamePrefix); @@ -63,6 +63,12 @@ static void LogThread(DefaultLogSystem::LogSynchronizationData* syncData, std::s logFile->flush(); } + messages.clear(); + if(messages.capacity() > 2 * BUFFERED_MSG_COUNT) + { + messages.shrink_to_fit(); + messages.reserve(BUFFERED_MSG_COUNT); + } } { @@ -77,6 +83,7 @@ DefaultLogSystem::DefaultLogSystem(LogLevel logLevel, const std::shared_ptrFreeMemory(memoryPtr); @@ -101,7 +111,7 @@ void Free(void* memoryPtr) static void* MemAcquire(aws_allocator* allocator, size_t size) { (void)allocator; // unused; - return Aws::Malloc("MemAcquire", size); + return Aws::Malloc("CrtMemAcquire", size); } static void MemRelease(aws_allocator* allocator, void* ptr) diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index 35124b6c236..0663bd99221 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -63,20 +63,20 @@ using namespace Aws::Utils; namespace { - static Aws::String BASE_CREATE_BUCKET_TEST_NAME = "createbuckettest"; - static Aws::String BASE_DNS_UNFRIENDLY_TEST_NAME = "dns.unfriendly"; - static Aws::String BASE_LOCATION_BUCKET_TEST_NAME = "locbuckettest"; - static Aws::String BASE_OBJECTS_BUCKET_NAME = "objecttest"; - static Aws::String BASE_OBJECTS_DEFAULT_CTOR_BUCKET_NAME = "ctortest"; - static Aws::String BASE_PUT_OBJECTS_BUCKET_NAME = "putobjecttest"; - static Aws::String BASE_PUT_WEIRD_CHARSETS_OBJECTS_BUCKET_NAME = "charsetstest"; - static Aws::String BASE_PUT_OBJECTS_PRESIGNED_URLS_BUCKET_NAME = "presignedtest"; - static Aws::String BASE_PUT_MULTIPART_BUCKET_NAME = "multiparttest"; - static Aws::String BASE_ERRORS_TESTING_BUCKET = "errorstest"; - static Aws::String BASE_EVENT_STREAM_TEST_BUCKET_NAME = "eventstream"; - static Aws::String BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME = "largeeventstream"; - static Aws::String BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME = "errorsinevent"; - static Aws::String BASE_CHECKSUMS_BUCKET_NAME = "checksums-crt"; + static std::string BASE_CREATE_BUCKET_TEST_NAME = "createbuckettest"; + static std::string BASE_DNS_UNFRIENDLY_TEST_NAME = "dns.unfriendly"; + static std::string BASE_LOCATION_BUCKET_TEST_NAME = "locbuckettest"; + static std::string BASE_OBJECTS_BUCKET_NAME = "objecttest"; + static std::string BASE_OBJECTS_DEFAULT_CTOR_BUCKET_NAME = "ctortest"; + static std::string BASE_PUT_OBJECTS_BUCKET_NAME = "putobjecttest"; + static std::string BASE_PUT_WEIRD_CHARSETS_OBJECTS_BUCKET_NAME = "charsetstest"; + static std::string BASE_PUT_OBJECTS_PRESIGNED_URLS_BUCKET_NAME = "presignedtest"; + static std::string BASE_PUT_MULTIPART_BUCKET_NAME = "multiparttest"; + static std::string BASE_ERRORS_TESTING_BUCKET = "errorstest"; + static std::string BASE_EVENT_STREAM_TEST_BUCKET_NAME = "eventstream"; + static std::string BASE_EVENT_STREAM_LARGE_FILE_TEST_BUCKET_NAME = "largeeventstream"; + static std::string BASE_EVENT_STREAM_ERRORS_IN_EVENT_TEST_BUCKET_NAME = "errorsinevent"; + static std::string BASE_CHECKSUMS_BUCKET_NAME = "checksums-crt"; static const char* ALLOCATION_TAG = "BucketAndObjectOperationTest"; static const char* TEST_OBJ_KEY = "TestObjectKey"; static const char* TEST_NOT_MODIFIED_OBJ_KEY = "TestNotModifiedObjectKey"; @@ -90,7 +90,7 @@ namespace static const int TIMEOUT_MAX = 20; - void AppendUUID(Aws::String& bucketName) + void AppendUUID(std::string& bucketName) { using Aws::Utils::UUID; Aws::StringStream s; @@ -100,7 +100,7 @@ namespace void EnsureUniqueBucketNames() { - Aws::Vector> TEST_BUCKETS = + Aws::Vector> TEST_BUCKETS = { std::ref(BASE_CREATE_BUCKET_TEST_NAME), std::ref(BASE_DNS_UNFRIENDLY_TEST_NAME), @@ -121,7 +121,7 @@ namespace for (auto& testBucketName : TEST_BUCKETS) { AppendUUID(testBucketName); - SCOPED_TRACE(Aws::String("EnsureUniqueBucketNames: ") + testBucketName.get()); + SCOPED_TRACE(Aws::String("EnsureUniqueBucketNames: ") + testBucketName.get().c_str()); } } @@ -621,7 +621,7 @@ namespace //Create Client with default constructor Client = Aws::MakeShared(ALLOCATION_TAG); - const Aws::String fullBucketName = CalculateBucketName(BASE_OBJECTS_DEFAULT_CTOR_BUCKET_NAME); + const Aws::String fullBucketName = CalculateBucketName(BASE_OBJECTS_DEFAULT_CTOR_BUCKET_NAME.c_str()); SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); CreateBucketRequest createBucketRequest; createBucketRequest.SetBucket(fullBucketName); diff --git a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp index 87267521fbc..42c120bbf79 100644 --- a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp @@ -614,7 +614,7 @@ namespace ASSERT_NE(S3Errors::VALIDATION, getObjectOutcome.GetError().GetErrorType()); Aws::StringStream ss; ss << "https://" << expectedEndpoint << "/fakeObjectKey"; - if (ss.str() != TestingMonitoringMetrics::s_lastUriString) { + if (ss.str() != TestingMonitoringMetrics::s_lastUriString.c_str()) { std::cout << "Error"; } ASSERT_STREQ(ss.str().c_str(), TestingMonitoringMetrics::s_lastUriString.c_str()); diff --git a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp index b90b8b6f778..c861f218b13 100644 --- a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp +++ b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp @@ -19,18 +19,14 @@ class S3UnitTest : public testing::Test { protected: static void SetUpTestSuite() { #ifdef USE_AWS_MEMORY_MANAGEMENT - _testMemorySystem = Aws::MakeShared(ALLOCATION_TAG, 1024, 128); + _testMemorySystem.reset(new ExactTestMemorySystem(1024, 128)); _options.memoryManagementOptions.memoryManager = _testMemorySystem.get(); #endif + InitAPI(_options); _mockClientFactory = Aws::MakeShared(ALLOCATION_TAG); _mockHttpClient = Aws::MakeShared(ALLOCATION_TAG); _mockClientFactory->SetClient(_mockHttpClient); - HttpOptions httpOptions; - httpOptions.httpClientFactory_create_fn = []() -> std::shared_ptr { - return _mockClientFactory; - }; - _options.httpOptions = httpOptions; - InitAPI(_options); + SetHttpClientFactory(_mockClientFactory); AWSCredentials credentials{"mock", "credentials"}; const auto epProvider = Aws::MakeShared(ALLOCATION_TAG); S3ClientConfiguration s3Config; @@ -62,7 +58,7 @@ class S3UnitTest : public testing::Test { static std::shared_ptr _mockClientFactory; static std::shared_ptr _s3Client; #ifdef USE_AWS_MEMORY_MANAGEMENT - static std::shared_ptr _testMemorySystem; + static std::unique_ptr _testMemorySystem; #endif }; @@ -71,7 +67,8 @@ std::shared_ptr S3UnitTest::_mockHttpClient = nullptr; std::shared_ptr S3UnitTest::_mockClientFactory = nullptr; std::shared_ptr S3UnitTest::_s3Client = nullptr; #ifdef USE_AWS_MEMORY_MANAGEMENT -std::shared_ptr S3UnitTest::_testMemorySystem = nullptr; +// this must be std:: because this is an utility to track allocations in the SDK and should not rely on SDK +std::unique_ptr S3UnitTest::_testMemorySystem = nullptr; #endif diff --git a/tests/testing-resources/include/aws/testing/mocks/monitoring/TestingMonitoring.h b/tests/testing-resources/include/aws/testing/mocks/monitoring/TestingMonitoring.h index 2bded16cca8..0902b72d632 100644 --- a/tests/testing-resources/include/aws/testing/mocks/monitoring/TestingMonitoring.h +++ b/tests/testing-resources/include/aws/testing/mocks/monitoring/TestingMonitoring.h @@ -18,21 +18,22 @@ struct TestingMonitoringMetrics static bool s_enablePayload; }; - static Aws::String s_lastUriString; - static Aws::String s_lastSigningRegion; - static Aws::String s_lastSigningServiceName; - static Aws::String s_lastPayload; - static Aws::Map s_lastRequestHeaders; + // Note: these must be std:: to avoid memory issues because they are used outside InitAPI {...} ShutdownAPI. + static std::string s_lastUriString; + static std::string s_lastSigningRegion; + static std::string s_lastSigningServiceName; + static std::string s_lastPayload; + static std::map s_lastRequestHeaders; }; bool TestingMonitoringMetrics::Config::s_enablePayload; std::mutex s_lastMutex; -Aws::String TestingMonitoringMetrics::s_lastUriString; -Aws::String TestingMonitoringMetrics::s_lastSigningRegion; -Aws::String TestingMonitoringMetrics::s_lastSigningServiceName; -Aws::String TestingMonitoringMetrics::s_lastPayload; -Aws::Map TestingMonitoringMetrics::s_lastRequestHeaders; +std::string TestingMonitoringMetrics::s_lastUriString; +std::string TestingMonitoringMetrics::s_lastSigningRegion; +std::string TestingMonitoringMetrics::s_lastSigningServiceName; +std::string TestingMonitoringMetrics::s_lastPayload; +std::map TestingMonitoringMetrics::s_lastRequestHeaders; class TestingMonitoring : public Aws::Monitoring::MonitoringInterface { @@ -82,8 +83,6 @@ class TestingMonitoring : public Aws::Monitoring::MonitoringInterface AWS_UNREFERENCED_PARAM(serviceName); AWS_UNREFERENCED_PARAM(requestName); AWS_UNREFERENCED_PARAM(context); - std::unique_lock locker(s_lastMutex); - TestingMonitoringMetrics::s_lastUriString = request->GetUri().GetURIString().c_str(); TestingMonitoringMetrics::s_lastSigningRegion = request->GetSigningRegion().c_str(); Aws::Vector authComponents = request->HasAwsAuthorization() ? @@ -156,7 +155,6 @@ class TestingMonitoringManager private: static void Init() { - std::unique_lock locker(s_lastMutex); TestingMonitoringMetrics::Config::s_enablePayload = false; TestingMonitoringMetrics::s_lastUriString = ""; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/generatedtests/ServiceEndpointRulesTests.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/generatedtests/ServiceEndpointRulesTests.vm index 4d5a1005196..7e37dc5c352 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/generatedtests/ServiceEndpointRulesTests.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/generatedtests/ServiceEndpointRulesTests.vm @@ -22,8 +22,6 @@ using ExpEpProps = Aws::UnorderedMap; using ExpEpHeaders = Aws::UnorderedMap>; -class ${metadata.classNamePrefix}EndpointProviderTests : public ::testing::TestWithParam {}; - struct ${metadata.classNamePrefix}EndpointProviderEndpointTestCase { using OperationParamsFromTest = EndpointParameters; @@ -57,7 +55,32 @@ struct ${metadata.classNamePrefix}EndpointProviderEndpointTestCase // Aws::Vector operationInput; }; -static const Aws::Vector<${metadata.classNamePrefix}EndpointProviderEndpointTestCase> TEST_CASES = { +class ${metadata.classNamePrefix}EndpointProviderTests : public ::testing::TestWithParam +{ +public: + static const size_t TEST_CASES_SZ; +protected: + static Aws::Vector<${metadata.classNamePrefix}EndpointProviderEndpointTestCase> getTestCase(); + static Aws::UniquePtrSafeDeleted> TEST_CASES; + static void SetUpTestSuite() + { + TEST_CASES = Aws::MakeUniqueSafeDeleted>(ALLOCATION_TAG, getTestCase()); + ASSERT_TRUE(TEST_CASES) << "Failed to allocate TEST_CASES table"; + assert(TEST_CASES->size() == TEST_CASES_SZ); + } + + static void TearDownTestSuite() + { + TEST_CASES.reset(); + } +}; + +Aws::UniquePtrSafeDeleted> ${metadata.classNamePrefix}EndpointProviderTests::TEST_CASES; +const size_t ${metadata.classNamePrefix}EndpointProviderTests::TEST_CASES_SZ = ${testCases.size()}; + +Aws::Vector<${metadata.classNamePrefix}EndpointProviderEndpointTestCase> ${metadata.classNamePrefix}EndpointProviderTests::getTestCase() { + + Aws::Vector<${metadata.classNamePrefix}EndpointProviderEndpointTestCase> test_cases = { #foreach($testCase in $testCases) /*TEST CASE ${foreach.index}*/ {"${testCase.documentation}", // documentation @@ -68,7 +91,9 @@ static const Aws::Vector<${metadata.classNamePrefix}EndpointProviderEndpointTest #if($foreach.hasNext) },#else }#end #end -}; + }; + return test_cases; +} Aws::String RulesToSdkSignerName(const Aws::String& rulesSignerName) { @@ -163,9 +188,10 @@ void ValidateOutcome(const ResolveEndpointOutcome& outcome, const ${metadata.cla TEST_P(${metadata.classNamePrefix}EndpointProviderTests, EndpointProviderTest) { const size_t TEST_CASE_IDX = GetParam(); - ASSERT_LT(TEST_CASE_IDX, TEST_CASES.size()) << "Something is wrong with the test fixture itself."; - const ${metadata.classNamePrefix}EndpointProviderEndpointTestCase& TEST_CASE = TEST_CASES.at(TEST_CASE_IDX); + ASSERT_LT(TEST_CASE_IDX, TEST_CASES->size()) << "Something is wrong with the test fixture itself."; + const ${metadata.classNamePrefix}EndpointProviderEndpointTestCase& TEST_CASE = TEST_CASES->at(TEST_CASE_IDX); SCOPED_TRACE(Aws::String("\nTEST CASE # ") + Aws::Utils::StringUtils::to_string(TEST_CASE_IDX) + ": " + TEST_CASE.documentation); + SCOPED_TRACE(Aws::String("\n--gtest_filter=EndpointTestsFromModel/${metadata.classNamePrefix}EndpointProviderTests.EndpointProviderTest/") + Aws::Utils::StringUtils::to_string(TEST_CASE_IDX)); std::shared_ptr<${metadata.classNamePrefix}EndpointProvider> endpointProvider = Aws::MakeShared<${metadata.classNamePrefix}EndpointProvider>(ALLOCATION_TAG); ASSERT_TRUE(endpointProvider) << "Failed to allocate/initialize ${metadata.classNamePrefix}EndpointProvider"; @@ -207,4 +233,4 @@ TEST_P(${metadata.classNamePrefix}EndpointProviderTests, EndpointProviderTest) INSTANTIATE_TEST_SUITE_P(EndpointTestsFromModel, ${metadata.classNamePrefix}EndpointProviderTests, - ::testing::Range((size_t) 0u, TEST_CASES.size())); + ::testing::Range((size_t) 0u, ${metadata.classNamePrefix}EndpointProviderTests::TEST_CASES_SZ));