Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,199 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting.DataSets.Types;
using System.Net.Http.Headers;
using System.Text;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
using Xunit.Extensions;
using System.Threading.Tasks;
namespace System.Net.Http.Formatting
{
public class BufferedMediaTypeFormatterTests : MediaTypeFormatterTestBase<MockBufferedMediaTypeFormatter>
{
private const string ExpectedSupportedMediaType = "text/test";
private const string TestData = "Hello World Hello World Hello World Hello World Hello World Hello World";
public static IEnumerable<object[]> ReadAndWriteCorrectCharacterEncoding
{
get { return HttpTestData.ReadAndWriteCorrectCharacterEncoding; }
}
public override IEnumerable<MediaTypeHeaderValue> ExpectedSupportedMediaTypes
{
get { return new List<MediaTypeHeaderValue> { new MediaTypeHeaderValue(ExpectedSupportedMediaType) }; }
}
public override IEnumerable<Encoding> ExpectedSupportedEncodings
{
get { return HttpTestData.StandardEncodings; }
}
public override byte[] ExpectedSampleTypeByteRepresentation
{
get { return ExpectedSupportedEncodings.ElementAt(0).GetBytes("System.Net.Http.Formatting.MediaTypeFormatterTestBase`1+SampleType[System.Net.Http.Formatting.MockBufferedMediaTypeFormatter]"); }
}
[Fact]
public void BufferSize_RoundTrips()
{
Assert.Reflection.IntegerProperty(
new MockBufferedMediaTypeFormatter(),
c => c.BufferSize,
expectedDefaultValue: 16 * 1024,
minLegalValue: 0,
illegalLowerValue: -1,
maxLegalValue: null,
illegalUpperValue: null,
roundTripTestValue: 1024);
}
[Fact]
public void WriteToStreamAsync_WhenTypeParameterIsNull_ThrowsException()
{
BufferedMediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
Assert.ThrowsArgumentNull(
() => formatter.WriteToStreamAsync(null, new object(), new MemoryStream(), null, null), "type");
}
[Fact]
public void WriteToStreamAsync_WhenStreamParameterIsNull_ThrowsException()
{
BufferedMediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
Assert.ThrowsArgumentNull(
() => formatter.WriteToStreamAsync(typeof(object), new object(), null, null, null), "stream");
}
[Fact]
public void ReadFromStreamAsync_WhenTypeParamterIsNull_ThrowsException()
{
BufferedMediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
Assert.ThrowsArgumentNull(() => formatter.ReadFromStreamAsync(null, new MemoryStream(), null, null), "type");
}
[Fact]
public void ReadFromStreamAsync_WhenStreamParamterIsNull_ThrowsException()
{
BufferedMediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
Assert.ThrowsArgumentNull(() => formatter.ReadFromStreamAsync(typeof(object), null, null, null), "stream");
}
[Fact]
public void BufferedWrite()
{
// Arrange. Specifically use the base class with async signatures.
MediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
MemoryStream output = new MemoryStream();
// Act. Call the async signature.
formatter.WriteToStreamAsync(TestData.GetType(), TestData, output, null, null).Wait();
// Assert
byte[] expectedBytes = ExpectedSupportedEncodings.ElementAt(0).GetBytes(TestData);
byte[] actualBytes = output.ToArray();
Assert.Equal(expectedBytes, actualBytes);
}
[Fact]
public void BufferedRead()
{
// Arrange. Specifically use the base class with async signatures.
MediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
byte[] expectedBytes = ExpectedSupportedEncodings.ElementAt(0).GetBytes(TestData);
MemoryStream input = new MemoryStream(expectedBytes);
// Act. Call the async signature.
object result = formatter.ReadFromStreamAsync(TestData.GetType(), input, null, null).Result;
// Assert
Assert.Equal(TestData, result);
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task ReadFromStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
// Arrange
MediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
string mediaType = string.Format("{0}; charset={1}", ExpectedSupportedMediaType, encoding);
// Act & assert
return ReadFromStreamAsync_UsesCorrectCharacterEncodingHelper(formatter, content, content, mediaType, encoding, isDefaultEncoding);
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task WriteToStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
// Arrange
MediaTypeFormatter formatter = new MockBufferedMediaTypeFormatter();
string mediaType = string.Format("{0}; charset={1}", ExpectedSupportedMediaType, encoding);
// Act & assert
return WriteToStreamAsync_UsesCorrectCharacterEncodingHelper(formatter, content, content, mediaType, encoding, isDefaultEncoding);
}
}
public class MockBufferedMediaTypeFormatter : BufferedMediaTypeFormatter
{
private const string SupportedMediaType = "text/test";
public MockBufferedMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue(SupportedMediaType));
// Set default supported character encodings
SupportedEncodings.Add(new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true));
SupportedEncodings.Add(new UnicodeEncoding(bigEndian: false, byteOrderMark: true, throwOnInvalidBytes: true));
}
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
public override object ReadFromStream(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
{
object result = null;
Encoding effectiveEncoding = SelectCharacterEncoding(contentHeaders);
using (StreamReader sReader = new StreamReader(stream, effectiveEncoding))
{
if (type == typeof(BufferedMediaTypeFormatterTests.SampleType))
{
return new BufferedMediaTypeFormatterTests.SampleType { Number = 42 };
}
else
{
result = sReader.ReadToEnd();
}
}
return result;
}
public override void WriteToStream(Type type, object value, Stream stream, HttpContentHeaders contentHeaders)
{
Encoding effectiveEncoding = SelectCharacterEncoding(contentHeaders);
using (StreamWriter sWriter = new StreamWriter(stream, effectiveEncoding))
{
if (value != null)
{
sWriter.Write(value.ToString());
}
else
{
sWriter.Write("null!");
}
}
}
}
}

View File

@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http.Headers;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class ContentNegotiationResultTest
{
private readonly MediaTypeFormatter _formatter = new Mock<MediaTypeFormatter>().Object;
private readonly MediaTypeHeaderValue _mediaType = new MediaTypeHeaderValue("app/json");
[Fact]
public void Constructor_WhenFormatterParameterIsNull_Throws()
{
Assert.ThrowsArgumentNull(() => new ContentNegotiationResult(formatter: null, mediaType: null), "formatter");
}
[Fact]
public void MediaTypeProperty()
{
Assert.Reflection.Property(new ContentNegotiationResult(_formatter, _mediaType),
nr => nr.MediaType, _mediaType, allowNull: true, roundTripTestValue: new MediaTypeHeaderValue("foo/bar"));
}
[Fact]
public void FormatterProperty()
{
Assert.Reflection.Property(new ContentNegotiationResult(_formatter, _mediaType),
nr => nr.Formatter, _formatter, allowNull: false, roundTripTestValue: new JsonMediaTypeFormatter());
}
}
}

View File

@ -0,0 +1,239 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting.DataSets.Types;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class DataContractJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public DataContractJsonMediaTypeFormatter()
{
UseDataContractJsonSerializer = true;
}
}
public class DataContractJsonMediaTypeFormatterTests : MediaTypeFormatterTestBase<DataContractJsonMediaTypeFormatter>
{
public static IEnumerable<object[]> ReadAndWriteCorrectCharacterEncoding
{
get { return HttpTestData.ReadAndWriteCorrectCharacterEncoding; }
}
public static IEnumerable<TestData> ValueAndRefTypeTestDataCollectionExceptULong
{
get
{
return CommonUnitTestDataSets.ValueAndRefTypeTestDataCollection.Except(new[] { CommonUnitTestDataSets.Ulongs });
}
}
public override IEnumerable<MediaTypeHeaderValue> ExpectedSupportedMediaTypes
{
get { return HttpTestData.StandardJsonMediaTypes; }
}
public override IEnumerable<Encoding> ExpectedSupportedEncodings
{
get { return HttpTestData.StandardEncodings; }
}
public override byte[] ExpectedSampleTypeByteRepresentation
{
get { return ExpectedSupportedEncodings.ElementAt(0).GetBytes("{\"Number\":42}"); }
}
[Fact]
public void DefaultMediaType_ReturnsApplicationJson()
{
MediaTypeHeaderValue mediaType = DataContractJsonMediaTypeFormatter.DefaultMediaType;
Assert.NotNull(mediaType);
Assert.Equal("application/json", mediaType.MediaType);
}
[Fact]
public void Indent_RoundTrips()
{
Assert.Reflection.BooleanProperty(
new XmlMediaTypeFormatter(),
c => c.Indent,
expectedDefaultValue: false);
}
[Fact]
public void MaxDepth_RoundTrips()
{
Assert.Reflection.IntegerProperty(
new DataContractJsonMediaTypeFormatter(),
c => c.MaxDepth,
expectedDefaultValue: 256,
minLegalValue: 1,
illegalLowerValue: 0,
maxLegalValue: null,
illegalUpperValue: null,
roundTripTestValue: 256);
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
public void CanReadType_ReturnsExpectedValues(Type variationType, object testData)
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
bool isSerializable = IsTypeSerializableWithJsonSerializer(variationType, testData);
bool canSupport = formatter.CanReadTypeProxy(variationType);
// If we don't agree, we assert only if the DCJ serializer says it cannot support something we think it should
Assert.False(isSerializable != canSupport && isSerializable, String.Format("CanReadType returned wrong value for '{0}'.", variationType));
// Ask a 2nd time to probe whether the cached result is treated the same
canSupport = formatter.CanReadTypeProxy(variationType);
Assert.False(isSerializable != canSupport && isSerializable, String.Format("2nd CanReadType returned wrong value for '{0}'.", variationType));
}
[Theory]
[InlineData(typeof(IQueryable<string>))]
[InlineData(typeof(IEnumerable<string>))]
public void UseJsonFormatterWithNull(Type type)
{
JsonMediaTypeFormatter xmlFormatter = new DataContractJsonMediaTypeFormatter();
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Task.Succeeds(xmlFormatter.WriteToStreamAsync(type, null, memoryStream, contentHeaders, transportContext: null));
memoryStream.Position = 0;
string serializedString = new StreamReader(memoryStream).ReadToEnd();
Assert.True(serializedString.Contains("null"), "Using Json formatter to serialize null should emit 'null'.");
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
[TestDataSet(typeof(JsonMediaTypeFormatterTests), "ValueAndRefTypeTestDataCollectionExceptULong")]
public void ReadFromStreamAsync_RoundTripsWriteToStreamAsync(Type variationType, object testData)
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
bool canSerialize = IsTypeSerializableWithJsonSerializer(variationType, testData) && Assert.Http.CanRoundTrip(variationType);
if (canSerialize)
{
object readObj = null;
Assert.Stream.WriteAndRead(
stream =>
{
Assert.Task.Succeeds(formatter.WriteToStreamAsync(variationType, testData, stream, contentHeaders, transportContext: null));
contentHeaders.ContentLength = stream.Length;
},
stream => readObj = Assert.Task.SucceedsWithResult(formatter.ReadFromStreamAsync(variationType, stream, contentHeaders, null)));
Assert.Equal(testData, readObj);
}
}
[Fact]
public void UseDataContractJsonSerializer_True()
{
DataContractJsonMediaTypeFormatter jsonFormatter = new DataContractJsonMediaTypeFormatter();
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Task.Succeeds(jsonFormatter.WriteToStreamAsync(typeof(XmlMediaTypeFormatterTests.SampleType), new XmlMediaTypeFormatterTests.SampleType(), memoryStream, contentHeaders, transportContext: null));
memoryStream.Position = 0;
string serializedString = new StreamReader(memoryStream).ReadToEnd();
Assert.False(serializedString.Contains("\r\n"), "Using DCJS should emit data without indentation by default.");
}
[Fact]
[Trait("Description", "UseDataContractJsonSerializer property with Indent throws when set to true.")]
public void UseDataContractJsonSerializer_True_Indent_Throws()
{
DataContractJsonMediaTypeFormatter jsonFormatter = new DataContractJsonMediaTypeFormatter { Indent = true };
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Throws<NotSupportedException>(
() => jsonFormatter.WriteToStreamAsync(typeof(XmlMediaTypeFormatterTests.SampleType),
new XmlMediaTypeFormatterTests.SampleType(),
memoryStream, contentHeaders, transportContext: null));
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task ReadFromStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
if (!isDefaultEncoding)
{
// XmlDictionaryReader/Writer only supports utf-8 and 16
return TaskHelpers.Completed();
}
// Arrange
DataContractJsonMediaTypeFormatter formatter = new DataContractJsonMediaTypeFormatter();
string formattedContent = "\"" + content + "\"";
string mediaType = string.Format("application/json; charset={0}", encoding);
// Act & assert
return ReadContentUsingCorrectCharacterEncodingHelper(
formatter, content, formattedContent, mediaType, encoding, isDefaultEncoding);
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task WriteToStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
// DataContractJsonSerializer does not honor the value of byteOrderMark in the UnicodeEncoding ctor.
// It doesn't include the BOM when byteOrderMark is set to true.
if (!isDefaultEncoding || encoding != "utf-8")
{
// XmlDictionaryReader/Writer only supports utf-8 and 16
return TaskHelpers.Completed();
}
// Arrange
DataContractJsonMediaTypeFormatter formatter = new DataContractJsonMediaTypeFormatter();
string formattedContent = "\"" + content + "\"";
string mediaType = string.Format("application/json; charset={0}", encoding);
// Act & assert
return WriteContentUsingCorrectCharacterEncodingHelper(
formatter, content, formattedContent, mediaType, encoding, isDefaultEncoding);
}
public class TestJsonMediaTypeFormatter : DataContractJsonMediaTypeFormatter
{
public bool CanReadTypeProxy(Type type)
{
return CanReadType(type);
}
public bool CanWriteTypeProxy(Type type)
{
return CanWriteType(type);
}
}
private bool IsTypeSerializableWithJsonSerializer(Type type, object obj)
{
try
{
new DataContractJsonSerializer(type);
if (obj != null && obj.GetType() != type)
{
new DataContractJsonSerializer(obj.GetType());
}
}
catch
{
return false;
}
return !Assert.Http.IsKnownUnserializable(type, obj, (t) => typeof(INotJsonSerializable).IsAssignableFrom(t));
}
}
}

