diff --git a/cmake/sdksCommon.cmake b/cmake/sdksCommon.cmake index 6206d961af3..4cc041d3ccf 100644 --- a/cmake/sdksCommon.cmake +++ b/cmake/sdksCommon.cmake @@ -167,6 +167,7 @@ list(APPEND SDK_TEST_PROJECT_LIST "monitoring:tests/aws-cpp-sdk-monitoring-integ list(APPEND SDK_TEST_PROJECT_LIST "rds:tests/aws-cpp-sdk-rds-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "redshift:tests/aws-cpp-sdk-redshift-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "s3:tests/aws-cpp-sdk-s3-integration-tests") +list(APPEND SDK_TEST_PROJECT_LIST "s3:tests/aws-cpp-sdk-s3-unit-tests") list(APPEND SDK_TEST_PROJECT_LIST "s3-crt:tests/aws-cpp-sdk-s3-crt-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "s3-encryption:tests/aws-cpp-sdk-s3-encryption-tests,tests/aws-cpp-sdk-s3-encryption-integration-tests") list(APPEND SDK_TEST_PROJECT_LIST "s3control:tests/aws-cpp-sdk-s3control-integration-tests") diff --git a/tests/aws-cpp-sdk-s3-unit-tests/CMakeLists.txt b/tests/aws-cpp-sdk-s3-unit-tests/CMakeLists.txt new file mode 100644 index 00000000000..a2b351012d9 --- /dev/null +++ b/tests/aws-cpp-sdk-s3-unit-tests/CMakeLists.txt @@ -0,0 +1,32 @@ +add_project(aws-cpp-sdk-s3-unit-tests + "Unit Tests for the S3 SDK Client" + aws-cpp-sdk-s3 + testing-resources + aws_test_main + aws-cpp-sdk-core) + +add_definitions(-DRESOURCES_DIR="${CMAKE_CURRENT_SOURCE_DIR}/resources") + +if(MSVC AND BUILD_SHARED_LIBS) + add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1) +endif() + +enable_testing() + +if(PLATFORM_ANDROID AND BUILD_SHARED_LIBS) + add_library(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/S3UnitTests.cpp) +else() + add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/S3UnitTests.cpp) +endif() + +set_compiler_flags(${PROJECT_NAME}) +set_compiler_warnings(${PROJECT_NAME}) + +target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBS}) + +if(MSVC AND BUILD_SHARED_LIBS) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/DELAYLOAD:aws-cpp-sdk-s3.dll /DELAYLOAD:aws-cpp-sdk-core.dll") +endif() + +include(GoogleTest) +gtest_discover_tests(${PROJECT_NAME}) diff --git a/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp new file mode 100644 index 00000000000..664e7780c27 --- /dev/null +++ b/tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace Aws; +using namespace Aws::Auth; +using namespace Aws::Http; +using namespace Aws::S3; +using namespace Aws::S3::Model; + +const char* ALLOCATION_TAG = "S3UnitTest"; + +class S3UnitTest : public testing::Test { +protected: + void SetUp() override { + _mockClientFactory = Aws::MakeShared(ALLOCATION_TAG); + _mockHttpClient = Aws::MakeShared(ALLOCATION_TAG); + _mockClientFactory->SetClient(_mockHttpClient); + HttpOptions httpOptions; + httpOptions.httpClientFactory_create_fn = [this]() -> std::shared_ptr { + return _mockClientFactory; + }; + _options.httpOptions = httpOptions; + InitAPI(_options); + AWSCredentials credentials{"mock", "credentials"}; + _s3Client = Aws::MakeUnique("ALLOCATION_TAG", credentials); + } + + void TearDown() override { + ShutdownAPI(_options); + } + + SDKOptions _options; + std::shared_ptr _mockHttpClient; + std::shared_ptr _mockClientFactory; + UniquePtr _s3Client; +}; + + +TEST_F(S3UnitTest, S3UriLeadingDots) { + auto putObjectRequest = PutObjectRequest() + .WithBucket("bluerev") + .WithKey("../BoredInBristol"); + + std::shared_ptr body = Aws::MakeShared(ALLOCATION_TAG, + "Bored in Bristol, always waiting", + std::ios_base::in | std::ios_base::binary); + + putObjectRequest.SetBody(body); + + //We have to mock requset because it is used to create the return body, it actually isnt used. + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + IOStream* stream = Aws::New(ALLOCATION_TAG, "response-string", std::ios_base::in | std::ios_base::binary); + return stream; + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + const auto response = _s3Client->PutObject(putObjectRequest); + AWS_EXPECT_SUCCESS(response); + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_EQ("https://bluerev.s3.us-east-1.amazonaws.com/../BoredInBristol", seenRequest.GetUri().GetURIString()); +} + +TEST_F(S3UnitTest, S3UriMiddleDots) { + auto putObjectRequest = PutObjectRequest() + .WithBucket("bluerev") + .WithKey("belinda/../says"); + + std::shared_ptr body = Aws::MakeShared(ALLOCATION_TAG, + "Blue Rev behind the rink I didn't really need it", + std::ios_base::in | std::ios_base::binary); + + putObjectRequest.SetBody(body); + + //We have to mock requset because it is used to create the return body, it actually isnt used. + auto mockRequest = Aws::MakeShared(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET); + mockRequest->SetResponseStreamFactory([]() -> IOStream* { + return Aws::New(ALLOCATION_TAG, "response-string", std::ios_base::in | std::ios_base::binary); + }); + auto mockResponse = Aws::MakeShared(ALLOCATION_TAG, mockRequest); + mockResponse->SetResponseCode(HttpResponseCode::OK); + _mockHttpClient->AddResponseToReturn(mockResponse); + const auto response = _s3Client->PutObject(putObjectRequest); + AWS_EXPECT_SUCCESS(response); + const auto seenRequest = _mockHttpClient->GetMostRecentHttpRequest(); + EXPECT_EQ("https://bluerev.s3.us-east-1.amazonaws.com/belinda/../says", seenRequest.GetUri().GetURIString()); +} diff --git a/tests/testing-resources/CMakeLists.txt b/tests/testing-resources/CMakeLists.txt index 179a65fbc72..0711dd14a8d 100644 --- a/tests/testing-resources/CMakeLists.txt +++ b/tests/testing-resources/CMakeLists.txt @@ -109,9 +109,12 @@ endif() add_library(${PROJECT_NAME} ${TestingResources_SRC}) add_library(AWS::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +add_library(aws_test_main source/external/gtest/src/gtest_main.cc) set_compiler_flags(${PROJECT_NAME}) set_compiler_warnings(${PROJECT_NAME}) +set_compiler_flags(aws_test_main) +set_compiler_warnings(aws_test_main) if(PLATFORM_CUSTOM) add_custom_testing_target_compile_definitions() @@ -123,6 +126,12 @@ target_include_directories(${PROJECT_NAME} PUBLIC $) target_link_libraries(${PROJECT_NAME} ${PLATFORM_DEP_LIBS} ${PROJECT_LIBS}) +target_include_directories(aws_test_main PUBLIC + $ + $) + +target_link_libraries(aws_test_main ${PROJECT_NAME}) + if(COMMAND add_custom_testing_link_libraries) add_custom_testing_link_libraries() endif() diff --git a/tools/scripts/run_integration_tests.py b/tools/scripts/run_integration_tests.py index dd964eb8a28..cd7dbed9fda 100644 --- a/tools/scripts/run_integration_tests.py +++ b/tools/scripts/run_integration_tests.py @@ -40,6 +40,7 @@ def main(): "aws-cpp-sdk-dynamodb-integration-tests", "aws-cpp-sdk-sqs-integration-tests", "aws-cpp-sdk-s3-integration-tests", + "aws-cpp-sdk-s3-unit-tests", #"aws-cpp-sdk-s3-crt-integration-tests", #"aws-cpp-sdk-s3control-integration-tests", # "aws-cpp-sdk-lambda-integration-tests",