Skip to content

Commit 710ce0e

Browse files
committed
commit 1
1 parent 63497b4 commit 710ce0e

File tree

2 files changed

+271
-0
lines changed

2 files changed

+271
-0
lines changed

sdk/test/Services/S3/UnitTests/Custom/EmbeddedResource/property-aliases.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,21 @@
8585
"SSECustomerKeyMD5": "ServerSideEncryptionCustomerProvidedKeyMD5",
8686
"SSEKMSKeyId": "ServerSideEncryptionKeyManagementServiceKeyId",
8787
"Tagging": "TagSet"
88+
},
89+
"InitiateMultipartUploadRequest": {
90+
"ACL": "CannedACL",
91+
"Bucket": "BucketName",
92+
"GrantFullControl": "Grants",
93+
"GrantRead": "Grants",
94+
"GrantReadACP": "Grants",
95+
"GrantWriteACP": "Grants",
96+
"ServerSideEncryption": "ServerSideEncryptionMethod",
97+
"SSECustomerAlgorithm": "ServerSideEncryptionCustomerMethod",
98+
"SSECustomerKey": "ServerSideEncryptionCustomerProvidedKey",
99+
"SSECustomerKeyMD5": "ServerSideEncryptionCustomerProvidedKeyMD5",
100+
"SSEKMSKeyId": "ServerSideEncryptionKeyManagementServiceKeyId",
101+
"Tagging": "TagSet",
102+
"SSEKMSEncryptionContext": "ServerSideEncryptionKeyManagementServiceEncryptionContext"
88103
}
89104
}
90105
}

sdk/test/Services/S3/UnitTests/Custom/ResponseMapperTests.cs

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class ResponseMapperTests
3535
private static JsonDocument _mappingJson;
3636
private static JsonDocument _propertyAliasesJson;
3737
private static Dictionary<string, Dictionary<string, string>> _propertyAliases;
38+
private static List<S3Grant> _s3Grants;
3839

3940
[ClassInitialize]
4041
public static void ClassInitialize(TestContext context)
@@ -214,6 +215,231 @@ public void MapPutObjectResponse_AllMappedProperties_WorkCorrectly()
214215
}
215216
}
216217

