Skip to content

Commit

Permalink
Retry-After header is honored for LRO polling. Added tests. Added LRO…
Browse files Browse the repository at this point in the history
… Patch scenario test. Cleaned up PollingState: Obsolete DelayInMillisecond propety, introduced DelayBetweenPolling property that returns TimeSpan. Bumped version. (Azure#3621)
  • Loading branch information
shahabhijeet authored Aug 24, 2017
1 parent 7c47282 commit 0d132e8
Show file tree
Hide file tree
Showing 9 changed files with 422 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1107,5 +1107,129 @@ static internal IEnumerable<HttpResponseMessage> MockDeleteWithRetryAfterTwoTrie
yield return response2;
}

static internal IEnumerable<HttpResponseMessage> MockPatchWithRetryAfterTwoTries()
{
var response1 = new HttpResponseMessage(HttpStatusCode.Accepted)
{
Content = new StringContent(@"")
};
response1.Headers.Add("Location", "http://custom/location/status");
response1.Headers.Add("Retry-After", "3");

yield return response1;

var response2 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("{ \"properties\": { }, \"id\": \"100\", \"name\": \"foo\" }")
};

yield return response2;
}

static internal IEnumerable<HttpResponseMessage> MockCreateOrUpdateWithDifferentRetryAfterValues()
{
var response1 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(@"
{
""location"": ""North US"",
""tags"": {
""key1"": ""value 1"",
""key2"": ""value 2""
},
""properties"": {
""provisioningState"": ""InProgerss"",
""comment"": ""Resource defined structure""
}
}")
};
response1.Headers.Add("Azure-AsyncOperation", "http://custom/status");
response1.Headers.Add("Retry-After", "2");

yield return response1;

var response2 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(@"
{
""status"" : ""InProgerss"",
""properties"": {
""provisioningState"": ""InProgerss"",
""comment"": ""Resource getting created""
}
}")
};
response2.Headers.Add("Retry-After", "5");

yield return response2;

var response3 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(@"
{
""status"" : ""Succeeded"",
""properties"": {
""id"": ""100"",
""name"": ""foo""
}
}")
};

yield return response3;

var response4 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(@"
{
""status"" : ""Succeeded"",
""properties"": {
""id"": ""100"",
""name"": ""foo""
}
}")
};

yield return response4;
}

static internal IEnumerable<HttpResponseMessage> MockCreateWithRetryAfterDefaultMin()
{
var response1 = new HttpResponseMessage(HttpStatusCode.Accepted)
{
Content = new StringContent(@"")
};
response1.Headers.Add("Location", "http://custom/location/status");
response1.Headers.Add("Retry-After", "0");

yield return response1;

var response2 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("{ \"properties\": { }, \"id\": \"100\", \"name\": \"foo\" }")
};

yield return response2;
}

static internal IEnumerable<HttpResponseMessage> MockCreateWithRetryAfterDefaultMax()
{
var response1 = new HttpResponseMessage(HttpStatusCode.Accepted)
{
Content = new StringContent(@"")
};
response1.Headers.Add("Location", "http://custom/location/status");
response1.Headers.Add("Retry-After", "50");

yield return response1;

var response2 = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("{ \"properties\": { }, \"id\": \"100\", \"name\": \"foo\" }")
};

yield return response2;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -506,20 +506,6 @@ public void TestCreateOrUpdateNoErrorBody()
}
}

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestCreateOrUpdateWithRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockCreateOrUpdateWithRetryAfterTwoTries());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var now = DateTime.Now;
fakeClient.RedisOperations.CreateOrUpdate("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");

Assert.True(DateTime.Now - now >= TimeSpan.FromSeconds(2));
}

/// <summary>
/// Test
Expand Down Expand Up @@ -600,20 +586,7 @@ public void TestDeleteWithLocationHeaderErrorHandlingSecondTime()
Assert.Equal("Long running operation failed with status 'InternalServerError'.", ex.Message);
}

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestDeleteWithRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockDeleteWithRetryAfterTwoTries());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var now = DateTime.Now;
fakeClient.RedisOperations.Delete("rg", "redis", "1234");

Assert.True(DateTime.Now - now >= TimeSpan.FromSeconds(2));
}