View File

@ -0,0 +1,257 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting.Mocks;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.TestCommon;
using Newtonsoft.Json.Linq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class DefaultContentNegotiatorTests
{
private readonly DefaultContentNegotiator _negotiator = new DefaultContentNegotiator();
private readonly HttpRequestMessage _request = new HttpRequestMessage();
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(DefaultContentNegotiator), TypeAssert.TypeProperties.IsPublicVisibleClass);
}
[Fact]
public void Negotiate_WhenTypeParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(null, _request, Enumerable.Empty<MediaTypeFormatter>()), "type");
}
[Fact]
public void Negotiate_WhenRequestParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(typeof(string), null, Enumerable.Empty<MediaTypeFormatter>()), "request");
}
[Fact]
public void Negotiate_WhenFormattersParameterIsNull_ThrowsException()
{
Assert.ThrowsArgumentNull(() => _negotiator.Negotiate(typeof(string), _request, null), "formatters");
}
[Fact]
public void Negotiate_ForEmptyFormatterCollection_ReturnsNull()
{
var result = _negotiator.Negotiate(typeof(string), _request, Enumerable.Empty<MediaTypeFormatter>());
Assert.Null(result);
}
[Fact]
public void MediaTypeMappingTakesPrecedenceOverAcceptHeader()
{
// Prepare the request message
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
_request.Headers.Add("Browser", "IE");
_request.Headers.Add("Cookie", "ABC");
// Prepare the formatters
List<MediaTypeFormatter> formatters = new List<MediaTypeFormatter>();
formatters.Add(new JsonMediaTypeFormatter());
formatters.Add(new XmlMediaTypeFormatter());
PlainTextFormatter frmtr = new PlainTextFormatter();
frmtr.SupportedMediaTypes.Clear();
frmtr.MediaTypeMappings.Clear();
frmtr.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
frmtr.MediaTypeMappings.Add(new MyMediaTypeMapping(new MediaTypeHeaderValue(("application/xml"))));
formatters.Add(frmtr);
// Act
var result = _negotiator.Negotiate(typeof(string), _request, formatters);
// Assert
Assert.NotNull(result);
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<PlainTextFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_ForRequestReturnsFirstMatchingFormatter()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/myMediaType");
MediaTypeFormatter formatter1 = new MockMediaTypeFormatter()
{
CanWriteTypeCallback = (Type t) => false
};
MediaTypeFormatter formatter2 = new MockMediaTypeFormatter()
{
CanWriteTypeCallback = (Type t) => true
};
formatter2.SupportedMediaTypes.Add(mediaType);
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(
new MediaTypeFormatter[]
{
formatter1,
formatter2
});
_request.Content = new StringContent("test", Encoding.Default, mediaType.MediaType);
var result = _negotiator.Negotiate(typeof(string), _request, collection);
Assert.Same(formatter2, result.Formatter);
Assert.MediaType.AreEqual(mediaType, result.MediaType, "Expected the formatter's media type to be returned.");
}
[Fact]
public void Negotiate_SelectsJsonAsDefaultFormatter()
{
// Arrange
_request.Content = new StringContent("test");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
Assert.Equal(MediaTypeConstants.ApplicationJsonMediaType.MediaType, result.MediaType.MediaType);
}
[Fact]
public void Negotiate_SelectsXmlFormatter_ForXhrRequestThatAcceptsXml()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<XmlMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXhrRequestThatDoesNotSpecifyAcceptHeaders()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_RespectsFormatterOrdering_ForXhrRequestThatDoesNotSpecifyAcceptHeaders()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection(new MediaTypeFormatter[]
{
new XmlMediaTypeFormatter(),
new JsonMediaTypeFormatter(),
new FormUrlEncodedMediaTypeFormatter()
});
// Act
var result = _negotiator.Negotiate(typeof(string), _request, formatters);
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXHRAndJsonValueResponse()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
// Act
var result = _negotiator.Negotiate(typeof(JToken), _request, new MediaTypeFormatterCollection());
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_SelectsJsonFormatter_ForXHRAndMatchAllAcceptHeader()
{
// Accept
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
_request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/json", result.MediaType.MediaType);
Assert.IsType<JsonMediaTypeFormatter>(result.Formatter);
}
[Fact]
public void Negotiate_UsesRequestedFormatterForXHRAndMatchAllPlusOtherAcceptHeader()
{
// Arrange
_request.Content = new StringContent("test");
_request.Headers.Add("x-requested-with", "XMLHttpRequest");
_request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); // XHR header sent by Firefox 3b5
// Act
var result = _negotiator.Negotiate(typeof(string), _request, new MediaTypeFormatterCollection());
// Assert
Assert.Equal("application/xml", result.MediaType.MediaType);
Assert.IsType<XmlMediaTypeFormatter>(result.Formatter);
}
private class PlainTextFormatter : MediaTypeFormatter
{
public override bool CanReadType(Type type)
{
return true;
}
public override bool CanWriteType(Type type)
{
return true;
}
}
private class MyMediaTypeMapping : MediaTypeMapping
{
public MyMediaTypeMapping(MediaTypeHeaderValue mediaType)
: base(mediaType)
{
}
public override double TryMatchMediaType(HttpRequestMessage request)
{
if (request.Headers.Contains("Cookie"))
{
return 1.0;
}
else
{
return 0;
}
}
}
}
}

View File

@ -0,0 +1,150 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class FormDataCollectionTests
{
[Fact]
public void CreateFromUri()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com/?x=1&y=2"));
Assert.Equal("1", form.Get("x"));
Assert.Equal("2", form.Get("y"));
}
[Fact]
public void CreateFromEmptyUri()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com"));
Assert.Empty(form);
}
[Fact]
public void UriConstructorThrowsNull()
{
Assert.Throws<ArgumentNullException>(() => new FormDataCollection((Uri)null));
}
[Fact]
public void CreateFromEmptyString()
{
FormDataCollection form = new FormDataCollection("");
Assert.Empty(form);
}
[Fact]
public void CreateFromNullString()
{
FormDataCollection form = new FormDataCollection((string) null);
Assert.Empty(form);
}
[Fact]
public void PairConstructorThrowsNull()
{
var arg = (IEnumerable<KeyValuePair<string, string>>)null;
Assert.Throws<ArgumentNullException>(() => new FormDataCollection(arg));
}
[Fact]
public void CreateFromPairs()
{
Dictionary<string, string> pairs = new Dictionary<string,string>
{
{ "x", "1"},
{ "y" , "2"}
};
var form = new FormDataCollection(pairs);
Assert.Equal("1", form.Get("x"));
Assert.Equal("2", form.Get("y"));
}
[Fact]
public void Enumeration()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com/?x=1&y=2"));
// Enumeration should be ordered
String s = "";
foreach (KeyValuePair<string, string> kv in form)
{
s += string.Format("{0}={1};", kv.Key, kv.Value);
}
Assert.Equal("x=1;y=2;", s);
}
[Fact]
public void GetValues()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com/?x=1&x=2&x=3"));
Assert.Equal(new string [] { "1", "2", "3"}, form.GetValues("x"));
}
[Fact]
public void CaseInSensitive()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com/?x=1&Y=2"));
NameValueCollection nvc = form.ReadAsNameValueCollection();
Assert.Equal(2, nvc.Count);
Assert.Equal("1", nvc.Get("x"));
Assert.Equal("2", nvc.Get("y"));
}
[Fact]
public void ToNameValueCollection()
{
FormDataCollection form = new FormDataCollection(new Uri("http://foo.com/?x=1a&y=2&x=1b&=ValueOnly&KeyOnly"));
NameValueCollection nvc = form.ReadAsNameValueCollection();
// y=2
// x=1a;x=1b
// =ValueOnly
// KeyOnly
Assert.Equal(4, nvc.Count);
Assert.Equal(new string[] { "1a", "1b"}, nvc.GetValues("x"));
Assert.Equal("1a,1b", nvc.Get("x"));
Assert.Equal("2", nvc.Get("y"));
Assert.Equal("", nvc.Get("KeyOnly"));
Assert.Equal("ValueOnly", nvc.Get(""));
}
const string SPACE = " "; // single literal space character
[Theory]
[InlineData("x=abc", "abc")] // normal
[InlineData("x", "")] // key only
[InlineData("x=", "")] // rhs only
[InlineData("x=%20", SPACE)] // escaped space
[InlineData("x=" + SPACE, SPACE)] // literal space
[InlineData("x=+", SPACE)] //
[InlineData("x=null", "null")] // null literal, not escaped
[InlineData("x=undefined", "undefined")] // undefined literal, not escaped
[InlineData("x=\"null\"", "\"null\"")] // quoted null, preserved as is
public void Whitespace(string queryString, string expected)
{
FormDataCollection fd = new FormDataCollection(queryString);
Assert.Equal(1, fd.Count());
Assert.Equal(expected, fd.Get("x"));
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.TestCommon;
using Newtonsoft.Json.Linq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class FormUrlEncodedJsonTests
{
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(FormUrlEncodedJson), TypeAssert.TypeProperties.IsClass | TypeAssert.TypeProperties.IsStatic);
}
[Fact]
public void ParseThrowsOnNull()
{
Assert.ThrowsArgumentNull(() => FormUrlEncodedJson.Parse(null), null);
}
[Fact]
public void ParseThrowsInvalidMaxDepth()
{
Assert.ThrowsArgumentGreaterThan(() => FormUrlEncodedJson.Parse(CreateQuery(), -1), "maxDepth", "0", -1);
Assert.ThrowsArgumentGreaterThan(() => FormUrlEncodedJson.Parse(CreateQuery(), 0), "maxDepth", "0", 0);
}
[Fact]
public void ParseThrowsMaxDepthExceeded()
{
// Depth of 'a[b]=1' is 3
IEnumerable<KeyValuePair<string, string>> query = CreateQuery(new KeyValuePair<string, string>("a[b]", "1"));
Assert.ThrowsArgument(() => { FormUrlEncodedJson.Parse(query, 2); }, null);
// This should succeed
Assert.NotNull(FormUrlEncodedJson.Parse(query, 3));
}
[Fact]
public void TryParseThrowsOnNull()
{
JObject value;
Assert.ThrowsArgumentNull(() => FormUrlEncodedJson.TryParse(null, out value), null);
}
[Fact]
public void TryParseThrowsInvalidMaxDepth()
{
JObject value;
Assert.ThrowsArgumentGreaterThan(() => FormUrlEncodedJson.TryParse(CreateQuery(), -1, out value), "maxDepth", "0", -1);
Assert.ThrowsArgumentGreaterThan(() => FormUrlEncodedJson.TryParse(CreateQuery(), 0, out value), "maxDepth", "0", 0);
}
[Fact]
public void TryParseReturnsFalseMaxDepthExceeded()
{
JObject value;
// Depth of 'a[b]=1' is 3
IEnumerable<KeyValuePair<string, string>> query = CreateQuery(new KeyValuePair<string, string>("a[b]", "1"));
Assert.False(FormUrlEncodedJson.TryParse(query, 2, out value), "Parse should have failed due to too high depth.");
// This should succeed
Assert.True(FormUrlEncodedJson.TryParse(query, 3, out value), "Expected non-null JsonObject instance");
Assert.NotNull(value);
}
private static IEnumerable<KeyValuePair<string, string>> CreateQuery(params KeyValuePair<string, string>[] namevaluepairs)
{
return new List<KeyValuePair<string, string>>(namevaluepairs);
}
}
}

View File

