[System] HttpListenerRequest: ignore bad cookies and keep request alive (#5657)
[mono.git] / mcs / class / System / Test / System.Net / CookieParserTest.cs
1 using System;
2 using System.IO;
3 using System.Threading;
4 using System.Globalization;
5 using System.Net;
6 using System.Net.Sockets;
7 using NUnit.Framework;
8
9 namespace MonoTests.System.Net
10 {
11         [TestFixture]
12         public class CookieParserTest
13         {
14                 public const string A = "Foo=Bar, expires=World; expires=Sat, 11-Oct-14 22:45:19 GMT, A=B";
15                 public const string B = "A=B=C, expires=Sat, 99-Dec-01 01:00:00 XDT; Hello=World, Foo=Bar";
16                 // Only the invariant culture is allowed.
17                 public const string C = "Foo=Bar, expires=Montag, 21. Juni 2012 23:11:45";
18                 // Only comma serves as separation character.
19                 public const string D = "A=B, C=D; E=F, G=H";
20                 public const string E = "A; C; expires=Tue, 25-Jun-19 00:51:34 GMT, E=F";
21                 public const string F = "Foo = \" A, B\"C D, E=F";
22
23                 CookieCollection DoRequest (string header)
24                 {
25                         HttpWebResponse res;
26                         using (var listener = new Listener ("Set-Cookie: " + header)) {
27                                 var req = (HttpWebRequest)HttpWebRequest.Create (listener.URI);
28                                 req.CookieContainer = new CookieContainer ();
29                                 req.Method = "POST";
30                                 res = (HttpWebResponse)req.GetResponse ();
31                         }
32
33                         Assert.AreEqual (header, res.Headers.Get ("Set-Cookie"));
34                         return res.Cookies;
35                 }
36
37                 void AssertCookie (Cookie cookie, string name, string value, long ticks)
38                 {
39                         AssertCookie (cookie, name, value);
40                         if (ticks == 0)
41                                 Assert.AreEqual (0, cookie.Expires.Ticks);
42                         else
43                                 Assert.AreEqual (ticks, cookie.Expires.ToUniversalTime ().Ticks);
44                 }
45
46                 void AssertCookie (Cookie cookie, string name, string value)
47                 {
48                         Assert.AreEqual (name, cookie.Name);
49                         Assert.AreEqual (value, cookie.Value);
50                 }
51
52                 [Test]
53                 public void TestDate ()
54                 {
55                         var d1 = "Sat, 11-Oct-14 22:45:19 GMT";
56                         var d2 = "Tue, 25-Jun-19 00:51:34 GMT";
57
58                         var format = "ddd, dd'-'MMM'-'yy HH':'mm':'ss 'GMT'";
59                         var p1 = DateTime.ParseExact (d1, format, CultureInfo.InvariantCulture);
60                         p1 = DateTime.SpecifyKind (p1, DateTimeKind.Utc);
61
62                         Assert.AreEqual ("10/11/2014 22:45:19", p1.ToString ("G", CultureInfo.InvariantCulture));
63                         Assert.AreEqual (p1.Ticks, p1.ToUniversalTime ().Ticks);
64                         Assert.AreEqual (635486643190000000, p1.Ticks);
65
66                         var p2 = DateTime.ParseExact (d2, format, CultureInfo.InvariantCulture);
67                         p2 = DateTime.SpecifyKind (p2, DateTimeKind.Utc);
68                         Assert.AreEqual ("06/25/2019 00:51:34", p2.ToString ("G", CultureInfo.InvariantCulture));
69                         Assert.AreEqual (p2.Ticks, p2.ToUniversalTime ().Ticks);
70                         Assert.AreEqual (636970206940000000, p2.Ticks);
71                 }
72
73                 [Test]
74 #if FEATURE_NO_BSD_SOCKETS
75                 [ExpectedException (typeof (PlatformNotSupportedException))]
76 #endif
77                 public void TestExpires ()
78                 {
79                         var cookies = DoRequest (A);
80                         Assert.AreEqual (3, cookies.Count);
81                         AssertCookie (cookies [0], "Foo", "Bar", 0);
82                         AssertCookie (cookies [1], "expires", "World", 635486643190000000);
83                         AssertCookie (cookies [2], "A", "B", 0);
84                 }
85
86                 [Test]
87 #if FEATURE_NO_BSD_SOCKETS
88                 [ExpectedException (typeof (PlatformNotSupportedException))]
89 #endif
90                 public void TestInvalidCookie ()
91                 {
92                         var cookies = DoRequest (B);
93                         Assert.AreEqual (3, cookies.Count);
94                         AssertCookie (cookies [0], "A", "B=C");
95                         AssertCookie (cookies [1], "expires", "Sat");
96                         AssertCookie (cookies [2], "Foo", "Bar");
97                 }
98
99                 [Test]
100 #if FEATURE_NO_BSD_SOCKETS
101                 [ExpectedException (typeof (PlatformNotSupportedException))]
102 #endif
103                 public void TestLocalCulture ()
104                 {
105                         var old = Thread.CurrentThread.CurrentCulture;
106                         try {
107                                 var culture = new CultureInfo ("de-DE");
108                                 Thread.CurrentThread.CurrentCulture = culture;
109
110                                 var cookies = DoRequest (C);
111                                 Assert.AreEqual (2, cookies.Count);
112                                 AssertCookie (cookies [0], "Foo", "Bar");
113                                 AssertCookie (cookies [1], "expires", "Montag");
114                         } finally {
115                                 Thread.CurrentThread.CurrentCulture = old;
116                         }
117                 }
118
119                 [Test]
120 #if FEATURE_NO_BSD_SOCKETS
121                 [ExpectedException (typeof (PlatformNotSupportedException))]
122 #endif
123                 public void TestMultiple ()
124                 {
125                         var cookies = DoRequest (D);
126                         Assert.AreEqual (3, cookies.Count);
127                         AssertCookie (cookies [0], "A", "B");
128                         AssertCookie (cookies [1], "C", "D");
129                         AssertCookie (cookies [2], "G", "H");
130                 }
131
132                 [Test]
133 #if FEATURE_NO_BSD_SOCKETS
134                 [ExpectedException (typeof (PlatformNotSupportedException))]
135 #endif
136                 public void TestMultiple2 ()
137                 {
138                         var cookies = DoRequest (E);
139                         Assert.AreEqual (2, cookies.Count);
140                         AssertCookie (cookies [0], "A", string.Empty, 636970206940000000);
141                         AssertCookie (cookies [1], "E", "F");
142                 }
143
144                 [Test]
145 #if FEATURE_NO_BSD_SOCKETS
146                 [ExpectedException (typeof (PlatformNotSupportedException))]
147 #endif
148                 public void TestQuotation ()
149                 {
150                         var cookies = DoRequest (F);
151                         Assert.AreEqual (2, cookies.Count);
152                         AssertCookie (cookies [0], "Foo", "\" A, B\"");
153                         AssertCookie (cookies [1], "E", "F");
154                 }
155
156                 public class Listener : IDisposable
157                 {
158                         Socket socket;
159                         string[] headers;
160                         Exception ex;
161
162                         public Listener (params string[] headers)
163                         {
164                                 this.headers = headers;
165                                 Start ();
166                         }
167
168                         void Start ()
169                         {
170                                 socket = new Socket (
171                                         AddressFamily.InterNetwork, SocketType.Stream,
172                                         ProtocolType.Tcp);
173                                 socket.Bind (new IPEndPoint (IPAddress.Loopback, 0));
174                                 socket.Listen (1);
175                                 socket.BeginAccept ((result) => {
176                                         try {
177                                                 var accepted = socket.EndAccept (result);
178                                                 HandleRequest (accepted);
179                                         } catch (Exception e) {
180                                                 ex = e;
181                                         }
182                                 }, null);
183                         }
184
185                         void ThrowIfException ()
186                         {
187                                 if (ex != null)
188                                         throw ex;
189                         }
190
191                         public void Dispose ()
192                         {
193                                 if (socket != null) {
194                                         socket.Close ();
195                                         socket = null;
196                                 }
197                                 ThrowIfException ();
198                         }
199
200                         void HandleRequest (Socket accepted)
201                         {
202                                 using (var stream = new NetworkStream (accepted)) {
203                                         using (var writer = new StreamWriter (stream)) {
204                                                 writer.WriteLine ("HTTP/1.1 200 OK");
205                                                 writer.WriteLine ("Content-Type: text/plain");
206                                                 foreach (var header in headers)
207                                                         writer.WriteLine (header);
208                                                 writer.WriteLine ();
209                                                 writer.WriteLine ("HELLO");
210                                         }
211                                 }
212                         }
213
214                         public EndPoint EndPoint {
215                                 get {
216                                         ThrowIfException ();
217                                         return socket.LocalEndPoint;
218                                 }
219                         }
220
221                         public string URI {
222                                 get {
223                                         ThrowIfException ();
224                                         return string.Format ("http://{0}/", EndPoint);
225                                 }
226                         }
227                 }
228         }
229 }