/// <summary>
Expand Down Expand Up @@ -692,4 +665,97 @@ public void TestLROWithNonStandardTerminalStatus()
Assert.Equal<string>("OK", foo.Response.StatusCode.ToString());
}
}

/// <summary>
/// Tests for Retry-After header
/// </summary>
public class LRO_RetryAfterTests
{

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestCreateOrUpdateWithRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockCreateOrUpdateWithRetryAfterTwoTries());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var now = DateTime.Now;
fakeClient.RedisOperations.CreateOrUpdate("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");

Assert.True(DateTime.Now - now >= TimeSpan.FromSeconds(2));
}

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestDeleteWithRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockDeleteWithRetryAfterTwoTries());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var now = DateTime.Now;
fakeClient.RedisOperations.Delete("rg", "redis", "1234");

Assert.True(DateTime.Now - now >= TimeSpan.FromSeconds(2));
}

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestPatchWithRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockPatchWithRetryAfterTwoTries());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var now = DateTime.Now;
fakeClient.RedisOperations.Patch("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");
Assert.True(DateTime.Now - now >= TimeSpan.FromSeconds(2));
}

/// <summary>
/// Test
/// </summary>
[Fact]
public void TestCreateWithDifferentRetryAfter()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockCreateOrUpdateWithDifferentRetryAfterValues());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var before = DateTime.Now;
fakeClient.RedisOperations.CreateOrUpdate("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");
Assert.True(DateTime.Now - before >= TimeSpan.FromSeconds(7));
}

/// <summary>
///
/// </summary>
[Fact]
public void TestCreateWithRetryAfterDefaultMin()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockCreateWithRetryAfterDefaultMin());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var before = DateTime.Now;
fakeClient.RedisOperations.CreateOrUpdate("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");
Assert.True(DateTime.Now - before >= TimeSpan.FromSeconds(1));
}

/// <summary>
///
/// </summary>
[Fact]
public void TestCreateWithRetryAfterDefaultMax()
{
var tokenCredentials = new TokenCredentials("123", "abc");
var handler = new PlaybackTestHandler(LROResponse.MockCreateWithRetryAfterDefaultMax());
var fakeClient = new RedisManagementClient(tokenCredentials, handler);
var before = DateTime.Now;
fakeClient.RedisOperations.CreateOrUpdate("rg", "redis", new RedisCreateOrUpdateParameters(), "1234");
Assert.True(DateTime.Now - before >= TimeSpan.FromSeconds(40));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
<Import Project="$([MSBuild]::GetPathOfFileAbove('CR.test.reference.props'))" />
<PropertyGroup>
<Description>Test Project for Microsoft.Rest.ClientRuntime.Azure</Description>
<VersionPrefix>2.0.0-preview</VersionPrefix>
<Version>1.0.0</Version>
<AssemblyName>Microsoft.Rest.ClientRuntime.Azure.Tests</AssemblyName>
<PackageId>Microsoft.Rest.ClientRuntime.Azure.Tests</PackageId>
<PackageTags>Rest ClientRuntime Azure Test $(NugetCommonTags) $(NugetCommonProfileTags)</PackageTags>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1</TargetFrameworks>
<TestProjectType>true</TestProjectType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp1.1|AnyCPU'">
<NoWarn>1701;1702;1705</NoWarn>
Expand All @@ -19,13 +18,7 @@
<PackageReference Include="Microsoft.Rest.ClientRuntime.Azure.Authentication" Version="[2.2.12,3.0.0)" />
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.Rest.ClientRuntime" Version="[2.3.6,3.0)" />
<PackageReference Include="Microsoft.Rest.ClientRuntime.Azure" Version="[3.3.5,4.0.0)" />
<PackageReference Include="Microsoft.Rest.ClientRuntime.Azure.Authentication" Version="[2.2.12,3.0.0)" />-->

<ProjectReference Include="..\ClientRuntime.Azure\Microsoft.Rest.ClientRuntime.Azure.csproj" />
<!--<ProjectReference Include="..\..\ClientRuntime\ClientRuntime\Microsoft.Rest.ClientRuntime.csproj" />-->
<!--<ProjectReference Include="..\..\ClientRuntime.Azure.Authentication\Microsoft.Rest.ClientRuntime.Azure.Authentication.csproj" />-->
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 0d132e8

Please sign in to comment.