@ -0,0 +1,200 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.IO;
using System.Net.Http.Formatting.DataSets;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.TestCommon;
using Newtonsoft.Json.Linq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class FormUrlEncodedMediaTypeFormatterTests
{
private const int MinBufferSize = 256;
private const int DefaultBufferSize = 32 * 1024;
private const int DefaultMaxDepth = 1024;
[Fact]
[Trait("Description", "FormUrlEncodedMediaTypeFormatter is public, concrete, and unsealed.")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(FormUrlEncodedMediaTypeFormatter), TypeAssert.TypeProperties.IsPublicVisibleClass);
}
[Theory]
[TestDataSet(typeof(HttpUnitTestDataSets), "StandardFormUrlEncodedMediaTypes")]
[Trait("Description", "FormUrlEncodedMediaTypeFormatter() constructor sets standard form URL encoded media types in SupportedMediaTypes.")]
public void Constructor(MediaTypeHeaderValue mediaType)
{
FormUrlEncodedMediaTypeFormatter formatter = new FormUrlEncodedMediaTypeFormatter();
Assert.True(formatter.SupportedMediaTypes.Contains(mediaType), String.Format("SupportedMediaTypes should have included {0}.", mediaType.ToString()));
}
[Fact]
[Trait("Description", "DefaultMediaType property returns application/x-www-form-urlencoded.")]
public void DefaultMediaTypeReturnsApplicationJson()
{
MediaTypeHeaderValue mediaType = FormUrlEncodedMediaTypeFormatter.DefaultMediaType;
Assert.NotNull(mediaType);
Assert.Equal("application/x-www-form-urlencoded", mediaType.MediaType);
}
[Fact]
public void ReadBufferSize_RoundTrips()
{
Assert.Reflection.IntegerProperty(
new FormUrlEncodedMediaTypeFormatter(),
c => c.ReadBufferSize,
expectedDefaultValue: 32 * 1024,
minLegalValue: 256,
illegalLowerValue: 255,
maxLegalValue: null,
illegalUpperValue: null,
roundTripTestValue: 1024);
}
[Fact]
[Trait("Description", "MaxDepth return correct value.")]
public void MaxDepthReturnsCorrectValue()
{
Assert.Reflection.IntegerProperty(
new FormUrlEncodedMediaTypeFormatter(),
f => f.MaxDepth,
expectedDefaultValue: 256,
minLegalValue: 1,
illegalLowerValue: 0,
maxLegalValue: null,
illegalUpperValue: null,
roundTripTestValue: 10);
}
[Fact]
[Trait("Description", "Deeply nested objects throws.")]
public void ReadDeeplyNestedObjectThrows()
{
FormUrlEncodedMediaTypeFormatter formatter = new FormUrlEncodedMediaTypeFormatter() { MaxDepth = 100 };
StringContent content = new StringContent(GetDeeplyNestedObject(125));
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
Assert.ThrowsArgument(
() => formatter.ReadFromStreamAsync(typeof(JToken), content.ReadAsStreamAsync().Result, content.Headers, null).Result,
null);
}
[Fact]
[Trait("Description", "Read DeeplyNestedobject WithBigDepthQuota should work")]
public void ReadDeeplyNestedObjectWithBigDepthQuotaWorks()
{
FormUrlEncodedMediaTypeFormatter formatter = new FormUrlEncodedMediaTypeFormatter() { MaxDepth = 150 };
StringContent content = new StringContent(GetDeeplyNestedObject(125));
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
JToken result = (JToken)formatter.ReadFromStreamAsync(typeof(JToken), content.ReadAsStreamAsync().Result, content.Headers, null).Result;
Assert.NotNull(result);
}
static string GetDeeplyNestedObject(int depth)
{
StringBuilder sb = new StringBuilder("a");
for (int i = 0; i < depth; i++)
{
sb.Append("[a]");
}
sb.Append("=1");
return sb.ToString();
}
[Fact]
[Trait("Description", "CanReadType() throws on null.")]
public void CanReadTypeThrowsOnNull()
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.ThrowsArgumentNull(() => { formatter.CanReadType(null); }, "type");
}
[Theory]
[InlineData(typeof(FormDataCollection))]
[InlineData(typeof(JToken))]
public void CanReadTypeTrue(Type type)
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.True(formatter.CanReadType(type));
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
[Trait("Description", "CanReadType(Type) returns false.")]
public void CanReadTypeReturnsFalse(Type variationType, object testData)
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.False(formatter.CanReadType(variationType));
// Ask a 2nd time to probe whether the cached result is treated the same
Assert.False(formatter.CanReadType(variationType));
}
[Fact]
[Trait("Description", "CanWriteType(Type) throws on null.")]
public void CanWriteTypeThrowsOnNull()
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.ThrowsArgumentNull(() => { formatter.CanWriteType(null); }, "type");
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
[Trait("Description", "CanWriteType() returns false.")]
public void CanWriteTypeReturnsFalse(Type variationType, object testData)
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.False(formatter.CanWriteType(variationType), "formatter should have returned false.");
// Ask a 2nd time to probe whether the cached result is treated the same
Assert.False(formatter.CanWriteType(variationType), "formatter should have returned false on 2nd try as well.");
}
[Fact]
[Trait("Description", "ReadFromStreamAsync() throws on null.")]
public void ReadFromStreamThrowsOnNull()
{
TestFormUrlEncodedMediaTypeFormatter formatter = new TestFormUrlEncodedMediaTypeFormatter();
Assert.ThrowsArgumentNull(() => { formatter.ReadFromStreamAsync(null, Stream.Null, null, null); }, "type");
Assert.ThrowsArgumentNull(() => { formatter.ReadFromStreamAsync(typeof(object), null, null, null); }, "stream");
}
[Fact]
[Trait("Description", "WriteToStreamAsync() throws not implemented.")]
public void WriteToStreamAsyncThrowsNotImplemented()
{
FormUrlEncodedMediaTypeFormatter formatter = new FormUrlEncodedMediaTypeFormatter();
Assert.Throws<NotSupportedException>(
() => formatter.WriteToStreamAsync(typeof(object), new object(), Stream.Null, null, null),
"The media type formatter of type 'FormUrlEncodedMediaTypeFormatter' does not support writing because it does not implement the WriteToStreamAsync method.");
}
public class TestFormUrlEncodedMediaTypeFormatter : FormUrlEncodedMediaTypeFormatter
{
public new bool CanReadType(Type type)
{
return base.CanReadType(type);
}
public new bool CanWriteType(Type type)
{
return base.CanWriteType(type);
}
}
}
}

View File

@ -0,0 +1,293 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Formatting.DataSets.Types;
using System.Net.Http.Headers;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TestCommon;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class JsonMediaTypeFormatterTests : MediaTypeFormatterTestBase<JsonMediaTypeFormatter>
{
public static IEnumerable<object[]> ReadAndWriteCorrectCharacterEncoding
{
get { return HttpTestData.ReadAndWriteCorrectCharacterEncoding; }
}
public static List<Type> JTokenTypes
{
get
{
return new List<Type>
{
typeof(JToken),
typeof(JValue),
typeof(JArray),
typeof(JObject)
};
}
}
public static IEnumerable<TestData> ValueAndRefTypeTestDataCollectionExceptULong
{
get
{
return CommonUnitTestDataSets.ValueAndRefTypeTestDataCollection.Except(new[] { CommonUnitTestDataSets.Ulongs });
}
}
public override IEnumerable<MediaTypeHeaderValue> ExpectedSupportedMediaTypes
{
get { return HttpTestData.StandardJsonMediaTypes; }
}
public override IEnumerable<Encoding> ExpectedSupportedEncodings
{
get { return HttpTestData.StandardEncodings; }
}
public override byte[] ExpectedSampleTypeByteRepresentation
{
get { return ExpectedSupportedEncodings.ElementAt(0).GetBytes("{\"Number\":42}"); }
}
[Fact]
public void DefaultMediaType_ReturnsApplicationJson()
{
MediaTypeHeaderValue mediaType = JsonMediaTypeFormatter.DefaultMediaType;
Assert.NotNull(mediaType);
Assert.Equal("application/json", mediaType.MediaType);
}
[Fact]
public void Indent_RoundTrips()
{
Assert.Reflection.BooleanProperty(
new XmlMediaTypeFormatter(),
c => c.Indent,
expectedDefaultValue: false);
}
[Fact]
public void MaxDepth_RoundTrips()
{
Assert.Reflection.IntegerProperty(
new JsonMediaTypeFormatter(),
c => c.MaxDepth,
expectedDefaultValue: 256,
minLegalValue: 1,
illegalLowerValue: 0,
maxLegalValue: null,
illegalUpperValue: null,
roundTripTestValue: 256);
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
public void CanReadType_ReturnsExpectedValues(Type variationType, object testData)
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
bool isSerializable = IsTypeSerializableWithJsonSerializer(variationType, testData);
bool canSupport = formatter.CanReadTypeProxy(variationType);
// If we don't agree, we assert only if the DCJ serializer says it cannot support something we think it should
Assert.False(isSerializable != canSupport && isSerializable, String.Format("CanReadType returned wrong value for '{0}'.", variationType));
// Ask a 2nd time to probe whether the cached result is treated the same
canSupport = formatter.CanReadTypeProxy(variationType);
Assert.False(isSerializable != canSupport && isSerializable, String.Format("2nd CanReadType returned wrong value for '{0}'.", variationType));
}
[Fact]
public void CanReadType_ReturnsTrueOnJtoken()
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
foreach (Type type in JTokenTypes)
{
Assert.True(formatter.CanReadTypeProxy(type), "formatter should have returned true.");
}
}
[Fact]
public void CanWriteType_ReturnsTrueOnJtoken()
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
foreach (Type type in JTokenTypes)
{
Assert.True(formatter.CanWriteTypeProxy(type), "formatter should have returned false.");
}
}
[Fact]
public void ReadFromStreamAsync_RoundTripsJToken()
{
string beforeMessage = "Hello World";
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
JToken before = beforeMessage;
MemoryStream memStream = new MemoryStream();
JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(memStream));
before.WriteTo(jsonWriter);
jsonWriter.Flush();
memStream.Position = 0;
JToken after = Assert.Task.SucceedsWithResult<object>(formatter.ReadFromStreamAsync(typeof(JToken), memStream, null, null)) as JToken;
Assert.NotNull(after);
string afterMessage = after.ToObject<string>();
Assert.Equal(beforeMessage, afterMessage);
}
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")]
[TestDataSet(typeof(JsonMediaTypeFormatterTests), "ValueAndRefTypeTestDataCollectionExceptULong")]
public void ReadFromStreamAsync_RoundTripsWriteToStreamAsync(Type variationType, object testData)
{
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
bool canSerialize = IsTypeSerializableWithJsonSerializer(variationType, testData) && Assert.Http.CanRoundTrip(variationType);
if (canSerialize)
{
object readObj = null;
Assert.Stream.WriteAndRead(
stream =>
{
Assert.Task.Succeeds(formatter.WriteToStreamAsync(variationType, testData, stream, contentHeaders, transportContext: null));
contentHeaders.ContentLength = stream.Length;
},
stream => readObj = Assert.Task.SucceedsWithResult(formatter.ReadFromStreamAsync(variationType, stream, contentHeaders, null)));
Assert.Equal(testData, readObj);
}
}
[Fact]
[Trait("Description", "UseDataContractJsonSerializer property works when set to false.")]
public void UseDataContractJsonSerializer_False()
{
JsonMediaTypeFormatter xmlFormatter = new JsonMediaTypeFormatter { UseDataContractJsonSerializer = false };
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Task.Succeeds(xmlFormatter.WriteToStreamAsync(typeof(XmlMediaTypeFormatterTests.SampleType), new XmlMediaTypeFormatterTests.SampleType(), memoryStream, contentHeaders, transportContext: null));
memoryStream.Position = 0;
string serializedString = new StreamReader(memoryStream).ReadToEnd();
//Assert.True(serializedString.Contains("DataContractSampleType"),
// "SampleType should be serialized with data contract name DataContractSampleType because UseDataContractJsonSerializer is set to true.");
Assert.False(serializedString.Contains("\r\n"), "Using JsonSerializer should emit data without indentation by default.");
}
[Fact]
[Trait("Description", "UseDataContractJsonSerializer property with Indent works when set to false.")]
public void UseDataContractJsonSerializer_False_Indent()
{
JsonMediaTypeFormatter xmlFormatter = new JsonMediaTypeFormatter { UseDataContractJsonSerializer = false, Indent = true };
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Task.Succeeds(xmlFormatter.WriteToStreamAsync(typeof(XmlMediaTypeFormatterTests.SampleType), new XmlMediaTypeFormatterTests.SampleType(), memoryStream, contentHeaders, transportContext: null));
memoryStream.Position = 0;
string serializedString = new StreamReader(memoryStream).ReadToEnd();
Console.WriteLine(serializedString);
Assert.True(serializedString.Contains("\r\n"), "Using JsonSerializer with Indent set to true should emit data with indentation.");
}
[Theory]
[InlineData(typeof(IQueryable<string>))]
[InlineData(typeof(IEnumerable<string>))]
public void UseJsonFormatterWithNull(Type type)
{
JsonMediaTypeFormatter xmlFormatter = new JsonMediaTypeFormatter { UseDataContractJsonSerializer = false};
MemoryStream memoryStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
Assert.Task.Succeeds(xmlFormatter.WriteToStreamAsync(type, null, memoryStream, contentHeaders, transportContext: null));
memoryStream.Position = 0;
string serializedString = new StreamReader(memoryStream).ReadToEnd();
Assert.True(serializedString.Contains("null"), "Using Json formatter to serialize null should emit 'null'.");
}
[Fact]
[Trait("Description", "OnWriteToStreamAsync() roundtrips JsonValue.")]
public void WriteToStreamAsync_RoundTripsJToken()
{
string beforeMessage = "Hello World";
TestJsonMediaTypeFormatter formatter = new TestJsonMediaTypeFormatter();
JToken before = new JValue(beforeMessage);
MemoryStream memStream = new MemoryStream();
Assert.Task.Succeeds(formatter.WriteToStreamAsync(typeof(JToken), before, memStream, null, null));
memStream.Position = 0;
JToken after = JToken.Load(new JsonTextReader(new StreamReader(memStream)));
string afterMessage = after.ToObject<string>();
Assert.Equal(beforeMessage, afterMessage);
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task ReadFromStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
// Arrange
JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
string formattedContent = "\"" + content + "\"";
string mediaType = string.Format("application/json; charset={0}", encoding);
// Act & assert
return ReadContentUsingCorrectCharacterEncodingHelper(
formatter, content, formattedContent, mediaType, encoding, isDefaultEncoding);
}
[Theory]
[PropertyData("ReadAndWriteCorrectCharacterEncoding")]
public override Task WriteToStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding)
{
// Arrange
JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
string formattedContent = "\"" + content + "\"";
string mediaType = string.Format("application/json; charset={0}", encoding);
// Act & assert
return WriteContentUsingCorrectCharacterEncodingHelper(
formatter, content, formattedContent, mediaType, encoding, isDefaultEncoding);
}
public class TestJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public bool CanReadTypeProxy(Type type)
{
return CanReadType(type);
}
public bool CanWriteTypeProxy(Type type)
{
return CanWriteType(type);
}
}
private bool IsTypeSerializableWithJsonSerializer(Type type, object obj)
{
try
{
new DataContractJsonSerializer(type);
if (obj != null && obj.GetType() != type)
{
new DataContractJsonSerializer(obj.GetType());
}
}
catch
{
return false;
}
return !Assert.Http.IsKnownUnserializable(type, obj, (t) => typeof(INotJsonSerializable).IsAssignableFrom(t));
}
}
}

