//-----------------------------------------------------------------------------
//
// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Amazon.XRay.Recorder.Core;
using Amazon.XRay.Recorder.Core.Internal.Entities;
using Amazon.XRay.Recorder.Core.Internal.Utils;
using Amazon.XRay.Recorder.Handlers.System.Net;
using Amazon.XRay.Recorder.UnitTests.Tools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Amazon.XRay.Recorder.UnitTests
{
[TestClass]
public class HttpWebRequestTracingExtensionTests : TestBase
{
private const string URL = "https://httpbin.org/";
private const string URL404 = "https://httpbin.org/404";
private static AWSXRayRecorder _recorder;
[TestInitialize]
public void TestInitialize()
{
_recorder = new AWSXRayRecorder();
AWSXRayRecorder.InitializeInstance(recorder: _recorder);
}
[TestCleanup]
public new void TestCleanup()
{
base.TestCleanup();
_recorder.Dispose();
_recorder = null;
}
[TestMethod]
public void TestGetResponseTraced()
{
var request = (HttpWebRequest)WebRequest.Create(URL);
AWSXRayRecorder.Instance.BeginSegment("parent", TraceId);
using (request.GetResponseTraced())
{
var segment = AWSXRayRecorder.Instance.TraceContext.GetEntity();
AWSXRayRecorder.Instance.EndSegment();
Assert.IsNotNull(request.Headers[TraceHeader.HeaderKey]);
var requestInfo = segment.Subsegments[0].Http["request"] as Dictionary;
Assert.AreEqual(URL, requestInfo["url"]);
Assert.AreEqual("GET", requestInfo["method"]);
var responseInfo = segment.Subsegments[0].Http["response"] as Dictionary;
Assert.AreEqual(200, responseInfo["status"]);
Assert.IsNotNull(responseInfo["content_length"]);
}
}
///
/// Ensures that when tracing is disabled that HTTP requests can execute as normal.
/// See https://github.com/aws/aws-xray-sdk-dotnet/issues/57 for more information.
///
[TestMethod]
public void TestXrayDisabledGetResponseTraced()
{
_recorder = new MockAWSXRayRecorder() { IsTracingDisabledValue = true };
AWSXRayRecorder.InitializeInstance(recorder: _recorder);
Assert.IsTrue(AWSXRayRecorder.Instance.IsTracingDisabled());
var request = (HttpWebRequest)WebRequest.Create(URL);
using (var response = request.GetResponseTraced() as HttpWebResponse)
{
Assert.IsNotNull(response);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
[TestMethod]
public async Task TestGetAsyncResponseTraced()
{
var request = (HttpWebRequest)WebRequest.Create(URL);
AWSXRayRecorder.Instance.BeginSegment("parent", TraceId);
using (await request.GetAsyncResponseTraced())
{
var segment = AWSXRayRecorder.Instance.TraceContext.GetEntity();
AWSXRayRecorder.Instance.EndSegment();
Assert.IsNotNull(request.Headers[TraceHeader.HeaderKey]);
var requestInfo = segment.Subsegments[0].Http["request"] as Dictionary;
Assert.AreEqual(URL, requestInfo["url"]);
Assert.AreEqual("GET", requestInfo["method"]);
var responseInfo = segment.Subsegments[0].Http["response"] as Dictionary;
Assert.AreEqual(200, responseInfo["status"]);
Assert.IsNotNull(responseInfo["content_length"]);
}
}
///
/// Ensures that when tracing is disabled that HTTP requests can execute as normal.
/// See https://github.com/aws/aws-xray-sdk-dotnet/issues/57 for more information.
///
[TestMethod]
public async Task TestXrayDisabledGetAsyncResponseTraced()
{
_recorder = new MockAWSXRayRecorder() { IsTracingDisabledValue = true };
AWSXRayRecorder.InitializeInstance(recorder: _recorder);
Assert.IsTrue(AWSXRayRecorder.Instance.IsTracingDisabled());
var request = (HttpWebRequest)WebRequest.Create(URL);
using (var response = await request.GetAsyncResponseTraced() as HttpWebResponse)
{
Assert.IsNotNull(response);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
#if !NETFRAMEWORK
[TestMethod]
public void TestExceptionGetResponseTraced()
{
var request = (HttpWebRequest)WebRequest.Create(URL404);
AWSXRayRecorder.Instance.BeginSegment("parent", TraceId);
try
{
using (request.GetResponseTraced()) {}
Assert.Fail();
}
catch (WebException) //expected
{
var segment = AWSXRayRecorder.Instance.TraceContext.GetEntity();
AWSXRayRecorder.Instance.EndSegment();
Assert.IsNotNull(request.Headers[TraceHeader.HeaderKey]);
var requestInfo = segment.Subsegments[0].Http["request"] as Dictionary;
Assert.AreEqual(URL404, requestInfo["url"]);
Assert.AreEqual("GET", requestInfo["method"]);
var responseInfo = segment.Subsegments[0].Http["response"] as Dictionary;
Assert.AreEqual(404, responseInfo["status"]);
Assert.IsNotNull(responseInfo["content_length"]);
var subsegment = segment.Subsegments[0];
Assert.IsTrue(subsegment.HasError);
Assert.IsFalse(subsegment.HasFault);
}
}
[TestMethod]
public async Task TestExceptionGetAsyncResponseTraced()
{
var request = (HttpWebRequest)WebRequest.Create(URL404);
AWSXRayRecorder.Instance.BeginSegment("parent", TraceId);
try
{
using (await request.GetAsyncResponseTraced()) {}
Assert.Fail();
}
catch (WebException) //expected
{
var segment = AWSXRayRecorder.Instance.TraceContext.GetEntity();
AWSXRayRecorder.Instance.EndSegment();
Assert.IsNotNull(request.Headers[TraceHeader.HeaderKey]);
var requestInfo = segment.Subsegments[0].Http["request"] as Dictionary;
Assert.AreEqual(URL404, requestInfo["url"]);
Assert.AreEqual("GET", requestInfo["method"]);
var responseInfo = segment.Subsegments[0].Http["response"] as Dictionary;
Assert.AreEqual(404, responseInfo["status"]);
Assert.IsNotNull(responseInfo["content_length"]);
var subsegment = segment.Subsegments[0];
Assert.IsTrue(subsegment.HasError);
Assert.IsFalse(subsegment.HasFault);
}
}
#endif
[TestMethod]
public async Task TestContextMissingStrategyGetAsyncResponseTraced()
{
_recorder = new AWSXRayRecorder();
AWSXRayRecorder.InitializeInstance(recorder: _recorder);
Assert.IsFalse(AWSXRayRecorder.Instance.IsTracingDisabled());
AWSXRayRecorder.Instance.ContextMissingStrategy = Core.Strategies.ContextMissingStrategy.LOG_ERROR;
_recorder.EndSegment();
// The test should not break. No segment is available in the context, however, since the context missing strategy is log error,
// no exception should be thrown by below code.
var request = (HttpWebRequest)WebRequest.Create(URL);
using (var response = await request.GetAsyncResponseTraced() as HttpWebResponse)
{
Assert.IsNotNull(response);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
}
}