using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Util;
using Amazon.Runtime;
using Amazon.Runtime.Internal.Util;
using AWSSDK_DotNet.IntegrationTests.Utils;
using System.Diagnostics;
using Amazon.Util;
using System.Threading.Tasks;
namespace AWSSDK_DotNet.IntegrationTests.Tests.S3
{
///
/// Summary description for PutObjectTest
///
[TestClass]
public class PutObjectTest : TestBase
{
public static readonly long MEG_SIZE = (int)Math.Pow(2, 20);
private Random random = new Random();
private static string bucketName;
private const string testContent = "This is the content body!";
private const string testKey = "test-key.json.gz";
[ClassInitialize()]
public static void Initialize(TestContext a)
{
StreamWriter writer = File.CreateText("PutObjectFile.txt");
writer.Write("This is some sample text.!!");
writer.Close();
bucketName = S3TestUtils.CreateBucketWithWait(Client, true);
}
[ClassCleanup]
public static void ClassCleanup()
{
AmazonS3Util.DeleteS3BucketWithObjects(Client, bucketName);
BaseClean();
}
#if AWS_APM_API
private int _callbackInvocationCount = 0;
[TestMethod]
[TestCategory("S3")]
public void TestAsyncExceptionHandling()
{
var s3Client = new AmazonS3Client(new AmazonS3Config
{
});
GetObjectRequest request = new GetObjectRequest
{
BucketName = "NonExistentBucket",
Key = "NonExistentKey",
};
var stopwatch = new Stopwatch();
stopwatch.Start();
IAsyncResult result = s3Client.BeginGetObject(request, new AsyncCallback(GetObjectExceptionCallback), null);
stopwatch.Stop();
Console.WriteLine("{0} BeginGetObject returned in {1} ms", DateTime.UtcNow, stopwatch.Elapsed.Milliseconds);
Assert.IsTrue(stopwatch.Elapsed < TimeSpan.FromSeconds(1));
result.AsyncWaitHandle.WaitOne();
}
void GetObjectExceptionCallback(IAsyncResult result)
{
_callbackInvocationCount++;
Assert.IsTrue(_callbackInvocationCount == 1);
Console.WriteLine("{0} GetObjectCallback was triggered", DateTime.UtcNow);
var exception = AssertExtensions.ExpectException(
() => Client.EndGetObject(result));
throw exception;
Console.WriteLine("{0} EndGetObject returned", DateTime.UtcNow);
}
private ManualResetEvent _testWaitHandle;
[TestMethod]
[TestCategory("S3")]
public void TestPutGetObjectAsync()
{
_testWaitHandle = new ManualResetEvent(false);
var key = "contentBodyPut" + random.Next();
PutObjectRequest putRequest = new PutObjectRequest()
{
BucketName = bucketName,
Key = key,
ContentBody = testContent,
CannedACL = S3CannedACL.AuthenticatedRead
};
putRequest.Metadata.Add("Subject", "Content-As-Object");
Client.BeginPutObject(putRequest, new AsyncCallback(PutObjectCallback), key);
_testWaitHandle.WaitOne();
}
void PutObjectCallback(IAsyncResult result)
{
try
{
var putResponse = Client.EndPutObject(result);
var key = result.AsyncState as string;
Console.WriteLine("S3 generated ETag: {0}", putResponse.ETag);
Assert.IsTrue(putResponse.ETag.Length > 0);
var getRequest = new GetObjectRequest
{
BucketName = bucketName,
Key = key
};
Client.BeginGetObject(getRequest, new AsyncCallback(GetObjectCallback), "GetState");
}
catch (Exception exception)
{
Assert.Fail(exception.Message);
_testWaitHandle.Set();
}
}
void GetObjectCallback(IAsyncResult result)
{
try
{
string responseData;
Assert.IsTrue(((string)result.AsyncState).Equals("GetState"));
using (var response = Client.EndGetObject(result))
using (var responseStream = response.ResponseStream)
using (StreamReader reader = new StreamReader(responseStream))
{
responseData = reader.ReadToEnd();
Assert.AreEqual(testContent, responseData);
}
}
catch (Exception exception)
{
Assert.Fail(exception.Message);
}
finally
{
_testWaitHandle.Set();
}
}
#endif
[TestMethod]
[TestCategory("S3")]
public void TestPutAndGetWithInvalidExpires()
{
var content = "TestInvalidExpiresHeader";
var key = UtilityMethods.GenerateName("TestPutAndGetWithInvalidExpires");
var putObjectRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
ContentBody = content
};
var invalidValue = "InvalidHeaderValue";
putObjectRequest.Headers["Expires"] = invalidValue;
Client.PutObject(putObjectRequest);
AmazonDateTimeUnmarshallingException exception = null;
var newExpires = DateTime.Now.AddDays(1);
var getObjectResponse = Client.GetObject(bucketName, key);
using (getObjectResponse)
{
var reader = new StreamReader(getObjectResponse.ResponseStream);
var contentRead = reader.ReadToEnd();
Assert.IsTrue(content.Equals(contentRead));
exception = AssertExtensions.ExpectException(() =>
{ var expires = getObjectResponse.Expires; });
Assert.IsTrue(exception.RequestId.Equals(getObjectResponse.ResponseMetadata.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsTrue(exception.Message.Contains(invalidValue));
Assert.IsTrue(invalidValue.Equals(exception.InvalidDateTimeToken));
// Test getObjectResponse.Expires being overwritten by user code
getObjectResponse.Expires = newExpires;
Assert.AreEqual(newExpires, getObjectResponse.Expires);
}
var getObjectMetadataResponse = Client.GetObjectMetadata(bucketName, key);
exception = AssertExtensions.ExpectException(() =>
{ var expires = getObjectMetadataResponse.Expires; });
Assert.IsTrue(exception.RequestId.Equals(getObjectMetadataResponse.ResponseMetadata.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsTrue(exception.Message.Contains(invalidValue));
Assert.IsTrue(invalidValue.Equals(exception.InvalidDateTimeToken));
// Test getObjectMetadataResponse.Expires being overwritten by user code
getObjectMetadataResponse.Expires = newExpires;
Assert.AreEqual(newExpires, getObjectMetadataResponse.Expires);
}
[TestMethod]
[TestCategory("S3")]
public void TestStorageClass()
{
var key = "contentBodyPut" + random.Next();
var storageClass = S3StorageClass.ReducedRedundancy;
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = key,
ContentBody = testContent,
CannedACL = S3CannedACL.AuthenticatedRead,
StorageClass = storageClass
};
request.Metadata.Add("Subject", "Content-As-Object");
PutObjectResponse response = Client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
var metadata = Client.GetObjectMetadata(bucketName, key);
Assert.IsNotNull(metadata);
Assert.IsNotNull(metadata.StorageClass);
Assert.AreEqual(metadata.StorageClass, storageClass);
VerifyPut(testContent, request);
}
[TestMethod]
[TestCategory("S3")]
public void TestHttpErrorResponseUnmarshalling()
{
try
{
Client.PutObject(new PutObjectRequest
{
BucketName = UtilityMethods.GenerateName("NonExistentBucket"),
Key = "1",
ContentBody = "TestContent"
});
}
catch (AmazonS3Exception exception)
{
Console.WriteLine(exception.Message);
Console.WriteLine(exception.ErrorCode);
Console.WriteLine(exception.StatusCode);
Assert.IsTrue(exception.Message.Contains("The specified bucket does not exist"));
Assert.AreEqual("NoSuchBucket", exception.ErrorCode);
Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
}
}
#if ASYNC_AWAIT
[TestMethod]
[TestCategory("S3")]
public async System.Threading.Tasks.Task PutObjectAsync()
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "contentBodyPut" + random.Next(),
ContentBody = testContent,
CannedACL = S3CannedACL.AuthenticatedRead
};
PutObjectResponse response = await Client.PutObjectAsync(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
}
[TestMethod]
[TestCategory("S3")]
public async System.Threading.Tasks.Task PutObjectCancellationTest()
{
var fileName = UtilityMethods.GenerateName(@"CancellationTest\LargeFile");
string basePath = @"c:\temp\test\";
var path = Path.Combine(basePath, fileName);
UtilityMethods.GenerateFile(path, 50 * MEG_SIZE);
var putObjectRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = "CancellationTest" + random.Next(),
CannedACL = S3CannedACL.AuthenticatedRead,
FilePath = path
};
var cts = new CancellationTokenSource();
cts.CancelAfter(1000);
var token = cts.Token;
try
{
await Client.PutObjectAsync(putObjectRequest, token);
}
catch(OperationCanceledException exception)
{
Assert.AreEqual(token, exception.CancellationToken);
Assert.AreEqual(true, exception.CancellationToken.IsCancellationRequested);
return;
}
finally
{
Directory.Delete(basePath, true);
}
Assert.Fail("An OperationCanceledException was not thrown");
}
#endif
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithExternalEndpoint()
{
var s3Client = new AmazonS3Client(new AmazonS3Config
{
ServiceURL = "https://s3-external-1.amazonaws.com",
SignatureVersion = "4"
});
var testBucketName = "aws-net-sdk-external" + random.Next();
var key = "testKey";
try
{
s3Client.PutBucket(testBucketName);
S3TestUtils.WaitForBucket(s3Client, testBucketName);
s3Client.PutObject(new PutObjectRequest
{
BucketName = testBucketName,
Key = key,
ContentBody = "testValue"
});
s3Client.GetObject(testBucketName, key);
}
finally
{
AmazonS3Util.DeleteS3BucketWithObjects(s3Client, testBucketName);
s3Client.Dispose();
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithLeadingSlash()
{
foreach(var useV4 in new bool[] { false, true })
{
AWSConfigsS3.UseSignatureVersion4 = useV4;
using(var client = new AmazonS3Client())
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "/contentBodyPut" + random.Next(),
ContentBody = "This is the content body!",
CannedACL = S3CannedACL.AuthenticatedRead
};
request.Metadata.Add("Subject", "Content-As-Object");
PutObjectResponse response = client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
}
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectKeyWithUrlEncodedCharacters()
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "X$abc,xyz",
ContentBody = testContent,
CannedACL = S3CannedACL.AuthenticatedRead
};
request.Metadata.Add("Subject", "Content-As-Object");
PutObjectResponse response = Client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
VerifyPut(testContent, request);
}
[TestMethod]
[TestCategory("S3")]
public void PutObject()
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "contentBodyPut" + random.Next(),
ContentBody = testContent,
CannedACL = S3CannedACL.AuthenticatedRead
};
request.Metadata.Add("Subject", "Content-As-Object");
PutObjectResponse response = Client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
VerifyPut(testContent, request);
}
[TestMethod]
[TestCategory("S3")]
public void PutObject_SigV4()
{
var oldS3SigV4 = AWSConfigsS3.UseSignatureVersion4;
AWSConfigsS3.UseSignatureVersion4 = true;
try
{
using (var client = new AmazonS3Client())
{
RetryUtilities.ConfigureClient(client);
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "contentBodyPut" + random.Next(),
ContentBody = "This is the content body!",
CannedACL = S3CannedACL.AuthenticatedRead
};
request.Metadata.Add("Subject", "Content-As-Object");
PutObjectResponse response = client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
}
}
finally
{
AWSConfigsS3.UseSignatureVersion4 = oldS3SigV4;
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObject_WithExpires()
{
var key = "contentBodyPut" + random.Next();
var expires = DateTime.Now.AddYears(5);
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = key,
ContentBody = "This is the content body!",
CannedACL = S3CannedACL.AuthenticatedRead,
};
request.Metadata.Add("Subject", "Content-As-Object");
request.Headers.Expires = expires;
PutObjectResponse response = Client.PutObject(request);
Console.WriteLine("S3 generated ETag: {0}", response.ETag);
Assert.IsTrue(response.ETag.Length > 0);
using (var getResponse = Client.GetObject(new GetObjectRequest { BucketName = bucketName, Key = key }))
{
Assert.IsTrue(expires.ApproximatelyEqual(getResponse.Expires));
}
}
[TestCategory("S3")]
[TestMethod]
public void PutObjectWeirdKeys()
{
var keys = new List
{
"b204a53f-781a-4cdd-a29c-3626818eb199:115740.pdf",
"46dbc16e-5f55-4bda-b275-75e2a8ab243c:115740.pdf"
};
string filePath = "SomeFile.txt";
string contents = "Sample content";
File.WriteAllText(filePath, contents);
foreach (var key in keys)
{
var request = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
FilePath = filePath,
};
Client.PutObject(request);
using (var response = Client.GetObject(new GetObjectRequest { BucketName = bucketName, Key = key }))
using (var reader = new StreamReader(response.ResponseStream))
{
var rtContents = reader.ReadToEnd();
Assert.IsNotNull(rtContents);
Assert.AreEqual(contents, rtContents);
}
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithBacklashInKey()
{
const string writtenContent = @"an object with a \ in the key";
const string key = @"My\Key";
var request = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
ContentBody = writtenContent,
};
Client.PutObject(request);
using (var response = Client.GetObject(new GetObjectRequest { BucketName = bucketName, Key = key }))
using (var reader = new StreamReader(response.ResponseStream))
{
var readContent = reader.ReadToEnd();
Assert.AreEqual(readContent, writtenContent);
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWrongRegion()
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "contentBodyPut" + random.Next(),
ContentBody = "This is the content body!",
CannedACL = S3CannedACL.AuthenticatedRead
};
using (var client = new AmazonS3Client(RegionEndpoint.USWest2))
{
// Returns an exception with HTTP 301 MovedPermanently
var exception = AssertExtensions.ExpectException(() => client.PutObject(request));
Assert.AreEqual("PermanentRedirect", exception.ErrorCode);
Assert.AreEqual(HttpStatusCode.MovedPermanently, exception.StatusCode);
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsFalse(string.IsNullOrEmpty(exception.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.AmazonId2));
}
}
[TestMethod]
[TestCategory("S3")]
public void GetObjectWithNonMatchingEtag()
{
var key = "TestMatchingEtag" + random.Next();
var request = new PutObjectRequest()
{
BucketName = bucketName,
Key = key,
ContentBody = "This is the content body!",
CannedACL = S3CannedACL.AuthenticatedRead
};
Client.PutObject(request);
var etag = Client.GetObject(new GetObjectRequest
{
BucketName = bucketName,
Key = key
}).ETag;
// Returns an exception with HTTP 304 NotModified
var exception = AssertExtensions.ExpectException(() =>
Client.GetObject(new GetObjectRequest
{
BucketName = bucketName,
Key = key,
EtagToNotMatch = etag
})
);
Assert.AreEqual("NotModified", exception.ErrorCode);
Assert.AreEqual(HttpStatusCode.NotModified, exception.StatusCode);
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsFalse(string.IsNullOrEmpty(exception.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.AmazonId2));
}
[TestMethod]
[TestCategory("S3")]
public void TemporaryRedirectForS3OperationsWithSigV4()
{
AWSConfigsS3.UseSignatureVersion4 = true;
TemporaryRedirectForS3Operations();
AWSConfigsS3.UseSignatureVersion4 = false;
}
[Ignore("Excluding tests that need IAM Write/Permissions management.")]
[TestMethod]
[TestCategory("S3")]
public void TemporaryRedirectForS3Operations()
{
var testBucketName = UtilityMethods.GenerateName(UtilityMethods.SDK_TEST_PREFIX);
using (var client = new AmazonS3Client())
{
var bucket = client.PutBucket(new PutBucketRequest
{
BucketName = testBucketName,
BucketRegion = S3Region.USW2
});
S3TestUtils.WaitForBucket(client, testBucketName);
try
{
client.PutObject(new PutObjectRequest
{
BucketName = testBucketName,
Key = "TestKey1",
ContentBody = "sample text"
});
client.PutObject(new PutObjectRequest
{
BucketName = testBucketName,
Key = "TestKey2",
InputStream = UtilityMethods.CreateStreamFromString("sample text")
});
// Returns an exception with HTTP 307 TemporaryRedirect
var exception = AssertExtensions.ExpectException(() =>
client.PutObject(new PutObjectRequest
{
BucketName = testBucketName,
Key = "TestKey3",
InputStream = UtilityMethods.CreateStreamFromString("sample text", new NonRewindableStream())
})
);
Assert.AreEqual("TemporaryRedirect", exception.ErrorCode);
Assert.AreEqual(HttpStatusCode.TemporaryRedirect, exception.StatusCode);
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsFalse(string.IsNullOrEmpty(exception.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.AmazonId2));
var objects = client.ListObjects(new ListObjectsRequest
{
BucketName = testBucketName
}).S3Objects;
Assert.AreEqual(2, objects.Count);
}
finally
{
AmazonS3Util.DeleteS3BucketWithObjects(client, testBucketName);
}
}
}
[TestMethod]
[TestCategory("S3")]
public void DeleteNonExistentBucket()
{
// Returns an exception with HTTP 404 NotFound
var exception = AssertExtensions.ExpectException(() =>
Client.DeleteBucket(new DeleteBucketRequest { BucketName = "nonexistentbucket1234567890" })
);
Assert.AreEqual("NoSuchBucket", exception.ErrorCode);
Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode);
Assert.IsFalse(string.IsNullOrEmpty(exception.Message));
Assert.IsFalse(string.IsNullOrEmpty(exception.RequestId));
Assert.IsFalse(string.IsNullOrEmpty(exception.AmazonId2));
}
[TestMethod]
[TestCategory("S3")]
public void GzipTest()
{
var request = CreatePutObjectRequest();
request.Headers.ContentEncoding = "gzip";
TestPutAndGet(request);
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithContentEncodingTests()
{
S3TestUtils.TestWithVariableSigV4(PutObjectWithContentEncoding, useSigV4: true);
S3TestUtils.TestWithVariableSigV4(PutObjectWithContentEncoding, useSigV4: false);
S3TestUtils.TestWithVariableSigV4(PutObjectWithContentEncodingIdentity, useSigV4: true);
S3TestUtils.TestWithVariableSigV4(PutObjectWithContentEncodingIdentity, useSigV4: false);
S3TestUtils.TestWithVariableSigV4(PutObjectWithoutContentEncoding, useSigV4: true);
S3TestUtils.TestWithVariableSigV4(PutObjectWithoutContentEncoding, useSigV4: false);
}
private void PutObjectWithContentEncoding()
{
var request = CreatePutObjectRequest();
request.Headers.ContentEncoding = "gzip";
request.Headers.ContentDisposition = "disposition";
var headers = TestPutAndGet(request);
Assert.AreEqual("disposition", headers.ContentDisposition);
Assert.AreEqual("gzip", headers.ContentEncoding);
}
private void PutObjectWithContentEncodingIdentity()
{
var request = CreatePutObjectRequest();
request.Headers.ContentEncoding = "identity";
request.Headers.ContentDisposition = "disposition";
var headers = TestPutAndGet(request);
Assert.AreEqual("disposition", headers.ContentDisposition);
Assert.AreEqual("identity", headers.ContentEncoding);
}
private void PutObjectWithoutContentEncoding()
{
var request = CreatePutObjectRequest();
request.Headers.ContentDisposition = "disposition";
var headers = TestPutAndGet(request);
Assert.AreEqual("disposition", headers.ContentDisposition);
Assert.IsNull(headers.ContentEncoding);
}
private HeadersCollection TestPutAndGet(PutObjectRequest request)
{
Client.PutObject(request);
var key = request.Key;
using (var response = Client.GetObject(bucketName, key))
using (var reader = new StreamReader(response.ResponseStream))
{
var contents = reader.ReadToEnd();
Assert.AreEqual(testContent, contents);
}
using (var response = Client.GetObject(bucketName, key))
{
response.WriteResponseStreamToFile(key, false);
var contents = File.ReadAllText(key);
Assert.AreEqual(testContent, contents);
}
var meta = Client.GetObjectMetadata(bucketName, key);
return meta.Headers;
}
private PutObjectRequest CreatePutObjectRequest()
{
var request = new PutObjectRequest
{
BucketName = bucketName,
Key = DateTime.Now.ToFileTime() + testKey,
ContentBody = testContent
};
return request;
}
[TestMethod]
[TestCategory("S3")]
public void PutEmptyFile()
{
string key = "contentBodyPut" + random.Next();
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = key;
request.ContentBody = string.Empty;
PutObjectResponse response = Client.PutObject(request);
using (GetObjectResponse getResponse = Client.GetObject(new GetObjectRequest() { BucketName = bucketName, Key = key }))
{
Assert.AreEqual(0, getResponse.ContentLength);
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectLeaveStreamOpen()
{
string filepath = @"c:\temp\PutObjectLeaveStreamOpen.txt";
string key = "PutObjectLeaveStreamOpen" + random.Next();
writeContent(@"c:\temp", "PutObjectLeaveStreamOpen.txt", "abcdefghighfsldfsdfn");
try
{
Stream stream = File.OpenRead(filepath);
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = key;
request.InputStream = stream;
Client.PutObject(request);
Assert.IsFalse(stream.CanSeek, "Stream should be closed and seek should not be allowed");
stream = File.OpenRead(filepath);
request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = key;
request.AutoCloseStream = false;
request.InputStream = stream;
Client.PutObject(request);
Assert.IsTrue(stream.CanSeek, "Stream should still be open and seek should be allowed");
stream.Close();
}
finally
{
File.Delete(filepath);
try
{
Client.DeleteObject(new DeleteObjectRequest() { BucketName = bucketName, Key = key });
}
catch { }
}
}
private void writeContent(string directory, string fileName, string content)
{
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
StreamWriter writer = new StreamWriter(directory + "/" + fileName);
writer.Write(content);
writer.Close();
}
[TestMethod]
[TestCategory("S3")]
[ExpectedException(typeof(ArgumentException))]
public void PutObject_ContentAndFile()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = "PutObjectTest";
request.ContentBody = "CAT";
request.FilePath = "PutObjectFile.txt";
try
{
Client.PutObject(request);
}
catch (ArgumentException ex)
{
Assert.AreEqual("Please specify one of either a FilePath or the ContentBody to be PUT as an S3 object.", ex.Message);
Console.WriteLine(ex.ToString());
throw ex;
}
}
[TestMethod]
[TestCategory("S3")]
[ExpectedException(typeof(ArgumentException), "Please specify one of either an InputStream or the ContentBody to be PUT as an S3 object.")]
public void PutObject_ContentAndStream()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = "PutObjectTest";
request.ContentBody = "CAT";
using (FileStream fStream = new FileStream("PutObjectFile.txt", FileMode.Open))
{
request.InputStream = fStream;
try
{
Client.PutObject(request);
}
catch (ArgumentException ex)
{
Assert.AreEqual("Please specify one of either an InputStream or the ContentBody to be PUT as an S3 object.", ex.Message);
Console.WriteLine(ex.ToString());
throw ex;
}
}
}
[TestMethod]
[TestCategory("S3")]
[ExpectedException(typeof(ArgumentException), "Please specify one of either an Input FileStream or a Filename to be PUT as an S3 object.")]
public void PutObject_StreamAndFile()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = "PutObjectTest";
using (FileStream fStream = new FileStream("PutObjectFile.txt", FileMode.Open))
{
request.InputStream = fStream;
request.FilePath = "PutObjectFile.txt";
try
{
Client.PutObject(request);
}
catch (ArgumentException ex)
{
Assert.AreEqual("Please specify one of either an InputStream or a FilePath to be PUT as an S3 object.", ex.Message);
Console.WriteLine(ex.ToString());
throw ex;
}
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObject_KeyFromPath()
{
string path = "PutObjectFile.txt";
TestKeyFromPath(path);
string fullPath = Path.GetFullPath(path);
TestKeyFromPath(fullPath);
string fullPathUnix = fullPath.Replace('\\', '/');
TestKeyFromPath(fullPathUnix);
}
private void TestKeyFromPath(string path)
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.FilePath = path;
Client.PutObject(request);
string key = Path.GetFileName(path);
var metadataRequest = new GetObjectMetadataRequest { BucketName = bucketName, Key = key };
var metadata = Client.GetObjectMetadata(metadataRequest);
Assert.IsNotNull(metadata);
Assert.IsTrue(metadata.ContentLength > 0);
Client.DeleteObject(new DeleteObjectRequest
{
BucketName = bucketName,
Key = key
});
AssertExtensions.ExpectException(() => Client.GetObjectMetadata(metadataRequest));
}
[TestMethod]
[TestCategory("S3")]
public void PutObject_FileNameOnly()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.FilePath = "PutObjectFile.txt";
Client.PutObject(request);
}
[TestMethod]
[TestCategory("S3")]
[ExpectedException(typeof(FileNotFoundException))]
public void PutObject_FileNameNotExist()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.FilePath = "FileThatDoesntExist";
try
{
Client.PutObject(request);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex.ToString());
throw ex;
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObject_StreamChecksumEnabled()
{
PutObjectRequest request = new PutObjectRequest();
request.BucketName = bucketName;
request.Key = "PutObjectStreamChecksum" + random.Next();
using (FileStream fStream = new FileStream("PutObjectFile.txt", FileMode.Open))
{
request.InputStream = fStream;
Client.PutObject(request);
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithACL()
{
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
Key = "putobjectwithacl",
ContentBody = "Some Random Nonsense",
Grants = new List()
{
//new S3Grant(){Grantee = new S3Grantee(){EmailAddress = "pavel@amazon.com"}, Permission = S3Permission.FULL_CONTROL},
//new S3Grant(){Grantee = new S3Grantee(){EmailAddress = "aws-dr-tools-test@amazon.com"}, Permission = S3Permission.FULL_CONTROL},
new S3Grant(){Grantee = new S3Grantee(){URI = "http://acs.amazonaws.com/groups/global/AllUsers"}, Permission = S3Permission.READ},
new S3Grant(){Grantee = new S3Grantee { URI = "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"}, Permission = S3Permission.READ}
}
};
Client.PutObject(request);
var acl = Client.GetACL(new GetACLRequest() { BucketName = bucketName, Key = "putobjectwithacl" }).AccessControlList;
Assert.AreEqual(2, acl.Grants.Count);
foreach (var grant in acl.Grants)
{
var grantee = grant.Grantee;
Console.WriteLine("Grantee:");
if (!string.IsNullOrEmpty(grantee.URI))
Console.WriteLine("Uri: {0}", grantee.URI);
if (!string.IsNullOrEmpty(grantee.EmailAddress))
Console.WriteLine("Email: {0}", grantee.EmailAddress);
if (grantee.CanonicalUser != null && !string.IsNullOrEmpty(grantee.CanonicalUser))
Console.WriteLine("Canonical user: {0}", grantee.CanonicalUser);
Console.WriteLine("Permissions: {0}", grant.Permission.ToString());
}
Client.PutACL(new PutACLRequest
{
BucketName = bucketName,
Key = "putobjectwithacl",
AccessControlList = new S3AccessControlList
{
Grants = new List
{
new S3Grant
{
Grantee = new S3Grantee { URI = "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" },
Permission = S3Permission.READ
}
},
Owner = acl.Owner
},
});
acl = S3TestUtils.WaitForConsistency(() =>
{
var res = Client.GetACL(new GetACLRequest() { BucketName = bucketName, Key = "putobjectwithacl" });
return res.AccessControlList?.Grants?.Count > 0 ? res.AccessControlList : null;
});
Assert.AreEqual(1, acl.Grants.Count);
}
[TestMethod]
[TestCategory("S3")]
public void PutBucketWithCannedACL()
{
string aclBucketName = "dotnet-integtests-cannedacl" + DateTime.Now.Ticks;
PutBucketRequest request = new PutBucketRequest() { BucketName = aclBucketName, CannedACL = S3CannedACL.LogDeliveryWrite, ObjectOwnership = ObjectOwnership.ObjectWriter };
Client.PutBucket(request);
S3TestUtils.WaitForBucket(Client, aclBucketName);
var acl = Client.GetACL(new GetACLRequest() { BucketName = aclBucketName }).AccessControlList;
Client.DeleteBucket(new DeleteBucketRequest() { BucketName = aclBucketName });
// should only have seen grants for full_control to test owner, LogDelivery read_acp and LogDelivery write
Assert.AreEqual(3, acl.Grants.Count);
foreach (var grant in acl.Grants)
{
if (!string.IsNullOrEmpty(grant.Grantee.DisplayName))
{
Assert.IsNotNull(grant.Grantee.DisplayName);
Assert.AreEqual(S3Permission.FULL_CONTROL, grant.Permission);
}
else if (!string.IsNullOrEmpty(grant.Grantee.CanonicalUser))
{
Assert.IsNotNull(grant.Grantee.CanonicalUser);
Assert.AreEqual(S3Permission.FULL_CONTROL, grant.Permission);
}
else
{
Assert.AreEqual("http://acs.amazonaws.com/groups/s3/LogDelivery", grant.Grantee.URI);
Assert.IsTrue(grant.Permission == S3Permission.READ_ACP || grant.Permission == S3Permission.WRITE);
}
}
}
[TestMethod]
[TestCategory("S3")]
public void PutObjectWithContentLength()
{
string sourceKey = "source";
string destKey = "dest";
string contents = "Sample contents";
int length = contents.Length;
Client.PutObject(new PutObjectRequest
{
BucketName = bucketName,
Key = sourceKey,
ContentBody = contents
});
// Disable clock skew testing when generating a presigned url
using (RetryUtilities.DisableClockSkewCorrection())
{
string url = Client.GetPreSignedURL(new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = sourceKey,
Expires = DateTime.Now + TimeSpan.FromHours(2)
});
HttpWebRequest httpRequest = HttpWebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse httpResponse = httpRequest.GetResponse() as HttpWebResponse)
using (Stream stream = httpResponse.GetResponseStream())
{
PutStream(destKey, length, stream);
}
string finalContents = GetContents(destKey);
Assert.AreEqual(contents, finalContents);
length -= 2;
httpRequest = HttpWebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse httpResponse = httpRequest.GetResponse() as HttpWebResponse)
using (Stream stream = httpResponse.GetResponseStream())
{
PutStream(destKey, length, stream);
}
finalContents = GetContents(destKey);
Assert.AreEqual(contents.Substring(0, length), finalContents);
}
}
private void PutStream(string destKey, int length, Stream stream)
{
PutObjectRequest request = new PutObjectRequest
{
BucketName = bucketName,
Key = destKey,
InputStream = stream,
};
request.Headers.ContentLength = length;
using (RetryUtilities.DisableClockSkewCorrection())
{
Client.PutObject(request);
}
}
private string GetContents(string key)
{
Stream stream = Client.GetObject(new GetObjectRequest
{
BucketName = bucketName,
Key = key
}).ResponseStream;
using (stream)
{
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
[TestMethod]
[TestCategory("S3")]
public void TestStreamRetry()
{
var s3ClientBufferSize = new AmazonS3Config().BufferSize;
var chunkedWrapperBufferSize = ChunkedUploadWrapperStream.DefaultChunkSize;
var sizeForFailWithoutWriting = 0;
var sizeForFailWithSomeWriting = chunkedWrapperBufferSize * 2;
var arbitrarySizeForSuccess = s3ClientBufferSize * 2;
var runs = 3;
var exceptions = new List();
for (int i = 0; i < runs; i++)
{
exceptions.Add(TryTest(sizeForFailWithoutWriting, failRequest: true));
exceptions.Add(TryTest(sizeForFailWithSomeWriting, failRequest: true));
exceptions.Add(TryTest(arbitrarySizeForSuccess, failRequest: false));
}
exceptions = exceptions.Where(e => e != null).ToList();
if (exceptions.Count > 0)
#if ASYNC_AWAIT
throw new AggregateException(exceptions);
#else
throw exceptions.First();
#endif
}
private static Exception TryTest(int errorSize, bool failRequest)
{
try
{
Test(errorSize, failRequest);
return null;
}
catch(Exception e)
{
return e;
}
}
private static void Test(int errorSize, bool failRequest)
{
var actualSize = errorSize + 128;
//var data = new string('@', actualSize + bufferSize);
//byte[] bytes = Encoding.UTF8.GetBytes(data);
var bytes = CreateData(actualSize);
// must precompute this and set in headers to avoid hash computation on ErrorStream
// affecting the test
var payloadhash = UtilityMethods.ToHex(UtilityMethods.ComputeSHA256(bytes), true);
ErrorStream es = ErrorStream.Create(bytes);
if (failRequest)
es.MaxReadBytes = errorSize;
// 1 rewind for S3 pre-marshallers which reset position to 0
// 1 rewind for exception at error size
es.MinRewinds = 2;
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = "foo1",
AutoCloseStream = false
};
putRequest.Headers["x-amz-content-sha256"] = payloadhash;
putRequest.InputStream = es;
CallWithTimeout(() => Client.PutObject(putRequest), TimeSpan.FromSeconds(10));
}
static void CallWithTimeout(Action action, TimeSpan timeout)
{
if (System.Diagnostics.Debugger.IsAttached)
{
action();
return;
}
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action();
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeout))
{
wrappedAction.EndInvoke(result);
}
else
{
threadToKill.Abort();
throw new TimeoutException();
}
}
private static byte[] CreateData(int size)
{
var data = new byte[size];
for(int i=0;i ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (OnRead != null)
OnRead(this, null);
var readCount = await base.ReadAsync(buffer, offset, count, cancellationToken);
TotalReadBytes += readCount;
ValidateRead(MaxReadBytes, TotalReadBytes, MinRewinds, Rewinds);
return readCount;
}
private void ValidateRead(int MaxReadBytes, int TotalReadBytes, int MinRewinds, int Rewinds)
{
bool throwBasedOnReadBytes = MaxReadBytes >= 0 && TotalReadBytes >= MaxReadBytes;
bool suppressThrowBasedOnRewinds = MinRewinds >= 0 && Rewinds >= MinRewinds;
if (throwBasedOnReadBytes && !suppressThrowBasedOnRewinds)
throw new IOException("Fake Exception");
}
public override long Seek(long offset, SeekOrigin origin)
{
var value = base.Seek(offset, origin);
TotalReadBytes = 0;
Rewinds++;
return value;
}
public override long Position
{
get
{
return base.Position;
}
set
{
this.Seek(value, SeekOrigin.Begin);
}
}
}
}
public class NonRewindableStream : MemoryStream
{
public override bool CanSeek
{
get
{
return false;
}
}
}
}