218+
[TestMethod]
219+
[TestCategory("S3")]
220+
public void MapUploadRequest_PutObjectRequest_AllMappedProperties_WorkCorrectly()
221+
{
222+
// Get the expected mappings from JSON
223+
var putObjectMappings = _mappingJson.RootElement
224+
.GetProperty("Conversion")
225+
.GetProperty("UploadRequest")
226+
.GetProperty("PutObjectRequest")
227+
.EnumerateArray()
228+
.Select(prop => prop.GetString())
229+
.ToList();
230+
231+
// Create source object with dynamically generated test data
232+
var sourceRequest = new TransferUtilityUploadRequest();
233+
var sourceType = typeof(TransferUtilityUploadRequest);
234+
var testDataValues = new Dictionary<string, object>();
235+
236+
// Generate test data for each mapped property
237+
foreach (var propertyName in putObjectMappings)
238+
{
239+
// Resolve alias to actual property name
240+
var resolvedPropertyName = ResolvePropertyName(propertyName, sourceType.Name);
241+
var sourceProperty = sourceType.GetProperty(resolvedPropertyName);
242+
if (sourceProperty?.CanWrite == true)
243+
{
244+
var testValue = GenerateTestValue(sourceProperty.PropertyType, propertyName);
245+
sourceProperty.SetValue(sourceRequest, testValue);
246+
testDataValues[propertyName] = testValue;
247+
}
248+
}
249+
250+
var simpleUploadCommand = new SimpleUploadCommand(null, null, sourceRequest);
251+
252+
// Map the response
253+
var mappedRequest = simpleUploadCommand.ConstructRequest();
254+
Assert.IsNotNull(mappedRequest, "Mapped request should not be null");
255+
256+
// Verify all mapped properties using reflection
257+
var targetType = typeof(PutObjectRequest);
258+
var failedAssertions = new List<string>();
259+
260+
foreach (var propertyName in putObjectMappings)
261+
{
262+
// Resolve alias to actual property name for reflection lookups
263+
var resolvedPropertyName = ResolvePropertyName(propertyName, sourceType.Name);
264+
var sourceProperty = sourceType.GetProperty(resolvedPropertyName);
265+
var targetProperty = targetType.GetProperty(resolvedPropertyName);
266+
267+
if (sourceProperty == null)
268+
{
269+
failedAssertions.Add($"Source property '{propertyName}' (resolved to: {resolvedPropertyName}) not found in PutObjectResponse");
270+
continue;
271+
}
272+
273+
if (targetProperty == null)
274+
{
275+
failedAssertions.Add($"Target property '{propertyName}' (resolved to: {resolvedPropertyName}) not found in TransferUtilityUploadResponse");
276+
continue;
277+
}
278+
279+
var sourceValue = sourceProperty.GetValue(sourceRequest);
280+
var targetValue = targetProperty.GetValue(mappedRequest);
281+
282+
// Special handling for complex object comparisons
283+
if (!AreValuesEqual(sourceValue, targetValue))
284+
{
285+
failedAssertions.Add($"{propertyName}: Expected '{sourceValue ?? "null"}', got '{targetValue ?? "null"}'");
286+
}
287+
}
288+
289+
// Report any failures
290+
if (failedAssertions.Any())
291+
{
292+
Assert.Fail($"Property mapping failures:\n{string.Join("\n", failedAssertions)}");
293+
}
294+
}
295+
296+
[TestMethod]
297+
[TestCategory("S3")]
298+
public void MapUploadRequest_CreateMultipartRequest_AllMappedProperties_WorkCorrectly()
299+
{
300+
// Get the expected mappings from JSON
301+
var createMultipartRequestMappings = _mappingJson.RootElement
302+
.GetProperty("Conversion")
303+
.GetProperty("UploadRequest")
304+
.GetProperty("CreateMultipartRequest")
305+
.EnumerateArray()
306+
.Select(prop => prop.GetString())
307+
.ToList();
308+
309+
// Create source object with dynamically generated test data
310+
var sourceRequest = new TransferUtilityUploadRequest();
311+
var sourceType = typeof(TransferUtilityUploadRequest);
312+
var testDataValues = new Dictionary<string, object>();
313+
314+
// Generate test data for each mapped property
315+
foreach (var propertyName in createMultipartRequestMappings)
316+
{
317+
// Resolve alias to actual property name
318+
var resolvedPropertyName = ResolvePropertyName(propertyName, sourceType.Name);
319+
var sourceProperty = sourceType.GetProperty(resolvedPropertyName);
320+
if (sourceProperty?.CanWrite == true)
321+
{
322+
var testValue = GenerateTestValue(sourceProperty.PropertyType, propertyName);
323+
sourceProperty.SetValue(sourceRequest, testValue);
324+
testDataValues[propertyName] = testValue;
325+
}
326+
}
327+
328+
// Add inherited properties for comprehensive testing
329+
sourceRequest.InputStream = new MemoryStream(1024);
330+
331+
var multipartUploadCommand = new MultipartUploadCommand(null, null, sourceRequest);
332+
333+
// Map the response
334+
var mappedRequest = multipartUploadCommand.ConstructInitiateMultipartUploadRequest();
335+
Assert.IsNotNull(mappedRequest, "Mapped request should not be null");
336+
337+
// Verify all mapped properties using reflection
338+
var targetType = typeof(InitiateMultipartUploadRequest);
339+
var failedAssertions = new List<string>();
340+
341+
foreach (var propertyName in createMultipartRequestMappings)
342+
{
343+
// Resolve alias to actual property name for reflection lookups
344+
var resolvedSourcePropertyName = ResolvePropertyName(propertyName, sourceType.Name);
345+
var resolvedTargetPropertyName = ResolvePropertyName(propertyName, targetType.Name);
346+
var sourceProperty = sourceType.GetProperty(resolvedSourcePropertyName);
347+
var targetProperty = targetType.GetProperty(resolvedTargetPropertyName);
348+
349+
object sourceValue = null;
350+
351+
if (sourceProperty != null)
352+
{
353+
// Property found directly on source type
354+
sourceValue = sourceProperty.GetValue(sourceRequest);
355+
}
356+
else
357+
{
358+
// Check if source type has a Headers property of type HeadersCollection
359+
var sourceHeadersProperty = sourceType.GetProperty("Headers");
360+
if (sourceHeadersProperty != null && typeof(HeadersCollection).IsAssignableFrom(sourceHeadersProperty.PropertyType))
361+
{
362+
var sourceHeadersCollection = sourceHeadersProperty.GetValue(sourceRequest) as HeadersCollection;
363+
if (sourceHeadersCollection != null)
364+
{
365+
var sourceHeadersCollectionProperty = typeof(HeadersCollection).GetProperty(resolvedSourcePropertyName);
366+
if (sourceHeadersCollectionProperty != null)
367+
{
368+
sourceValue = sourceHeadersCollectionProperty.GetValue(sourceHeadersCollection);
369+
}
370+
else
371+
{
372+
failedAssertions.Add($"Source property '{propertyName}' (resolved to: {resolvedSourcePropertyName}) not found in TransferUtilityUploadRequest or HeadersCollection");
373+
continue;
374+
}
375+
}
376+
else
377+
{
378+
failedAssertions.Add($"Source Headers collection is null in TransferUtilityUploadRequest");
379+
continue;
380+
}
381+
}
382+
else
383+
{
384+
failedAssertions.Add($"Source property '{propertyName}' (resolved to: {resolvedSourcePropertyName}) not found in TransferUtilityUploadRequest");
385+
continue;
386+
}
387+
}
388+
389+
object targetValue = null;
390+
391+
if (targetProperty != null)
392+
{
393+
// Property found directly on target type
394+
targetValue = targetProperty.GetValue(mappedRequest);
395+
}
396+
else
397+
{
398+
// Check if target type has a Headers property of type HeadersCollection
399+
var headersProperty = targetType.GetProperty("Headers");
400+
if (headersProperty != null && typeof(HeadersCollection).IsAssignableFrom(headersProperty.PropertyType))
401+
{
402+
var headersCollection = headersProperty.GetValue(mappedRequest) as HeadersCollection;
403+
if (headersCollection != null)
404+
{
405+
var headersCollectionProperty = typeof(HeadersCollection).GetProperty(resolvedTargetPropertyName);
406+
if (headersCollectionProperty != null)
407+
{
408+
targetValue = headersCollectionProperty.GetValue(headersCollection);
409+
}
410+
else
411+
{
412+
failedAssertions.Add($"Target property '{propertyName}' (resolved to: {resolvedTargetPropertyName}) not found in InitiateMultipartUploadRequest or HeadersCollection");
413+
continue;
414+
}
415+
}
416+
else
417+
{
418+
failedAssertions.Add($"Headers collection is null in InitiateMultipartUploadRequest");
419+
continue;
420+
}
421+
}
422+
else
423+
{
424+
failedAssertions.Add($"Target property '{propertyName}' (resolved to: {resolvedTargetPropertyName}) not found in InitiateMultipartUploadRequest");
425+
continue;
426+
}
427+
}
428+
429+
// Special handling for complex object comparisons
430+
if (!AreValuesEqual(sourceValue, targetValue))
431+
{
432+
failedAssertions.Add($"{propertyName}: Expected '{sourceValue ?? "null"}', got '{targetValue ?? "null"}'");
433+
}
434+
}
435+
436+
// Report any failures
437+
if (failedAssertions.Any())
438+
{
439+
Assert.Fail($"Property mapping failures:\n{string.Join("\n", failedAssertions)}");
440+
}
441+
}
442+
217443
[TestMethod]
218444
[TestCategory("S3")]
219445
public void MapPutObjectResponse_NullValues_HandledCorrectly()
@@ -439,6 +665,36 @@ private static object GenerateTestValue(Type propertyType, string propertyName)
439665
return 1024;
440666
}
441667

668+
if (propertyType == typeof(List<S3Grant>))
669+
{
670+
if (_s3Grants is null)
671+
{
672+
_s3Grants = new List<S3Grant> { new S3Grant { Grantee = new S3Grantee { DisplayName = "test-s3grantee"} } };
673+
}
674+
675+
return _s3Grants;
676+
}
677+
678+
if (propertyType == typeof(MetadataCollection))
679+
{
680+
var metadataCollection = new MetadataCollection();
681+
metadataCollection.Add("x-amz-meta-testkey", "testvalue");
682+
return metadataCollection;
683+
}
684+
685+
if (propertyType == typeof(DateTime))
686+
{
687+
return DateTime.UtcNow;
688+
}
689+
690+
if (propertyType == typeof(List<Tag>))
691+
{
692+
return new List<Tag>
693+
{
694+
new Tag { Key = "test-key", Value = "test-value" }
695+
};
696+
}
697+
442698
// For unknown types, throw an exception instead of returning null
443699
// If we've reached this point it means there is an unhandled scenario/missing mapping in our test code that we need to handle.
444700
throw new NotSupportedException(

0 commit comments

Comments
 (0)