View File

@ -0,0 +1,157 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http.Formatting.DataSets;
using System.Net.Http.Headers;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class MediaRangeMappingTests
{
[Fact]
[Trait("Description", "MediaRangeMappring is public, and concrete.")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(
typeof(MediaRangeMapping),
TypeAssert.TypeProperties.IsPublicVisibleClass,
typeof(MediaTypeMapping));
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeValues",
typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")]
[Trait("Description", "MediaRangeMapping(MediaTypeHeaderValue, MediaTypeHeaderValue) sets public properties.")]
public void Constructor(MediaTypeHeaderValue mediaRange, MediaTypeHeaderValue mediaType)
{
MediaRangeMapping mapping = new MediaRangeMapping(mediaRange, mediaType);
Assert.MediaType.AreEqual(mediaRange, mapping.MediaRange, "MediaRange failed to set.");
Assert.MediaType.AreEqual(mediaType, mapping.MediaType, "MediaType failed to set.");
}
[Theory]
[TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")]
[Trait("Description", "MediaRangeMapping(MediaTypeHeaderValue, MediaTypeHeaderValue) throws if the MediaRange parameter is null.")]
public void ConstructorThrowsWithNullMediaRange(MediaTypeHeaderValue mediaType)
{
Assert.ThrowsArgumentNull(() => new MediaRangeMapping((MediaTypeHeaderValue)null, mediaType), "mediaRange");
}
[Theory]
[TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaRangeValues")]
[Trait("Description", "MediaRangeMapping(MediaTypeHeaderValue, MediaTypeHeaderValue) throws if the MediaType parameter is null.")]
public void ConstructorThrowsWithNullMediaType(MediaTypeHeaderValue mediaRange)
{
Assert.ThrowsArgumentNull(() => new MediaRangeMapping(mediaRange, (MediaTypeHeaderValue)null), "mediaType");
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "IllegalMediaRangeValues",
typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")]
[Trait("Description", "MediaRangeMapping(MediaTypeHeaderValue, MediaTypeHeaderValue) throws if the MediaRange parameter is not really a media range.")]
public void ConstructorThrowsWithIllegalMediaRange(MediaTypeHeaderValue mediaRange, MediaTypeHeaderValue mediaType)
{
string errorMessage = RS.Format(Properties.Resources.InvalidMediaRange, mediaRange.MediaType);
Assert.Throws<InvalidOperationException>(() => new MediaRangeMapping(mediaRange, mediaType), errorMessage);
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "MediaRangeMapping(string, string) sets public properties.")]
public void Constructor1(string mediaRange, string mediaType)
{
MediaRangeMapping mapping = new MediaRangeMapping(mediaRange, mediaType);
Assert.MediaType.AreEqual(mediaRange, mapping.MediaRange, "MediaRange failed to set.");
Assert.MediaType.AreEqual(mediaType, mapping.MediaType, "MediaType failed to set.");
}
[Theory]
[TestDataSet(
typeof(CommonUnitTestDataSets), "EmptyStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "MediaRangeMapping(string, string) throws if the MediaRange parameter is empty.")]
public void Constructor1ThrowsWithEmptyMediaRange(string mediaRange, string mediaType)
{
Assert.ThrowsArgumentNull(() => new MediaRangeMapping(mediaRange, mediaType), "mediaRange");
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeStrings",
typeof(CommonUnitTestDataSets), "EmptyStrings")]
[Trait("Description", "MediaRangeMapping(string, string) throws if the MediaType parameter is empty.")]
public void Constructor1ThrowsWithEmptyMediaType(string mediaRange, string mediaType)
{
Assert.ThrowsArgumentNull(() => new MediaRangeMapping(mediaRange, mediaType), "mediaType");
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "IllegalMediaRangeStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "MediaRangeMapping(string, string) throws if the MediaRange parameter is not really a media range.")]
public void Constructor1ThrowsWithIllegalMediaRange(string mediaRange, string mediaType)
{
string errorMessage = RS.Format(Properties.Resources.InvalidMediaRange, mediaRange);
Assert.Throws<InvalidOperationException>(() => new MediaRangeMapping(mediaRange, mediaType), errorMessage);
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "TryMatchMediaType(HttpRequestMessage) throws with null HttpRequestMessage.")]
public void TryMatchMediaTypeThrowsWithNullHttpRequestMessage(string mediaRange, string mediaType)
{
MediaRangeMapping mapping = new MediaRangeMapping(mediaRange, mediaType);
Assert.ThrowsArgumentNull(() => mapping.TryMatchMediaType(request: null), "request");
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "TryMatchMediaType(HttpRequestMessage) returns 1.0 when the MediaRange is in the accept headers.")]
public void TryMatchMediaTypeReturnsOneWithMediaRangeInAcceptHeader(string mediaRange, string mediaType)
{
MediaRangeMapping mapping = new MediaRangeMapping(mediaRange, mediaType);
HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(mediaRange));
Assert.Equal(1.0, mapping.TryMatchMediaType(request));
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "MediaRangeValuesWithQuality",
typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")]
[Trait("Description", "TryMatchMediaType(HttpRequestMessage) returns quality factor when a MediaRange with quality is in the accept headers.")]
public void TryMatchMediaTypeReturnsQualityWithMediaRangeWithQualityInAcceptHeader(MediaTypeWithQualityHeaderValue mediaRangeWithQuality, MediaTypeHeaderValue mediaType)
{
MediaTypeWithQualityHeaderValue mediaRangeWithNoQuality = new MediaTypeWithQualityHeaderValue(mediaRangeWithQuality.MediaType);
MediaRangeMapping mapping = new MediaRangeMapping(mediaRangeWithNoQuality, mediaType);
HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Accept.Add(mediaRangeWithQuality);
double quality = mediaRangeWithQuality.Quality.Value;
Assert.Equal(quality, mapping.TryMatchMediaType(request));
}
[Theory]
[TestDataSet(
typeof(HttpUnitTestDataSets), "LegalMediaRangeStrings",
typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")]
[Trait("Description", "TryMatchMediaType(HttpRequestMessage) returns 0.0 when the MediaRange is not in the accept headers.")]
public void TryMatchMediaTypeReturnsFalseWithMediaRangeNotInAcceptHeader(string mediaRange, string mediaType)
{
MediaRangeMapping mapping = new MediaRangeMapping(mediaRange, mediaType);
HttpRequestMessage request = new HttpRequestMessage();
Assert.Equal(0.0, mapping.TryMatchMediaType(request));
}
}
}

View File

@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using Microsoft.TestCommon;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http
{
public class MediaTypeConstantsTests
{
[Fact]
[Trait("Description", "Class is internal static type.")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(MediaTypeConstants), TypeAssert.TypeProperties.IsClass | TypeAssert.TypeProperties.IsStatic);
}
private static void ValidateClones(MediaTypeHeaderValue clone1, MediaTypeHeaderValue clone2, string charset)
{
Assert.NotNull(clone1);
Assert.NotNull(clone2);
Assert.NotSame(clone1, clone2);
Assert.Equal(clone1.MediaType, clone2.MediaType);
Assert.Equal(charset, clone1.CharSet);
Assert.Equal(charset, clone2.CharSet);
}
[Fact]
[Trait("Description", "HtmlMediaType returns clone")]
public void HtmlMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.HtmlMediaType, MediaTypeConstants.HtmlMediaType, Encoding.UTF8.WebName);
}
[Fact]
[Trait("Description", "ApplicationXmlMediaType returns clone")]
public void ApplicationXmlMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.ApplicationXmlMediaType, MediaTypeConstants.ApplicationXmlMediaType, null);
}
[Fact]
[Trait("Description", "ApplicationJsonMediaType returns clone")]
public void ApplicationJsonMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.ApplicationJsonMediaType, MediaTypeConstants.ApplicationJsonMediaType, null);
}
[Fact]
[Trait("Description", "TextXmlMediaType returns clone")]
public void TextXmlMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.TextXmlMediaType, MediaTypeConstants.TextXmlMediaType, null);
}
[Fact]
[Trait("Description", "TextJsonMediaType returns clone")]
public void TextJsonMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.TextJsonMediaType, MediaTypeConstants.TextJsonMediaType, null);
}
[Fact]
[Trait("Description", "ApplicationFormUrlEncodedMediaType returns clone")]
public void ApplicationFormUrlEncodedMediaTypeReturnsClone()
{
ValidateClones(MediaTypeConstants.ApplicationFormUrlEncodedMediaType, MediaTypeConstants.ApplicationFormUrlEncodedMediaType, null);
}
}
}

View File

@ -0,0 +1,224 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http.Formatting.DataSets;
using Microsoft.TestCommon;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class MediaTypeFormatterCollectionTests
{
[Fact]
[Trait("Description", "MediaTypeFormatterCollection is public, concrete, and unsealed.")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(MediaTypeFormatterCollection), TypeAssert.TypeProperties.IsPublicVisibleClass, typeof(Collection<MediaTypeFormatter>));
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection() initializes default formatters.")]
public void Constructor()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection();
Assert.Equal(3, collection.Count);
Assert.NotNull(collection.XmlFormatter);
Assert.NotNull(collection.JsonFormatter);
Assert.NotNull(collection.FormUrlEncodedFormatter);
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) accepts empty collection and does not add to it.")]
public void Constructor1AcceptsEmptyList()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[0]);
Assert.Equal(0, collection.Count);
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) sets XmlFormatter and JsonFormatter for all known collections of formatters that contain them.")]
public void Constructor1SetsProperties()
{
// All combination of formatters presented to ctor should still set XmlFormatter
foreach (IEnumerable<MediaTypeFormatter> formatterCollection in HttpUnitTestDataSets.AllFormatterCollections)
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(formatterCollection);
if (collection.OfType<XmlMediaTypeFormatter>().Any())
{
Assert.NotNull(collection.XmlFormatter);
}
else
{
Assert.Null(collection.XmlFormatter);
}
if (collection.OfType<JsonMediaTypeFormatter>().Any())
{
Assert.NotNull(collection.JsonFormatter);
}
else
{
Assert.Null(collection.JsonFormatter);
}
}
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) sets derived classes of Xml and Json formatters.")]
public void Constructor1SetsDerivedFormatters()
{
// force to array to get stable instances
MediaTypeFormatter[] derivedFormatters = HttpUnitTestDataSets.DerivedFormatters.ToArray();
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(derivedFormatters);
Assert.True(derivedFormatters.SequenceEqual(collection));
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) throws with null formatters collection.")]
public void Constructor1ThrowsWithNullFormatters()
{
Assert.ThrowsArgumentNull(() => new MediaTypeFormatterCollection(null), "formatters");
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) throws with null formatter in formatters collection.")]
public void Constructor1ThrowsWithNullFormatterInCollection()
{
Assert.ThrowsArgument(
() => new MediaTypeFormatterCollection(new MediaTypeFormatter[] { null }), "formatters",
RS.Format(Properties.Resources.CannotHaveNullInList,
typeof(MediaTypeFormatter).Name));
}
[Fact]
[Trait("Description", "MediaTypeFormatterCollection(IEnumerable<MediaTypeFormatter>) accepts multiple instances of same formatter type.")]
public void Constructor1AcceptsDuplicateFormatterTypes()
{
MediaTypeFormatter[] formatters = new MediaTypeFormatter[]
{
new XmlMediaTypeFormatter(),
new JsonMediaTypeFormatter(),
new FormUrlEncodedMediaTypeFormatter(),
new XmlMediaTypeFormatter(),
new JsonMediaTypeFormatter(),
new FormUrlEncodedMediaTypeFormatter(),
};
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(formatters);
Assert.True(formatters.SequenceEqual(collection));
}
[Fact]
[Trait("Description", "XmlFormatter is set by ctor.")]
public void XmlFormatterSetByCtor()
{
XmlMediaTypeFormatter formatter = new XmlMediaTypeFormatter();
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[] { formatter });
Assert.Same(formatter, collection.XmlFormatter);
}
[Fact]
[Trait("Description", "XmlFormatter is cleared by ctor with empty collection.")]
public void XmlFormatterClearedByCtor()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[0]);
Assert.Null(collection.XmlFormatter);
}
[Fact]
[Trait("Description", "JsonFormatter is set by ctor.")]
public void JsonFormatterSetByCtor()
{
JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[] { formatter });
Assert.Same(formatter, collection.JsonFormatter);
}
[Fact]
[Trait("Description", "JsonFormatter is cleared by ctor with empty collection.")]
public void JsonFormatterClearedByCtor()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[0]);
Assert.Null(collection.JsonFormatter);
}
[Fact]
[Trait("Description", "FormUrlEncodedFormatter is set by ctor.")]
public void FormUrlEncodedFormatterSetByCtor()
{
FormUrlEncodedMediaTypeFormatter formatter = new FormUrlEncodedMediaTypeFormatter();
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[] { formatter });
Assert.Same(formatter, collection.FormUrlEncodedFormatter);
}
[Fact]
[Trait("Description", "FormUrlEncodedFormatter is cleared by ctor with empty collection.")]
public void FormUrlEncodedFormatterClearedByCtor()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection(new MediaTypeFormatter[0]);
Assert.Null(collection.FormUrlEncodedFormatter);
}
[Fact]
[Trait("Description", "Remove(MediaTypeFormatter) sets XmlFormatter to null.")]
public void RemoveSetsXmlFormatter()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection();
int count = collection.Count;
collection.Remove(collection.XmlFormatter);
Assert.Null(collection.XmlFormatter);
Assert.Equal(count - 1, collection.Count);
}
[Fact]
[Trait("Description", "Remove(MediaTypeFormatter) sets JsonFormatter to null.")]
public void RemoveSetsJsonFormatter()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection();
int count = collection.Count;
collection.Remove(collection.JsonFormatter);
Assert.Null(collection.JsonFormatter);
Assert.Equal(count - 1, collection.Count);
}
[Fact]
[Trait("Description", "Insert(int, MediaTypeFormatter) sets XmlFormatter.")]
public void InsertSetsXmlFormatter()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection();
int count = collection.Count;
XmlMediaTypeFormatter formatter = new XmlMediaTypeFormatter();
collection.Insert(0, formatter);
Assert.Same(formatter, collection.XmlFormatter);
Assert.Equal(count + 1, collection.Count);
}
[Fact]
[Trait("Description", "Insert(int, MediaTypeFormatter) sets JsonFormatter.")]
public void InsertSetsJsonFormatter()
{
MediaTypeFormatterCollection collection = new MediaTypeFormatterCollection();
int count = collection.Count;
JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
collection.Insert(0, formatter);
Assert.Same(formatter, collection.JsonFormatter);
Assert.Equal(count + 1, collection.Count);
}
}
}

