I got an error report from the field in Upload to YouTube where the user was getting an unhandled exception when I copied their Camera Roll video to temporary storage to hand off to Movie Maker for editing. Great catch, now to shore up the UX when this happens. Only problem is, I need to test filling up the disk during a copy. How could I possibly do this?
It was suggested that I simply write to the disk until it’s full. Yeah, if you’re testing filling up a disk, that’s the way to do it. But what about filling up the disk during a copy? Hmm… well, if I wanted to do this, I basically need to create a source file that’s as big as it needs to be to fill the disk.
Enter EndlessReadStream
:)
If you ever need to test this kind of scenario, hopefully this will come in handy for you as well!
1: class EndlessReadStream : Stream
2: {
3: public override bool CanRead
4: {
5: get { return true; }
6: }
7:
8: public override bool CanSeek
9: {
10: get { return true; }
11: }
12:
13: public override bool CanWrite
14: {
15: get { return false; }
16: }
17:
18: public override void Flush()
19: {
20: return;
21: }
22:
23: public override long Length
24: {
25: get { return long.MaxValue; }
26: }
27:
28: public override long Position { get; set; }
29:
30: public override int Read(byte[] buffer, int offset, int count)
31: {
32: for (int i = 0; i < count; i++)
33: {
34: buffer[offset + i] = 0;
35: }
36:
37: return count;
38: }
39:
40: public override long Seek(long offset, SeekOrigin origin)
41: {
42: return 0;
43: }
44:
45: public override void SetLength(long value)
46: {
47: throw new InvalidOperationException();
48: }
49:
50: public override void Write(byte[] buffer, int offset, int count)
51: {
52: throw new InvalidOperationException();
53: }
54: }
Usage:
1: using (var outStream = await outFile.OpenStreamForWriteAsync())
2: using (var inStream = new EndlessReadStream())
3: {
4: try
5: {
6: await inStream.CopyToAsync(outStream);
7: }
8: catch (Exception ex)
9: {
10: if (ex.Message.Contains("80070070"))
11: {
12:
13: }
14: }
15: }
I do wish the API would throw an IOException
in this case, but it doesn’t so we have to trap it by looking specifically for the HResult
code. Curious what the Exception does look like? Here’s the output from “Copy exception detail to clipboard”:
System.Exception was caught
HResult=-2147024784
Message=There is not enough space on the disk. (Exception from HRESULT: 0x80070070)
Source=mscorlib
StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.IO.BufferedStream.<WriteToUnderlyingStreamAsync>d__d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.IO.Stream.<CopyToAsyncInternal>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at
<My code here>
InnerException: