Merge pull request #4433 from kumpera/android-fixes
[mono.git] / mcs / class / System.Net.Http / Test / System.Net.Http / StreamContentTest.cs
1 //
2 // StreamContentTest.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2012 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using NUnit.Framework;
33 using System.Net.Http;
34 using System.Net.Http.Headers;
35 using System.IO;
36 using System.Threading.Tasks;
37 using System.Net;
38 using System.Linq;
39 using System.Text;
40
41 namespace MonoTests.System.Net.Http
42 {
43         [TestFixture]
44         public class StreamContentTest
45         {
46                 class StreamContentMock : StreamContent
47                 {
48                         public Func<long> OnTryComputeLength;
49                         public Action OnSerializeToStreamAsync;
50
51                         public StreamContentMock (Stream stream)
52                                 : base (stream)
53                         {
54                         }
55
56                         protected override bool TryComputeLength (out long length)
57                         {
58                                 if (OnTryComputeLength != null) {
59                                         length = OnTryComputeLength ();
60                                         return true;
61                                 }
62
63                                 return base.TryComputeLength (out length);
64                         }
65
66                         protected override Task SerializeToStreamAsync (Stream stream, TransportContext context)
67                         {
68                                 if (OnSerializeToStreamAsync != null)
69                                         OnSerializeToStreamAsync ();
70
71                                 return base.SerializeToStreamAsync (stream, context);
72                         }
73                 }
74
75                 class ExceptionStream : MemoryStream
76                 {
77                         public ExceptionStream ()
78                         {
79                                 base.WriteByte (10);
80                                 base.Seek (0, SeekOrigin.Begin);
81                         }
82
83                         public override int Read (byte[] buffer, int offset, int count)
84                         {
85                                 throw new ApplicationException ("Read");
86                         }
87
88                         public override byte[] GetBuffer ()
89                         {
90                                 throw new ApplicationException ("GetBuffer");
91                         }
92                 }
93
94                 class CannotSeekStream : MemoryStream
95                 {
96                         public CannotSeekStream ()
97                                 : base (new byte [11])
98                         {
99                         }
100
101                         public override bool CanSeek {
102                                 get {
103                                         return false;
104                                 }
105                         }
106                 }
107
108                 [Test]
109                 public void Ctor_Invalid ()
110                 {
111                         try {
112                                 new StreamContent (null);
113                                 Assert.Fail ("#1");
114                         } catch (ArgumentNullException) {
115                         }
116
117                         try {
118                                 new StreamContent (new MemoryStream (), 0);
119                                 Assert.Fail ("#2");
120                         } catch (ArgumentOutOfRangeException) {
121                         }
122                 }
123
124                 [Test]
125                 public void Ctor ()
126                 {
127                         var ms = new MemoryStream ();
128                         ms.WriteByte (44);
129
130                         using (var m = new StreamContent (ms)) {
131                         }
132                 }
133
134                 [Test]
135                 public void CopyToAsync_Invalid ()
136                 {
137                         var m = new MemoryStream ();
138
139                         var sc = new StreamContent (new MemoryStream ());
140                         try {
141                                 sc.CopyToAsync (null);
142                                 Assert.Fail ("#1");
143                         } catch (ArgumentNullException) {
144                         }
145
146                         //
147                         // For some reason does not work on .net
148                         //
149                         /*
150                         sc = new StreamContent (new ExceptionStream ());
151                         try {
152                                 sc.CopyToAsync (m).Wait ();
153                                 Assert.Fail ("#2");
154                         } catch (AggregateException) {
155                         }
156                         */ 
157                 }
158
159                 [Test]
160                 /*
161                  * The .NET runtime hits the "#9" assertion.
162                  * The test succeeds with Mono.
163                  */
164                 [Category ("NotDotNet")]
165                 public void CopyToAsync ()
166                 {
167                         var ms = new MemoryStream ();
168                         ms.WriteByte (4);
169                         ms.WriteByte (2);
170                         ms.Seek (0, SeekOrigin.Begin);
171
172                         var sc = new StreamContent (ms);
173
174                         var dest = new MemoryStream ();
175                         var task = sc.CopyToAsync (dest);
176                         task.Wait ();
177                         Assert.AreEqual (2, dest.Length, "#1");
178
179                         bool hit = false;
180                         dest = new MemoryStream ();
181                         var scm = new StreamContentMock (new ExceptionStream ());
182                         scm.OnSerializeToStreamAsync = () => { hit = true; };
183                         task = scm.CopyToAsync (dest);
184                         try {
185                                 task.Wait ();
186                                 Assert.Fail ("#9");
187                         } catch (AggregateException) {
188                         }
189
190                         Assert.IsTrue (hit, "#10");
191                 }
192
193                 [Test]
194                 public void CopyToAsync_Twice ()
195                 {
196                         var ms = new MemoryStream();
197                         ms.WriteByte(4);
198                         ms.WriteByte(12);
199                         ms.WriteByte(7);
200                         ms.Seek(1, SeekOrigin.Begin);
201
202                         var sc = new StreamContent(ms);
203
204                         var dest = new MemoryStream();
205                         var task = sc.CopyToAsync(dest);
206                         Assert.True(task.Wait(3000), "#0");
207                         Assert.AreEqual(2, dest.Length, "#1");
208                         dest.Seek(0, SeekOrigin.Begin);
209                         Assert.AreEqual(12, dest.ReadByte(), "#2");
210
211                         dest = new MemoryStream();
212                         task = sc.CopyToAsync(dest);
213                         Assert.True(task.Wait(3000), "#10");
214                         Assert.AreEqual(2, dest.Length, "#11");
215                         dest.Seek(0, SeekOrigin.Begin);
216                         Assert.AreEqual(12, dest.ReadByte(), "#12");
217                 }
218
219                 [Test]
220                 public void CopyToAsync_ClosedInput ()
221                 {
222                         var stream = new MemoryStream (new byte[] { 1 });
223                         var content = new StreamContent (stream);
224                         Assert.IsTrue (content.LoadIntoBufferAsync ().Wait (3000), "#1");
225                         stream.Close ();
226
227                         var stream_out = new MemoryStream (10);
228                         Assert.IsTrue (content.CopyToAsync (stream_out).Wait (3000), "#2");
229                 }
230
231                 [Test]
232                 public void Headers ()
233                 {
234                         var ms = new MemoryStream ();
235                         ms.WriteByte (4);
236                         ms.WriteByte (2);
237                         ms.Seek (0, SeekOrigin.Begin);
238
239                         var sc = new StreamContent (ms);
240                         var headers = sc.Headers;
241                         Assert.AreEqual (2, headers.ContentLength, "#1");
242
243                         headers.ContentLength = 400;
244                         Assert.AreEqual (400, headers.ContentLength, "#1a");
245                         headers.ContentLength = null;
246
247                         var scm = new StreamContentMock (MemoryStream.Null);
248                         scm.OnTryComputeLength = () => 330;
249                         Assert.AreEqual (330, scm.Headers.ContentLength, "#2");
250
251                         headers.Allow.Add ("a1");
252                         headers.ContentDisposition = new ContentDispositionHeaderValue ("cd1");
253                         headers.ContentEncoding.Add ("ce1");
254                         headers.ContentLanguage.Add ("cl1");
255                         headers.ContentLength = 23;
256                         headers.ContentLocation = new Uri ("http://xamarin.com");
257                         headers.ContentMD5 = new byte[] { 3, 5 };
258                         headers.ContentRange = new ContentRangeHeaderValue (88, 444);
259                         headers.ContentType = new MediaTypeHeaderValue ("multipart/*");
260                         headers.Expires = new DateTimeOffset (DateTime.Today);
261                         headers.LastModified = new DateTimeOffset (DateTime.Today);
262
263
264                         headers.Add ("allow", "a2");
265                         try {
266                                 headers.Add ("content-disposition", "cd2");
267                                 Assert.Fail ("content-disposition");
268                         } catch (FormatException) {
269                         }
270
271                         headers.Add ("content-encoding", "ce3");
272                         headers.Add ("content-language", "cl2");
273
274                         try {
275                                 headers.Add ("content-length", "444");
276                                 Assert.Fail ("content-length");
277                         } catch (FormatException) {
278                         }
279
280                         try {
281                                 headers.Add ("content-location", "cl2");
282                                 Assert.Fail ("content-location");
283                         } catch (FormatException) {
284                         }
285
286                         try {
287                                 headers.Add ("content-MD5", "cmd5");
288                                 Assert.Fail ("content-MD5");
289                         } catch (FormatException) {
290                         }
291
292                         try {
293                                 headers.Add ("content-range", "133");
294                                 Assert.Fail ("content-range");
295                         } catch (FormatException) {
296                         }
297
298                         try {
299                                 headers.Add ("content-type", "ctype");
300                                 Assert.Fail ("content-type");
301                         } catch (FormatException) {
302                         }
303
304                         try {
305                                 headers.Add ("expires", "ctype");
306                                 Assert.Fail ("expires");
307                         } catch (FormatException) {
308                         }
309
310                         try {
311                                 headers.Add ("last-modified", "lmo");
312                                 Assert.Fail ("last-modified");
313                         } catch (FormatException) {
314                         }
315
316                         Assert.IsTrue (headers.Allow.SequenceEqual (
317                                 new[] {
318                                         "a1",
319                                         "a2"
320                                 }
321                         ));
322
323                         Assert.IsTrue (headers.ContentEncoding.SequenceEqual (
324                                 new[] {
325                                         "ce1",
326                                         "ce3"
327                                 }
328                         ));
329
330                         Assert.IsTrue (headers.ContentLanguage.SequenceEqual (
331                                 new[] {
332                                         "cl1",
333                                         "cl2"
334                                 }
335                         ));
336
337                         Assert.AreEqual (23, headers.ContentLength);
338                         Assert.AreEqual (new Uri ("http://xamarin.com"), headers.ContentLocation);
339                         Assert.AreEqual (new byte[] { 3, 5 }, headers.ContentMD5);
340                         Assert.AreEqual (new ContentRangeHeaderValue (88, 444), headers.ContentRange);
341                         Assert.AreEqual (new MediaTypeHeaderValue ("multipart/*"), headers.ContentType);
342                         Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.Expires);
343                         Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.LastModified);
344                         Assert.AreEqual (new ContentDispositionHeaderValue ("cd1"), headers.ContentDisposition);
345                 }
346
347                 [Test]
348                 public void Headers_ToString ()
349                 {
350                         var sc = new StreamContent (new MemoryStream ());
351                         var headers = sc.Headers;
352                         headers.ContentMD5 = new byte[] { 3, 5 };
353
354                         Assert.AreEqual ("Content-MD5: AwU=\r\n", headers.ToString (), "#1");
355                 }
356
357                 [Test]
358                 public void Headers_ContentLength ()
359                 {
360                         var content = new StreamContent (new MemoryStream (Encoding.UTF8.GetBytes ("test")));
361                         Assert.AreEqual ("", content.Headers.ToString ());
362                         var length = content.Headers.ContentLength;
363                         Assert.AreEqual ("Content-Length: 4\r\n", content.Headers.ToString ());
364                 }
365
366                 [Test]
367                 public void Headers_Invalid ()
368                 {
369                         var sc = new StreamContent (MemoryStream.Null);
370                         var h = sc.Headers;
371
372                         try {
373                                 h.Add ("Age", "");
374                                 Assert.Fail ("#1");
375                         } catch (InvalidOperationException) {
376                         }
377                 }
378
379                 [Test]
380                 public void Headers_Multi ()
381                 {
382                         var sc = new StreamContent (MemoryStream.Null);
383                         var headers = sc.Headers;
384
385                         headers.Add ("Allow", "");
386                         headers.Add ("Allow", "a , b, c");
387
388                         Assert.AreEqual (3, headers.Allow.Count, "#1a");
389                         Assert.IsTrue (headers.Allow.SequenceEqual (
390                                 new[] { "a", "b", "c" }
391                         ), "#1b");
392                 }
393
394                 [Test]
395                 public void LoadIntoBuffer ()
396                 {
397                         var ms = new MemoryStream ();
398                         ms.WriteByte (4);
399                         ms.Seek (0, SeekOrigin.Begin);
400
401                         var sc = new StreamContent (ms);
402                         Assert.IsTrue (sc.LoadIntoBufferAsync (400).Wait (200));
403                 }
404
405                 [Test]
406                 public void LoadIntoBuffer_BufferOverflow ()
407                 {
408                         var ms = new MemoryStream ();
409                         ms.Write (new byte[10000], 0, 10000);
410                         ms.Seek (0, SeekOrigin.Begin);
411
412                         var sc = new StreamContent (ms);
413                         try {
414                                 Assert.IsTrue (sc.LoadIntoBufferAsync (50).Wait (200));
415                                 Assert.Fail ("#1");
416                         } catch (AggregateException e) {
417                                 Assert.IsTrue (e.InnerException is HttpRequestException, "#2");
418                         }
419                 }
420
421                 [Test]
422                 public void ReadAsByteArrayAsync ()
423                 {
424                         var ms = new MemoryStream ();
425                         ms.WriteByte (4);
426                         ms.WriteByte (55);
427
428                         var sc = new StreamContent (ms);
429                         var res = sc.ReadAsByteArrayAsync ().Result;
430                         Assert.AreEqual (0, res.Length, "#1");
431
432                         ms.Seek (0, SeekOrigin.Begin);
433                         sc = new StreamContent (ms);
434                         res = sc.ReadAsByteArrayAsync ().Result;
435                         Assert.AreEqual (2, res.Length, "#10");
436                         Assert.AreEqual (55, res[1], "#11");
437                 }
438
439                 [Test]
440                 public void ReadAsString ()
441                 {
442                         var ms = new MemoryStream ();
443                         ms.WriteByte (77);
444                         ms.WriteByte (55);
445                         ms.Seek (0, SeekOrigin.Begin);
446
447                         var sc = new StreamContent (ms);
448                         var res = sc.ReadAsStringAsync ().Result;
449                         Assert.AreEqual ("M7", res, "#1");
450                 }
451
452                 [Test]
453                 public void ReadAsStream ()
454                 {
455                         var ms = new MemoryStream ();
456                         ms.WriteByte (77);
457                         ms.WriteByte (55);
458                         ms.Seek (0, SeekOrigin.Begin);
459
460                         var sc = new StreamContent (ms);
461                         var res = sc.ReadAsStreamAsync ().Result;
462                         Assert.AreEqual (77, res.ReadByte (), "#1");
463                 }
464
465                 [Test]
466                 public void ReadAsStreamAsync_ClosedInput ()
467                 {
468                         var stream = new MemoryStream (new byte[] { 1 });
469                         var content = new StreamContent (stream);
470                         Assert.IsTrue (content.LoadIntoBufferAsync ().Wait (3000), "#1");
471                         stream.Close ();
472
473                         var stream_read = content.ReadAsStreamAsync ().Result;
474                         Assert.IsTrue (stream_read.CanSeek, "#2");
475                         Assert.AreEqual (0, stream_read.Position, "#3");        
476                         Assert.AreEqual (1, stream_read.Length, "#4");
477                 }
478
479                 [Test]
480                 public void ContentLengthAfterLoad ()
481                 {
482                         var sc = new StreamContent (new CannotSeekStream ());
483                         Assert.IsTrue (sc.LoadIntoBufferAsync ().Wait (3000), "#1");
484                         Assert.AreEqual (11, sc.Headers.ContentLength, "#2");
485                 }
486         }
487 }