View File

@ -0,0 +1,106 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting.Mocks;
using System.Net.Http.Headers;
using Microsoft.TestCommon;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class MediaTypeFormatterExtensionsTests
{
[Fact]
[Trait("Description", "MediaTypeFormatterExtensionMethods is public and static.")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties(typeof(MediaTypeFormatterExtensions), TypeAssert.TypeProperties.IsPublicVisibleClass | TypeAssert.TypeProperties.IsStatic);
}
[Fact]
[Trait("Description", "AddQueryStringMapping(MediaTypeFormatter, string, string, MediaTypeHeaderValue) throws for null 'this'.")]
public void AddQueryStringMappingThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddQueryStringMapping("name", "value", new MediaTypeHeaderValue("application/xml")), "formatter");
}
[Fact]
[Trait("Description", "AddQueryStringMapping(MediaTypeFormatter, string, string, string) throws for null 'this'.")]
public void AddQueryStringMapping1ThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddQueryStringMapping("name", "value", "application/xml"), "formatter");
}
[Fact]
[Trait("Description", "AddMediaRangeMapping(MediaTypeFormatter, MediaTypeHeaderValue, MediaTypeHeaderValue) throws for null 'this'.")]
public void AddMediaRangeMappingThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddMediaRangeMapping(new MediaTypeHeaderValue("application/*"), new MediaTypeHeaderValue("application/xml")), "formatter");
}
[Fact]
[Trait("Description", "AddMediaRangeMapping(MediaTypeFormatter, string, string) throws for null 'this'.")]
public void AddMediaRangeMapping1ThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddMediaRangeMapping("application/*", "application/xml"), "formatter");
}
[Fact]
[Trait("Description", "AddRequestHeaderMapping(MediaTypeFormatter, string, string, StringComparison, bool, MediaTypeHeaderValue) throws for null 'this'.")]
public void AddRequestHeaderMappingThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddRequestHeaderMapping("name", "value", StringComparison.CurrentCulture, true, new MediaTypeHeaderValue("application/xml")), "formatter");
}
[Fact]
[Trait("Description", "AddRequestHeaderMapping(MediaTypeFormatter, string, string, StringComparison, bool, MediaTypeHeaderValue) adds formatter on 'this'.")]
public void AddRequestHeaderMappingAddsSuccessfully()
{
MediaTypeFormatter formatter = new MockMediaTypeFormatter();
Assert.Equal(0, formatter.MediaTypeMappings.Count);
formatter.AddRequestHeaderMapping("name", "value", StringComparison.CurrentCulture, true, new MediaTypeHeaderValue("application/xml"));
IEnumerable<RequestHeaderMapping> mappings = formatter.MediaTypeMappings.OfType<RequestHeaderMapping>();
Assert.Equal(1, mappings.Count());
RequestHeaderMapping mapping = mappings.ElementAt(0);
Assert.Equal("name", mapping.HeaderName);
Assert.Equal("value", mapping.HeaderValue);
Assert.Equal(StringComparison.CurrentCulture, mapping.HeaderValueComparison);
Assert.Equal(true, mapping.IsValueSubstring);
Assert.Equal(new MediaTypeHeaderValue("application/xml"), mapping.MediaType);
}
[Fact]
[Trait("Description", "AddRequestHeaderMapping(MediaTypeFormatter, string, string, StringComparison, bool, string) throws for null 'this'.")]
public void AddRequestHeaderMapping1ThrowsWithNullThis()
{
MediaTypeFormatter formatter = null;
Assert.ThrowsArgumentNull(() => formatter.AddRequestHeaderMapping("name", "value", StringComparison.CurrentCulture, true, "application/xml"), "formatter");
}
[Fact]
[Trait("Description", "AddRequestHeaderMapping(MediaTypeFormatter, string, string, StringComparison, bool, string) adds formatter on 'this'.")]
public void AddRequestHeaderMapping1AddsSuccessfully()
{
MediaTypeFormatter formatter = new MockMediaTypeFormatter();
Assert.Equal(0, formatter.MediaTypeMappings.Count);
formatter.AddRequestHeaderMapping("name", "value", StringComparison.CurrentCulture, true, "application/xml");
IEnumerable<RequestHeaderMapping> mappings = formatter.MediaTypeMappings.OfType<RequestHeaderMapping>();
Assert.Equal(1, mappings.Count());
RequestHeaderMapping mapping = mappings.ElementAt(0);
Assert.Equal("name", mapping.HeaderName);
Assert.Equal("value", mapping.HeaderValue);
Assert.Equal(StringComparison.CurrentCulture, mapping.HeaderValueComparison);
Assert.Equal(true, mapping.IsValueSubstring);
Assert.Equal(new MediaTypeHeaderValue("application/xml"), mapping.MediaType);
}
}
}

View File

@ -0,0 +1,390 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TestCommon;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
/// <summary>
/// A test class for common <see cref="MediaTypeFormatter"/> functionality across multiple implementations.
/// </summary>
/// <typeparam name="TFormatter">The type of formatter under test.</typeparam>
public abstract class MediaTypeFormatterTestBase<TFormatter> where TFormatter : MediaTypeFormatter, new()
{
protected MediaTypeFormatterTestBase()
{
}
public abstract IEnumerable<MediaTypeHeaderValue> ExpectedSupportedMediaTypes { get; }
public abstract IEnumerable<Encoding> ExpectedSupportedEncodings { get; }
/// <summary>
/// Byte representation of an <see cref="SampleType"/> with value 42 using the default encoding
/// for this media type formatter.
/// </summary>
public abstract byte[] ExpectedSampleTypeByteRepresentation { get; }
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties<TFormatter, MediaTypeFormatter>(TypeAssert.TypeProperties.IsPublicVisibleClass);
}
[Fact]
public void SupportEncoding_DefaultSupportedMediaTypes()
{
TFormatter formatter = new TFormatter();
Assert.True(ExpectedSupportedMediaTypes.SequenceEqual(formatter.SupportedMediaTypes));
}
[Fact]
public void SupportEncoding_DefaultSupportedEncodings()
{
TFormatter formatter = new TFormatter();
Assert.True(ExpectedSupportedEncodings.SequenceEqual(formatter.SupportedEncodings));
}
[Fact]
public void ReadFromStreamAsync_ThrowsOnNull()
{
TFormatter formatter = new TFormatter();
Assert.ThrowsArgumentNull(() => { formatter.ReadFromStreamAsync(null, Stream.Null, null, null); }, "type");
Assert.ThrowsArgumentNull(() => { formatter.WriteToStreamAsync(typeof(object), null, null, null, null); }, "stream");
}
[Fact]
public Task ReadFromStreamAsync_WhenContentLengthIsZero_DoesNotReadStream()
{
// Arrange
TFormatter formatter = new TFormatter();
Mock<Stream> mockStream = new Mock<Stream>();
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
contentHeaders.ContentLength = 0;
// Act
return formatter.ReadFromStreamAsync(typeof(object), mockStream.Object, contentHeaders, mockFormatterLogger).
ContinueWith(
readTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
mockStream.Verify(s => s.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never());
mockStream.Verify(s => s.ReadByte(), Times.Never());
mockStream.Verify(s => s.BeginRead(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()), Times.Never());
});
}
[Fact]
public Task ReadFromStreamAsync_WhenContentLengthIsZero_DoesNotCloseStream()
{
// Arrange
TFormatter formatter = new TFormatter();
Mock<Stream> mockStream = new Mock<Stream>();
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
contentHeaders.ContentLength = 0;
// Act
return formatter.ReadFromStreamAsync(typeof(object), mockStream.Object, contentHeaders, mockFormatterLogger).
ContinueWith(
readTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
mockStream.Verify(s => s.Close(), Times.Never());
});
}
[Theory]
[InlineData(false)]
[InlineData(0)]
[InlineData("")]
public void ReadFromStreamAsync_WhenContentLengthIsZero_ReturnsDefaultTypeValue<T>(T value)
{
// Arrange
TFormatter formatter = new TFormatter();
HttpContent content = new StringContent("");
// Act
var result = formatter.ReadFromStreamAsync(typeof(T), content.ReadAsStreamAsync().Result,
content.Headers, null);
result.WaitUntilCompleted();
// Assert
Assert.Equal(default(T), (T)result.Result);
}
[Fact]
public Task ReadFromStreamAsync_ReadsDataButDoesNotCloseStream()
{
// Arrange
TFormatter formatter = new TFormatter();
MemoryStream memStream = new MemoryStream(ExpectedSampleTypeByteRepresentation);
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
contentHeaders.ContentLength = memStream.Length;
// Act
return formatter.ReadFromStreamAsync(typeof(SampleType), memStream, contentHeaders, null).ContinueWith(
readTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
Assert.True(memStream.CanRead);
var value = Assert.IsType<SampleType>(readTask.Result);
Assert.Equal(42, value.Number);
});
}
[Fact]
public Task ReadFromStreamAsync_WhenContentLengthIsNull_ReadsDataButDoesNotCloseStream()
{
// Arrange
TFormatter formatter = new TFormatter();
MemoryStream memStream = new MemoryStream(ExpectedSampleTypeByteRepresentation);
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
contentHeaders.ContentLength = null;
// Act
return formatter.ReadFromStreamAsync(typeof(SampleType), memStream, contentHeaders, null).ContinueWith(
readTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
Assert.True(memStream.CanRead);
var value = Assert.IsType<SampleType>(readTask.Result);
Assert.Equal(42, value.Number);
});
}
[Fact]
public void WriteToStreamAsync_ThrowsOnNull()
{
TFormatter formatter = new TFormatter();
Assert.ThrowsArgumentNull(() => { formatter.WriteToStreamAsync(null, new object(), Stream.Null, null, null); }, "type");
Assert.ThrowsArgumentNull(() => { formatter.WriteToStreamAsync(typeof(object), new object(), null, null, null); }, "stream");
}
[Fact]
public Task WriteToStreamAsync_WhenObjectIsNull_WritesDataButDoesNotCloseStream()
{
// Arrange
TFormatter formatter = new TFormatter();
Mock<Stream> mockStream = new Mock<Stream>();
mockStream.Setup(s => s.CanWrite).Returns(true);
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
// Act
return formatter.WriteToStreamAsync(typeof(object), null, mockStream.Object, contentHeaders, null).ContinueWith(
writeTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, writeTask.Status);
mockStream.Verify(s => s.Close(), Times.Never());
mockStream.Verify(s => s.BeginWrite(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<AsyncCallback>(), It.IsAny<object>()), Times.Never());
});
}
[Fact]
public Task WriteToStreamAsync_WritesDataButDoesNotCloseStream()
{
// Arrange
TFormatter formatter = new TFormatter();
SampleType sampleType = new SampleType { Number = 42 };
MemoryStream memStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
// Act
return formatter.WriteToStreamAsync(typeof(SampleType), sampleType, memStream, contentHeaders, null).ContinueWith(
writeTask =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, writeTask.Status);
Assert.True(memStream.CanRead);
byte[] actualSampleTypeByteRepresentation = memStream.ToArray();
Assert.Equal(ExpectedSampleTypeByteRepresentation, actualSampleTypeByteRepresentation);
});
}
public abstract Task ReadFromStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding);
public abstract Task WriteToStreamAsync_UsesCorrectCharacterEncoding(string content, string encoding, bool isDefaultEncoding);
public Task ReadFromStreamAsync_UsesCorrectCharacterEncodingHelper(MediaTypeFormatter formatter, string content, string formattedContent, string mediaType, string encoding, bool isDefaultEncoding)
{
// Arrange
Encoding enc = null;
if (isDefaultEncoding)
{
enc = formatter.SupportedEncodings.First((e) => e.WebName.Equals(encoding, StringComparison.OrdinalIgnoreCase));
}
else
{
enc = Encoding.GetEncoding(encoding);
formatter.SupportedEncodings.Add(enc);
}
byte[] data = enc.GetBytes(formattedContent);
MemoryStream memStream = new MemoryStream(data);
StringContent dummyContent = new StringContent(string.Empty);
HttpContentHeaders headers = dummyContent.Headers;
headers.Clear();
headers.ContentType = MediaTypeHeaderValue.Parse(mediaType);
headers.ContentLength = data.Length;
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
// Act
return formatter.ReadFromStreamAsync(typeof(string), memStream, headers, mockFormatterLogger).ContinueWith(
(readTask) =>
{
string result = readTask.Result as string;
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
Assert.Equal(content, result);
});
}
public Task WriteToStreamAsync_UsesCorrectCharacterEncodingHelper(MediaTypeFormatter formatter, string content, string formattedContent, string mediaType, string encoding, bool isDefaultEncoding)
{
// Arrange
Encoding enc = null;
if (isDefaultEncoding)
{
enc = formatter.SupportedEncodings.First((e) => e.WebName.Equals(encoding, StringComparison.OrdinalIgnoreCase));
}
else
{
enc = Encoding.GetEncoding(encoding);
formatter.SupportedEncodings.Add(enc);
}
byte[] preamble = enc.GetPreamble();
byte[] data = enc.GetBytes(formattedContent);
byte[] expectedData = new byte[preamble.Length + data.Length];
Buffer.BlockCopy(preamble, 0, expectedData, 0, preamble.Length);
Buffer.BlockCopy(data, 0, expectedData, preamble.Length, data.Length);
MemoryStream memStream = new MemoryStream();
HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders();
contentHeaders.Clear();
contentHeaders.ContentType = MediaTypeHeaderValue.Parse(mediaType);
contentHeaders.ContentLength = expectedData.Length;
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
// Act
return formatter.WriteToStreamAsync(typeof(string), content, memStream, contentHeaders, null).ContinueWith(
(writeTask) =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, writeTask.Status);
byte[] actualData = memStream.ToArray();
Assert.Equal(expectedData, actualData);
});
}
public static Task ReadContentUsingCorrectCharacterEncodingHelper(MediaTypeFormatter formatter, string content, string formattedContent, string mediaType, string encoding, bool isDefaultEncoding)
{
// Arrange
Encoding enc = null;
if (isDefaultEncoding)
{
enc = formatter.SupportedEncodings.First((e) => e.WebName.Equals(encoding, StringComparison.OrdinalIgnoreCase));
}
else
{
enc = Encoding.GetEncoding(encoding);
formatter.SupportedEncodings.Add(enc);
}
byte[] data = enc.GetBytes(formattedContent);
MemoryStream memStream = new MemoryStream(data);
StringContent dummyContent = new StringContent(string.Empty);
HttpContentHeaders headers = dummyContent.Headers;
headers.Clear();
headers.ContentType = MediaTypeHeaderValue.Parse(mediaType);
headers.ContentLength = data.Length;
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
// Act
return formatter.ReadFromStreamAsync(typeof(string), memStream, headers, mockFormatterLogger).ContinueWith(
(readTask) =>
{
string result = readTask.Result as string;
// Assert
Assert.Equal(TaskStatus.RanToCompletion, readTask.Status);
Assert.Equal(content, result);
});
}
public static Task WriteContentUsingCorrectCharacterEncodingHelper(MediaTypeFormatter formatter, string content, string formattedContent, string mediaType, string encoding, bool isDefaultEncoding)
{
// Arrange
Encoding enc = null;
if (isDefaultEncoding)
{
enc = formatter.SupportedEncodings.First((e) => e.WebName.Equals(encoding, StringComparison.OrdinalIgnoreCase));
}
else
{
enc = Encoding.GetEncoding(encoding);
formatter.SupportedEncodings.Add(enc);
}
byte[] preamble = enc.GetPreamble();
byte[] data = enc.GetBytes(formattedContent);
byte[] expectedData = new byte[preamble.Length + data.Length];
Buffer.BlockCopy(preamble, 0, expectedData, 0, preamble.Length);
Buffer.BlockCopy(data, 0, expectedData, preamble.Length, data.Length);
MemoryStream memStream = new MemoryStream();
StringContent dummyContent = new StringContent(string.Empty);
HttpContentHeaders headers = dummyContent.Headers;
headers.Clear();
headers.ContentType = MediaTypeHeaderValue.Parse(mediaType);
headers.ContentLength = expectedData.Length;
IFormatterLogger mockFormatterLogger = new Mock<IFormatterLogger>().Object;
// Act
return formatter.WriteToStreamAsync(typeof(string), content, memStream, headers, null).ContinueWith(
(writeTask) =>
{
// Assert
Assert.Equal(TaskStatus.RanToCompletion, writeTask.Status);
byte[] actualData = memStream.ToArray();
Assert.Equal(expectedData, actualData);
});
}
[DataContract(Name = "DataContractSampleType")]
public class SampleType
{
[DataMember]
public int Number { get; set; }
}
}
}

