Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An attempt to add cancellation token to async methods (#41) #209

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
119 changes: 119 additions & 0 deletions dropbox-sdk-dotnet/Dropbox.Api.Integration.Tests/DropboxApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// </copyright>
//-----------------------------------------------------------------------------

using System.Threading;

namespace Dropbox.Api.Tests
{
using System;
Expand Down Expand Up @@ -526,6 +528,123 @@ public async Task TestCreateFolderWithDateFormat()
Assert.IsTrue(folders.Entries.Any(f => f.Name == folderNameWithDateFormat));
}

/// <summary>
/// Test retry with cancellation token.
/// </summary>
/// <returns>The <see cref="Task" />.</returns>
[TestMethod]
public async Task TestRetryWithCancellation()
{
var count = 0;

var mockHandler = new MockHttpMessageHandler((r, s) =>
{
if (count++ < 3)
{
var error = new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("Error"),
};

return Task.FromResult(error);
}

return s(r);
});
var mockClient = new HttpClient(mockHandler);
var mockedClient = new DropboxClient(userAccessToken, new DropboxClientConfig { HttpClient = mockClient, MaxRetriesOnError = 10 });
var filePath = $"{TestingPath}/{DateTime.Now.Ticks}.txt";
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
using var ctx = new CancellationTokenSource();
var response = mockedClient.Files.UploadAsync(filePath, body: GetStream("abc"), cancellationToken: ctx.Token);
ctx.Cancel();
await response;
});
await Assert.ThrowsExceptionAsync<ApiException<GetMetadataError>>(async () =>
{
await DropboxApiTests.client.Files.GetMetadataAsync(filePath);
});
}

/// <summary>
/// Test download with cancellation token.
/// </summary>
/// <returns>The <see cref="Task" />.</returns>
[TestMethod]
public async Task TestDownloadWithCancellation()
{
var filePath = $"{TestingPath}/{DateTime.Now.Ticks}.txt";
await client.Files.UploadAsync(filePath, body: GetStream("abc"));
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
using var cts = new CancellationTokenSource();
var downloadResponse = client.Files.DownloadAsync(TestingPath + "/Foo.txt", cancellationToken: cts.Token);
cts.Cancel();
await downloadResponse;
});
}

/// <summary>
/// Test upload with cancellation token.
/// </summary>
/// <returns>The <see cref="Task" />.</returns>
[TestMethod]
public async Task TestUploadWithCancellation()
{
var filePath = $"{TestingPath}/{DateTime.Now.Ticks}.txt";
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
using var cts = new CancellationTokenSource();
var response = client.Files.UploadAsync(filePath, body: GetStream("abc"), cancellationToken: cts.Token);
cts.Cancel();
await response;
});
await Assert.ThrowsExceptionAsync<ApiException<GetMetadataError>>(async () =>
{
await client.Files.GetMetadataAsync(filePath);
});
}

/// <summary>
/// Test CreateFolder with cancellation token.
/// </summary>
/// <returns>The <see cref="Task" />.</returns>
[TestMethod]
public async Task TestCreateFolderWithCancellation()
{
var folderPath = $"{TestingPath}/{DateTime.Now.Ticks}";
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
using var cts = new CancellationTokenSource();
var response = client.Files.CreateFolderAsync(folderPath, cancellationToken: cts.Token);
cts.Cancel();
await response;
});
await Assert.ThrowsExceptionAsync<ApiException<GetMetadataError>>(async () =>
{
await client.Files.GetMetadataAsync(folderPath);
});
}

/// <summary>
/// Test refresh access token with cancellation token.
/// </summary>
/// <returns>The <see cref="Task" />.</returns>
[TestMethod]
public async Task TestRefreshAccessTokenWithCancellation()
{
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
var clientToRefreshToken = new DropboxClient(userRefreshToken, appKey, appSecret);
using var cts = new CancellationTokenSource();
var response = clientToRefreshToken.RefreshAccessToken(Array.Empty<string>(), cts.Token);
cts.Cancel();
var isRefreshed = await response;
Assert.IsFalse(isRefreshed);
});
}

/// <summary>
/// Converts string to a memory stream.
/// </summary>
Expand Down
26 changes: 23 additions & 3 deletions dropbox-sdk-dotnet/Dropbox.Api.Unit.Tests/StoneTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
namespace Dropbox.Api.Unit.Tests
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Dropbox.Api.Files;
using Dropbox.Api.Stone;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand All @@ -21,9 +23,9 @@ public class StoneTests
/// Smoke test for nested unions.
/// </summary>
[TestMethod]
public void TestNestedUnion()
public async Task TestNestedUnion()
{
var result = JsonWriter.Write(
var result = await JsonWriter.WriteAsync(
new GetMetadataError.Path(LookupError.NotFound.Instance),
GetMetadataError.Encoder);

Expand All @@ -32,5 +34,23 @@ public void TestNestedUnion()
Assert.IsTrue(obj.IsPath);
Assert.IsTrue(obj.AsPath.Value.IsNotFound);
}

/// <summary>
/// Smoke test for JsonWriter with cancellation token.
/// </summary>
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
[TestMethod]
public async Task TestNestedUnionWithCancellation()
{
using var cts = new CancellationTokenSource();
cts.Cancel();
await Assert.ThrowsExceptionAsync<TaskCanceledException>(async () =>
{
await JsonWriter.WriteAsync(
new GetMetadataError.Path(LookupError.NotFound.Instance),
GetMetadataError.Encoder,
cancellationToken: cts.Token);
});
}
}
}
}
6 changes: 4 additions & 2 deletions dropbox-sdk-dotnet/Dropbox.Api/DropboxClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
namespace Dropbox.Api
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Dropbox.Api.Common;

Expand Down Expand Up @@ -256,10 +257,11 @@ public DropboxClient WithPathRoot(PathRoot pathRoot)
/// Refreshes access token regardless of if existing token is expired.
/// </summary>
/// <param name="scopeList">subset of scopes to refresh token with, or null to refresh with all scopes.</param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
/// <returns>true if token is successfully refreshed, false otherwise.</returns>
public Task<bool> RefreshAccessToken(string[] scopeList)
public Task<bool> RefreshAccessToken(string[] scopeList, CancellationToken cancellationToken = default)
{
return this.requestHandler.RefreshAccessToken(scopeList);
return this.requestHandler.RefreshAccessToken(scopeList, cancellationToken);
}
}
}
Loading