Skip to content

Commit

Permalink
Make the cancelation can be executed before the task is done (#11225)
Browse files Browse the repository at this point in the history
* Make the file large enough so that the cancelation can be executed before the task is done

* Use StreamContent to indefinitely provide single char per couple dozens milliseconds

* Use a fake stream that provides a single character A~Z per a couple of milliseconds without high memory cost instead

* Correct the TimeSpan with Milliseconds

* Change the implementation of Read() in the fake stream with simple logic and add a comment
  • Loading branch information
GangWang01 authored Jan 23, 2025
1 parent a7bf111 commit 291a810
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions src/Tasks.UnitTests/DownloadFile_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void CanBeCanceled()
DestinationFolder = new TaskItem(folder.Path),
HttpMessageHandler = new MockHttpMessageHandler((message, token) => new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(new String('!', 10000000)),
Content = new StreamContent(new FakeStream()),
RequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://largedownload/foo.txt")
}),
SourceUrl = "http://largedownload/foo.txt"
Expand All @@ -47,7 +47,7 @@ public void CanBeCanceled()

downloadFile.Cancel();

task.Wait(TimeSpan.FromSeconds(1)).ShouldBeTrue();
task.Wait(TimeSpan.FromMilliseconds(1500)).ShouldBeTrue();

task.Result.ShouldBeFalse();
}
Expand Down Expand Up @@ -401,4 +401,40 @@ protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage reques
}
}
}

// Fake stream that simulates providing a single character A~Z per a couple of milliseconds without high memory cost.
public class FakeStream : Stream
{
private readonly int delayMilliseconds;

public FakeStream(int delayInMilliseconds = 20)
{
delayMilliseconds = delayInMilliseconds;
Position = 0;
}

public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => long.MaxValue;
public override long Position { get; set; }

public override int Read(byte[] buffer, int offset, int count)
{
// Simulate infinite stream by keeping providing a single character to the beginning of the requested destination.
// Writes next char A ~ Z in alphabet into the begining of requested destination. The count could be ignored.
buffer[offset] = (byte)('A' + Position % 26);
Position++;
Task.Delay(delayMilliseconds).Wait();
return 1;
}

public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException();

public override void SetLength(long value) => throw new NotImplementedException();

public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();

public override void Flush() => throw new NotImplementedException();
}
}

0 comments on commit 291a810

Please sign in to comment.