View File

@ -0,0 +1,167 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net.Http.Headers;
using Xunit;
using Xunit.Extensions;
namespace System.Net.Http.Formatting
{
public class MediaTypeHeaderValueExtensionsTests
{
public static IEnumerable<object[]> EqualValues
{
get
{
// These values are all equal
yield return new[] { "text/xml", "text/xml" };
yield return new[] { "text/xml", "TEXT/XML" };
yield return new[] { "text/xml; charset=utf-8", "text/xml; charset=utf-8" };
yield return new[] { "text/xml; parameter=value", "text/xml; parameter=value" };
yield return new[] { "text/xml; charset=utf-8; parameter=value", "text/xml; parameter=value; charset=utf-8" };
yield return new[] { "text/*", "text/*" };
yield return new[] { "text/*", "TEXT/*" };
yield return new[] { "text/*; charset=utf-8", "text/*; charset=utf-8" };
yield return new[] { "text/*; parameter=value", "text/*; parameter=value" };
yield return new[] { "text/*; charset=utf-8; parameter=value", "text/*; parameter=value; charset=utf-8" };
yield return new[] { "*/*", "*/*" };
yield return new[] { "*/*; charset=utf-8", "*/*; charset=utf-8" };
yield return new[] { "*/*; parameter=value", "*/*; parameter=value" };
yield return new[] { "*/*; charset=utf-8; parameter=value", "*/*; parameter=value; charset=utf-8" };
}
}
public static IEnumerable<object[]> NonEqualValues
{
get
{
// These values are all subsets. If compared in reverse they are all non-subsets.
yield return new[] { "text/xml", "text/xml; charset=utf-8" };
yield return new[] { "text/xml", "TEXT/XML; charset=utf-8" };
yield return new[] { "text/xml", "text/xml; parameter=value" };
yield return new[] { "text/xml; charset=utf-8", "text/xml; parameter=value; charset=utf-8" };
yield return new[] { "text/*", "text/*; charset=utf-8" };
yield return new[] { "text/*", "TEXT/*; charset=utf-8" };
yield return new[] { "text/*", "text/*; parameter=value" };
yield return new[] { "text/*; charset=utf-8", "text/*; parameter=value; charset=utf-8" };
yield return new[] { "text/xml", "text/*" };
yield return new[] { "text/xml", "text/*; charset=utf-8" };
yield return new[] { "text/xml", "TEXT/*; charset=utf-8" };
yield return new[] { "text/xml", "text/*; parameter=value" };
yield return new[] { "text/xml; charset=utf-8", "text/*; parameter=value; charset=utf-8" };
yield return new[] { "*/*", "*/*; charset=utf-8" };
yield return new[] { "*/*", "*/*; parameter=value" };
yield return new[] { "*/*; charset=utf-8", "*/*; parameter=value; charset=utf-8" };
yield return new[] { "text/*", "*/*" };
yield return new[] { "text/*", "*/*; charset=utf-8" };
yield return new[] { "text/*", "*/*; charset=utf-8" };
yield return new[] { "text/*", "*/*; parameter=value" };
yield return new[] { "text/*; charset=utf-8", "*/*; parameter=value; charset=utf-8" };
yield return new[] { "text/xml", "*/*" };
yield return new[] { "text/xml", "*/*; charset=utf-8" };
yield return new[] { "text/xml", "*/*; parameter=value" };
yield return new[] { "text/xml; charset=utf-8", "*/*; parameter=value; charset=utf-8" };
}
}
public static IEnumerable<object[]> NonOverlappingValues
{
get
{
// These values are all value1 < value2 regardless of which value is first and second
// We do this asymmetric sorting algorithm to ensure that subsets are always <=0.
yield return new[] { "text/xml", "application/xml" };
yield return new[] { "text/xml", "APPLICATION/XML" };
yield return new[] { "text/xml", "application/xml; charset=utf-8" };
yield return new[] { "text/xml; charset=utf-8", "application/xml; charset=utf-8" };
yield return new[] { "text/xml; charset=utf-8", "application/xml; parameter=value" };
yield return new[] { "text/xml", "text/plain" };
yield return new[] { "text/xml", "TEXT/PLAIN" };
yield return new[] { "text/xml", "text/plain; charset=utf-8" };
yield return new[] { "text/xml; charset=utf-8", "text/plain; charset=utf-8" };
yield return new[] { "text/xml; charset=utf-8", "text/plain; parameter=value" };
}
}
public static IEnumerable<object[]> MediaRanges
{
get
{
yield return new[] { "text/*" };
yield return new[] { "TEXT/*" };
yield return new[] { "application/*; charset=utf-8" };
yield return new[] { "APPLICATION/*; charset=utf-8" };
yield return new[] { "*/*" };
yield return new[] { "*/*; charset=utf-8" };
yield return new[] { "*/*; charset=utf-8" };
}
}
public static IEnumerable<object[]> NonMediaRanges
{
get
{
yield return new[] { "text/plain" };
yield return new[] { "TEXT/XML" };
yield return new[] { "application/xml; charset=utf-8" };
yield return new[] { "APPLICATION/xml; charset=utf-8" };
}
}
[Theory]
[PropertyData("EqualValues")]
public void IsSubsetOf_ReturnsTrueForEqualValues(string mediaType1, string mediaType2)
{
MediaTypeHeaderValue mediaTypeHeaderValue1 = MediaTypeHeaderValue.Parse(mediaType1);
MediaTypeHeaderValue mediaTypeHeaderValue2 = MediaTypeHeaderValue.Parse(mediaType2);
Assert.True(mediaTypeHeaderValue1.IsSubsetOf(mediaTypeHeaderValue2));
Assert.True(mediaTypeHeaderValue2.IsSubsetOf(mediaTypeHeaderValue1));
}
[Theory]
[PropertyData("NonEqualValues")]
public void IsSubsetOf_ReturnsTrueForNonEqualValues(string mediaType1, string mediaType2)
{
MediaTypeHeaderValue mediaTypeHeaderValue1 = MediaTypeHeaderValue.Parse(mediaType1);
MediaTypeHeaderValue mediaTypeHeaderValue2 = MediaTypeHeaderValue.Parse(mediaType2);
Assert.True(mediaTypeHeaderValue1.IsSubsetOf(mediaTypeHeaderValue2));
Assert.False(mediaTypeHeaderValue2.IsSubsetOf(mediaTypeHeaderValue1));
}
[Theory]
[PropertyData("NonOverlappingValues")]
public void IsSubsetOf_ReturnsFalseForNonOverlappingValues(string mediaType1, string mediaType2)
{
MediaTypeHeaderValue mediaTypeHeaderValue1 = MediaTypeHeaderValue.Parse(mediaType1);
MediaTypeHeaderValue mediaTypeHeaderValue2 = MediaTypeHeaderValue.Parse(mediaType2);
Assert.False(mediaTypeHeaderValue1.IsSubsetOf(mediaTypeHeaderValue2));
}
[Theory]
[PropertyData("MediaRanges")]
public void IsMediaRange_ReturnsTrueForMediaRanges(string mediaRange)
{
MediaTypeHeaderValue mediaTypeHeader = MediaTypeHeaderValue.Parse(mediaRange);
Assert.True(mediaTypeHeader.IsMediaRange());
}
[Theory]
[PropertyData("NonMediaRanges")]
public void IsMediaRange_ReturnsFalseForNonMediaRanges(string nonMediaRange)
{
MediaTypeHeaderValue mediaTypeHeader = MediaTypeHeaderValue.Parse(nonMediaRange);
Assert.False(mediaTypeHeader.IsMediaRange());
}
}
}

View File

