ResumeFileResultTests.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. using Masuit.Tools.Mvc;
  2. using Masuit.Tools.Mvc.ActionResults;
  3. using Masuit.Tools.Test.Mvc.Mocks;
  4. using System;
  5. using System.IO;
  6. using System.Net;
  7. using System.Threading;
  8. using Xunit;
  9. namespace Masuit.Tools.Test.Mvc
  10. {
  11. public class ResumeFileResultTests : BaseTests
  12. {
  13. private FileInfo _file;
  14. private FileInfo _file2;
  15. public ResumeFileResultTests()
  16. {
  17. _file = new FileInfo(FilePath("download-test-file.txt"));
  18. _file2 = new FileInfo(FilePath("download-test-file2.txt"));
  19. Request.Headers.Clear();
  20. Response.ClearTestResponse();
  21. }
  22. [Fact]
  23. public void CanCalculateEtagForFile()
  24. {
  25. Assert.NotNull(ResumeFileResult.Util.Etag(_file));
  26. }
  27. [Fact]
  28. public void EtagDoesNotDependOnTime()
  29. {
  30. var etag1 = ResumeFileResult.Util.Etag(_file);
  31. Thread.Sleep(100);
  32. var etag2 = ResumeFileResult.Util.Etag(_file);
  33. Assert.Equal(etag1, etag2);
  34. }
  35. [Fact]
  36. public void EtagDoesDependOnFile()
  37. {
  38. var etag1 = ResumeFileResult.Util.Etag(_file);
  39. Thread.Sleep(100);
  40. var etag2 = ResumeFileResult.Util.Etag(_file2);
  41. Assert.NotEqual(etag1, etag2);
  42. }
  43. [Fact]
  44. public void IsRangeNotSatisfiable_Is_True_If_Range_Header_Has_Invalid_Format()
  45. {
  46. Request.Headers[HttpHeaders.Range] = "blah";
  47. Assert.True(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  48. }
  49. [Fact]
  50. public void IsRangeNotSatisfiable_Is_True_If_Start_Greater_Than_End()
  51. {
  52. Request.Headers[HttpHeaders.Range] = "bytes=100-0";
  53. Assert.True(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  54. }
  55. [Fact]
  56. public void IsRangeNotSatisfiable_Is_True_If_End_Equals_Total_File_Size()
  57. {
  58. Request.Headers[HttpHeaders.Range] = "bytes=0-" + _file.Length;
  59. Assert.True(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  60. }
  61. [Fact]
  62. public void IsRangeNotSatisfiable_Is_True_If_End_Greater_Than_Total_File_Size()
  63. {
  64. Request.Headers[HttpHeaders.Range] = "bytes=0-" + _file.Length + 10;
  65. Assert.True(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  66. }
  67. [Fact]
  68. public void IsRangeNotSatisfiable_Is_False_If_Range_Has_StartsWith_Format()
  69. {
  70. Request.Headers[HttpHeaders.Range] = "bytes=0-";
  71. Assert.False(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  72. }
  73. [Fact]
  74. public void IsRangeNotSatisfiable_Is_False_If_Range_Has_LastXbytes_Format()
  75. {
  76. Request.Headers[HttpHeaders.Range] = "bytes=-100";
  77. Assert.False(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  78. }
  79. [Fact]
  80. public void IsRangeNotSatisfiable_Is_False_If_Range_Ends_With_Last_Byte_Position()
  81. {
  82. Request.Headers[HttpHeaders.Range] = "bytes=100-" + (_file.Length - 1);
  83. Assert.False(new MockResumeFileResult(_file.FullName, Request).IsRangeNotSatisfiable());
  84. }
  85. [Fact]
  86. public void SendRange_Is_True_If_Range_Is_Correct_And_ifRange_Is_Null()
  87. {
  88. Request.Headers[HttpHeaders.Range] = "bytes=0-100";
  89. Assert.True(new MockResumeFileResult(_file.FullName, Request).SendRange());
  90. }
  91. [Fact]
  92. public void SendRange_Is_True_If_Range_And_ifRange_Are_Correct()
  93. {
  94. Request.Headers[HttpHeaders.IfRange] = ResumeFileResult.Util.Etag(_file);
  95. Request.Headers[HttpHeaders.Range] = "bytes=0-100";
  96. Assert.True(new MockResumeFileResult(_file.FullName, Request).SendRange());
  97. }
  98. [Fact]
  99. public void SendRange_Is_False_If_Range_Is_Correct_But_ifRange_Is_InCorrect()
  100. {
  101. Request.Headers[HttpHeaders.IfRange] = "incorrect etag";
  102. Request.Headers[HttpHeaders.Range] = "bytes=0-100";
  103. Assert.False(new MockResumeFileResult(_file.FullName, Request).SendRange());
  104. }
  105. [Fact]
  106. public void HeadersTest_Should_Not_Send_File_Is_RangeNotSatisfiable()
  107. {
  108. Request.Headers[HttpHeaders.Range] = "invalid";
  109. var result = new MockResumeFileResult(_file.FullName, Request);
  110. Assert.True(result.IsRangeNotSatisfiable());
  111. result.WriteFileTest(Response);
  112. Assert.Equal((int)HttpStatusCode.RequestedRangeNotSatisfiable, Response.StatusCode);
  113. Assert.NotNull(Response.Headers[HttpHeaders.Etag]);
  114. Assert.NotNull(Response.Headers[HttpHeaders.Expires]);
  115. Assert.NotNull(Response.Headers[HttpHeaders.LastModified]);
  116. Assert.Equal("bytes */" + _file.Length, Response.Headers[HttpHeaders.ContentRange]);
  117. Assert.Equal(0, Response.OutputStream.Length);
  118. }
  119. [Fact]
  120. public void Range_First_500b()
  121. {
  122. var stream = GetResponseStream("bytes=0-499");
  123. Assert.Equal(500, stream.Length);
  124. Assert.Equal(206, Response.StatusCode);
  125. Assert.Equal($"bytes 0-499/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  126. }
  127. [Fact]
  128. public void Range_From_500b_to_899b()
  129. {
  130. var stream = GetResponseStream("bytes=500-899");
  131. Assert.Equal(400, stream.Length);
  132. Assert.Equal(206, Response.StatusCode);
  133. Assert.Equal($"bytes 500-899/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  134. }
  135. [Fact]
  136. public void Range_Last_300b()
  137. {
  138. var stream = GetResponseStream("bytes=-300");
  139. Assert.Equal(300, stream.Length);
  140. Assert.Equal(206, Response.StatusCode);
  141. var from = _file.Length - 300;
  142. var to = _file.Length - 1;
  143. Assert.Equal($"bytes {from}-{to}/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  144. }
  145. [Fact]
  146. public void Range_From_100b_toThe_End()
  147. {
  148. var stream = GetResponseStream($"bytes={(_file.Length - 100)}-");
  149. Assert.Equal(100, stream.Length);
  150. Assert.Equal(206, Response.StatusCode);
  151. var from = _file.Length - 100;
  152. var to = _file.Length - 1;
  153. Assert.Equal($"bytes {from}-{to}/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  154. }
  155. [Fact]
  156. public void Range_First_1b()
  157. {
  158. var stream = GetResponseStream("bytes=0-0");
  159. Assert.Equal(1, stream.Length);
  160. Assert.Equal(206, Response.StatusCode);
  161. Assert.Equal($"bytes 0-0/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  162. }
  163. [Fact]
  164. public void Range_Last_1b()
  165. {
  166. var stream = GetResponseStream("bytes=-1");
  167. Assert.Equal(1, stream.Length);
  168. Assert.Equal(206, Response.StatusCode);
  169. var from = _file.Length - 1;
  170. var to = _file.Length - 1;
  171. Assert.Equal($"bytes {from}-{to}/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  172. }
  173. [Fact]
  174. public void Range_Whole_File_With_RangeHeader()
  175. {
  176. var stream = GetResponseStream("bytes=0-" + (_file.Length - 1));
  177. Assert.Equal(_file.Length, stream.Length);
  178. Assert.Equal(206, Response.StatusCode);
  179. Assert.Equal($"bytes 0-{(_file.Length - 1)}/{_file.Length}", Response.Headers[HttpHeaders.ContentRange]);
  180. }
  181. [Fact]
  182. public void TransmissionRange_From_0_To_0()
  183. {
  184. Request.Headers[HttpHeaders.Range] = "bytes=0-0";
  185. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  186. Assert.Equal(1, Response.OutputStream.Length);
  187. AssertBytes(_file, Response.OutputStream, 0, 1);
  188. }
  189. [Fact]
  190. public void TransmissionRange_From_1_To_100()
  191. {
  192. Request.Headers[HttpHeaders.Range] = "bytes=1-100";
  193. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  194. Assert.Equal(100, Response.OutputStream.Length);
  195. AssertBytes(_file, Response.OutputStream, 1, 100);
  196. }
  197. [Fact]
  198. public void TransmissionRange_From_101_To_theEnd()
  199. {
  200. Request.Headers[HttpHeaders.Range] = "bytes=101-";
  201. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  202. Assert.Equal(_file.Length - 101, Response.OutputStream.Length);
  203. AssertBytes(_file, Response.OutputStream, 101, (int)_file.Length);
  204. }
  205. [Fact]
  206. public void TransmissionRange_WholeFile_WithRangeHeader()
  207. {
  208. Request.Headers[HttpHeaders.Range] = "bytes=0-";
  209. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  210. Assert.Equal(_file.Length, Response.OutputStream.Length);
  211. AssertBytes(_file, Response.OutputStream, 0, (int)_file.Length);
  212. }
  213. [Fact]
  214. public void ShouldSend206If_Range_HeaderExists()
  215. {
  216. Request.Headers[HttpHeaders.Range] = "bytes=0-";
  217. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  218. Assert.Equal(206, Response.StatusCode);
  219. }
  220. [Fact]
  221. public void Etag_Should_Be_Added_To_Response_If_It_Equals_With_IfRange_In_Request__PartialResponse()
  222. {
  223. var etag = ResumeFileResult.Util.Etag(_file);
  224. Request.Headers[HttpHeaders.IfRange] = etag;
  225. Request.Headers[HttpHeaders.Range] = "bytes=0-";
  226. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  227. Assert.Equal(Response.Headers[HttpHeaders.Etag], etag);
  228. Assert.NotNull(Response.Headers[HttpHeaders.ContentRange]);
  229. Assert.Equal(206, Response.StatusCode);
  230. }
  231. private Stream GetResponseStream(string range)
  232. {
  233. Response.ClearTestResponse();
  234. Response.StatusCode = 500;
  235. Request.Headers[HttpHeaders.Range] = range;
  236. new MockResumeFileResult(_file.FullName, Request).WriteFileTest(Response);
  237. return Response.OutputStream;
  238. }
  239. private void AssertBytes(FileInfo file, Stream responseStream, int from, int to)
  240. {
  241. using (var fileStream = file.OpenRead())
  242. {
  243. responseStream.Seek(0, SeekOrigin.Begin);
  244. fileStream.Seek(from, SeekOrigin.Begin);
  245. for (var byteIndex = from; byteIndex < to; byteIndex++)
  246. {
  247. var responseByte = responseStream.ReadByte();
  248. var fileByte = fileStream.ReadByte();
  249. Assert.Equal(responseByte, fileByte);
  250. }
  251. }
  252. }
  253. }
  254. }