Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
Add IfRange header tests; merge with 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
jbagga committed May 18, 2017
1 parent 356fa9a commit c863a85
Show file tree
Hide file tree
Showing 10 changed files with 545 additions and 21 deletions.
4 changes: 2 additions & 2 deletions src/Microsoft.AspNetCore.Mvc.Core/SerializableError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public SerializableError()
/// <summary>
/// Creates a new instance of <see cref="SerializableError"/>.
/// </summary>
/// <param name="modelState"><see cref="ModelStateEntry"/> containing the validation errors.</param>
/// <param name="modelState"><see cref="ModelStateDictionary"/> containing the validation errors.</param>
public SerializableError(ModelStateDictionary modelState)
: this()
{
Expand Down Expand Up @@ -57,4 +57,4 @@ public SerializableError(ModelStateDictionary modelState)
}
}
}
}
}
92 changes: 90 additions & 2 deletions test/Microsoft.AspNetCore.Mvc.Core.Test/FileContentResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,100 @@ public async Task WriteFileAsync_PreconditionStateShouldProcess_WritesRangeReque
Assert.Equal(expectedString, body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
{
// Arrange
var contentType = "text/plain";
var lastModified = DateTimeOffset.MinValue;
var entityTag = new EntityTagHeaderValue("\"Etag\"");
var byteArray = Encoding.ASCII.GetBytes("Hello World");

var result = new FileContentResult(byteArray, contentType)
{
LastModified = lastModified,
EntityTag = entityTag
};

var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfMatch = new[]
{
new EntityTagHeaderValue("\"Etag\""),
};
requestHeaders.Range = new RangeHeaderValue(0, 4);
requestHeaders.IfRange = new RangeConditionHeaderValue(DateTimeOffset.MinValue);
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
var contentRange = new ContentRangeHeaderValue(0, 4, byteArray.Length);
Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
Assert.Equal(lastModified.ToString("R"), httpResponse.Headers[HeaderNames.LastModified]);
Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
Assert.Equal(5, httpResponse.ContentLength);
Assert.Equal("Hello", body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderInvalid_RangeRequestedNotSatisfiable()
{
// Arrange
var contentType = "text/plain";
var lastModified = DateTimeOffset.MinValue.AddDays(1);
var entityTag = new EntityTagHeaderValue("\"Etag\"");
var byteArray = Encoding.ASCII.GetBytes("Hello World");

var result = new FileContentResult(byteArray, contentType)
{
LastModified = lastModified,
EntityTag = entityTag
};

var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfMatch = new[]
{
new EntityTagHeaderValue("\"Etag\""),
};
requestHeaders.Range = new RangeHeaderValue(0, 4);
requestHeaders.IfRange = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"NotEtag\""));
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
var contentRange = new ContentRangeHeaderValue(byteArray.Length);
Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
Assert.Equal(lastModified.ToString("R"), httpResponse.Headers[HeaderNames.LastModified]);
Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
Assert.Empty(body);
}

[Theory]
[InlineData("0-5")]
[InlineData("bytes = 11-0")]
[InlineData("bytes = 1-4, 5-11")]
public async Task WriteFileAsync__PreconditionStateUnspecified_RangeRequestedNotSatisfiable(string rangeString)
public async Task WriteFileAsync_PreconditionStateUnspecified_RangeRequestedNotSatisfiable(string rangeString)
{
// Arrange
var contentType = "text/plain";
Expand All @@ -163,7 +252,6 @@ public async Task WriteFileAsync__PreconditionStateUnspecified_RangeRequestedNot
};

var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
httpContext.Request.Headers[HeaderNames.Range] = rangeString;
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
Expand Down
18 changes: 9 additions & 9 deletions test/Microsoft.AspNetCore.Mvc.Core.Test/FileResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ public async Task SetsAcceptRangeHeader()
[InlineData("\"Etag\"", "\"NotEtag\"")]
[InlineData("\"Etag\"", null)]
[InlineData(null, "\"NotEtag\"")]
public void ComputeConditionalHeaders_ShouldProcess(string ifMatch, string ifNoneMatch)
public void GetPreconditionState_ShouldProcess(string ifMatch, string ifNoneMatch)
{
var actionContext = new ActionContext();
var httpContext = new DefaultHttpContext();
Expand All @@ -293,21 +293,21 @@ public void ComputeConditionalHeaders_ShouldProcess(string ifMatch, string ifNon
httpRequestHeaders.IfUnmodifiedSince = lastModified;
httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(1);
actionContext.HttpContext = httpContext;
var shouldProcess = FileResultExecutorBase.GetPreconditionState(
var state = FileResultExecutorBase.GetPreconditionState(
actionContext,
httpRequestHeaders,
lastModified,
etag);

// Assert
Assert.Equal(FileResultExecutorBase.PreconditionState.ShouldProcess, shouldProcess);
Assert.Equal(FileResultExecutorBase.PreconditionState.ShouldProcess, state);
}

[Theory]
[InlineData("\"NotEtag\"", null)]
[InlineData("\"Etag\"", "\"Etag\"")]
[InlineData(null, null)]
public void ComputeConditionalHeaders_ShouldNotProcess_PreconditionFailed(string ifMatch, string ifNoneMatch)
public void GetPreconditionState_ShouldNotProcess_PreconditionFailed(string ifMatch, string ifNoneMatch)
{
var actionContext = new ActionContext();
var httpContext = new DefaultHttpContext();
Expand All @@ -329,20 +329,20 @@ public void ComputeConditionalHeaders_ShouldNotProcess_PreconditionFailed(string
httpRequestHeaders.IfUnmodifiedSince = DateTimeOffset.MinValue;
httpRequestHeaders.IfModifiedSince = DateTimeOffset.MinValue.AddDays(2);
actionContext.HttpContext = httpContext;
var shouldProcess = FileResultExecutorBase.GetPreconditionState(
var state = FileResultExecutorBase.GetPreconditionState(
actionContext,
httpRequestHeaders,
lastModified,
etag);

// Assert
Assert.Equal(FileResultExecutorBase.PreconditionState.PreconditionFailed, shouldProcess);
Assert.Equal(FileResultExecutorBase.PreconditionState.PreconditionFailed, state);
}

[Theory]
[InlineData(null, "\"Etag\"")]
[InlineData(null, null)]
public void ComputeConditionalHeaders_ShouldNotProcess_NotModified(string ifMatch, string ifNoneMatch)
public void GetPreconditionState_ShouldNotProcess_NotModified(string ifMatch, string ifNoneMatch)
{
var actionContext = new ActionContext();
var httpContext = new DefaultHttpContext();
Expand All @@ -363,14 +363,14 @@ public void ComputeConditionalHeaders_ShouldNotProcess_NotModified(string ifMatc
};
httpRequestHeaders.IfModifiedSince = lastModified;
actionContext.HttpContext = httpContext;
var shouldProcess = FileResultExecutorBase.GetPreconditionState(
var state = FileResultExecutorBase.GetPreconditionState(
actionContext,
httpRequestHeaders,
lastModified,
etag);

// Assert
Assert.Equal(FileResultExecutorBase.PreconditionState.NotModified, shouldProcess);
Assert.Equal(FileResultExecutorBase.PreconditionState.NotModified, state);
}

private static IServiceCollection CreateServices()
Expand Down
93 changes: 93 additions & 0 deletions test/Microsoft.AspNetCore.Mvc.Core.Test/FileStreamResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,99 @@ public async Task WriteFileAsync_PreconditionStateShouldProcess_WritesRangeReque
Assert.Equal(expectedString, body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
{
// Arrange
var contentType = "text/plain";
var lastModified = DateTimeOffset.MinValue;
var entityTag = new EntityTagHeaderValue("\"Etag\"");
var byteArray = Encoding.ASCII.GetBytes("Hello World");
var readStream = new MemoryStream(byteArray);
readStream.SetLength(11);

var result = new FileStreamResult(readStream, contentType)
{
LastModified = lastModified,
EntityTag = entityTag,
};

var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfMatch = new[]
{
new EntityTagHeaderValue("\"Etag\""),
};
requestHeaders.Range = new RangeHeaderValue(0, 4);
requestHeaders.IfRange = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
var contentRange = new ContentRangeHeaderValue(0, 4, byteArray.Length);
Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
Assert.Equal(lastModified.ToString("R"), httpResponse.Headers[HeaderNames.LastModified]);
Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
Assert.Equal(5, httpResponse.ContentLength);
Assert.Equal("Hello", body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderInvalid_RangeRequestedNotSatisfiable()
{
// Arrange
var contentType = "text/plain";
var lastModified = DateTimeOffset.MinValue.AddDays(1);
var entityTag = new EntityTagHeaderValue("\"Etag\"");
var byteArray = Encoding.ASCII.GetBytes("Hello World");
var readStream = new MemoryStream(byteArray);
readStream.SetLength(11);

var result = new FileStreamResult(readStream, contentType)
{
LastModified = lastModified,
EntityTag = entityTag,
};

var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfMatch = new[]
{
new EntityTagHeaderValue("\"Etag\""),
};
requestHeaders.Range = new RangeHeaderValue(0, 4);
requestHeaders.IfRange = new RangeConditionHeaderValue(DateTimeOffset.MinValue);
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
var contentRange = new ContentRangeHeaderValue(byteArray.Length);
Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
Assert.Equal(lastModified.ToString("R"), httpResponse.Headers[HeaderNames.LastModified]);
Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
Assert.Empty(body);
}

[Theory]
[InlineData("0-5")]
[InlineData("bytes = 11-0")]
Expand Down
62 changes: 62 additions & 0 deletions test/Microsoft.AspNetCore.Mvc.Core.Test/PhysicalFileResultTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,68 @@ public async Task WriteFileAsync_WritesRangeRequested(long? start, long? end, st
Assert.Equal(expectedString, body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderValid_WritesRequestedRange()
{
// Arrange
var path = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
var result = new TestPhysicalFileResult(path, "text/plain");
var entityTag = result.EntityTag = new EntityTagHeaderValue("\"Etag\"");
var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
requestHeaders.Range = new RangeHeaderValue(0, 3);
requestHeaders.IfRange = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"Etag\""));
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
Assert.Equal(StatusCodes.Status206PartialContent, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
var contentRange = new ContentRangeHeaderValue(0, 3, 34);
Assert.Equal(contentRange.ToString(), httpResponse.Headers[HeaderNames.ContentRange]);
Assert.Equal(entityTag.ToString(), httpResponse.Headers[HeaderNames.ETag]);
Assert.Equal(4, httpResponse.ContentLength);
Assert.Equal("File", body);
}

[Fact]
public async Task WriteFileAsync_IfRangeHeaderInvalid_RangeRequestedNotSatisfiable()
{
// Arrange
var path = Path.GetFullPath(Path.Combine("TestFiles", "FilePathResultTestFile.txt"));
var result = new TestPhysicalFileResult(path, "text/plain");
var entityTag = result.EntityTag = new EntityTagHeaderValue("\"Etag\"");
var httpContext = GetHttpContext();
var requestHeaders = httpContext.Request.GetTypedHeaders();
requestHeaders.IfModifiedSince = DateTimeOffset.MinValue;
requestHeaders.Range = new RangeHeaderValue(0, 3);
requestHeaders.IfRange = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"NotEtag\""));
httpContext.Request.Method = HttpMethods.Get;
httpContext.Response.Body = new MemoryStream();
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

// Act
await result.ExecuteResultAsync(actionContext);

// Assert
var httpResponse = actionContext.HttpContext.Response;
httpResponse.Body.Seek(0, SeekOrigin.Begin);
var streamReader = new StreamReader(httpResponse.Body);
var body = streamReader.ReadToEndAsync().Result;
Assert.Equal(StatusCodes.Status416RangeNotSatisfiable, httpResponse.StatusCode);
Assert.Equal("bytes", httpResponse.Headers[HeaderNames.AcceptRanges]);
Assert.Empty(body);
}

[Theory]
[InlineData("0-5")]
[InlineData("bytes = 11-0")]
Expand Down
Loading

0 comments on commit c863a85

Please sign in to comment.