@ -0,0 +1,177 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class MediaTypeWithQualityHeaderValueComparerTests
{
public static IEnumerable<object[]> EqualValues
{
get
{
yield return new[] { "text/xml", "text/xml" };
yield return new[] { "text/xml", "TEXT/XML" };
yield return new[] { "text/plain", "text/xml" };
yield return new[] { "text/*", "text/*" };
yield return new[] { "text/*", "TEXT/*" };
yield return new[] { "*/*", "*/*" };
yield return new[] { "text/xml", "text/xml; charset=utf8" };
yield return new[] { "text/xml", "text/xml; parameter=value" };
yield return new[] { "text/xml; parameter=value", "text/xml; parameter=value" };
yield return new[] { "text/xml; parameter1=value1", "text/xml; parameter2=value2" };
yield return new[] { "text/xml; q=0.5", "text/xml; q=0.50" };
yield return new[] { "application/xml; q=0.5", "text/xml; q=0.5" };
yield return new[] { "application/xml; q=0.1", "text/xml; q=0.1" };
yield return new[] { "application/xml; parameter=value1; q=0.5", "text/xml; parameter=value2; q=0.5" };
yield return new[] { "text/xml", "text/xml;q=1" };
yield return new[] { "text/xml", "text/xml; q=1" };
yield return new[] { "text/xml", "text/xml;q=1.0" };
yield return new[] { "text/xml", "text/xml; q=1.0" };
yield return new[] { "text/xml", "text/xml; q=1.00000" };
yield return new[] { "text/xml; q=0.5", "text/xml; q=0.5" };
yield return new[] { "text/xml; q=1.0", "text/xml; q=1.0" };
yield return new[] { "*/*", "*/*;q=1" };
yield return new[] { "*/*", "*/*; q=1" };
yield return new[] { "*/*", "*/*;q=1.0" };
yield return new[] { "*/*", "*/*; q=1.0" };
yield return new[] { "*/*; q=0.5", "*/*; q=0.5" };
yield return new[] { "*/*; q=1.0", "*/*; q=1.0" };
yield return new[] { "text/xml", "text/xml;q=1" };
yield return new[] { "text/xml", "text/xml; q=1" };
yield return new[] { "text/xml", "text/xml;q=1.0" };
yield return new[] { "text/xml", "text/xml; q=1.0" };
}
}
public static IEnumerable<object[]> NonEqualValues
{
get
{
yield return new[] { "text/plain; q=0.5", "text/plain; q=1.0" };
yield return new[] { "text/plain; q=0.5", "text/xml; q=1.0" };
yield return new[] { "text/*", "text/plain" };
yield return new[] { "*/*", "text/xml" };
yield return new[] { "*/*", "text/*" };
yield return new[] { "*/*;q=0.5", "*/*;q=0.6" };
yield return new[] { "*/*;q=0.5", "text/*;q=0.5" };
yield return new[] { "*/*;q=1", "text/plain" };
yield return new[] { "*/*; q=1", "text/plain" };
yield return new[] { "*/*;q=1.0", "text/plain" };
yield return new[] { "*/*; q=1.0", "text/plain" };
yield return new[] { "*/*; q=0.5", "text/plain; q=0.5" };
yield return new[] { "*/*; q=1.0", "text/plain; q=1.0" };
yield return new[] { "*/*; q=0.5", "text/*; q=0.6" };
}
}
public static IEnumerable<object[]> BeforeAfterSortedValues
{
get
{
yield return new[]
{
new List<string>
{
"text/plain",
"text/plain;q=1.0",
"text/plain",
"text/plain;q=0",
"*/*;q=0.8",
"*/*;q=1",
"text/*;q=1",
"text/plain;q=0.8",
"text/*;q=0.8",
"text/*;q=0.6",
"text/*;q=1.0",
"*/*;q=0.4",
"text/plain;q=0.6",
"text/xml",
},
new List<string>
{
"text/plain",
"text/plain;q=1.0",
"text/plain",
"text/xml",
"text/*;q=1",
"text/*;q=1.0",
"*/*;q=1",
"text/plain;q=0.8",
"text/*;q=0.8",
"*/*;q=0.8",
"text/plain;q=0.6",
"text/*;q=0.6",
"*/*;q=0.4",
"text/plain;q=0",
},
};
}
}
[Fact]
public void StaticComparer_Returns_SameInstance()
{
MediaTypeWithQualityHeaderValueComparer comparer1 = MediaTypeWithQualityHeaderValueComparer.QualityComparer;
MediaTypeWithQualityHeaderValueComparer comparer2 = MediaTypeWithQualityHeaderValueComparer.QualityComparer;
Assert.NotNull(comparer1);
Assert.Same(comparer1, comparer2);
}
[Theory]
[PropertyData("EqualValues")]
public void ComparerReturnsZeroForEqualValues(string mediaType1, string mediaType2)
{
// Arrange
MediaTypeWithQualityHeaderValueComparer comparer = MediaTypeWithQualityHeaderValueComparer.QualityComparer;
// Act
MediaTypeWithQualityHeaderValue mediaTypeHeaderValue1 = MediaTypeWithQualityHeaderValue.Parse(mediaType1);
MediaTypeWithQualityHeaderValue mediaTypeHeaderValue2 = MediaTypeWithQualityHeaderValue.Parse(mediaType2);
// Assert
Assert.Equal(0, comparer.Compare(mediaTypeHeaderValue1, mediaTypeHeaderValue2));
Assert.Equal(0, comparer.Compare(mediaTypeHeaderValue2, mediaTypeHeaderValue1));
}
[Theory]
[PropertyData("NonEqualValues")]
public void ComparerReturnsNonZeroForNonEqualValues(string mediaType1, string mediaType2)
{
// Arrange
MediaTypeWithQualityHeaderValueComparer comparer = MediaTypeWithQualityHeaderValueComparer.QualityComparer;
// Act
MediaTypeWithQualityHeaderValue mediaTypeHeaderValue1 = MediaTypeWithQualityHeaderValue.Parse(mediaType1);
MediaTypeWithQualityHeaderValue mediaTypeHeaderValue2 = MediaTypeWithQualityHeaderValue.Parse(mediaType2);
// Assert
Assert.Equal(-1, comparer.Compare(mediaTypeHeaderValue1, mediaTypeHeaderValue2));
Assert.Equal(1, comparer.Compare(mediaTypeHeaderValue2, mediaTypeHeaderValue1));
}
[Theory]
[PropertyData("BeforeAfterSortedValues")]
public void ComparerSortsListCorrectly(List<string> unsorted, List<string> expectedSorted)
{
// Arrange
IEnumerable<MediaTypeWithQualityHeaderValue> unsortedValues =
unsorted.Select(u => MediaTypeWithQualityHeaderValue.Parse(u));
IEnumerable<MediaTypeWithQualityHeaderValue> expectedSortedValues =
expectedSorted.Select(u => MediaTypeWithQualityHeaderValue.Parse(u));
// Act
IEnumerable<MediaTypeWithQualityHeaderValue> actualSorted = unsortedValues.OrderByDescending(m => m, MediaTypeWithQualityHeaderValueComparer.QualityComparer);
// Assert
Assert.True(expectedSortedValues.SequenceEqual(actualSorted));
}
}
}

View File

