Merge pull request #1870 from saper/langinfo_h
[mono.git] / mcs / class / System.ServiceModel.Web / Test / System.ServiceModel.Description / WebHttpBehaviorTest.cs
1 using System;
2 using System.IO;
3 using System.Runtime.Serialization;
4 using System.ServiceModel;
5 using System.ServiceModel.Channels;
6 using System.ServiceModel.Description;
7 using System.ServiceModel.Dispatcher;
8 using System.ServiceModel.Web;
9 using System.Text;
10 using NUnit.Framework;
11
12 namespace MonoTests.System.ServiceModel.Description
13 {
14         public class WebHttpBehaviorExt : WebHttpBehavior
15         {
16                 public IClientMessageFormatter DoGetReplyClientFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
17                 {
18                         return GetReplyClientFormatter (operationDescription, endpoint);
19                 }
20
21                 public IClientMessageFormatter DoGetRequestClientFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
22                 {
23                         return GetRequestClientFormatter (operationDescription, endpoint);
24                 }
25 #if !MOBILE
26                 public IDispatchMessageFormatter DoGetReplyDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
27                 {
28                         return GetReplyDispatchFormatter (operationDescription, endpoint);
29                 }
30
31                 public IDispatchMessageFormatter DoGetRequestDispatchFormatter (OperationDescription operationDescription, ServiceEndpoint endpoint)
32                 {
33                         return GetRequestDispatchFormatter (operationDescription, endpoint);
34                 }
35 #endif
36                 public event Action<ServiceEndpoint, ClientRuntime> ApplyClientBehaviorInvoked;
37
38                 public override void ApplyClientBehavior (ServiceEndpoint endpoint, ClientRuntime client)
39                 {
40                         base.ApplyClientBehavior (endpoint, client);
41                         if (ApplyClientBehaviorInvoked != null)
42                                 ApplyClientBehaviorInvoked (endpoint, client);
43                 }
44         }
45
46         [TestFixture]
47         public class WebHttpBehaviorTest
48         {
49                 ServiceEndpoint CreateEndpoint ()
50                 {
51                         return new ServiceEndpoint (ContractDescription.GetContract (typeof (IMyService)), new WebHttpBinding (),
52                                                     new EndpointAddress ("http://localhost:37564"));
53                 }
54
55                 [Test]
56                 public void DefaultValues ()
57                 {
58                         var b = new WebHttpBehavior ();
59                         Assert.AreEqual (WebMessageBodyStyle.Bare, b.DefaultBodyStyle, "#1");
60                         Assert.AreEqual (WebMessageFormat.Xml, b.DefaultOutgoingRequestFormat, "#2");
61                         Assert.AreEqual (WebMessageFormat.Xml, b.DefaultOutgoingResponseFormat, "#3");
62                         Assert.IsFalse (b.AutomaticFormatSelectionEnabled, "#11");
63                         Assert.IsFalse (b.FaultExceptionEnabled, "#12");
64                         Assert.IsFalse (b.HelpEnabled, "#13");
65                 }
66
67                 [Test]
68                 public void AddBiningParameters ()
69                 {
70                         var se = CreateEndpoint ();
71                         var b = new WebHttpBehavior ();
72                         var pl = new BindingParameterCollection ();
73                         b.AddBindingParameters (se, pl);
74                         Assert.AreEqual (0, pl.Count, "#1");
75                 }
76
77 #if !MOBILE
78                 [Test]
79                 public void ApplyDispatchBehavior ()
80                 {
81                         var se = CreateEndpoint ();
82                         var od = se.Contract.Operations [0];
83                         // in .NET 3.5 it adds "OperationSelectorBehavior"
84                         int initCB = ContractDescription.GetContract (typeof (IMyService)).Behaviors.Count;
85                         // in .NET 3.5 it adds
86                         // - OperationInvokeBehavior, 
87                         // - OperationBehaviorAttribute, 
88                         // - DataContractSerializerOperationBehavior and 
89                         // - DataContractSerializerOperationGenerator
90                         int initOB = od.Behaviors.Count;
91                         // Assert.AreEqual (1, initCB, "#0-1");
92                         // Assert.AreEqual (4, initOB, "#0-2");
93
94                         var b = new WebHttpBehavior ();
95                         se.Behaviors.Add (b);
96                         var ed = new EndpointDispatcher (se.Address, se.Contract.Name, se.Contract.Namespace);
97                         IChannelListener l = new WebHttpBinding ().BuildChannelListener<IReplyChannel> (new BindingParameterCollection ());
98                         var cd = new ChannelDispatcher (l);
99                         cd.Endpoints.Add (ed); // without it this test results in NRE (it blindly adds IErrorHandler).
100                         Assert.AreEqual (0, cd.ErrorHandlers.Count, "#1-1");
101                         Assert.IsNull (ed.DispatchRuntime.OperationSelector, "#1-2");
102                         Assert.AreEqual (1, se.Behaviors.Count, "#1-3-1");
103                         Assert.AreEqual (initCB, se.Contract.Behaviors.Count, "#1-3-2");
104                         Assert.AreEqual (initOB, od.Behaviors.Count, "#1-3-3");
105
106                         Assert.IsTrue (ed.AddressFilter is EndpointAddressMessageFilter, "#1-4");
107
108                         b.ApplyDispatchBehavior (se, ed);
109                         // FIXME: implement and enable it later
110                         //Assert.AreEqual (1, cd.ErrorHandlers.Count, "#2-1");
111                         Assert.AreEqual (typeof (WebHttpDispatchOperationSelector),
112                                          ed.DispatchRuntime.OperationSelector.GetType (), "#2-2");
113                         Assert.AreEqual (1, se.Behaviors.Count, "#3-1");
114                         Assert.AreEqual (initCB, se.Contract.Behaviors.Count, "#3-2");
115                         Assert.AreEqual (initOB, od.Behaviors.Count, "#3-3");
116                         // ... i.e. nothing is added.
117
118                         Assert.IsTrue (ed.AddressFilter is PrefixEndpointAddressMessageFilter, "#3-4");
119
120                         Assert.AreEqual (0, ed.DispatchRuntime.Operations.Count, "#4-0"); // hmm... really?
121                 }
122 #endif
123
124                 [Test]
125                 public void GetMessageFormatters ()
126                 {
127                         var se = CreateEndpoint ();
128                         var od = se.Contract.Operations [0];
129                         var b = new WebHttpBehaviorExt ();
130                         Assert.IsNotNull (b.DoGetRequestClientFormatter (od, se), "#1");
131                         Assert.IsNotNull (b.DoGetReplyClientFormatter (od, se), "#2");
132 #if !MOBILE
133                         Assert.IsNotNull (b.DoGetRequestDispatchFormatter (od, se), "#3");
134                         Assert.IsNotNull (b.DoGetReplyDispatchFormatter (od, se), "#4");
135 #endif
136                 }
137
138                 [Test]
139                 public void RequestClientFormatter ()
140                 {
141                         var se = CreateEndpoint ();
142                         var od = se.Contract.Operations [0];
143                         var b = new WebHttpBehaviorExt ();
144                         var rcf = b.DoGetRequestClientFormatter (od, se);
145                         var msg = rcf.SerializeRequest (MessageVersion.None, new object [] {"foo"});
146                         var hp = msg.Properties [HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
147                         Assert.IsNotNull (hp, "#1");
148                         Assert.IsTrue (msg.IsEmpty, "#2");
149                         Assert.AreEqual (String.Empty, hp.QueryString, "#3");
150                         var mb = msg.CreateBufferedCopy (1000);
151                         try {
152                                 rcf.DeserializeReply (mb.CreateMessage (), new object [0]);
153                                 Assert.Fail ("It should not support reply deserialization");
154                         } catch (NotSupportedException) {
155                         }
156                 }
157
158 #if !MOBILE
159                 [Test]
160                 public void RequestClientFormatter2 ()
161                 {
162                         var se = CreateEndpoint ();
163                         var od = se.Contract.Operations [0];
164                         var b = new WebHttpBehaviorExt ();
165                         IClientMessageFormatter rcf = null;
166                         b.ApplyClientBehaviorInvoked += delegate (ServiceEndpoint e, ClientRuntime cr) {
167                                 rcf = cr.Operations [0].Formatter;
168                         };
169                         se.Behaviors.Add (b);
170                         var ch = new WebChannelFactory<IMyServiceClient> (se).CreateChannel ();
171                         var msg = rcf.SerializeRequest (MessageVersion.None, new object [] {"foo"});
172                         var hp = msg.Properties [HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
173                         Assert.IsNotNull (hp, "#1");
174                         Assert.IsTrue (msg.IsEmpty, "#2");
175                         Assert.AreEqual (String.Empty, hp.QueryString, "#3");
176                         //var mb = msg.CreateBufferedCopy (1000);
177
178                         // TODO: test DeserializeReply too (it is supported unlike above).
179                 }
180 #endif
181
182                 [ServiceContract]
183                 public interface IMyService
184                 {
185                         [OperationContract]
186                         [WebGet]
187                         string Echo (string input);
188                 }
189
190                 public interface IMyServiceClient : IMyService, IClientChannel
191                 {
192                 }
193
194                 public class MyService: IMyService
195                 {
196 #if !MOBILE
197                         [OperationBehavior]
198 #endif
199                         public string Echo (string input)
200                         {
201                                 return input;
202                         }
203                 }
204                 
205                 [Test]
206                 public void TestWebGetExists()
207                 {
208                         ContractDescription cd = ContractDescription.GetContract (typeof(IMyService), typeof (MyService));
209                         OperationDescription od = cd.Operations[0];
210                         Assert.IsTrue (od.Behaviors.Contains (typeof (WebGetAttribute)), "Operation is recognized as WebGet");
211                 }
212
213 #if !MOBILE
214                 [Test]
215                 public void MessageFormatterSupportsRaw ()
216                 {
217                         // serializing reply
218                         var ms = new MemoryStream ();
219                         var bytes = new byte [] {0, 1, 2, 0xFF};
220                         ms.Write (bytes, 0, bytes.Length);
221                         ms.Position = 0;
222                         var cd = ContractDescription.GetContract (typeof (ITestService));
223                         var od = cd.Operations [0];
224                         var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:37564/"));
225                         var formatter = new WebHttpBehaviorExt ().DoGetReplyDispatchFormatter (od, se);
226
227                         var msg = formatter.SerializeReply (MessageVersion.None, null, ms);
228                         var wp = msg.Properties ["WebBodyFormatMessageProperty"] as WebBodyFormatMessageProperty;
229                         Assert.IsNotNull (wp, "#1");
230                         Assert.AreEqual (WebContentFormat.Raw, wp.Format, "#2");
231
232                         var wmebe = new WebMessageEncodingBindingElement ();
233                         var wme = wmebe.CreateMessageEncoderFactory ().Encoder;
234                         var ms2 = new MemoryStream ();
235                         wme.WriteMessage (msg, ms2);
236                         Assert.AreEqual (bytes, ms2.ToArray (), "#3");
237                 }
238
239                 [Test]
240                 public void MessageFormatterSupportsRaw2 ()
241                 {
242                         // deserializing request
243                         var ms = new MemoryStream ();
244                         ms.Write (new byte [] {0, 1, 2, 0xFF}, 0, 4);
245                         ms.Position = 0;
246                         var cd = ContractDescription.GetContract (typeof (ITestService));
247                         var od = cd.Operations [0];
248                         var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
249                         var wmebe = new WebMessageEncodingBindingElement ();
250                         var wme = wmebe.CreateMessageEncoderFactory ().Encoder;
251                         var msg = wme.ReadMessage (ms, 100, null); // "application/xml" causes error.
252                         var formatter = new WebHttpBehaviorExt ().DoGetRequestDispatchFormatter (od, se);
253                         object [] pars = new object [1];
254                         formatter.DeserializeRequest (msg, pars);
255                         Assert.IsTrue (pars [0] is Stream, "ret");
256                 }
257 #endif
258                 [ServiceContract]
259                 public interface IMultipleParametersGet
260                 {
261                         [OperationContract]
262                         [WebGet (UriTemplate = "get")]
263                         void Get (string p1, string p2);
264                 }
265
266                 [ServiceContract]
267                 public interface IMultipleParameters
268                 {
269                         [OperationContract]
270                         [WebInvoke (UriTemplate = "posturi?p1={p1}&p2={p2}")]
271                         string PostUri (string p1, string p2);
272
273                         [OperationContract]
274                         [WebInvoke (UriTemplate = "postone?p1={p1}")]
275                         string PostOne (string p1, string p2);
276
277                         [OperationContract]
278                         [WebInvoke (UriTemplate = "postwrapped", BodyStyle=WebMessageBodyStyle.WrappedRequest)]
279                         string PostWrapped (string p1, string p2);
280
281                         [OperationContract]
282                         [WebInvoke (UriTemplate = "out?p1={p1}&p2={p2}", BodyStyle=WebMessageBodyStyle.WrappedResponse)]
283                         void PostOut (string p1, string p2, out string ret);
284                 }
285
286                 [Test]
287                 public void MultipleParameters ()
288                 {
289                         var behavior = new WebHttpBehaviorExt ();
290                         var cd = ContractDescription.GetContract (typeof (IMultipleParameters));
291                         var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
292                         behavior.Validate (se);
293
294                         foreach (var od in cd.Operations)
295                                 behavior.DoGetRequestClientFormatter (od, se);
296                 }
297
298                 [Test]
299                 [Category ("NotWorking")]
300                 public void MultipleParameters2 ()
301                 {
302                         var behavior = new WebHttpBehaviorExt ();
303                         var cd = ContractDescription.GetContract (typeof (IMultipleParametersGet));
304                         var se = new ServiceEndpoint (cd, new WebHttpBinding (), new EndpointAddress ("http://localhost:8080/"));
305                         behavior.Validate (se);
306
307                         try {
308                                 foreach (var od in cd.Operations)
309                                         behavior.DoGetRequestClientFormatter (od, se);
310                                 Assert.Fail ("Should result in invalid operation");
311                         } catch (InvalidOperationException) {
312                         }
313                 }
314         }
315
316         [ServiceContract]
317         public interface ITestService
318         {
319                 [OperationContract]
320                 Stream Receive (Stream input);
321         }
322 }