/test/System.Net.Http.Formatting.Test.Unit/Formatting/Parsers/HttpRequestHeaderParserTests.cs

https://bitbucket.org/mdavid/aspnetwebstack · C# · 275 lines · 231 code · 44 blank · 0 comment · 13 complexity · 19fabe04cca1a644a85bd04eebfbb85a MD5 · raw file

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Net.Http.Formatting.DataSets;
  4. using System.Text;
  5. using Microsoft.TestCommon;
  6. using Xunit;
  7. using Xunit.Extensions;
  8. using Assert = Microsoft.TestCommon.AssertEx;
  9. namespace System.Net.Http.Formatting.Parsers
  10. {
  11. public class HttpRequestHeaderParserTests
  12. {
  13. [Fact]
  14. [Trait("Description", "HttpRequestHeaderParser is internal class")]
  15. public void TypeIsCorrect()
  16. {
  17. Assert.Type.HasProperties<HttpRequestHeaderParser>(TypeAssert.TypeProperties.IsClass);
  18. }
  19. private static byte[] CreateBuffer(string method, string address, string version, Dictionary<string, string> headers)
  20. {
  21. const string SP = " ";
  22. const string CRLF = "\r\n";
  23. string lws = SP;
  24. StringBuilder request = new StringBuilder();
  25. request.AppendFormat("{0}{1}{2}{3}{4}{5}", method, lws, address, lws, version, CRLF);
  26. if (headers != null)
  27. {
  28. foreach (var h in headers)
  29. {
  30. request.AppendFormat("{0}: {1}{2}", h.Key, h.Value, CRLF);
  31. }
  32. }
  33. request.Append(CRLF);
  34. return Encoding.UTF8.GetBytes(request.ToString());
  35. }
  36. private static ParserState ParseBufferInSteps(HttpRequestHeaderParser parser, byte[] buffer, int readsize, out int totalBytesConsumed)
  37. {
  38. ParserState state = ParserState.Invalid;
  39. totalBytesConsumed = 0;
  40. while (totalBytesConsumed <= buffer.Length)
  41. {
  42. int size = Math.Min(buffer.Length - totalBytesConsumed, readsize);
  43. byte[] parseBuffer = new byte[size];
  44. Buffer.BlockCopy(buffer, totalBytesConsumed, parseBuffer, 0, size);
  45. int bytesConsumed = 0;
  46. state = parser.ParseBuffer(parseBuffer, parseBuffer.Length, ref bytesConsumed);
  47. totalBytesConsumed += bytesConsumed;
  48. if (state != ParserState.NeedMoreData)
  49. {
  50. return state;
  51. }
  52. }
  53. return state;
  54. }
  55. private static void ValidateResult(
  56. HttpUnsortedRequest requestLine,
  57. string method,
  58. string requestUri,
  59. Version version,
  60. Dictionary<string, string> headers)
  61. {
  62. Assert.Equal(new HttpMethod(method), requestLine.Method);
  63. Assert.Equal(requestUri, requestLine.RequestUri);
  64. Assert.Equal(version, requestLine.Version);
  65. if (headers != null)
  66. {
  67. Assert.Equal(headers.Count, requestLine.HttpHeaders.Count());
  68. foreach (var header in headers)
  69. {
  70. Assert.True(requestLine.HttpHeaders.Contains(header.Key), "Parsed header did not contain expected key " + header.Key);
  71. Assert.Equal(header.Value, requestLine.HttpHeaders.GetValues(header.Key).ElementAt(0));
  72. }
  73. }
  74. }
  75. [Fact]
  76. [Trait("Description", "HttpRequestHeaderParser constructor throws on invalid arguments")]
  77. public void HttpRequestHeaderParserConstructorTest()
  78. {
  79. HttpUnsortedRequest result = new HttpUnsortedRequest();
  80. Assert.NotNull(result);
  81. Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize - 1, ParserData.MinHeaderSize),
  82. "maxRequestLineSize", ParserData.MinRequestLineSize.ToString(), ParserData.MinRequestLineSize - 1);
  83. Assert.ThrowsArgumentGreaterThanOrEqualTo(() => new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize - 1),
  84. "maxHeaderSize", ParserData.MinHeaderSize.ToString(), ParserData.MinHeaderSize - 1);
  85. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
  86. Assert.NotNull(parser);
  87. Assert.ThrowsArgumentNull(() => { new HttpRequestHeaderParser(null); }, "httpRequest");
  88. }
  89. [Fact]
  90. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer throws on null buffer.")]
  91. public void RequestHeaderParserNullBuffer()
  92. {
  93. HttpUnsortedRequest result = new HttpUnsortedRequest();
  94. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
  95. Assert.NotNull(parser);
  96. int bytesConsumed = 0;
  97. Assert.ThrowsArgumentNull(() => { parser.ParseBuffer(null, 0, ref bytesConsumed); }, "buffer");
  98. }
  99. [Fact]
  100. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses minimum requestline.")]
  101. public void RequestHeaderParserMinimumBuffer()
  102. {
  103. byte[] data = CreateBuffer("G", "/", "HTTP/1.1", null);
  104. HttpUnsortedRequest result = new HttpUnsortedRequest();
  105. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result, ParserData.MinRequestLineSize, ParserData.MinHeaderSize);
  106. Assert.NotNull(parser);
  107. int bytesConsumed = 0;
  108. ParserState state = parser.ParseBuffer(data, data.Length, ref bytesConsumed);
  109. Assert.Equal(ParserState.Done, state);
  110. Assert.Equal(data.Length, bytesConsumed);
  111. ValidateResult(result, "G", "/", new Version("1.1"), null);
  112. }
  113. [Fact]
  114. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses standard methods.")]
  115. public void RequestHeaderParserAcceptsStandardMethods()
  116. {
  117. foreach (HttpMethod method in HttpUnitTestDataSets.AllHttpMethods)
  118. {
  119. byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1", ParserData.ValidHeaders);
  120. for (var cnt = 1; cnt <= data.Length; cnt++)
  121. {
  122. HttpUnsortedRequest result = new HttpUnsortedRequest();
  123. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  124. Assert.NotNull(parser);
  125. int totalBytesConsumed = 0;
  126. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  127. Assert.Equal(ParserState.Done, state);
  128. Assert.Equal(data.Length, totalBytesConsumed);
  129. ValidateResult(result, method.ToString(), "/", new Version("1.1"), ParserData.ValidHeaders);
  130. }
  131. }
  132. }
  133. [Fact]
  134. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer parses custom methods.")]
  135. public void RequestHeaderParserAcceptsCustomMethods()
  136. {
  137. foreach (HttpMethod method in HttpUnitTestDataSets.CustomHttpMethods)
  138. {
  139. byte[] data = CreateBuffer(method.ToString(), "/", "HTTP/1.1", ParserData.ValidHeaders);
  140. for (var cnt = 1; cnt <= data.Length; cnt++)
  141. {
  142. HttpUnsortedRequest result = new HttpUnsortedRequest();
  143. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  144. Assert.NotNull(parser);
  145. int totalBytesConsumed = 0;
  146. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  147. Assert.Equal(ParserState.Done, state);
  148. Assert.Equal(data.Length, totalBytesConsumed);
  149. ValidateResult(result, method.ToString(), "/", new Version("1.1"), ParserData.ValidHeaders);
  150. }
  151. }
  152. }
  153. [Fact]
  154. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects invalid method")]
  155. public void RequestHeaderParserRejectsInvalidMethod()
  156. {
  157. foreach (string invalidMethod in ParserData.InvalidMethods)
  158. {
  159. byte[] data = CreateBuffer(invalidMethod, "/", "HTTP/1.1", ParserData.ValidHeaders);
  160. for (var cnt = 1; cnt <= data.Length; cnt++)
  161. {
  162. HttpUnsortedRequest result = new HttpUnsortedRequest();
  163. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  164. Assert.NotNull(parser);
  165. int totalBytesConsumed = 0;
  166. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  167. Assert.Equal(ParserState.Invalid, state);
  168. }
  169. }
  170. }
  171. [Fact]
  172. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects invalid URI.")]
  173. public void RequestHeaderParserRejectsInvalidUri()
  174. {
  175. foreach (string invalidRequestUri in ParserData.InvalidRequestUris)
  176. {
  177. byte[] data = CreateBuffer("GET", invalidRequestUri, "HTTP/1.1", ParserData.ValidHeaders);
  178. for (var cnt = 1; cnt <= data.Length; cnt++)
  179. {
  180. HttpUnsortedRequest result = new HttpUnsortedRequest();
  181. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  182. Assert.NotNull(parser);
  183. int totalBytesConsumed = 0;
  184. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  185. Assert.Equal(ParserState.Invalid, state);
  186. }
  187. }
  188. }
  189. public static IEnumerable<object[]> Versions
  190. {
  191. get { return ParserData.Versions; }
  192. }
  193. [Theory]
  194. [PropertyData("Versions")]
  195. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer accepts valid versions.")]
  196. public void RequestHeaderParserAcceptsValidVersion(Version version)
  197. {
  198. byte[] data = CreateBuffer("GET", "/", String.Format("HTTP/{0}", version.ToString(2)), ParserData.ValidHeaders);
  199. for (var cnt = 1; cnt <= data.Length; cnt++)
  200. {
  201. HttpUnsortedRequest result = new HttpUnsortedRequest();
  202. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  203. Assert.NotNull(parser);
  204. int totalBytesConsumed = 0;
  205. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  206. Assert.Equal(data.Length, totalBytesConsumed);
  207. ValidateResult(result, "GET", "/", version, ParserData.ValidHeaders);
  208. }
  209. }
  210. public static IEnumerable<object[]> InvalidVersions
  211. {
  212. get { return ParserData.InvalidVersions; }
  213. }
  214. [Theory]
  215. [PropertyData("InvalidVersions")]
  216. [Trait("Description", "HttpRequestHeaderParser.ParseBuffer rejects lower case protocol version.")]
  217. public void RequestHeaderParserRejectsInvalidVersion(string invalidVersion)
  218. {
  219. byte[] data = CreateBuffer("GET", "/", invalidVersion, ParserData.ValidHeaders);
  220. for (var cnt = 1; cnt <= data.Length; cnt++)
  221. {
  222. HttpUnsortedRequest result = new HttpUnsortedRequest();
  223. HttpRequestHeaderParser parser = new HttpRequestHeaderParser(result);
  224. Assert.NotNull(parser);
  225. int totalBytesConsumed = 0;
  226. ParserState state = ParseBufferInSteps(parser, data, cnt, out totalBytesConsumed);
  227. Assert.Equal(ParserState.Invalid, state);
  228. }
  229. }
  230. }
  231. }