1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. 2 3 using System.Collections.Generic; 4 using System.Collections.ObjectModel; 5 using System.Linq; 6 using System.Net.Http.Formatting.DataSets; 7 using System.Net.Http.Formatting.Mocks; 8 using System.Net.Http.Headers; 9 using System.Text; 10 using Microsoft.TestCommon; 11 using Moq; 12 using Xunit; 13 using Xunit.Extensions; 14 using Assert = Microsoft.TestCommon.AssertEx; 15 16 namespace System.Net.Http.Formatting 17 { 18 public class MediaTypeFormatterTests 19 { 20 private const string TestMediaType = "text/test"; 21 22 [Fact] 23 [Trait("Description", "MediaTypeFormatter is public, abstract, and unsealed.")] TypeIsCorrect()24 public void TypeIsCorrect() 25 { 26 Assert.Type.HasProperties(typeof(MediaTypeFormatter), TypeAssert.TypeProperties.IsPublicVisibleClass | TypeAssert.TypeProperties.IsAbstract); 27 } 28 29 [Fact] 30 [Trait("Description", "MediaTypeFormatter() constructor (via derived class) sets SupportedMediaTypes and MediaTypeMappings.")] Constructor()31 public void Constructor() 32 { 33 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 34 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 35 Assert.NotNull(supportedMediaTypes); 36 Assert.Equal(0, supportedMediaTypes.Count); 37 38 Collection<MediaTypeMapping> mappings = formatter.MediaTypeMappings; 39 Assert.NotNull(mappings); 40 Assert.Equal(0, mappings.Count); 41 } 42 43 [Fact] MaxCollectionKeySize_RoundTrips()44 public void MaxCollectionKeySize_RoundTrips() 45 { 46 Assert.Reflection.IntegerProperty<MediaTypeFormatter, int>( 47 null, 48 c => MediaTypeFormatter.MaxHttpCollectionKeys, 49 expectedDefaultValue: 1000, 50 minLegalValue: 1, 51 illegalLowerValue: 0, 52 maxLegalValue: null, 53 illegalUpperValue: null, 54 roundTripTestValue: 125); 55 } 56 57 [Fact] 58 [Trait("Description", "SupportedMediaTypes is a mutable collection.")] SupportedMediaTypesIsMutable()59 public void SupportedMediaTypesIsMutable() 60 { 61 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 62 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 63 MediaTypeHeaderValue[] mediaTypes = HttpUnitTestDataSets.LegalMediaTypeHeaderValues.ToArray(); 64 foreach (MediaTypeHeaderValue mediaType in mediaTypes) 65 { 66 supportedMediaTypes.Add(mediaType); 67 } 68 69 Assert.True(mediaTypes.SequenceEqual(formatter.SupportedMediaTypes)); 70 } 71 72 [Fact] 73 [Trait("Description", "SupportedMediaTypes Add throws with a null media type.")] SupportedMediaTypesAddThrowsWithNullMediaType()74 public void SupportedMediaTypesAddThrowsWithNullMediaType() 75 { 76 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 77 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 78 79 Assert.ThrowsArgumentNull(() => supportedMediaTypes.Add(null), "item"); 80 } 81 82 [Theory] 83 [TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaRangeValues")] 84 [Trait("Description", "SupportedMediaTypes Add throws with a media range.")] SupportedMediaTypesAddThrowsWithMediaRange(MediaTypeHeaderValue mediaType)85 public void SupportedMediaTypesAddThrowsWithMediaRange(MediaTypeHeaderValue mediaType) 86 { 87 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 88 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 89 Assert.ThrowsArgument(() => supportedMediaTypes.Add(mediaType), "item", RS.Format(Properties.Resources.CannotUseMediaRangeForSupportedMediaType, typeof(MediaTypeHeaderValue).Name, mediaType.MediaType)); 90 } 91 92 [Fact] 93 [Trait("Description", "SupportedMediaTypes Insert throws with a null media type.")] SupportedMediaTypesInsertThrowsWithNullMediaType()94 public void SupportedMediaTypesInsertThrowsWithNullMediaType() 95 { 96 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 97 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 98 99 Assert.ThrowsArgumentNull(() => supportedMediaTypes.Insert(0, null), "item"); 100 } 101 102 [Theory] 103 [TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaRangeValues")] 104 [Trait("Description", "SupportedMediaTypes Insert throws with a media range.")] SupportedMediaTypesInsertThrowsWithMediaRange(MediaTypeHeaderValue mediaType)105 public void SupportedMediaTypesInsertThrowsWithMediaRange(MediaTypeHeaderValue mediaType) 106 { 107 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 108 Collection<MediaTypeHeaderValue> supportedMediaTypes = formatter.SupportedMediaTypes; 109 110 Assert.ThrowsArgument(() => supportedMediaTypes.Insert(0, mediaType), "item", RS.Format(Properties.Resources.CannotUseMediaRangeForSupportedMediaType, typeof(MediaTypeHeaderValue).Name, mediaType.MediaType)); 111 } 112 113 [Fact] 114 [Trait("Description", "MediaTypeMappings is a mutable collection.")] MediaTypeMappingsIsMutable()115 public void MediaTypeMappingsIsMutable() 116 { 117 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 118 Collection<MediaTypeMapping> mappings = formatter.MediaTypeMappings; 119 MediaTypeMapping[] standardMappings = HttpUnitTestDataSets.StandardMediaTypeMappings.ToArray(); 120 foreach (MediaTypeMapping mapping in standardMappings) 121 { 122 mappings.Add(mapping); 123 } 124 125 Assert.True(standardMappings.SequenceEqual(formatter.MediaTypeMappings)); 126 } 127 128 [Theory] 129 [TestDataSet(typeof(HttpUnitTestDataSets), "StandardMediaTypesWithQuality")] 130 [Trait("Description", "TryMatchSupportedMediaType(MediaTypeHeaderValue, out MediaTypeMatch) returns media type and quality.")] TryMatchSupportedMediaTypeWithQuality(MediaTypeWithQualityHeaderValue mediaTypeWithQuality)131 public void TryMatchSupportedMediaTypeWithQuality(MediaTypeWithQualityHeaderValue mediaTypeWithQuality) 132 { 133 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 134 MediaTypeHeaderValue mediaTypeWithoutQuality = new MediaTypeHeaderValue(mediaTypeWithQuality.MediaType); 135 formatter.SupportedMediaTypes.Add(mediaTypeWithoutQuality); 136 MediaTypeMatch match; 137 bool result = formatter.TryMatchSupportedMediaType(mediaTypeWithQuality, out match); 138 Assert.True(result, String.Format("TryMatchSupportedMediaType should have succeeded for '{0}'.", mediaTypeWithQuality)); 139 Assert.NotNull(match); 140 double quality = mediaTypeWithQuality.Quality.Value; 141 Assert.Equal(quality, match.Quality); 142 Assert.NotNull(match.MediaType); 143 Assert.Equal(mediaTypeWithoutQuality.MediaType, match.MediaType.MediaType); 144 } 145 146 [Theory] 147 [TestDataSet(typeof(HttpUnitTestDataSets), "StandardMediaTypesWithQuality")] 148 [Trait("Description", "TryMatchSupportedMediaType(MediaTypeHeaderValue, out MediaTypeMatch) returns cloned media type, not original.")] TryMatchSupportedMediaTypeReturnsClone(MediaTypeWithQualityHeaderValue mediaTypeWithQuality)149 public void TryMatchSupportedMediaTypeReturnsClone(MediaTypeWithQualityHeaderValue mediaTypeWithQuality) 150 { 151 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 152 MediaTypeHeaderValue mediaTypeWithoutQuality = new MediaTypeHeaderValue(mediaTypeWithQuality.MediaType); 153 formatter.SupportedMediaTypes.Add(mediaTypeWithoutQuality); 154 MediaTypeMatch match; 155 bool result = formatter.TryMatchSupportedMediaType(mediaTypeWithQuality, out match); 156 157 Assert.True(result); 158 Assert.NotNull(match); 159 Assert.NotNull(match.MediaType); 160 Assert.NotSame(mediaTypeWithoutQuality, match.MediaType); 161 } 162 163 [Theory] 164 [TestDataSet(typeof(HttpUnitTestDataSets), "MediaRangeValuesWithQuality")] 165 [Trait("Description", "TryMatchMediaTypeMapping(HttpRequestMessage, out MediaTypeMatch) returns media type and quality from media range with quality.")] TryMatchMediaTypeMappingWithQuality(MediaTypeWithQualityHeaderValue mediaRangeWithQuality)166 public void TryMatchMediaTypeMappingWithQuality(MediaTypeWithQualityHeaderValue mediaRangeWithQuality) 167 { 168 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 169 MediaTypeHeaderValue mediaRangeWithoutQuality = new MediaTypeHeaderValue(mediaRangeWithQuality.MediaType); 170 MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/xml"); 171 MediaRangeMapping mapping = new MediaRangeMapping(mediaRangeWithoutQuality, mediaType); 172 formatter.MediaTypeMappings.Add(mapping); 173 174 HttpRequestMessage request = new HttpRequestMessage(); 175 request.Headers.Accept.Add(mediaRangeWithQuality); 176 MediaTypeMatch match; 177 bool result = formatter.TryMatchMediaTypeMapping(request, out match); 178 Assert.True(result, String.Format("TryMatchMediaTypeMapping should have succeeded for '{0}'.", mediaRangeWithQuality)); 179 Assert.NotNull(match); 180 double quality = mediaRangeWithQuality.Quality.Value; 181 Assert.Equal(quality, match.Quality); 182 Assert.NotNull(match.MediaType); 183 Assert.Equal(mediaType.MediaType, match.MediaType.MediaType); 184 } 185 186 [Theory] 187 [TestDataSet(typeof(HttpUnitTestDataSets), "MediaRangeValuesWithQuality")] 188 [Trait("Description", "TryMatchMediaTypeMapping(HttpRequestMessage, out MediaTypeMatch) returns a clone of the original media type.")] TryMatchMediaTypeMappingClonesMediaType(MediaTypeWithQualityHeaderValue mediaRangeWithQuality)189 public void TryMatchMediaTypeMappingClonesMediaType(MediaTypeWithQualityHeaderValue mediaRangeWithQuality) 190 { 191 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 192 MediaTypeHeaderValue mediaRangeWithoutQuality = new MediaTypeHeaderValue(mediaRangeWithQuality.MediaType); 193 MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/xml"); 194 MediaRangeMapping mapping = new MediaRangeMapping(mediaRangeWithoutQuality, mediaType); 195 formatter.MediaTypeMappings.Add(mapping); 196 197 HttpRequestMessage request = new HttpRequestMessage(); 198 request.Headers.Accept.Add(mediaRangeWithQuality); 199 MediaTypeMatch match; 200 formatter.TryMatchMediaTypeMapping(request, out match); 201 Assert.NotNull(match); 202 Assert.NotNull(match.MediaType); 203 Assert.NotSame(mediaType, match.MediaType); 204 } 205 206 [Fact] 207 [Trait("Description", "SelectResponseMediaType(Type, HttpRequestMessage) matches based only on type.")] SelectResponseMediaTypeMatchesType()208 public void SelectResponseMediaTypeMatchesType() 209 { 210 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 211 HttpRequestMessage request = new HttpRequestMessage(); 212 ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(typeof(string), request); 213 214 Assert.NotNull(match); 215 Assert.Equal(ResponseFormatterSelectionResult.MatchOnCanWriteType, match.ResponseFormatterSelectionResult); 216 Assert.Null(match.MediaTypeMatch.MediaType); 217 } 218 219 [Theory] 220 [TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")] 221 [Trait("Description", "SelectResponseMediaType(Type, HttpRequestMessage) matches media type from request content type.")] SelectResponseMediaTypeMatchesRequestContentType(MediaTypeHeaderValue mediaType)222 public void SelectResponseMediaTypeMatchesRequestContentType(MediaTypeHeaderValue mediaType) 223 { 224 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 225 formatter.SupportedMediaTypes.Add(mediaType); 226 HttpRequestMessage request = new HttpRequestMessage() { Content = new StringContent("fred") }; 227 request.Content.Headers.ContentType = mediaType; 228 HttpResponseMessage response = new HttpResponseMessage() { RequestMessage = request }; 229 ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(typeof(string), request); 230 231 Assert.NotNull(match); 232 Assert.Equal(ResponseFormatterSelectionResult.MatchOnRequestContentType, match.ResponseFormatterSelectionResult); 233 Assert.NotNull(match.MediaTypeMatch.MediaType); 234 Assert.Equal(mediaType.MediaType, match.MediaTypeMatch.MediaType.MediaType); 235 } 236 237 [TestDataSet(typeof(HttpUnitTestDataSets), "LegalMediaTypeHeaderValues")] 238 [Trait("Description", "SelectResponseMediaType(Type, HttpRequestMessage) matches media type from response content type.")] SelectResponseMediaTypeMatchesResponseContentType(MediaTypeHeaderValue mediaType)239 public void SelectResponseMediaTypeMatchesResponseContentType(MediaTypeHeaderValue mediaType) 240 { 241 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 242 formatter.SupportedMediaTypes.Add(mediaType); 243 HttpRequestMessage request = new HttpRequestMessage(); 244 HttpResponseMessage response = new HttpResponseMessage() { RequestMessage = request, Content = new StringContent("fred") }; 245 response.Content.Headers.ContentType = mediaType; 246 ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(typeof(string), request); 247 248 Assert.NotNull(match); 249 Assert.Equal(ResponseFormatterSelectionResult.MatchOnResponseContentType, match.ResponseFormatterSelectionResult); 250 Assert.NotNull(match.MediaTypeMatch.MediaType); 251 Assert.Equal(mediaType.MediaType, match.MediaTypeMatch.MediaType.MediaType); 252 } 253 254 [Theory] 255 [TestDataSet(typeof(HttpUnitTestDataSets), "StandardMediaTypesWithQuality")] 256 [Trait("Description", "SelectResponseMediaType(Type, HttpRequestMessage) matches supported media type from accept headers.")] SelectResponseMediaTypeMatchesAcceptHeaderToSupportedMediaTypes(MediaTypeWithQualityHeaderValue mediaTypeWithQuality)257 public void SelectResponseMediaTypeMatchesAcceptHeaderToSupportedMediaTypes(MediaTypeWithQualityHeaderValue mediaTypeWithQuality) 258 { 259 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 260 MediaTypeHeaderValue mediaTypeWithoutQuality = new MediaTypeHeaderValue(mediaTypeWithQuality.MediaType); 261 formatter.SupportedMediaTypes.Add(mediaTypeWithoutQuality); 262 263 HttpRequestMessage request = new HttpRequestMessage(); 264 request.Headers.Accept.Add(mediaTypeWithQuality); 265 ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(typeof(string), request); 266 267 Assert.NotNull(match); 268 Assert.Equal(ResponseFormatterSelectionResult.MatchOnRequestAcceptHeader, match.ResponseFormatterSelectionResult); 269 double quality = mediaTypeWithQuality.Quality.Value; 270 Assert.Equal(quality, match.MediaTypeMatch.Quality); 271 Assert.NotNull(match.MediaTypeMatch.MediaType); 272 Assert.Equal(mediaTypeWithoutQuality.MediaType, match.MediaTypeMatch.MediaType.MediaType); 273 } 274 275 [TestDataSet(typeof(HttpUnitTestDataSets), "MediaRangeValuesWithQuality")] 276 [Trait("Description", "SelectResponseMediaType(Type, HttpRequestMessage) matches media type with quality from media type mapping.")] SelectResponseMediaTypeMatchesWithMediaTypeMapping(MediaTypeWithQualityHeaderValue mediaRangeWithQuality)277 public void SelectResponseMediaTypeMatchesWithMediaTypeMapping(MediaTypeWithQualityHeaderValue mediaRangeWithQuality) 278 { 279 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 280 MediaTypeHeaderValue mediaRangeWithoutQuality = new MediaTypeHeaderValue(mediaRangeWithQuality.MediaType); 281 MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/xml"); 282 MediaRangeMapping mapping = new MediaRangeMapping(mediaRangeWithoutQuality, mediaType); 283 formatter.MediaTypeMappings.Add(mapping); 284 285 HttpRequestMessage request = new HttpRequestMessage(); 286 request.Headers.Accept.Add(mediaRangeWithQuality); 287 ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(typeof(string), request); 288 289 Assert.NotNull(match); 290 Assert.Equal(ResponseFormatterSelectionResult.MatchOnRequestWithMediaTypeMapping, match.ResponseFormatterSelectionResult); 291 double quality = mediaRangeWithQuality.Quality.Value; 292 Assert.Equal(quality, match.MediaTypeMatch.Quality); 293 Assert.NotNull(match.MediaTypeMatch.MediaType); 294 Assert.Equal(mediaType.MediaType, match.MediaTypeMatch.MediaType.MediaType); 295 } 296 297 public static IEnumerable<object[]> SelectCharacterEncodingTestData 298 { 299 get 300 { 301 yield return new object[] 302 { 303 null, 304 new[] { "utf-8", "utf-16"}, 305 "utf-8" 306 }; 307 yield return new object[] 308 { 309 null, 310 new[] { "utf-16", "utf-8"}, 311 "utf-16" 312 }; 313 yield return new object[] 314 { 315 "utf-32", 316 new[] { "utf-8", "utf-16"}, 317 "utf-8" 318 }; 319 yield return new object[] 320 { 321 "utf-32", 322 new[] { "utf-8", "utf-16", "utf-32"}, 323 "utf-32" 324 }; 325 } 326 } 327 328 public static IEnumerable<object[]> SelectResponseCharacterEncodingTestData 329 { 330 get 331 { 332 yield return new object[] 333 { 334 new[] { "*;q=0.5", "utf-8;q=0.8", "utf-16;q=0.7" }, 335 null, 336 new[] { "utf-16", "utf-8"}, 337 "utf-8" 338 }; 339 yield return new object[] 340 { 341 new[] { "*;q=0.5", "utf-8;q=0.8", "utf-16;q=0.9" }, 342 null, 343 new[] { "utf-8", "utf-16"}, 344 "utf-16" 345 }; 346 yield return new object[] 347 { 348 new[] { "*;q=0.9", "utf-8;q=0.5", "utf-16;q=0.5" }, 349 null, 350 new[] { "utf-8", "utf-16"}, 351 "utf-8" 352 }; 353 yield return new object[] 354 { 355 new string[] { }, 356 "utf-16", 357 new[] { "utf-8", "utf-16"}, 358 "utf-16" 359 }; 360 yield return new object[] 361 { 362 new[] { "*;q=0.5" }, 363 "utf-16", 364 new[] { "utf-8", "utf-16"}, 365 "utf-8" 366 }; 367 yield return new object[] 368 { 369 new[] { "*;q=0.5", "utf-16;q=0.7", "utf-8;q=0.8" }, 370 "utf-16", 371 new[] { "utf-8", "utf-16"}, 372 "utf-8" 373 }; 374 } 375 } 376 377 [Fact] SelectCharacterEncoding_ThrowsIfNoSupportedEncodings()378 public void SelectCharacterEncoding_ThrowsIfNoSupportedEncodings() 379 { 380 // Arrange 381 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter { CallBase = true }; 382 HttpContent content = new StringContent("Hello World", Encoding.UTF8, "text/plain"); 383 384 // Act 385 Assert.Throws<InvalidOperationException>(() => formatter.SelectCharacterEncoding(content.Headers)); 386 } 387 388 [Theory] 389 [PropertyData("SelectCharacterEncodingTestData")] SelectCharacterEncoding_ReturnsBestEncoding(string bodyEncoding, string[] supportedEncodings, string expectedEncoding)390 public void SelectCharacterEncoding_ReturnsBestEncoding(string bodyEncoding, string[] supportedEncodings, string expectedEncoding) 391 { 392 // Arrange 393 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter { CallBase = true }; 394 395 foreach (string supportedEncoding in supportedEncodings) 396 { 397 formatter.SupportedEncodings.Add(Encoding.GetEncoding(supportedEncoding)); 398 } 399 400 HttpContentHeaders contentHeaders = null; 401 if (bodyEncoding != null) 402 { 403 Encoding bodyEnc = Encoding.GetEncoding(bodyEncoding); 404 HttpContent content = new StringContent("Hello World", bodyEnc, "text/plain"); 405 contentHeaders = content.Headers; 406 } 407 408 // Act 409 Encoding actualEncoding = formatter.SelectCharacterEncoding(contentHeaders); 410 411 // Assert 412 Encoding expectedEnc = expectedEncoding != null ? Encoding.GetEncoding(expectedEncoding) : null; 413 Assert.Equal(expectedEnc, actualEncoding); 414 } 415 416 [Theory] 417 [PropertyData("SelectResponseCharacterEncodingTestData")] SelectResponseCharacterEncoding_ReturnsBestEncodingBasedOnAcceptCharsetMatch(string[] acceptCharsetValues, string bodyEncoding, string[] supportedEncodings, string expectedEncoding)418 public void SelectResponseCharacterEncoding_ReturnsBestEncodingBasedOnAcceptCharsetMatch(string[] acceptCharsetValues, string bodyEncoding, string[] supportedEncodings, string expectedEncoding) 419 { 420 // Arrange 421 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 422 HttpRequestMessage request = new HttpRequestMessage(); 423 foreach (var acceptCharsetValue in acceptCharsetValues) 424 { 425 request.Headers.AcceptCharset.Add(StringWithQualityHeaderValue.Parse(acceptCharsetValue)); 426 } 427 428 foreach (var supportedEncoding in supportedEncodings) 429 { 430 Encoding supportedEnc = Encoding.GetEncoding(supportedEncoding); 431 formatter.SupportedEncodings.Add(supportedEnc); 432 } 433 434 if (bodyEncoding != null) 435 { 436 Encoding bodyEnc = Encoding.GetEncoding(bodyEncoding); 437 request.Method = HttpMethod.Post; 438 request.Content = new StringContent("Hello World", bodyEnc, "text/plain"); 439 } 440 441 // Act 442 Encoding actualEncoding = formatter.SelectResponseCharacterEncoding(request); 443 444 // Assert 445 Encoding expectedEnc = expectedEncoding != null ? Encoding.GetEncoding(expectedEncoding) : null; 446 Assert.Equal(expectedEnc, actualEncoding); 447 } 448 449 [Theory] 450 [TestDataSet( 451 typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection", 452 typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")] 453 [Trait("Description", "CanReadAs(Type, MediaTypeHeaderValue) returns true for all standard media types.")] CanReadAsReturnsTrue(Type variationType, object testData, string mediaType)454 public void CanReadAsReturnsTrue(Type variationType, object testData, string mediaType) 455 { 456 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 457 string[] legalMediaTypeStrings = HttpUnitTestDataSets.LegalMediaTypeStrings.ToArray(); 458 foreach (string legalMediaType in legalMediaTypeStrings) 459 { 460 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(legalMediaType)); 461 } 462 463 MediaTypeHeaderValue contentType = new MediaTypeHeaderValue(mediaType); 464 Assert.True(formatter.CanReadAs(variationType, contentType)); 465 } 466 467 [Fact] 468 [Trait("Description", "CanReadAs(Type, MediaTypeHeaderValue) throws with null type.")] CanReadAsThrowsWithNullType()469 public void CanReadAsThrowsWithNullType() 470 { 471 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 472 Assert.ThrowsArgumentNull(() => formatter.CanReadAs(type: null, mediaType: null), "type"); 473 } 474 475 [Fact] 476 [Trait("Description", "CanReadAs(Type, MediaTypeHeaderValue) throws with null formatter context.")] CanReadAsThrowsWithNullMediaType()477 public void CanReadAsThrowsWithNullMediaType() 478 { 479 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 480 Assert.ThrowsArgumentNull(() => formatter.CanReadAs(typeof(int), mediaType: null), "mediaType"); 481 } 482 483 [Theory] 484 [TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")] 485 [Trait("Description", "CanWriteAs(Type, MediaTypeHeaderValue, out MediaTypeHeaderValue) returns true always for supported media types.")] CanWriteAsReturnsTrue(Type variationType, object testData)486 public void CanWriteAsReturnsTrue(Type variationType, object testData) 487 { 488 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 489 foreach (string mediaType in HttpUnitTestDataSets.LegalMediaTypeStrings) 490 { 491 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType)); 492 } 493 494 MediaTypeHeaderValue matchedMediaType = null; 495 Assert.True(formatter.CanWriteAs(variationType, formatter.SupportedMediaTypes[0], out matchedMediaType)); 496 } 497 498 [Fact] 499 [Trait("Description", "CanWriteAs(Type, MediaTypeHeaderValue, out MediaTypeHeaderValue) throws with null content.")] CanWriteAsThrowsWithNullContent()500 public void CanWriteAsThrowsWithNullContent() 501 { 502 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 503 MediaTypeHeaderValue mediaType = null; 504 Assert.ThrowsArgumentNull(() => formatter.CanWriteAs(typeof(int), null, out mediaType), "mediaType"); 505 } 506 507 [Theory] 508 [TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")] 509 [Trait("Description", "CanWriteAs(Type, MediaTypeHeaderValue, out MediaTypeHeaderValue) returns true always for supported media types.")] CanWriteAsUsingRequestReturnsTrue(Type variationType, object testData)510 public void CanWriteAsUsingRequestReturnsTrue(Type variationType, object testData) 511 { 512 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 513 foreach (string mediaType in HttpUnitTestDataSets.LegalMediaTypeStrings) 514 { 515 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType)); 516 } 517 518 MediaTypeHeaderValue matchedMediaType = null; 519 Assert.True(formatter.CanWriteAs(variationType, formatter.SupportedMediaTypes[0], out matchedMediaType)); 520 } 521 522 [Theory] 523 [TestDataSet( 524 typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection", 525 typeof(HttpUnitTestDataSets), "LegalMediaTypeStrings")] 526 [Trait("Description", "CanReadType(Type) base implementation returns true for all types.")] CanReadTypeReturnsTrue(Type variationType, object testData, string mediaType)527 public void CanReadTypeReturnsTrue(Type variationType, object testData, string mediaType) 528 { 529 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 530 string[] legalMediaTypeStrings = HttpUnitTestDataSets.LegalMediaTypeStrings.ToArray(); 531 foreach (string mediaTypeTmp in legalMediaTypeStrings) 532 { 533 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaTypeTmp)); 534 } 535 536 // Invoke CanReadAs because it invokes CanReadType 537 Assert.True(formatter.CanReadAs(variationType, new MediaTypeHeaderValue(mediaType))); 538 } 539 540 [Theory] 541 [TestDataSet(typeof(CommonUnitTestDataSets), "RepresentativeValueAndRefTypeTestDataCollection")] 542 [Trait("Description", "CanWriteType() base implementation returns true always.")] CanWriteTypeReturnsTrue(Type variationType, object testData)543 public void CanWriteTypeReturnsTrue(Type variationType, object testData) 544 { 545 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter() { CallBase = true }; 546 foreach (string mediaType in HttpUnitTestDataSets.LegalMediaTypeStrings) 547 { 548 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType)); 549 } 550 551 MediaTypeHeaderValue matchedMediaType = null; 552 Assert.True(formatter.CanWriteAs(variationType, formatter.SupportedMediaTypes[0], out matchedMediaType)); 553 } 554 555 [Fact] ReadFromStreamAsync_ThrowsNotSupportedException()556 public void ReadFromStreamAsync_ThrowsNotSupportedException() 557 { 558 var formatter = new Mock<MediaTypeFormatter> { CallBase = true }.Object; 559 560 Assert.Throws<NotSupportedException>(() => formatter.ReadFromStreamAsync(null, null, null, null), 561 "The media type formatter of type 'MediaTypeFormatterProxy' does not support reading because it does not implement the ReadFromStreamAsync method."); 562 } 563 564 [Fact] WriteToStreamAsync_ThrowsNotSupportedException()565 public void WriteToStreamAsync_ThrowsNotSupportedException() 566 { 567 var formatter = new Mock<MediaTypeFormatter> { CallBase = true }.Object; 568 569 Assert.Throws<NotSupportedException>(() => formatter.WriteToStreamAsync(null, null, null, null, null), 570 "The media type formatter of type 'MediaTypeFormatterProxy' does not support writing because it does not implement the WriteToStreamAsync method."); 571 } 572 573 [Theory] 574 [InlineData(typeof(object))] 575 [InlineData(typeof(string))] 576 [InlineData(typeof(Nullable<int>))] GetDefaultValueForType_ReturnsNullForReferenceTypes(Type referenceType)577 public void GetDefaultValueForType_ReturnsNullForReferenceTypes(Type referenceType) 578 { 579 Assert.Null(MediaTypeFormatter.GetDefaultValueForType(referenceType)); 580 } 581 582 [Theory] 583 [InlineData(false)] 584 [InlineData(0)] 585 [InlineData('a')] GetDefaultValueForType_ReturnsValueForValueTypes(T value)586 public void GetDefaultValueForType_ReturnsValueForValueTypes<T>(T value) 587 { 588 Type valueType = value.GetType(); 589 T defaultValue = default(T); 590 Assert.Equal(defaultValue, MediaTypeFormatter.GetDefaultValueForType(valueType)); 591 } 592 593 [Fact] GetDefaultValueForType_ReturnsValueForStruct()594 public void GetDefaultValueForType_ReturnsValueForStruct() 595 { 596 TestStruct s = new TestStruct(); 597 598 TestStruct result = (TestStruct)MediaTypeFormatter.GetDefaultValueForType(typeof(TestStruct)); 599 600 Assert.Equal(s, result); 601 } 602 603 [Fact] SetDefaultContentHeaders_ThrowsOnNullType()604 public void SetDefaultContentHeaders_ThrowsOnNullType() 605 { 606 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 607 HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders(); 608 Assert.ThrowsArgumentNull(() => formatter.SetDefaultContentHeaders(null, contentHeaders, TestMediaType), "type"); 609 } 610 611 [Fact] SetDefaultContentHeaders_ThrowsOnNullHeaders()612 public void SetDefaultContentHeaders_ThrowsOnNullHeaders() 613 { 614 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 615 Type type = typeof(object); 616 Assert.ThrowsArgumentNull(() => formatter.SetDefaultContentHeaders(type, null, TestMediaType), "headers"); 617 } 618 619 [Fact] SetDefaultContentHeaders_UsesNonNullMediaType()620 public void SetDefaultContentHeaders_UsesNonNullMediaType() 621 { 622 // Arrange 623 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 624 Type type = typeof(object); 625 HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders(); 626 627 // Act 628 formatter.SetDefaultContentHeaders(type, contentHeaders, TestMediaType); 629 630 // Assert 631 Assert.Equal(TestMediaType, contentHeaders.ContentType.MediaType); 632 } 633 634 [Fact] SetDefaultContentHeaders_UsesDefaultSupportedMediaType()635 public void SetDefaultContentHeaders_UsesDefaultSupportedMediaType() 636 { 637 // Arrange 638 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 639 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(TestMediaType)); 640 Type type = typeof(object); 641 HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders(); 642 643 // Act 644 formatter.SetDefaultContentHeaders(type, contentHeaders, null); 645 646 // Assert 647 Assert.Equal(TestMediaType, contentHeaders.ContentType.MediaType); 648 } 649 650 [Fact] SetDefaultContentHeaders_UsesDefaultSupportedEncoding()651 public void SetDefaultContentHeaders_UsesDefaultSupportedEncoding() 652 { 653 // Arrange 654 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 655 Encoding encoding = new UnicodeEncoding(); 656 formatter.SupportedEncodings.Add(encoding); 657 Type type = typeof(object); 658 HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders(); 659 660 // Act 661 formatter.SetDefaultContentHeaders(type, contentHeaders, TestMediaType); 662 663 // Assert 664 Assert.Equal(TestMediaType, contentHeaders.ContentType.MediaType); 665 Assert.Equal(encoding.WebName, contentHeaders.ContentType.CharSet); 666 } 667 668 [Fact] SetDefaultContentHeaders_UsesDefaultSupportedMediaTypeAndEncoding()669 public void SetDefaultContentHeaders_UsesDefaultSupportedMediaTypeAndEncoding() 670 { 671 // Arrange 672 MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); 673 formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue(TestMediaType)); 674 Encoding encoding = new UnicodeEncoding(); 675 formatter.SupportedEncodings.Add(encoding); 676 Type type = typeof(object); 677 HttpContentHeaders contentHeaders = FormattingUtilities.CreateEmptyContentHeaders(); 678 679 // Act 680 formatter.SetDefaultContentHeaders(type, contentHeaders, null); 681 682 // Assert 683 Assert.Equal(TestMediaType, contentHeaders.ContentType.MediaType); 684 Assert.Equal(encoding.WebName, contentHeaders.ContentType.CharSet); 685 } 686 687 public struct TestStruct 688 { 689 private int I; TestStructSystem.Net.Http.Formatting.MediaTypeFormatterTests.TestStruct690 public TestStruct(int i) 691 { 692 I = i + 1; 693 } 694 } 695 } 696 } 697