@@ -160,9 +160,12 @@ class MockS3Client : public S3Client
160
160
{
161
161
public:
162
162
MockS3Client (const Aws::Client::ClientConfiguration& clientConfiguration = Aws::Client::ClientConfiguration()):
163
- S3Client (clientConfiguration), listObjectsV2RequestCount(0 )
163
+ S3Client (clientConfiguration), executor(clientConfiguration.executor), listObjectsV2RequestCount(0 )
164
+ {}
165
+
166
+ ~MockS3Client ()
164
167
{
165
- executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>(ALLOCATION_TAG, 4 ) ;
168
+ executor = nullptr ;
166
169
}
167
170
168
171
// Override this function to do verification.
@@ -197,8 +200,13 @@ class TransferTests : public ::testing::Test
197
200
m_executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>(ALLOCATION_TAG, 4 );
198
201
}
199
202
200
- protected:
203
+ void TearDown ()
204
+ {
205
+ m_executor = nullptr ;
206
+ }
201
207
208
+ protected:
209
+ // Executor used by transferManager
202
210
std::shared_ptr<Aws::Utils::Threading::Executor> m_executor;
203
211
204
212
static Aws::String GetTestBucketName ()
@@ -311,7 +319,8 @@ class TransferTests : public ::testing::Test
311
319
config.scheme = Scheme::HTTP;
312
320
config.connectTimeoutMs = 3000 ;
313
321
config.requestTimeoutMs = 60000 ;
314
-
322
+ // executor used for s3Client
323
+ config.executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>(ALLOCATION_TAG, 5 );
315
324
m_s3Client = Aws::MakeShared<MockS3Client>(ALLOCATION_TAG, config);
316
325
317
326
DeleteBucket (GetTestBucketName ());
@@ -1109,6 +1118,7 @@ TEST_F(TransferTests, TransferManager_CancelAndRetryUploadTest)
1109
1118
bool completedPartsStayedCompletedDuringRetry = true ;
1110
1119
bool completionCheckDone = false ;
1111
1120
const char uuid[] = " Bjarne Stroustrup!" ;
1121
+ std::atomic<bool > cancelHasBeenCalled (false );
1112
1122
1113
1123
TransferManagerConfiguration transferManagerConfig (m_executor.get ());
1114
1124
transferManagerConfig.transferStatusUpdatedCallback =
@@ -1119,8 +1129,8 @@ TEST_F(TransferTests, TransferManager_CancelAndRetryUploadTest)
1119
1129
ASSERT_NE (nullptr , handle->GetContext ());
1120
1130
ASSERT_STREQ (uuid, handle->GetContext ()->GetUUID ().c_str ());
1121
1131
}
1122
-
1123
- if (!retryInProgress && handle->GetCompletedParts ().size () >= 15 && handle-> GetStatus () != TransferStatus::CANCELED )
1132
+ bool expected = false ;
1133
+ if (handle->GetCompletedParts ().size () >= 15 && cancelHasBeenCalled. compare_exchange_strong (expected, true ) )
1124
1134
{
1125
1135
std::const_pointer_cast<TransferHandle>(handle)->Cancel ();
1126
1136
}
@@ -1225,14 +1235,16 @@ TEST_F(TransferTests, TransferManager_AbortAndRetryUploadTest)
1225
1235
bool retryInProgress = false ;
1226
1236
bool completedPartsStayedCompletedDuringRetry = true ;
1227
1237
bool completionCheckDone = false ;
1238
+ std::atomic<bool > cancelHasBeenCalled (false );
1228
1239
1229
1240
std::shared_ptr<TransferHandle> requestPtr (nullptr );
1230
1241
1231
1242
TransferManagerConfiguration transferManagerConfig (m_executor.get ());
1232
1243
transferManagerConfig.transferStatusUpdatedCallback =
1233
1244
[&](const TransferManager* manager, const std::shared_ptr<const TransferHandle>& handle)
1234
1245
{
1235
- if (!retryInProgress && handle->GetCompletedParts ().size () >= 15 && handle->GetStatus () != TransferStatus::CANCELED)
1246
+ bool expected = false ;
1247
+ if (handle->GetCompletedParts ().size () >= 15 && cancelHasBeenCalled.compare_exchange_strong (expected, true ))
1236
1248
{
1237
1249
const_cast <TransferManager*>(manager)->AbortMultipartUpload (std::const_pointer_cast<TransferHandle>(handle));
1238
1250
}
@@ -1273,6 +1285,15 @@ TEST_F(TransferTests, TransferManager_AbortAndRetryUploadTest)
1273
1285
ListMultipartUploadsOutcome listMultipartOutcome = m_s3Client->ListMultipartUploads (listMultipartRequest);
1274
1286
1275
1287
EXPECT_TRUE (listMultipartOutcome.IsSuccess ());
1288
+ // S3 has eventual consistency, even thought we called AbortMultiPartUpload and get successful return,
1289
+ // following call of listMultiPartUpload will not gurantee to return 0.
1290
+ size_t retries = 0 ;
1291
+ while (listMultipartOutcome.GetResult ().GetUploads ().size () != 0u && retries++ < 5 )
1292
+ {
1293
+ std::this_thread::sleep_for (std::chrono::seconds (1 ));
1294
+ listMultipartOutcome = m_s3Client->ListMultipartUploads (listMultipartRequest);
1295
+ EXPECT_TRUE (listMultipartOutcome.IsSuccess ());
1296
+ }
1276
1297
ASSERT_EQ (0u , listMultipartOutcome.GetResult ().GetUploads ().size ());
1277
1298
1278
1299
HeadObjectRequest headObjectRequest;
@@ -1287,7 +1308,7 @@ TEST_F(TransferTests, TransferManager_AbortAndRetryUploadTest)
1287
1308
ASSERT_NE (requestPtr, tempPtr);
1288
1309
requestPtr->WaitUntilFinished ();
1289
1310
1290
- size_t retries = 0 ;
1311
+ retries = 0 ;
1291
1312
// just make sure we don't fail because an upload part failed. (e.g. network problems or interuptions)
1292
1313
while (requestPtr->GetStatus () == TransferStatus::FAILED && retries++ < 5 )
1293
1314
{
@@ -1540,6 +1561,7 @@ TEST_F(TransferTests, TransferManager_CancelAndRetryDownloadTest)
1540
1561
bool completedPartsStayedCompletedDuringRetry = true ;
1541
1562
bool completionCheckDone = false ;
1542
1563
const char uuid[] = " Bjarne Stroustrup!" ;
1564
+ std::atomic<bool > cancelHasBeenCalled (false );
1543
1565
1544
1566
TransferManagerConfiguration downloadConfig (m_executor.get ());
1545
1567
downloadConfig.s3Client = m_s3Client;
@@ -1550,7 +1572,8 @@ TEST_F(TransferTests, TransferManager_CancelAndRetryDownloadTest)
1550
1572
ASSERT_STREQ (uuid, handle->GetContext ()->GetUUID ().c_str ());
1551
1573
1552
1574
ASSERT_EQ (downloadFileName, handle->GetTargetFilePath ());
1553
- if (!retryInProgress && handle->GetCompletedParts ().size () >= 15 && handle->GetStatus () != TransferStatus::CANCELED)
1575
+ bool expected = false ;
1576
+ if (handle->GetCompletedParts ().size () >= 15u && cancelHasBeenCalled.compare_exchange_strong (expected, true ))
1554
1577
{
1555
1578
std::const_pointer_cast<TransferHandle>(handle)->Cancel ();
1556
1579
}
@@ -1578,7 +1601,12 @@ TEST_F(TransferTests, TransferManager_CancelAndRetryDownloadTest)
1578
1601
requestPtr->WaitUntilFinished ();
1579
1602
}
1580
1603
1581
- ASSERT_EQ (TransferStatus::CANCELED, requestPtr->GetStatus ());
1604
+ // call Cancel() in TransferStatusUpdateCallback function will not set status to CANCELED immediately.
1605
+ // It only set up m_cancel to true, status will be updated by following UpdateStatus() call.
1606
+ while (requestPtr->GetStatus () != TransferStatus::CANCELED)
1607
+ {
1608
+ std::this_thread::sleep_for (std::chrono::seconds (1 ));
1609
+ }
1582
1610
ASSERT_TRUE (15u <= requestPtr->GetCompletedParts ().size ());
1583
1611
ASSERT_EQ (0u , requestPtr->GetPendingParts ().size ());
1584
1612
ASSERT_TRUE (15u >= requestPtr->GetFailedParts ().size ()); // some may have been in flight at cancelation time.
0 commit comments