Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add URI S3 Client unit tests #2901

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/sdksCommon.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
32 changes: 32 additions & 0 deletions tests/aws-cpp-sdk-s3-unit-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
126 changes: 126 additions & 0 deletions tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include <gtest/gtest.h>
#include <aws/core/Aws.h>
#include <aws/core/auth/AWSCredentials.h>
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <aws/testing/mocks/http/MockHttpClient.h>
#include <aws/testing/AwsTestHelpers.h>
#include <aws/testing/MemoryTesting.h>

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:
static void SetUpTestSuite() {
#ifdef USE_AWS_MEMORY_MANAGEMENT
_testMemorySystem = Aws::MakeShared<ExactTestMemorySystem>(ALLOCATION_TAG, 1024, 128);
_options.memoryManagementOptions.memoryManager = _testMemorySystem.get();
#endif
_mockClientFactory = Aws::MakeShared<MockHttpClientFactory>(ALLOCATION_TAG);
_mockHttpClient = Aws::MakeShared<MockHttpClient>(ALLOCATION_TAG);
_mockClientFactory->SetClient(_mockHttpClient);
HttpOptions httpOptions;
httpOptions.httpClientFactory_create_fn = []() -> std::shared_ptr<HttpClientFactory> {
return _mockClientFactory;
};
_options.httpOptions = httpOptions;
InitAPI(_options);
AWSCredentials credentials{"mock", "credentials"};
const auto epProvider = Aws::MakeShared<S3EndpointProvider>(ALLOCATION_TAG);
S3ClientConfiguration s3Config;
s3Config.region = "us-east-1";
_s3Client = Aws::MakeShared<S3Client>("ALLOCATION_TAG", credentials, epProvider, s3Config);
}

static void TearDownTestSuite() {
_mockClientFactory.reset();
_mockHttpClient.reset();
_s3Client.reset();
ShutdownAPI(_options);
#ifdef USE_AWS_MEMORY_MANAGEMENT
EXPECT_EQ(_testMemorySystem->GetCurrentOutstandingAllocations(), 0ULL);
EXPECT_EQ(_testMemorySystem->GetCurrentBytesAllocated(), 0ULL);
EXPECT_TRUE(_testMemorySystem->IsClean());
if (_testMemorySystem->GetCurrentOutstandingAllocations() != 0ULL)
FAIL();
if (_testMemorySystem->GetCurrentBytesAllocated() != 0ULL)
FAIL();
if (!_testMemorySystem->IsClean())
FAIL();
_testMemorySystem.reset();
#endif
}

static SDKOptions _options;
static std::shared_ptr<MockHttpClient> _mockHttpClient;
static std::shared_ptr<MockHttpClientFactory> _mockClientFactory;
static std::shared_ptr<S3Client> _s3Client;
#ifdef USE_AWS_MEMORY_MANAGEMENT
static std::shared_ptr<ExactTestMemorySystem> _testMemorySystem;
#endif
};

SDKOptions S3UnitTest::_options;
std::shared_ptr<MockHttpClient> S3UnitTest::_mockHttpClient = nullptr;
std::shared_ptr<MockHttpClientFactory> S3UnitTest::_mockClientFactory = nullptr;
std::shared_ptr<S3Client> S3UnitTest::_s3Client = nullptr;
#ifdef USE_AWS_MEMORY_MANAGEMENT
std::shared_ptr<ExactTestMemorySystem> S3UnitTest::_testMemorySystem = nullptr;
#endif


TEST_F(S3UnitTest, S3UriLeadingDots) {
auto putObjectRequest = PutObjectRequest()
.WithBucket("bluerev")
.WithKey("../BoredInBristol");

std::shared_ptr<IOStream> body = Aws::MakeShared<StringStream>(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<Standard::StandardHttpRequest>(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET);
mockRequest->SetResponseStreamFactory([]() -> IOStream* {
return Aws::New<StringStream>(ALLOCATION_TAG, "response-string", std::ios_base::in | std::ios_base::binary);
});
auto mockResponse = Aws::MakeShared<Standard::StandardHttpResponse>(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<IOStream> body = Aws::MakeShared<StringStream>(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<Standard::StandardHttpRequest>(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET);
mockRequest->SetResponseStreamFactory([]() -> IOStream* {
return Aws::New<StringStream>(ALLOCATION_TAG, "response-string", std::ios_base::in | std::ios_base::binary);
});
auto mockResponse = Aws::MakeShared<Standard::StandardHttpResponse>(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());
}
9 changes: 9 additions & 0 deletions tests/testing-resources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -123,6 +126,12 @@ target_include_directories(${PROJECT_NAME} PUBLIC
$<INSTALL_INTERFACE:include>)
target_link_libraries(${PROJECT_NAME} ${PLATFORM_DEP_LIBS} ${PROJECT_LIBS})

target_include_directories(aws_test_main PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/aws/external>
$<INSTALL_INTERFACE:include>)

target_link_libraries(aws_test_main ${PROJECT_NAME})

if(COMMAND add_custom_testing_link_libraries)
add_custom_testing_link_libraries()
endif()
Expand Down
2 changes: 1 addition & 1 deletion tools/scripts/build-tests/run-al2-integ-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ aws configure set aws_secret_access_key $(echo "$sts" | jq -r '.[1]') --profile
aws configure set aws_session_token $(echo "$sts" | jq -r '.[2]') --profile "$profile"
aws configure list --profile "$profile"
export AWS_PROFILE=$profile
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${PREFIX_DIR}/al2-install/lib64/:${PREFIX_DIR}/al2-build/tests/testing-resources/"
cd "${PREFIX_DIR}/al2-build"
if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi
python3 ../aws-sdk-cpp/tools/scripts/run_integration_tests.py --testDir ./tests
2 changes: 1 addition & 1 deletion tools/scripts/build-tests/run-mac-integ-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ aws configure set aws_secret_access_key $(echo "$sts" | jq -r '.[1]') --profile
aws configure set aws_session_token $(echo "$sts" | jq -r '.[2]') --profile "$profile"
aws configure list --profile "$profile"
export AWS_PROFILE=$profile
export DYLD_LIBRARY_PATH=$CATAPULT_WORKSPACE_DIR/mac-install/lib
export DYLD_LIBRARY_PATH="${CATAPULT_WORKSPACE_DIR}/mac-install/lib:${CATAPULT_WORKSPACE_DIR}/mac-build/tests/testing-resources/"
cd "${PREFIX_DIR}/mac-build"
if [ -f "${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt" ]; then export LSAN_OPTIONS=suppressions="${PREFIX_DIR}/aws-sdk-cpp/tools/scripts/suppressions.txt"; fi
python3 ../aws-sdk-cpp/tools/scripts/run_integration_tests.py --testDir ./tests
1 change: 1 addition & 0 deletions tools/scripts/run_integration_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im adding to the run integ tests right now. likely this should be a completely seperate step in our CI, and we should have other clients in it. We can create a seperate sep once we have enough client unit tests to justify it.

#"aws-cpp-sdk-s3-crt-integration-tests",
#"aws-cpp-sdk-s3control-integration-tests",
# "aws-cpp-sdk-lambda-integration-tests",
Expand Down
Loading