Merge pull request #1496 from echampet/serializers
[mono.git] / mcs / class / System.Net.Http / Test / System.Net.Http / HttpResponseMessageTest.cs
1 //
2 // HttpResponseMessageTest.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2011 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 System.Text.RegularExpressions;
33 using NUnit.Framework;
34 using System.Net.Http;
35 using System.Net;
36 using System.Net.Http.Headers;
37 using System.Linq;
38
39 namespace MonoTests.System.Net.Http
40 {
41         [TestFixture]
42         public class HttpResponseMessageTest
43         {
44                 [Test]
45                 public void Ctor_Invalid ()
46                 {
47                         try {
48                                 new HttpResponseMessage ((HttpStatusCode) (-1));
49                                 Assert.Fail ("#1");
50                         } catch (ArgumentOutOfRangeException) {
51                         }
52                 }
53
54                 [Test]
55                 public void Ctor_Default ()
56                 {
57                         var m = new HttpResponseMessage ();
58                         Assert.IsNull (m.Content, "#1");
59                         Assert.IsNotNull (m.Headers, "#2");
60                         Assert.IsTrue (m.IsSuccessStatusCode, "#3");
61                         Assert.AreEqual ("OK", m.ReasonPhrase, "#4");
62                         Assert.IsNull (m.RequestMessage, "#5");
63                         Assert.AreEqual (HttpStatusCode.OK, m.StatusCode, "#6");
64                         Assert.AreEqual (new Version (1, 1), m.Version, "#7");
65                         Assert.IsNull (m.Headers.CacheControl, "#8");
66
67                         Assert.AreEqual ("StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: <null>, Headers:\r\n{\r\n}", m.ToString (), "#9");
68                 }
69
70                 [Test]
71                 public void Headers ()
72                 {
73                         HttpResponseMessage message = new HttpResponseMessage ();
74                         HttpResponseHeaders headers = message.Headers;
75
76                         headers.AcceptRanges.Add ("ac-v");
77                         headers.Age = TimeSpan.MaxValue;
78                         headers.CacheControl = new CacheControlHeaderValue () {
79                                 MaxStale = true
80                         };
81                         headers.Connection.Add ("test-value");
82                         headers.ConnectionClose = true;
83                         headers.Date = new DateTimeOffset (DateTime.Today);
84                         headers.ETag = new EntityTagHeaderValue ("\"tag\"", true);
85                         headers.Location = new Uri ("http://xamarin.com");
86                         headers.Pragma.Add (new NameValueHeaderValue ("name", "value"));
87                         headers.ProxyAuthenticate.Add (new AuthenticationHeaderValue ("proxy", "par"));
88                         headers.RetryAfter = new RetryConditionHeaderValue (TimeSpan.MinValue);
89                         headers.Server.Add (new ProductInfoHeaderValue ("(comment)"));
90                         headers.Trailer.Add ("trailer-vvv");
91                         headers.TransferEncoding.Add (new TransferCodingHeaderValue ("tchv"));
92                         headers.TransferEncodingChunked = true;
93                         headers.Upgrade.Add (new ProductHeaderValue ("prod", "ver"));
94                         headers.Vary.Add ("vary");
95                         headers.Via.Add (new ViaHeaderValue ("protocol", "rec-by"));
96                         headers.Warning.Add (new WarningHeaderValue (5, "agent", "\"txt\""));
97                         headers.WwwAuthenticate.Add (new AuthenticationHeaderValue ("www", "par"));
98
99                         try {
100                                 headers.Add ("age", "");
101                                 Assert.Fail ("age");
102                         } catch (FormatException) {
103                         }
104
105                         try {
106                                 headers.Add ("date", "");
107                                 Assert.Fail ("date");
108                         } catch (FormatException) {
109                         }
110
111                         try {
112                                 headers.Add ("etag", "");
113                                 Assert.Fail ("etag");
114                         } catch (FormatException) {
115                         }
116
117                         try {
118                                 headers.Add ("location", "extra");
119                                 Assert.Fail ("location");
120                         } catch (FormatException) {
121                         }
122
123                         try {
124                                 headers.Add ("retry-after", "extra");
125                                 Assert.Fail ("retry-after");
126                         } catch (FormatException) {
127                         }
128
129                         headers.Add ("accept-ranges", "achs");
130 // TODO:                        headers.Add ("cache-control", "cache-value");
131                         headers.Add ("connection", "ccc");
132                         headers.Add ("pragma", "p");
133                         headers.Add ("proxy-authenticate", "ttt");
134                         headers.Add ("server", "server");
135                         headers.Add ("trailer", "tt-r");
136                         headers.Add ("transfer-encoding", "ttt");
137                         headers.Add ("upgrade", "uuu");
138                         headers.Add ("upgrade", "vvvvaa");
139                         headers.Add ("vary", "vvaar");
140                         headers.Add ("via", "prot v");
141                         headers.Add ("warning", "4 ww \"t\"");
142                         headers.Add ("www-Authenticate", "ww");
143
144                         Assert.IsTrue (headers.AcceptRanges.SequenceEqual (
145                                 new[] {
146                                         "ac-v",
147                                         "achs"
148                                 }
149                         ));
150
151                         Assert.AreEqual (TimeSpan.MaxValue, headers.Age);
152
153                         Assert.AreEqual (
154                                 new CacheControlHeaderValue () {
155                                                 MaxStale = true,
156 // TODO                                         Extensions = { new NameValueHeaderValue ("cache-value") }
157                                         }, headers.CacheControl);
158
159                         Assert.IsTrue (headers.Connection.SequenceEqual (
160                                 new string[] { "test-value", "close", "ccc" }));
161
162                         Assert.AreEqual (new DateTimeOffset (DateTime.Today), headers.Date);
163
164                         Assert.AreEqual (new EntityTagHeaderValue ("\"tag\"", true), headers.ETag);
165
166                         Assert.AreEqual (new Uri ("http://xamarin.com"), headers.Location);
167
168                         Assert.IsTrue (headers.Pragma.SequenceEqual (
169                                 new [] {
170                                         new NameValueHeaderValue ("name", "value"),
171                                         new NameValueHeaderValue ("p"),
172                                 }));
173
174                         Assert.IsTrue (headers.ProxyAuthenticate.SequenceEqual (
175                                 new [] {
176                                         new AuthenticationHeaderValue ("proxy", "par"),
177                                         new AuthenticationHeaderValue ("ttt")
178                                 }
179                         ));
180
181                         Assert.AreEqual (new RetryConditionHeaderValue (TimeSpan.MinValue), headers.RetryAfter);
182
183                         Assert.IsTrue (headers.Server.SequenceEqual (
184                                 new [] {
185                                         new ProductInfoHeaderValue ("(comment)"),
186                                         new ProductInfoHeaderValue (new ProductHeaderValue ("server"))
187                                 }
188                         ));
189
190                         Assert.IsTrue (headers.Trailer.SequenceEqual (
191                                 new [] {
192                                         "trailer-vvv",
193                                         "tt-r"
194                                 }));
195
196                         Assert.IsTrue (headers.TransferEncoding.SequenceEqual (
197                                 new[] {
198                                         new TransferCodingHeaderValue ("tchv"),
199                                         new TransferCodingHeaderValue ("chunked"),
200                                         new TransferCodingHeaderValue ("ttt")
201                                 }
202                         ));
203
204                         Assert.IsTrue (headers.Upgrade.SequenceEqual (
205                                 new[] {
206                                         new ProductHeaderValue ("prod", "ver"),
207                                         new ProductHeaderValue ("uuu"),
208                                         new ProductHeaderValue ("vvvvaa")
209                                 }
210                         ));
211
212                         Assert.IsTrue (headers.Vary.SequenceEqual (
213                                 new[] {
214                                         "vary",
215                                         "vvaar"
216                                 }
217                         ));
218
219                         Assert.IsTrue (headers.Via.SequenceEqual (
220                                 new[] {
221                                         new ViaHeaderValue ("protocol", "rec-by"),
222                                         new ViaHeaderValue ("prot", "v")
223                                 }
224                         ));
225
226                         Assert.IsTrue (headers.Warning.SequenceEqual (
227                                 new[] {
228                                         new WarningHeaderValue (5, "agent", "\"txt\""),
229                                         new WarningHeaderValue (4, "ww", "\"t\"")
230                                 }
231                         ));
232
233                         Assert.IsTrue (headers.WwwAuthenticate.SequenceEqual (
234                                 new[] {
235                                         new AuthenticationHeaderValue ("www", "par"),
236                                         new AuthenticationHeaderValue ("ww")
237                                 }
238                         ));
239                 }
240
241                 [Test]
242                 public void EnsureSuccessStatusCode ()
243                 {
244                         HttpResponseMessage message = new HttpResponseMessage ();
245                         Assert.AreSame (message, message.EnsureSuccessStatusCode (), "#1");
246
247                         message = new HttpResponseMessage (HttpStatusCode.BadRequest);
248                         message.ReasonPhrase = "test reason";
249                         try {
250                                 message.EnsureSuccessStatusCode ();
251                                 Assert.Fail ("#2");
252                         } catch (HttpRequestException e) {
253                                 Assert.IsTrue (e.Message.Contains ("400 (test reason)"), "#3");
254                         }
255                 }
256
257                 [Test]
258                 public void Headers_GetEnumerator ()
259                 {
260                         HttpResponseMessage message = new HttpResponseMessage ();
261                         HttpResponseHeaders headers = message.Headers;
262
263                         headers.Add ("a", new[] { "v1", "v2" });
264                         headers.Add ("cache-control", "audio");
265                         headers.Age = new TimeSpan (4444, 2, 3, 4, 5);
266
267                         int i = 0;
268                         List<string> values;
269                         foreach (var entry in headers) {
270                                 switch (i) {
271                                 case 0:
272                                         Assert.AreEqual ("a", entry.Key);
273                                         values = entry.Value.ToList ();
274                                         Assert.AreEqual (2, values.Count);
275                                         Assert.AreEqual ("v1", values[0]);
276                                         break;
277                                 case 1:
278                                         Assert.AreEqual ("cache-control", entry.Key);
279                                         values = entry.Value.ToList ();
280                                         Assert.AreEqual (1, values.Count);
281                                         Assert.AreEqual ("audio", values[0]);
282                                         break;
283                                 case 2:
284                                         Assert.AreEqual ("Age", entry.Key);
285                                         values = entry.Value.ToList ();
286                                         Assert.AreEqual (1, values.Count);
287                                         Assert.AreEqual ("383968984", values[0]);
288                                         break;
289                                 }
290
291                                 ++i;
292                         }
293
294                         Assert.AreEqual (3, i, "#10");
295                 }
296
297                 [Test]
298                 public void Headers_MultiValues ()
299                 {
300                         var message = new HttpResponseMessage ();
301                         var headers = message.Headers;
302
303                         headers.Add ("Proxy-Authenticate", "x, y, z,i");
304                         headers.Add ("Upgrade", "HTTP/2.0, SHTTP/1.3, IRC, RTA/x11");
305                         headers.Add ("Via", "1.0 fred, 1.1 nowhere.com (Apache/1.1)");
306                         headers.Add ("Warning", "199 Miscellaneous \"w\", 200 a \"b\"");
307
308                         Assert.AreEqual (4, headers.ProxyAuthenticate.Count, "#1a");
309                         Assert.IsTrue (headers.ProxyAuthenticate.SequenceEqual (
310                                 new[] {
311                                         new AuthenticationHeaderValue ("x"),
312
313                                         new AuthenticationHeaderValue ("y"),
314                                         new AuthenticationHeaderValue ("z"),
315                                         new AuthenticationHeaderValue ("i")
316                                 }
317                         ), "#1b");
318
319                         
320                         Assert.AreEqual (4, headers.Upgrade.Count, "#2a");
321                         Assert.IsTrue (headers.Upgrade.SequenceEqual (
322                                 new[] {
323                                         new ProductHeaderValue ("HTTP", "2.0"),
324                                         new ProductHeaderValue ("SHTTP", "1.3"),
325                                         new ProductHeaderValue ("IRC"),
326                                         new ProductHeaderValue ("RTA", "x11")
327                                 }
328                         ), "#2b");
329
330                         Assert.AreEqual (2, headers.Via.Count, "#3a");
331                         Assert.IsTrue (headers.Via.SequenceEqual (
332                                 new[] {
333                                         new ViaHeaderValue ("1.0", "fred"),
334                                         new ViaHeaderValue ("1.1", "nowhere.com", null, "(Apache/1.1)")
335                                 }
336                         ), "#2b");
337
338                         Assert.AreEqual (2, headers.Warning.Count, "#4a");
339                         Assert.IsTrue (headers.Warning.SequenceEqual (
340                                 new[] {
341                                         new WarningHeaderValue (199, "Miscellaneous", "\"w\""),
342                                         new WarningHeaderValue (200, "a", "\"b\"")
343                                 }
344                         ), "#4b");
345                 }
346
347                 [Test]
348                 public void Header_BaseImplementation ()
349                 {
350                         HttpResponseMessage message = new HttpResponseMessage ();
351                         HttpResponseHeaders headers = message.Headers;
352
353                         headers.Add ("a", "a-value");
354                         headers.Add ("b", new List<string> { "v1", "v2" });
355                         headers.Add ("c", null as string);
356                         headers.Add ("d", new string[0]);
357
358                         headers.TryAddWithoutValidation ("cache-control", "audio");
359
360                         Assert.IsFalse (headers.Contains ("nn"), "#1a");
361                         Assert.IsTrue (headers.Contains ("b"), "#1b");
362
363                         var values = headers.GetValues ("b").ToList ();
364                         Assert.AreEqual ("v1", values[0], "#2a");
365                         Assert.AreEqual ("v2", values[1], "#2b");
366
367                         Assert.IsFalse (headers.Remove ("p"), "#3a");
368                         Assert.IsTrue (headers.Remove ("b"), "#3b");
369                         Assert.IsFalse (headers.Contains ("b"), "#3b-c");
370
371                         IEnumerable<string> values2;
372                         Assert.IsTrue (headers.TryGetValues ("c", out values2));
373                         values = values2.ToList ();
374                         Assert.AreEqual ("", values[0], "#4a");
375
376                         int counter = 0;
377                         foreach (var i in headers) {
378                                 ++counter;
379                         }
380
381                         Assert.AreEqual (3, counter, "#5");
382
383                         headers.Clear ();
384                 }
385
386                 [Test]
387                 public void Headers_Invalid ()
388                 {
389                         HttpResponseMessage message = new HttpResponseMessage ();
390                         HttpResponseHeaders headers = message.Headers;
391
392                         try {
393                                 headers.Add ("age", "");
394                                 Assert.Fail ("#1");
395                         } catch (FormatException) {
396                         }
397
398                         try {
399                                 headers.Add (null, "");
400                                 Assert.Fail ("#2");
401                         } catch (ArgumentException) {
402                         }
403
404                         try {
405                                 headers.Add ("mm", null as IEnumerable<string>);
406                                 Assert.Fail ("#2b");
407                         } catch (ArgumentNullException) {
408                         }
409
410                         try {
411                                 headers.Add ("Allow", "audio");
412                                 Assert.Fail ("#2c");
413                         } catch (InvalidOperationException) {
414                         }
415
416                         Assert.IsFalse (headers.TryAddWithoutValidation ("Allow", ""), "#3");
417
418                         Assert.IsFalse (headers.TryAddWithoutValidation (null, ""), "#4");
419
420                         try {
421                                 headers.Contains (null);
422                                 Assert.Fail ("#5");
423                         } catch (ArgumentException) {
424                         }
425
426                         try {
427                                 headers.GetValues (null);
428                                 Assert.Fail ("#6a");
429                         } catch (ArgumentException) {
430                         }
431
432                         try {
433                                 headers.GetValues ("bbbb");
434                                 Assert.Fail ("#6b");
435                         } catch (InvalidOperationException) {
436                         }
437
438                         try {
439                                 headers.Add ("location", new[] { "google.com", "xamarin.com" });
440                                 Assert.Fail ("#7a");
441                         } catch (FormatException) {
442                         }
443
444                         headers.TryAddWithoutValidation ("location", "a@a.com");
445                         try {
446                                 headers.Add ("location", "w3.org");
447                                 Assert.Fail ("#7b");
448                         } catch (FormatException) {
449                         }
450                 }
451
452                 [Test]
453                 public void Headers_Request ()
454                 {
455                         HttpResponseMessage message = new HttpResponseMessage ();
456                         HttpResponseHeaders headers = message.Headers;
457
458                         headers.Add ("accept", "audio");
459                         Assert.AreEqual ("audio", headers.GetValues ("Accept").First (), "#1");
460
461                         headers.Clear ();
462                         Assert.IsTrue (headers.TryAddWithoutValidation ("accept", "audio"), "#2a");
463                         Assert.AreEqual ("audio", headers.GetValues ("Accept").First (), "#2");
464                 }
465
466                 [Test]
467                 public void Headers_ConnectionClose ()
468                 {
469                         HttpResponseMessage message = new HttpResponseMessage ();
470                         HttpResponseHeaders headers = message.Headers;
471                         Assert.IsNull (headers.ConnectionClose, "#1");
472
473                         headers.ConnectionClose = false;
474                         Assert.IsFalse (headers.ConnectionClose.Value, "#2");
475
476                         headers.Clear ();
477
478                         headers.ConnectionClose = true;
479                         Assert.IsTrue (headers.ConnectionClose.Value, "#3");
480
481                         headers.Clear ();
482                         headers.Connection.Add ("Close");
483                         Assert.IsTrue (headers.ConnectionClose.Value, "#4");
484
485                         // .NET encloses the "Connection: Close" with two whitespaces.
486                         var normalized = Regex.Replace (message.ToString (), @"\s", "");
487                         Assert.AreEqual ("StatusCode:200,ReasonPhrase:'OK',Version:1.1,Content:<null>,Headers:{Connection:Close}", normalized, "#5");
488                 }
489
490                 [Test]
491                 public void Headers_Location ()
492                 {
493                         HttpResponseMessage message = new HttpResponseMessage ();
494                         HttpResponseHeaders headers = message.Headers;
495                         headers.TryAddWithoutValidation ("location", "http://w3.org");
496                         Assert.AreEqual (new Uri ("http://w3.org"), headers.Location);
497                 }
498
499                 [Test]
500                 public void Headers_TransferEncoding ()
501                 {
502                         HttpResponseMessage message = new HttpResponseMessage ();
503                         HttpResponseHeaders headers = message.Headers;
504                         headers.TryAddWithoutValidation ("Transfer-Encoding", "mmm");
505                         headers.TryAddWithoutValidation ("Transfer-Encoding", "▀");
506                         headers.TryAddWithoutValidation ("Transfer-Encoding", "zz");
507
508                         var a = headers.TransferEncoding;
509                         Assert.AreEqual (2, a.Count, "#1");
510
511                         // Assert.AreEqual ("mmm, zz, ▀", a.ToString (), "#2");
512                 }
513
514                 [Test]
515                 public void Headers_TransferEncodingChunked ()
516                 {
517                         HttpResponseMessage message = new HttpResponseMessage ();
518                         HttpResponseHeaders headers = message.Headers;
519                         Assert.IsNull (headers.TransferEncodingChunked, "#1");
520
521                         headers.TransferEncodingChunked = false;
522                         Assert.IsFalse (headers.TransferEncodingChunked.Value, "#2");
523
524                         headers.Clear ();
525
526                         headers.TransferEncodingChunked = true;
527                         Assert.IsTrue (headers.TransferEncodingChunked.Value, "#3");
528                         Assert.AreEqual (1, headers.TransferEncoding.Count, "#3b");
529
530                         headers.Clear ();
531                         Assert.IsTrue (headers.TryAddWithoutValidation ("Transfer-Encoding", "value"), "#4-0");
532 //                      Assert.AreEqual (false, headers.TransferEncodingChunked, "#4");
533
534                         headers.Clear ();
535                         Assert.IsTrue (headers.TryAddWithoutValidation ("Transfer-Encoding", "chunked"), "#5-0");
536                         Assert.AreEqual (true, headers.TransferEncodingChunked, "#5");
537
538                         message = new HttpResponseMessage ();
539                         headers = message.Headers;
540                         Assert.IsTrue (headers.TryAddWithoutValidation ("Transfer-Encoding", "ß"), "#6-0");
541                         Assert.IsNull (headers.TransferEncodingChunked, "#6");
542                 }
543
544                 [Test]
545                 public void Properties ()
546                 {
547                         var c = new HttpResponseMessage ();
548                         c.Content = null;
549                         c.ReasonPhrase = "rphr";
550                         c.RequestMessage = new HttpRequestMessage ();
551                         c.RequestMessage.Properties.Add ("a", "test");
552                         c.StatusCode = HttpStatusCode.UnsupportedMediaType;
553                         c.Version = HttpVersion.Version10;
554
555                         Assert.IsNull (c.Content, "#1");
556                         Assert.AreEqual ("rphr", c.ReasonPhrase, "#2");
557                         Assert.AreEqual ("test", c.RequestMessage.Properties["a"], "#3");
558                         Assert.AreEqual (HttpStatusCode.UnsupportedMediaType, c.StatusCode, "#4");
559                         Assert.AreEqual (HttpVersion.Version10, c.Version, "#5");
560                         Assert.IsFalse (c.IsSuccessStatusCode, "#6");
561                 }
562
563                 [Test]
564                 public void Properties_Invalid ()
565                 {
566                         var c = new HttpResponseMessage ();
567
568                         try {
569                                 c.StatusCode = (HttpStatusCode) (-1);
570                                 Assert.Fail ("#1");
571                         } catch (ArgumentException) {
572                         }
573
574                         try {
575                                 c.Version = null;
576                                 Assert.Fail ("#2");
577                         } catch (ArgumentNullException) {
578                         }
579                 }
580         }
581 }