// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using Xunit; namespace Microsoft.Net.Http.Headers { public class StringWithQualityHeaderValueTest { [Fact] public void Ctor_StringOnlyOverload_MatchExpectation() { var value = new StringWithQualityHeaderValue("token"); Assert.Equal("token", value.Value); Assert.Null(value.Quality); Assert.Throws(() => new StringWithQualityHeaderValue(null)); Assert.Throws(() => new StringWithQualityHeaderValue("")); Assert.Throws(() => new StringWithQualityHeaderValue("in valid")); } [Fact] public void Ctor_StringWithQualityOverload_MatchExpectation() { var value = new StringWithQualityHeaderValue("token", 0.5); Assert.Equal("token", value.Value); Assert.Equal(0.5, value.Quality); Assert.Throws(() => new StringWithQualityHeaderValue(null, 0.1)); Assert.Throws(() => new StringWithQualityHeaderValue("", 0.1)); Assert.Throws(() => new StringWithQualityHeaderValue("in valid", 0.1)); Assert.Throws(() => new StringWithQualityHeaderValue("t", 1.1)); Assert.Throws(() => new StringWithQualityHeaderValue("t", -0.1)); } [Fact] public void ToString_UseDifferentValues_AllSerializedCorrectly() { var value = new StringWithQualityHeaderValue("token"); Assert.Equal("token", value.ToString()); value = new StringWithQualityHeaderValue("token", 0.1); Assert.Equal("token; q=0.1", value.ToString()); value = new StringWithQualityHeaderValue("token", 0); Assert.Equal("token; q=0.0", value.ToString()); value = new StringWithQualityHeaderValue("token", 1); Assert.Equal("token; q=1.0", value.ToString()); // Note that the quality value gets rounded value = new StringWithQualityHeaderValue("token", 0.56789); Assert.Equal("token; q=0.568", value.ToString()); } [Fact] public void GetHashCode_UseSameAndDifferentValues_SameOrDifferentHashCodes() { var value1 = new StringWithQualityHeaderValue("t", 0.123); var value2 = new StringWithQualityHeaderValue("t", 0.123); var value3 = new StringWithQualityHeaderValue("T", 0.123); var value4 = new StringWithQualityHeaderValue("t"); var value5 = new StringWithQualityHeaderValue("x", 0.123); var value6 = new StringWithQualityHeaderValue("t", 0.5); var value7 = new StringWithQualityHeaderValue("t", 0.1234); var value8 = new StringWithQualityHeaderValue("T"); var value9 = new StringWithQualityHeaderValue("x"); Assert.Equal(value1.GetHashCode(), value2.GetHashCode()); Assert.Equal(value1.GetHashCode(), value3.GetHashCode()); Assert.NotEqual(value1.GetHashCode(), value4.GetHashCode()); Assert.NotEqual(value1.GetHashCode(), value5.GetHashCode()); Assert.NotEqual(value1.GetHashCode(), value6.GetHashCode()); Assert.NotEqual(value1.GetHashCode(), value7.GetHashCode()); Assert.Equal(value4.GetHashCode(), value8.GetHashCode()); Assert.NotEqual(value4.GetHashCode(), value9.GetHashCode()); } [Fact] public void Equals_UseSameAndDifferentRanges_EqualOrNotEqualNoExceptions() { var value1 = new StringWithQualityHeaderValue("t", 0.123); var value2 = new StringWithQualityHeaderValue("t", 0.123); var value3 = new StringWithQualityHeaderValue("T", 0.123); var value4 = new StringWithQualityHeaderValue("t"); var value5 = new StringWithQualityHeaderValue("x", 0.123); var value6 = new StringWithQualityHeaderValue("t", 0.5); var value7 = new StringWithQualityHeaderValue("t", 0.1234); var value8 = new StringWithQualityHeaderValue("T"); var value9 = new StringWithQualityHeaderValue("x"); Assert.False(value1.Equals(null), "t; q=0.123 vs. "); Assert.True(value1.Equals(value2), "t; q=0.123 vs. t; q=0.123"); Assert.True(value1.Equals(value3), "t; q=0.123 vs. T; q=0.123"); Assert.False(value1.Equals(value4), "t; q=0.123 vs. t"); Assert.False(value4.Equals(value1), "t vs. t; q=0.123"); Assert.False(value1.Equals(value5), "t; q=0.123 vs. x; q=0.123"); Assert.False(value1.Equals(value6), "t; q=0.123 vs. t; q=0.5"); Assert.False(value1.Equals(value7), "t; q=0.123 vs. t; q=0.1234"); Assert.True(value4.Equals(value8), "t vs. T"); Assert.False(value4.Equals(value9), "t vs. T"); } [Fact] public void Parse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidParse("text", new StringWithQualityHeaderValue("text")); CheckValidParse("text;q=0.5", new StringWithQualityHeaderValue("text", 0.5)); CheckValidParse("text ; q = 0.5", new StringWithQualityHeaderValue("text", 0.5)); CheckValidParse("\r\n text ; q = 0.5 ", new StringWithQualityHeaderValue("text", 0.5)); CheckValidParse(" text ", new StringWithQualityHeaderValue("text")); CheckValidParse(" \r\n text \r\n ; \r\n q = 0.123", new StringWithQualityHeaderValue("text", 0.123)); CheckValidParse(" text ; q = 0.123 ", new StringWithQualityHeaderValue("text", 0.123)); CheckValidParse("text;q=1 ", new StringWithQualityHeaderValue("text", 1)); CheckValidParse("*", new StringWithQualityHeaderValue("*")); CheckValidParse("*;q=0.7", new StringWithQualityHeaderValue("*", 0.7)); CheckValidParse(" t", new StringWithQualityHeaderValue("t")); CheckValidParse("t;q=0.", new StringWithQualityHeaderValue("t", 0)); CheckValidParse("t;q=1.", new StringWithQualityHeaderValue("t", 1)); CheckValidParse("t ; q = 0", new StringWithQualityHeaderValue("t", 0)); CheckValidParse("iso-8859-5", new StringWithQualityHeaderValue("iso-8859-5")); CheckValidParse("unicode-1-1; q=0.8", new StringWithQualityHeaderValue("unicode-1-1", 0.8)); } [Theory] [InlineData("text,")] [InlineData("\r\n text ; q = 0.5, next_text ")] [InlineData(" text,next_text ")] [InlineData(" ,, text, , ,next")] [InlineData(" ,, text, , ,")] [InlineData(", \r\n text \r\n ; \r\n q = 0.123")] [InlineData("teäxt")] [InlineData("text会")] [InlineData("会")] [InlineData("t;q=会")] [InlineData("t;q=")] [InlineData("t;q")] [InlineData("t;会=1")] [InlineData("t;q会=1")] [InlineData("t y")] [InlineData("t;q=1 y")] [InlineData(null)] [InlineData("")] [InlineData(" ")] [InlineData(" ,,")] [InlineData("t;q=-1")] [InlineData("t;q=1.00001")] [InlineData("t;")] [InlineData("t;;q=1")] [InlineData("t;q=a")] [InlineData("t;qa")] [InlineData("t;q1")] public void Parse_SetOfInvalidValueStrings_Throws(string input) { Assert.Throws(() => StringWithQualityHeaderValue.Parse(input)); } [Fact] public void TryParse_SetOfValidValueStrings_ParsedCorrectly() { CheckValidTryParse("text", new StringWithQualityHeaderValue("text")); CheckValidTryParse("text;q=0.5", new StringWithQualityHeaderValue("text", 0.5)); CheckValidTryParse("text ; q = 0.5", new StringWithQualityHeaderValue("text", 0.5)); CheckValidTryParse("\r\n text ; q = 0.5 ", new StringWithQualityHeaderValue("text", 0.5)); CheckValidTryParse(" text ", new StringWithQualityHeaderValue("text")); CheckValidTryParse(" \r\n text \r\n ; \r\n q = 0.123", new StringWithQualityHeaderValue("text", 0.123)); } [Fact] public void TryParse_SetOfInvalidValueStrings_ReturnsFalse() { CheckInvalidTryParse("text,"); CheckInvalidTryParse("\r\n text ; q = 0.5, next_text "); CheckInvalidTryParse(" text,next_text "); CheckInvalidTryParse(" ,, text, , ,next"); CheckInvalidTryParse(" ,, text, , ,"); CheckInvalidTryParse(", \r\n text \r\n ; \r\n q = 0.123"); CheckInvalidTryParse("teäxt"); CheckInvalidTryParse("text会"); CheckInvalidTryParse("会"); CheckInvalidTryParse("t;q=会"); CheckInvalidTryParse("t;q="); CheckInvalidTryParse("t;q"); CheckInvalidTryParse("t;会=1"); CheckInvalidTryParse("t;q会=1"); CheckInvalidTryParse("t y"); CheckInvalidTryParse("t;q=1 y"); CheckInvalidTryParse(null); CheckInvalidTryParse(string.Empty); CheckInvalidTryParse(" "); CheckInvalidTryParse(" ,,"); } [Fact] public void ParseList_SetOfValidValueStrings_ParsedCorrectly() { var inputs = new[] { "", "text1", "text2,", "textA,textB", "text3;q=0.5", "text4;q=0.5,", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; IList results = StringWithQualityHeaderValue.ParseList(inputs); var expectedResults = new[] { new StringWithQualityHeaderValue("text1"), new StringWithQualityHeaderValue("text2"), new StringWithQualityHeaderValue("textA"), new StringWithQualityHeaderValue("textB"), new StringWithQualityHeaderValue("text3", 0.5), new StringWithQualityHeaderValue("text4", 0.5), new StringWithQualityHeaderValue("text5", 0.5), new StringWithQualityHeaderValue("text6", 0.05), new StringWithQualityHeaderValue("text7"), new StringWithQualityHeaderValue("text8", 0.5), new StringWithQualityHeaderValue("text9"), new StringWithQualityHeaderValue("text10", 0.5), }.ToList(); Assert.Equal(expectedResults, results); } [Fact] public void TryParseList_SetOfValidValueStrings_ParsedCorrectly() { var inputs = new[] { "", "text1", "text2,", "textA,textB", "text3;q=0.5", "text4;q=0.5,", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; IList results; Assert.True(StringWithQualityHeaderValue.TryParseList(inputs, out results)); var expectedResults = new[] { new StringWithQualityHeaderValue("text1"), new StringWithQualityHeaderValue("text2"), new StringWithQualityHeaderValue("textA"), new StringWithQualityHeaderValue("textB"), new StringWithQualityHeaderValue("text3", 0.5), new StringWithQualityHeaderValue("text4", 0.5), new StringWithQualityHeaderValue("text5", 0.5), new StringWithQualityHeaderValue("text6", 0.05), new StringWithQualityHeaderValue("text7"), new StringWithQualityHeaderValue("text8", 0.5), new StringWithQualityHeaderValue("text9"), new StringWithQualityHeaderValue("text10", 0.5), }.ToList(); Assert.Equal(expectedResults, results); } [Fact] public void ParseList_WithSomeInvlaidValues_Throws() { var inputs = new[] { "", "text1", "text 1", "text2", "\"text 2\",", "text3;q=0.5", "text4;q=0.5, extra stuff", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; Assert.Throws(() => StringWithQualityHeaderValue.ParseList(inputs)); } [Fact] public void TryParseList_WithSomeInvlaidValues_ReturnsFalse() { var inputs = new[] { "", "text1", "text 1", "text2", "\"text 2\",", "text3;q=0.5", "text4;q=0.5, extra stuff", " text5 ; q = 0.50 ", "\r\n text6 ; q = 0.05 ", "text7,text8;q=0.5", " text9 , text10 ; q = 0.5 ", }; IList results; Assert.False(StringWithQualityHeaderValue.TryParseList(inputs, out results)); } #region Helper methods private void CheckValidParse(string input, StringWithQualityHeaderValue expectedResult) { var result = StringWithQualityHeaderValue.Parse(input); Assert.Equal(expectedResult, result); } private void CheckValidTryParse(string input, StringWithQualityHeaderValue expectedResult) { StringWithQualityHeaderValue result = null; Assert.True(StringWithQualityHeaderValue.TryParse(input, out result)); Assert.Equal(expectedResult, result); } private void CheckInvalidTryParse(string input) { StringWithQualityHeaderValue result = null; Assert.False(StringWithQualityHeaderValue.TryParse(input, out result)); Assert.Null(result); } #endregion } }