[sgen] Clear the card table in the finishing pause
[mono.git] / mcs / class / System.ServiceModel.Web / Test / System.ServiceModel.Dispatcher / WebHttpDispatchOperationSelectorTest.cs
1 //
2 // WebHttpDispatchOperationSelectorTest.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 #if !MOBILE
30 using System;
31 using System.Globalization;
32 using System.Runtime.Serialization;
33 using System.ServiceModel;
34 using System.ServiceModel.Channels;
35 using System.ServiceModel.Description;
36 using System.ServiceModel.Dispatcher;
37 using System.ServiceModel.Web;
38 using System.Text;
39 using System.Xml;
40 using NUnit.Framework;
41
42 namespace MonoTests.System.ServiceModel.Dispatcher
43 {
44         [TestFixture]
45         public class WebHttpDispatchOperationSelectorTest
46         {
47                 [Test]
48                 [ExpectedException (typeof (ArgumentNullException))]
49                 public void ConstructorNullEndpoint ()
50                 {
51                         new WebHttpDispatchOperationSelector (null);
52                 }
53
54                 [Test]
55                 [ExpectedException (typeof (InvalidOperationException))]
56                 public void ConstructorEndpointNullAddress ()
57                 {
58                         ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService)));
59                         new WebHttpDispatchOperationSelector (se);
60                 }
61
62                 #region SelectOperation
63
64                 [Test]
65                 public void SelectOperation ()
66                 {
67                         SelectOperationCore (Create ());
68                 }
69
70                 [Test]
71                 public void SelectOperation2 ()
72                 {
73                         SelectOperationCore (Create2 ());
74                 }
75
76                 [Test]
77                 public void SelectOperation3 ()
78                 {
79                         ContractDescription cd = ContractDescription.GetContract (typeof (MyService2));
80                         Assert.IsNotNull (cd.Operations [0].Behaviors.Find<WebGetAttribute> (), "#1");
81
82                         cd = ContractDescription.GetContract (typeof (MyService));
83                         Assert.IsNull (cd.Operations [0].Behaviors.Find<WebGetAttribute> (), "#2");
84                 }
85
86                 void SelectOperationCore (MySelector d)
87                 {
88                         string name;
89                         var msg = Message.CreateMessage (MessageVersion.Soap12, "http://temuri.org/MyService/Echo"); // looks like Version is not checked
90                         Assert.IsNull (msg.Headers.To, "#1-0");
91                         Assert.IsFalse (d.SelectOperation (ref msg, out name), "#1");
92                         Assert.AreEqual ("", name, "#1-2");
93                         Assert.IsNull (msg.Headers.To, "#1-3"); // no overwrite
94                         Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#1-4");
95
96                         msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo");
97                         Assert.IsFalse (d.SelectOperation (ref msg, out name), "#2");
98                         Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#2-2");
99
100                         msg = Message.CreateMessage (MessageVersion.None, "http://foobar.org/MyService/NonExistent");
101                         Assert.IsFalse (d.SelectOperation (ref msg, out name), "#3");
102                         Assert.AreEqual ("", name, "#3-2");
103                         Assert.IsFalse (msg.Properties.ContainsKey ("UriMatched"), "#3-3");
104
105                         // version and action do not matter
106                         msg = Message.CreateMessage (MessageVersion.Soap12, "http://nonexistent.org/");
107                         var http = new HttpRequestMessageProperty ();
108                         // this mismatch is allowed. Lack of this value is OK.
109 //                      http.Method = "POST";
110                         // this mismatch is allowed. Lack of this value is OK.
111 //                      http.QueryString = "foo=bar";
112                         // this mismatch is allowed. Lack of this value is OK.
113 //                      http.Headers.Add ("Content-Type", "application/json");
114                         // so, the http property can be empty, but is required.
115                         msg.Properties.Add (HttpRequestMessageProperty.Name, http);
116                         msg.Headers.To = new Uri ("http://localhost:8080/Echo?input=hoge");
117                         Assert.IsTrue (d.SelectOperation (ref msg, out name), "#4");
118                         // FIXME: hmm... isn'y "Echo" expected?
119                         // Assert.AreEqual ("", name, "#4-2");
120                 }
121
122                 [Test]
123                 [Category ("NotWorking")]
124                 public void SelectOperationOnlyMessage ()
125                 {
126                         // This test shows strange result ... it adds UriMatched property while it does not really match the URI.
127
128                         var d = Create ();
129                         var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); // looks like Version is not checked
130                         Assert.AreEqual ("", d.SelectOperation (ref msg), "#1");
131                         Assert.IsTrue (msg.Properties.ContainsKey ("UriMatched"), "#1-2");
132
133                         msg = Message.CreateMessage (MessageVersion.None, "http://foobar.org/MyService/NonExistent");
134                         Assert.AreEqual ("", d.SelectOperation (ref msg), "#2");
135                         Assert.IsNotNull (msg.Properties ["UriMatched"], "#2-2");
136                 }
137
138                 [Test]
139                 [ExpectedException (typeof (ArgumentException))]
140                 public void SelectOperationCheckExistingProperty ()
141                 {
142                         var d = Create ();
143                         var msg = Message.CreateMessage (MessageVersion.None, "http://temuri.org/MyService/Echo"); // heh, I mistyped it and turned to prove that Action does not matter.
144                         msg.Headers.To = new Uri ("http://localhost:8080/Echo");
145
146                         // LAMESPEC: .NET does returns String.Empty, while we return the name of the operation (as IOperationSelector.SelectOperation is expected to do!)
147                         // Assert.AreEqual (String.Empty, d.SelectOperation (ref msg), "#1");
148                         d.SelectOperation (ref msg);
149
150                         // The second invocation should raise the expected exception
151                         d.SelectOperation (ref msg);
152                 }
153
154                 // Types
155
156                 class MySelector : WebHttpDispatchOperationSelector
157                 {
158                         public MySelector (ServiceEndpoint se)
159                                 : base (se)
160                         {
161                         }
162
163                         public bool SelectOperation (ref Message msg, out string name)
164                         {
165                                 bool ret;
166                                 name = SelectOperation (ref msg, out ret);
167                                 return ret;
168                         }
169                 }
170
171                 class MyBehavior : WebHttpBehavior
172                 {
173                         public WebHttpDispatchOperationSelector GetPublicOperationSelector (ServiceEndpoint se)
174                         {
175                                 return GetOperationSelector (se);
176                         }
177
178                         protected override WebHttpDispatchOperationSelector GetOperationSelector (ServiceEndpoint se)
179                         {
180                                 return new MySelector (se);
181                         }
182                 }
183
184                 [ServiceContract]
185                 public interface MyService
186                 {
187                         [OperationContract]
188 //                      [WebGet (UriTemplate = "MyService/Echo?input={input}")]
189 //                      [WebGet] // UriTemplate = "Echo?input={input}"
190                         string Echo (string input);
191                 }
192
193                 [ServiceContract (Name = "MyService")]
194                 public interface MyService2
195                 {
196                         [OperationContract (Name = "Echo")]
197                         [WebGet] // UriTemplate = "Echo?input={input}"
198                         string Echo (string input);
199                 }
200
201                 MySelector Create ()
202                 {
203                         ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService)));
204                         se.Address = new EndpointAddress ("http://localhost:8080");
205                         se.Contract.Operations [0].Behaviors.Add (new WebGetAttribute ());
206                         return new MySelector (se);
207                         //var b = new MyBehavior ();
208                         //se.Behaviors.Add (b);
209                         //return (MySelector) b.GetPublicOperationSelector (se);
210                 }
211
212                 MySelector Create2 ()
213                 {
214                         ServiceEndpoint se = new ServiceEndpoint (ContractDescription.GetContract (typeof (MyService2)));
215                         se.Address = new EndpointAddress ("http://localhost:8080");
216                         //se.Contract.Operations [0].Behaviors.Add (new WebGetAttribute ());
217                         return new MySelector (se);
218                 }
219
220                 #endregion
221
222                 #region "bug #656020"
223
224                 [DataContract]
225                 public class User
226                 {
227                         [DataMember]
228                         public string Name { get; set; }
229                 }
230
231                 [ServiceContract]
232                 interface IHello
233                 {
234                         [WebGet(UriTemplate = "{name}?age={age}&blah={blah}")]
235                         [OperationContract]
236                         string SayHi (string name, int age, string blah);
237
238                         [WebInvoke(UriTemplate = "blah")]
239                         [OperationContract]
240                         string SayHi2 (User user);
241                 }
242
243                 class Hello : IHello
244                 {
245                         public string SayHi (string name, int age, string blah)
246                         {
247                                 return string.Format ("Hi {0}: {1}, {2}", name, age, blah == null);
248                         }
249                 
250                         public string SayHi2 (User user)
251                         {
252                                 return string.Format ("Hi {0}.", user.Name);
253                         }
254                 }
255
256                 [Test]
257                 public void WebMessageFormats ()
258                 {
259                         var host = new WebServiceHost (typeof (Hello));
260                         host.AddServiceEndpoint (typeof (IHello), new WebHttpBinding (), "http://localhost:37564/");
261                         host.Description.Behaviors.Find<ServiceDebugBehavior> ().IncludeExceptionDetailInFaults = true;
262                         host.Open ();
263                         try {
264                                 // run client
265                                 using (ChannelFactory<IHello> factory = new ChannelFactory<IHello> (new WebHttpBinding (), "http://localhost:37564/"))
266                                 {
267                                         factory.Endpoint.Behaviors.Add (new WebHttpBehavior ());
268                                         IHello h = factory.CreateChannel ();
269                                         //Console.WriteLine(h.SayHi("Joe", 42, null));
270                                         Assert.AreEqual ("Hi Joe.", h.SayHi2 (new User { Name = "Joe" }), "#1");
271                                 }
272                         } finally {
273                                 host.Close ();
274                         }
275                 }
276                 
277                 #endregion
278         }
279 }
280 #endif