Skip to content
This repository was archived by the owner on Apr 24, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Analytics.NetStandard20/Analytics.NetStandard20.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@
<ItemGroup>
<Compile Include="../Analytics/**/*.cs" Exclude="../Analytics/obj/**/*.cs" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>Test.NetStandard20</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
</Project>
16 changes: 13 additions & 3 deletions Analytics/Request/BlockingRequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,20 @@ internal class BlockingRequestHandler : IRequestHandler
/// </summary>
public TimeSpan Timeout { get; set; }

internal BlockingRequestHandler(Client client, TimeSpan timeout)
internal BlockingRequestHandler(Client client, TimeSpan timeout) : this(client, timeout, null)
{
}

internal BlockingRequestHandler(Client client, TimeSpan timeout, HttpClient httpClient)
{
this._client = client;
this.Timeout = timeout;

if (httpClient != null)
{
_httpClient = httpClient;
return;
}
// Create HttpClient instance in .Net 3.5
#if NET35
_httpClient = new HttpClient { Timeout = Timeout };
Expand Down Expand Up @@ -189,6 +198,7 @@ public async Task MakeRequest(Batch batch)
watch.Stop();

Succeed(batch, watch.ElapsedMilliseconds);
statusCode = 200;
break;
}
catch (WebException ex)
Expand Down Expand Up @@ -228,15 +238,15 @@ public async Task MakeRequest(Batch batch)
var response = await _httpClient.PostAsync(uri, content).ConfigureAwait(false);

watch.Stop();
statusCode = (int)response.StatusCode;

if (response.StatusCode == HttpStatusCode.OK)
if (statusCode == (int)HttpStatusCode.OK)
{
Succeed(batch, watch.ElapsedMilliseconds);
break;
}
else
{
statusCode = (int)response.StatusCode;
if ((statusCode >= 500 && statusCode <= 600) || statusCode == 429)
{
// If status code is greater than 500 and less than 600, it indicates server error
Expand Down
177 changes: 177 additions & 0 deletions Test.NetStandard20/Request/BlockingRequestHandlerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using Moq;
using Moq.Protected;
using NUnit.Framework;
using Segment;
using Segment.Model;
using Segment.Request;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Test.NetStandard20.Request
{

[TestFixture()]
class BlockingRequestHandlerTest
{
private Mock<HttpMessageHandler> _mockHttpMessageHandler;
private Client _client;

private BlockingRequestHandler _handler;
Func<HttpResponseMessage> _httpBehavior;

[SetUp]
public void Init()
{
_mockHttpMessageHandler = new Mock<HttpMessageHandler>(MockBehavior.Strict);
_httpBehavior = SingleHttpResponseBehavior(HttpStatusCode.OK);

_mockHttpMessageHandler.Protected().Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
// prepare the expected response of the mocked http call
.ReturnsAsync(() => _httpBehavior())
.Verifiable();

_client = new Client("foo");
_handler = new BlockingRequestHandler(_client, new TimeSpan(0, 0, 10), new HttpClient(_mockHttpMessageHandler.Object));
}

[Test]
public async Task MakeRequestWith5xxStatusCode()
{
//Arrange
_httpBehavior = SingleHttpResponseBehavior(HttpStatusCode.InternalServerError);
var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(0, _client.Statistics.Succeeded);
Assert.AreEqual(1, _client.Statistics.Failed);
AssertSendAsyncWasCalled(7);
}

[Test]
public async Task MakeRequestWith429StatusCode()
{
//Arrange
_httpBehavior = SingleHttpResponseBehavior((HttpStatusCode)429);
var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(0, _client.Statistics.Succeeded);
Assert.AreEqual(1, _client.Statistics.Failed);
AssertSendAsyncWasCalled(7);
}


[Test]
public async Task MakeRequestWith4xxStatusCode()
{
//Arrange
_httpBehavior = SingleHttpResponseBehavior(HttpStatusCode.MethodNotAllowed);
var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(0, _client.Statistics.Succeeded);
Assert.AreEqual(1, _client.Statistics.Failed);
AssertSendAsyncWasCalled(1);
}

[Test]
public async Task MakeRequestWith200StatusCode()
{
//Arrange
var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(1, _client.Statistics.Succeeded);
Assert.AreEqual(0, _client.Statistics.Failed);
AssertSendAsyncWasCalled();
}

[Test]
public async Task MakeRequestWithErrorStatusCodeRetryUntilSuccess()
{
//Arrange
_httpBehavior = MultipleHttpResponseBehavior(
HttpStatusCode.InternalServerError,
HttpStatusCode.NotImplemented,
(HttpStatusCode)429,
HttpStatusCode.OK);

var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(1, _client.Statistics.Succeeded);
Assert.AreEqual(0, _client.Statistics.Failed);
AssertSendAsyncWasCalled(4);
}
[Test]
public async Task MakeRequestWithErrorStatusCodeRetryUntil4xxErrorExcept429()
{
//Arrange
_httpBehavior = MultipleHttpResponseBehavior(
HttpStatusCode.InternalServerError,
HttpStatusCode.NotImplemented,
(HttpStatusCode)429,
HttpStatusCode.NotFound);

var batch = GetBatch();

//Act
await _handler.MakeRequest(batch);

//Assert
Assert.AreEqual(0, _client.Statistics.Succeeded);
Assert.AreEqual(1, _client.Statistics.Failed);
AssertSendAsyncWasCalled(4);
}


private Func<HttpResponseMessage> SingleHttpResponseBehavior(HttpStatusCode statusCode)
{
return () => new HttpResponseMessage(statusCode: statusCode);
}

private Func<HttpResponseMessage> MultipleHttpResponseBehavior(params HttpStatusCode[] statusCode)
{
var response = new Queue<HttpResponseMessage>(statusCode.Select(s => new HttpResponseMessage { StatusCode = s }));
return () => response.Count > 0 ? response.Dequeue() : null;
}


private void AssertSendAsyncWasCalled(int times = 1)
{
_mockHttpMessageHandler.Protected().Verify("SendAsync", Times.Exactly(times),
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>());
}

private Batch GetBatch()
{
return new Batch("", new List<BaseAction> { new Track("user", "TestEvent", null, null) });
}
}
}
1 change: 1 addition & 0 deletions Test.NetStandard20/Test.NetStandard20.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
<PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="NUnit" Version="3.8.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0" />
</ItemGroup>
Expand Down