@ -0,0 +1,170 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http.Headers;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting
{
public class ParsedMediaTypeHeadeValueTests
{
[Fact]
[Trait("Description", "MediaTypeHeaderValue ensures only valid media types are constructed.")]
public void MediaTypeHeaderValue_Ensures_Valid_MediaType()
{
string[] invalidMediaTypes = new string[] { "", " ", "\n", "\t", "text", "text/", "text\\", "\\", "//", "text/[", "text/ ", " text/", " text/ ", "text\\ ", " text\\", " text\\ ", "text\\xml", "text//xml" };
foreach (string invalidMediaType in invalidMediaTypes)
{
Assert.Throws<Exception>(() => new MediaTypeHeaderValue(invalidMediaType), exceptionMessage: null, allowDerivedExceptions: true);
}
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.Type returns the media type.")]
public void Type_Returns_Just_The_Type()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/xml");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("text", parsedMediaType.Type);
mediaType = new MediaTypeHeaderValue("text/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("text", parsedMediaType.Type);
mediaType = new MediaTypeHeaderValue("*/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("*", parsedMediaType.Type);
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.SubType returns the media sub-type.")]
public void SubType_Returns_Just_The_Sub_Type()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/xml");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("xml", parsedMediaType.SubType);
mediaType = new MediaTypeHeaderValue("text/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("*", parsedMediaType.SubType);
mediaType = new MediaTypeHeaderValue("*/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("*", parsedMediaType.SubType);
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.IsSubTypeMediaRange returns true for media ranges.")]
public void IsSubTypeMediaRange_Returns_True_For_Media_Ranges()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/*");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.True(parsedMediaType.IsSubTypeMediaRange, "ParsedMediaTypeHeadeValue.IsSubTypeMediaRange should have returned true.");
mediaType = new MediaTypeHeaderValue("*/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.True(parsedMediaType.IsSubTypeMediaRange, "ParsedMediaTypeHeadeValue.IsSubTypeMediaRange should have returned true.");
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.IsAllMediaRange returns true only when both the type and subtype are wildcard characters.")]
public void IsAllMediaRange_Returns_True_Only_When_Type_And_SubType_Are_Wildcards()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/*");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.False(parsedMediaType.IsAllMediaRange, "ParsedMediaTypeHeadeValue.IsAllMediaRange should have returned false.");
mediaType = new MediaTypeHeaderValue("*/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.True(parsedMediaType.IsAllMediaRange, "ParsedMediaTypeHeadeValue.IsAllMediaRange should have returned true.");
mediaType = new MediaTypeHeaderValue("*/xml");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.False(parsedMediaType.IsAllMediaRange, "ParsedMediaTypeHeadeValue.IsAllMediaRange should have returned false.");
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.QualityFactor always returns 1.0 for MediaTypeHeaderValue.")]
public void QualityFactor_Returns_1_For_MediaTypeHeaderValue()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("text/*");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeHeaderValue("*/*");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeHeaderValue("application/xml");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeHeaderValue("application/xml");
mediaType.Parameters.Add(new NameValueHeaderValue("q", "0.5"));
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.QualityFactor returns q value given by MediaTypeWithQualityHeaderValue.")]
public void QualityFactor_Returns_Q_Value_For_MediaTypeWithQualityHeaderValue()
{
MediaTypeHeaderValue mediaType = new MediaTypeWithQualityHeaderValue("text/*", 0.5);
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(0.5, parsedMediaType.QualityFactor);
mediaType = new MediaTypeWithQualityHeaderValue("*/*", 0.0);
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(0.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeWithQualityHeaderValue("application/xml", 1.0);
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeWithQualityHeaderValue("application/xml");
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(1.0, parsedMediaType.QualityFactor);
mediaType = new MediaTypeWithQualityHeaderValue("application/xml");
mediaType.Parameters.Add(new NameValueHeaderValue("q", "0.5"));
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal(0.5, parsedMediaType.QualityFactor);
MediaTypeWithQualityHeaderValue mediaTypeWithQuality = new MediaTypeWithQualityHeaderValue("application/xml");
mediaTypeWithQuality.Quality = 0.2;
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaTypeWithQuality);
Assert.Equal(0.2, parsedMediaType.QualityFactor);
}
[Fact]
[Trait("Description", "ParsedMediaTypeHeadeValue.CharSet is just the value of the CharSet from the MediaTypeHeaderValue.")]
public void CharSet_Is_CharSet_Of_MediaTypeHeaderValue()
{
MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/*");
ParsedMediaTypeHeaderValue parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Null(parsedMediaType.CharSet);
mediaType = new MediaTypeHeaderValue("application/*");
mediaType.CharSet = "";
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Null(parsedMediaType.CharSet);
mediaType = new MediaTypeHeaderValue("application/xml");
mediaType.CharSet = "someCharSet";
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("someCharSet", parsedMediaType.CharSet);
mediaType = new MediaTypeHeaderValue("text/xml");
mediaType.CharSet = "someCharSet";
parsedMediaType = new ParsedMediaTypeHeaderValue(mediaType);
Assert.Equal("someCharSet", parsedMediaType.CharSet);
}
}
}

View File

@ -0,0 +1,178 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting.Parsers
{
public class FormUrlEncodedParserTests
{
private const int MinMessageSize = 1;
private const int Iterations = 16;
internal static Collection<KeyValuePair<string, string>> CreateCollection()
{
return new Collection<KeyValuePair<string, string>>();
}
internal static FormUrlEncodedParser CreateParser(int maxMessageSize, out ICollection<KeyValuePair<string, string>> nameValuePairs)
{
nameValuePairs = CreateCollection();
return new FormUrlEncodedParser(nameValuePairs, maxMessageSize);
}
internal static byte[] CreateBuffer(params string[] nameValuePairs)
{
StringBuilder buffer = new StringBuilder();
bool first = true;
foreach (var h in nameValuePairs)
{
if (first)
{
first = false;
}
else
{
buffer.Append('&');
}
buffer.Append(h);
}
return Encoding.UTF8.GetBytes(buffer.ToString());
}
internal static ParserState ParseBufferInSteps(FormUrlEncodedParser parser, byte[] buffer, int readsize, out int totalBytesConsumed)
{
ParserState state = ParserState.Invalid;
totalBytesConsumed = 0;
while (totalBytesConsumed <= buffer.Length)
{
int size = Math.Min(buffer.Length - totalBytesConsumed, readsize);
byte[] parseBuffer = new byte[size];
Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size);
int bytesConsumed = 0;
state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed, totalBytesConsumed == buffer.Length - size);
totalBytesConsumed += bytesConsumed;
if (state != ParserState.NeedMoreData)
{
return state;
}
}
return state;
}
[Fact]
public void TypeIsCorrect()
{
Assert.Type.HasProperties<FormUrlEncodedParser>(TypeAssert.TypeProperties.IsClass);
}
[Fact]
public void FormUrlEncodedParserThrowsOnNull()
{
Assert.ThrowsArgumentNull(() => { new FormUrlEncodedParser(null, ParserData.MinHeaderSize); }, "nameValuePairs");
}
[Fact]
public void FormUrlEncodedParserThrowsOnInvalidSize()
{
Assert.ThrowsArgumentGreaterThanOrEqualTo(() => { new FormUrlEncodedParser(CreateCollection(), MinMessageSize - 1); }, "maxMessageSize", MinMessageSize.ToString(), MinMessageSize - 1);
FormUrlEncodedParser parser = new FormUrlEncodedParser(CreateCollection(), MinMessageSize);
Assert.NotNull(parser);
parser = new FormUrlEncodedParser(CreateCollection(), MinMessageSize + 1);
Assert.NotNull(parser);
}
[Fact]
public void ParseBufferThrowsOnNullBuffer()
{
ICollection<KeyValuePair<string, string>> collection;
FormUrlEncodedParser parser = CreateParser(128, out collection);
int bytesConsumed = 0;
Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed, false); }, "buffer");
}
[Fact]
public void ParseBufferHandlesEmptyBuffer()
{
byte[] data = CreateBuffer();
ICollection<KeyValuePair<string, string>> collection;
FormUrlEncodedParser parser = CreateParser(MinMessageSize, out collection);
int bytesConsumed = 0;
ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed, true);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, bytesConsumed);
Assert.Equal(0, collection.Count());
}
public static TheoryDataSet<string, string, string> UriQueryData
{
get
{
return UriQueryTestData.UriQueryData;
}
}
[Theory]
[InlineData("N", "N", "")]
[InlineData("%26", "&", "")]
[PropertyData("UriQueryData")]
public void ParseBufferCorrectly(string segment, string name, string value)
{
for (int index = 1; index < Iterations; index++)
{
List<string> segments = new List<string>();
for (int cnt = 0; cnt < index; cnt++)
{
segments.Add(segment);
}
byte[] data = CreateBuffer(segments.ToArray());
for (var cnt = 1; cnt <= data.Length; cnt++)
{
ICollection<KeyValuePair<string, string>> collection;
FormUrlEncodedParser parser = CreateParser(data.Length + 1, out collection);
Assert.NotNull(parser);
int totalBytesConsumed;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, totalBytesConsumed);
Assert.Equal(index, collection.Count());
foreach (KeyValuePair<string, string> element in collection)
{
Assert.Equal(name, element.Key);
Assert.Equal(value, element.Value);
}
}
}
}
[Fact]
public void HeaderParserDataTooBig()
{
byte[] data = CreateBuffer("N=V");
ICollection<KeyValuePair<string, string>> collection;
FormUrlEncodedParser parser = CreateParser(MinMessageSize, out collection);
int bytesConsumed = 0;
ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed, true);
Assert.Equal(ParserState.DataTooBig, state);
Assert.Equal(MinMessageSize, bytesConsumed);
}
}
}

View File

@ -0,0 +1,277 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting.DataSets;
using System.Text;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting.Parsers
{
public class HttpRequestHeaderParserTests
{
[Fact]
[Trait("Description", "HttpRequestHeaderParser is internal class")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties<HttpRequestHeaderParser>(TypeAssert.TypeProperties.IsClass);
}
private static byte[] CreateBuffer(string method, string address, string version, Dictionary<string, string> headers)
{
const string SP = " ";
const string CRLF = "\r\n";
string lws = SP;
StringBuilder request = new StringBuilder();
request.AppendFormat("{0}{1}{2}{3}{4}{5}", method, lws, address, lws, version, CRLF);
if (headers != null)
{
foreach (var h in headers)
{
request.AppendFormat("{0}: {1}{2}", h.Key, h.Value, CRLF);
}
}
request.Append(CRLF);
return Encoding.UTF8.GetBytes(request.ToString());
}
private static ParserState ParseBufferInSteps(HttpRequestHeaderParser parser, byte[] buffer, int readsize, out int totalBytesConsumed)
{
ParserState state = ParserState.Invalid;
totalBytesConsumed = 0;
while (totalBytesConsumed <= buffer.Length)
{
int size = Math.Min(buffer.Length - totalBytesConsumed, readsize);
byte[] parseBuffer = new byte[size];
Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size);
int bytesConsumed = 0;
state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed);
totalBytesConsumed += bytesConsumed;
if (state != ParserState.NeedMoreData)
{
return state;
}
}
return state;
}
private static void ValidateResult(
HttpUnsortedRequest requestLine,
string method,
string requestUri,
Version version,
Dictionary<string, string> headers)
{
Assert.Equal(new HttpMethod(method), requestLine.Method);
Assert.Equal(requestUri, requestLine.RequestUri);
Assert.Equal(version, requestLine.Version);
if (headers != null)
{
Assert.Equal(headers.Count, requestLine.HttpHeaders.Count());
foreach (var header in headers)
{
Assert.True(requestLine.HttpHeaders.Contains(header.Key), "Parsed header did not contain expected key " + header.Key);
Assert.Equal(header.Value, requestLine.HttpHeaders.GetValues(header.Key).ElementAt(0));
}
}
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser constructor throws on invalid arguments")]
public void HttpRequestHeaderParserConstructorTest()
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
Assert.NotNull(result);
Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize - 1, ParserData.MinHeaderSize),
"maxRequestLineSize", ParserData.MinRequestLineSize.ToString(), ParserData.MinRequestLineSize - 1);
Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize - 1),
"maxHeaderSize", ParserData.MinHeaderSize.ToString(), ParserData.MinHeaderSize - 1);
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
Assert.NotNull(parser);
Assert.ThrowsArgumentNull(() => { new HttpRequestHeaderParser(null); }, "httpRequest");
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer throws on null buffer.")]
public void RequestHeaderParserNullBuffer()
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
Assert.NotNull(parser);
int bytesConsumed = 0;
Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed); }, "buffer");
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses minimum requestline.")]
public void RequestHeaderParserMinimumBuffer()
{
byte[] data = CreateBuffer("G", "/", "HTTP/1.1", null);
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
Assert.NotNull(parser);
int bytesConsumed = 0;
ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, bytesConsumed);
ValidateResult(result, "G", "/", new Version("1.1"), null);
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses standard methods.")]
public void RequestHeaderParserAcceptsStandardMethods()
{
foreach (HttpMethod method in HttpUnitTestDataSets.AllHttpMethods)
{
byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1", ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(result, method.ToString(), "/", new Version("1.1"), ParserData.ValidHeaders);
}
}
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses custom methods.")]
public void RequestHeaderParserAcceptsCustomMethods()
{
foreach (HttpMethod method in HttpUnitTestDataSets.CustomHttpMethods)
{
byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1", ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(result, method.ToString(), "/", new Version("1.1"), ParserData.ValidHeaders);
}
}
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects invalid method")]
public void RequestHeaderParserRejectsInvalidMethod()
{
foreach (string invalidMethod in ParserData.InvalidMethods)
{
byte[] data = CreateBuffer(invalidMethod, "/", "HTTP/1.1", ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
[Fact]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects invalid URI.")]
public void RequestHeaderParserRejectsInvalidUri()
{
foreach (string invalidRequestUri in ParserData.InvalidRequestUris)
{
byte[] data = CreateBuffer("GET", invalidRequestUri, "HTTP/1.1", ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
public static IEnumerable<object[]> Versions
{
get { return ParserData.Versions; }
}
[Theory]
[PropertyData("Versions")]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer accepts valid versions.")]
public void RequestHeaderParserAcceptsValidVersion(Version version)
{
byte[] data = CreateBuffer("GET", "/", String.Format("HTTP/{0}", version.ToString(2)), ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(result, "GET", "/", version, ParserData.ValidHeaders);
}
}
public static IEnumerable<object[]> InvalidVersions
{
get { return ParserData.InvalidVersions; }
}
[Theory]
[PropertyData("InvalidVersions")]
[Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects lower case protocol version.")]
public void RequestHeaderParserRejectsInvalidVersion(string invalidVersion)
{
byte[] data = CreateBuffer("GET", "/", invalidVersion, ParserData.ValidHeaders);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest result = new HttpUnsortedRequest();
HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
}

View File

@ -0,0 +1,276 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net.Http.Formatting.DataSets;
using System.Text;
using Microsoft.TestCommon;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Net.Http.Formatting.Parsers
{
public class HttpRequestLineParserTests
{
[Fact]
[Trait("Description", "HttpRequestLineParser is internal class")]
public void TypeIsCorrect()
{
Assert.Type.HasProperties<HttpRequestLineParser>(TypeAssert.TypeProperties.IsClass);
}
internal static byte[] CreateBuffer(string method, string address, string version)
{
return CreateBuffer(method, address, version, false);
}
private static byte[] CreateBuffer(string method, string address, string version, bool withLws)
{
const string SP = " ";
const string HTAB = "\t";
const string CRLF = "\r\n";
string lws = SP;
if (withLws)
{
lws = SP + SP + HTAB + SP;
}
string requestLine = String.Format("{0}{1}{2}{3}{4}{5}", method, lws, address, lws, version, CRLF);
return Encoding.UTF8.GetBytes(requestLine);
}
private static ParserState ParseBufferInSteps(HttpRequestLineParser parser, byte[] buffer, int readsize, out int totalBytesConsumed)
{
ParserState state = ParserState.Invalid;
totalBytesConsumed = 0;
while (totalBytesConsumed <= buffer.Length)
{
int size = Math.Min(buffer.Length - totalBytesConsumed, readsize);
byte[] parseBuffer = new byte[size];
Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size);
int bytesConsumed = 0;
state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed);
totalBytesConsumed += bytesConsumed;
if (state != ParserState.NeedMoreData)
{
return state;
}
}
return state;
}
private static void ValidateResult(HttpUnsortedRequest requestLine, string method, string requestUri, Version version)
{
Assert.Equal(new HttpMethod(method), requestLine.Method);
Assert.Equal(requestUri, requestLine.RequestUri);
Assert.Equal(version, requestLine.Version);
}
[Fact]
[Trait("Description", "HttpRequestLineParser constructor throws on invalid arguments")]
public void HttpRequestLineParserConstructorTest()
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
Assert.NotNull(requestLine);
Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpRequestLineParser(requestLine, ParserData.MinRequestLineSize - 1),
"maxRequestLineSize", ParserData.MinRequestLineSize.ToString(), ParserData.MinRequestLineSize - 1);
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, ParserData.MinRequestLineSize);
Assert.NotNull(parser);
Assert.ThrowsArgumentNull(() => { new HttpRequestLineParser(null, ParserData.MinRequestLineSize); }, "httpRequest");
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer throws on null buffer.")]
public void RequestLineParserNullBuffer()
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, ParserData.MinRequestLineSize);
Assert.NotNull(parser);
int bytesConsumed = 0;
Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed); }, "buffer");
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer parses minimum requestline.")]
public void RequestLineParserMinimumBuffer()
{
byte[] data = CreateBuffer("G", "/", "HTTP/1.1");
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, ParserData.MinRequestLineSize);
Assert.NotNull(parser);
int bytesConsumed = 0;
ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, bytesConsumed);
ValidateResult(requestLine, "G", "/", new Version("1.1"));
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer rejects LWS requestline.")]
public void RequestLineParserRejectsLws()
{
byte[] data = CreateBuffer("GET", "/", "HTTP/1.1", true);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, data.Length);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer parses standard methods.")]
public void RequestLineParserAcceptsStandardMethods()
{
foreach (HttpMethod method in HttpUnitTestDataSets.AllHttpMethods)
{
byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1");
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, data.Length);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(requestLine, method.ToString(), "/", new Version("1.1"));
}
}
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer parses custom methods.")]
public void RequestLineParserAcceptsCustomMethods()
{
foreach (HttpMethod method in HttpUnitTestDataSets.CustomHttpMethods)
{
byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1");
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, data.Length);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Done, state);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(requestLine, method.ToString(), "/", new Version("1.1"));
}
}
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer rejects invalid method")]
public void RequestLineParserRejectsInvalidMethod()
{
foreach (string invalidMethod in ParserData.InvalidMethods)
{
byte[] data = CreateBuffer(invalidMethod, "/", "HTTP/1.1");
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, 256);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
[Fact]
[Trait("Description", "HttpRequestLineParser.ParseBuffer rejects invalid URI.")]
public void RequestLineParserRejectsInvalidUri()
{
foreach (string invalidRequestUri in ParserData.InvalidRequestUris)
{
byte[] data = CreateBuffer("GET", invalidRequestUri, "HTTP/1.1");
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, 256);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
public static IEnumerable<object[]> Versions
{
get { return ParserData.Versions; }
}
[Theory]
[PropertyData("Versions")]
[Trait("Description", "HttpRequestLineParser.ParseBuffer accepts valid versions.")]
public void RequestLineParserAcceptsValidVersion(Version version)
{
byte[] data = CreateBuffer("GET", "/", String.Format("HTTP/{0}", version.ToString(2)));
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, 256);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(data.Length, totalBytesConsumed);
ValidateResult(requestLine, "GET", "/", version);
}
}
public static IEnumerable<object[]> InvalidVersions
{
get { return ParserData.InvalidVersions; }
}
[Theory]
[PropertyData("InvalidVersions")]
[Trait("Description", "HttpRequestLineParser.ParseBuffer rejects invalid protocol version.")]
public void RequestLineParserRejectsInvalidVersion(string invalidVersion)
{
byte[] data = CreateBuffer("GET", "/", invalidVersion);
for (var cnt = 1; cnt <= data.Length; cnt++)
{
HttpUnsortedRequest requestLine = new HttpUnsortedRequest();
HttpRequestLineParser parser = new HttpRequestLineParser(requestLine, 256);
Assert.NotNull(parser);
int totalBytesConsumed = 0;
ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
Assert.Equal(ParserState.Invalid, state);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More