Skip to content

Commit

Permalink
ODataMessageWriter can't dispose the stream if there's no write metho…
Browse files Browse the repository at this point in the history
…d called (#1714)

* ODataMessageWriter can't dispose the stream if there's no write method
called. This is an edge case because customer creates the message writer
to write something. However, if there's some control to prevent the
message writer writing anything, the outside stream still needs to
dispose. This PR is to resolve this edge problem.

* Address the comments
  • Loading branch information
xuzhg authored Mar 24, 2020
1 parent 6f3c0d5 commit 3e02e30
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/Microsoft.OData.Core/ODataMessageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,14 @@ private void Dispose(bool disposing)
{
this.outputContext.Dispose();
}
else if (this.settings.EnableMessageStreamDisposal)
{
Stream stream = this.message.GetStream();
if (stream != null)
{
stream.Dispose();
}
}
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,5 +184,51 @@ public void WriteUndeclaredUIntValueShouldFail()
Action write = () => writer.WriteValue((UInt16)123);
write.Throws<ODataException>("The value of type 'System.UInt16' could not be converted to a raw string.");
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void CanDisposeStreamWithOrWithoutAnyWriteCalled(bool withWriteCalled)
{
var settings = new ODataMessageWriterSettings();
var model = new EdmModel();

DisposeMemoryStream stream = new DisposeMemoryStream();
Assert.False(stream.DisposeCalled); // Guard;

IODataRequestMessage request = new InMemoryMessage()
{
Stream = stream
};

using (var writer = new ODataMessageWriter(request, settings, model))
{
if (withWriteCalled)
{
writer.WriteProperty(new ODataProperty()
{
Name = "Name",
Value = "abc"
});
}
else
{
// nothing here
}
}

Assert.True(stream.DisposeCalled);
}
}

public class DisposeMemoryStream : MemoryStream
{
public bool DisposeCalled { get; set; }

protected override void Dispose(bool disposing)
{
DisposeCalled = true;
base.Dispose(disposing);
}
}
}

0 comments on commit 3e02e30

Please sign in to comment.