using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Threading; using System.Net; using Amazon.Runtime; using Amazon.S3; using Amazon.Runtime.Internal; using Amazon.Runtime.Internal.Auth; using Amazon.Runtime.Internal.Util; using Moq; using Ploeh.AutoFixture; using Ploeh.AutoFixture.AutoMoq; namespace AWSSDK.UnitTests { [TestClass] public class HttpWebRequestFactoryTests { private readonly IFixture _fixture; public HttpWebRequestFactoryTests() { _fixture = new Fixture() .Customize(new AutoMoqCustomization()); } [TestMethod] [TestCategory("UnitTest")] [TestCategory("Runtime")] public void TestHttpRequestSuccess() { #if ASYNC_AWAIT _fixture.Customize(cc => cc.With(config => config.CancellationToken, CancellationToken.None) ); #endif TestHttpRequest(CancellationToken.None); } #if ASYNC_AWAIT [TestMethod] [TestCategory("UnitTest")] [TestCategory("Runtime")] public async System.Threading.Tasks.Task TestHttpRequestCancellation() { var cts = new CancellationTokenSource(); cts.Cancel(); var token = cts.Token; try { await TestHttpRequest(token); } catch (OperationCanceledException exception) { Assert.AreEqual(token, exception.CancellationToken); Assert.AreEqual(true, exception.CancellationToken.IsCancellationRequested); return; } Assert.Fail("An OperationCanceledException was not thrown"); } [TestMethod] [TestCategory("UnitTest")] [TestCategory("Runtime")] public void TestHttpResponseCancellation() { var cts = new CancellationTokenSource(); var token = cts.Token; try { var request = CreateHttpRequest(token, out var requestContext, TimeSpan.FromMilliseconds(1)); var testContent = _fixture.Create(); var sourceStream = new MemoryStream(Encoding.UTF8.GetBytes(testContent)); var destinationStream = new MemoryStream(); request.WriteToRequestBody(destinationStream, sourceStream, null, requestContext); request.GetResponseAsync(token).GetAwaiter().GetResult(); } catch (OperationCanceledException exception) { Assert.AreNotEqual(token, exception.CancellationToken); Assert.AreEqual(true, exception.CancellationToken.IsCancellationRequested); return; } Assert.Fail("An WebException was not thrown"); } #endif #if BCL45 public async System.Threading.Tasks.Task TestHttpRequest(CancellationToken cancellationToken) #else public void TestHttpRequest(CancellationToken cancellationToken) #endif { var request = CreateHttpRequest(cancellationToken, out var requestContext); var testContent = _fixture.Create(); var sourceStream = new MemoryStream(Encoding.UTF8.GetBytes(testContent)); var destinationStream = new MemoryStream(); #if BCL45 await request.WriteToRequestBodyAsync(destinationStream, sourceStream, null, requestContext); #else request.WriteToRequestBody(destinationStream, sourceStream, null, requestContext); #endif var sourceContent = Encoding.UTF8.GetBytes(testContent); destinationStream = new MemoryStream(); #if BCL45 await request.WriteToRequestBodyAsync(destinationStream, sourceContent, null, cancellationToken); #else request.WriteToRequestBody(destinationStream, sourceContent, null); #endif } private IHttpRequest CreateHttpRequest(CancellationToken cancellationToken, out RequestContext requestContext, TimeSpan? requestTimeout = null) { //Create Web Request var targetUri = _fixture.Create(); var sut = _fixture.Create(); var request = sut.CreateHttpRequest(targetUri); Assert.IsNotNull(request); //Target Method var targetMethod = "PUT"; request.Method = targetMethod; var httpWebRequest = ((HttpRequest) request).Request; Assert.AreEqual(targetMethod, httpWebRequest.Method); // Request Context var proxyCreds = _fixture.Create(); var proxyHost = _fixture.Create(); var timeout = requestTimeout ?? TimeSpan.FromSeconds(40); var readWriteTimeout = TimeSpan.FromSeconds(20); var maxIdleTime = _fixture.Create(); var proxyPort = _fixture.Create(); var useNagleAlgorithm = _fixture.Create(); _fixture.Customize(cc => cc .With(config => config.ProxyHost, proxyHost) .With(config => config.ProxyPort, proxyPort) .With(config => config.ProxyCredentials, proxyCreds) .With(config => config.Timeout, timeout) .With(config => config.ReadWriteTimeout, readWriteTimeout) .With(config => config.MaxIdleTime, maxIdleTime) .With(config => config.UseNagleAlgorithm, useNagleAlgorithm) .With(config => config.ConnectionLimit, 10) .With(config => config.ServiceURL, "") ); _fixture.Customize(cc => cc .FromFactory(() => new RequestContext(true, new NullSigner())) #if ASYNC_AWAIT .With(context => context.CancellationToken, cancellationToken) #endif .With(context => context.ClientConfig, _fixture.Create()) .Without(context => context.CSMCallAttempt) .Without(context => context.CSMCallEvent) ); requestContext = _fixture.Create(); request.ConfigureRequest(requestContext); Assert.IsInstanceOfType(httpWebRequest.Proxy, typeof(WebProxy)); Assert.AreEqual(new Uri($"http://{proxyHost}:{proxyPort}"), ((WebProxy) httpWebRequest.Proxy).Address); Assert.AreEqual(proxyCreds, httpWebRequest.Proxy.Credentials); Assert.AreEqual(timeout.TotalMilliseconds, httpWebRequest.Timeout); Assert.AreEqual(readWriteTimeout.TotalMilliseconds, httpWebRequest.ReadWriteTimeout); Assert.AreEqual(maxIdleTime, httpWebRequest.ServicePoint.MaxIdleTime); Assert.AreEqual(useNagleAlgorithm, httpWebRequest.ServicePoint.UseNagleAlgorithm); var acceptHeader = _fixture.Create(); var contentTypeHeader = _fixture.Create(); var contentLength = 0; var userAgentHeader = _fixture.Create(); var date = DateTime.Now.ToUniversalTime(); var rangeHeader = _fixture.Create(); var contentRangeHeader = _fixture.Create(); var nonStandardHeader = _fixture.Create(); request.SetRequestHeaders(new Dictionary { {"Accept", acceptHeader}, {"Content-Type", contentTypeHeader}, {"Content-Length", contentLength.ToString()}, {"User-Agent", userAgentHeader}, {"Date", date.ToString("r")}, {"Range", rangeHeader}, {"Content-Range", contentRangeHeader}, {"If-Modified-Since", date.ToString("r")}, {"Expires", date.ToString("r")}, {"NonStandardHeader", nonStandardHeader}, }); Assert.AreEqual(acceptHeader, httpWebRequest.Accept); Assert.AreEqual(contentTypeHeader, httpWebRequest.ContentType); Assert.AreEqual(contentLength, httpWebRequest.ContentLength); Assert.AreEqual(userAgentHeader, httpWebRequest.UserAgent); Assert.AreEqual(DateTime.Parse(date.ToString("r")), httpWebRequest.Date); Assert.AreEqual(targetUri.Host, httpWebRequest.Host); Assert.AreEqual(DateTime.Parse(date.ToString("r")), httpWebRequest.IfModifiedSince); Assert.AreEqual(DateTime.Parse(date.ToString("r")), DateTime.Parse(httpWebRequest.Headers["Expires"])); Assert.AreEqual(rangeHeader, httpWebRequest.Headers["Range"]); Assert.AreEqual(contentRangeHeader, httpWebRequest.Headers["Content-Range"]); Assert.AreEqual(nonStandardHeader, httpWebRequest.Headers["NonStandardHeader"]); return request; } } }