Merge pull request #496 from nicolas-raoul/unit-test-for-issue2907
[mono.git] / mcs / class / System.ServiceModel / Test / System.ServiceModel.Channels / CustomBindingTest.cs
1 //
2 // CustomBindingTest.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005 Novell, Inc.  http://www.novell.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 using System;
29 using System.Collections.ObjectModel;
30 using System.Net.Security;
31 using System.IdentityModel.Tokens;
32 using System.Runtime.Serialization;
33 using System.Security.Cryptography.X509Certificates;
34 using System.ServiceModel;
35 using System.ServiceModel.Channels;
36 using System.ServiceModel.Description;
37 using System.ServiceModel.Security;
38 using System.ServiceModel.Security.Tokens;
39 using System.Text;
40 using System.Xml;
41 using NUnit.Framework;
42
43 namespace MonoTests.System.ServiceModel.Channels
44 {
45         [TestFixture]
46         public class CustomBindingTest
47         {
48                 [Test]
49                 public void DefaultCtor ()
50                 {
51                         CustomBinding cb = new CustomBinding ();
52                         
53                         Assert.AreEqual (0, cb.Elements.Count, "#1");
54                         Assert.AreEqual ("CustomBinding", cb.Name, "#3");
55                         Assert.AreEqual ("http://tempuri.org/", cb.Namespace, "#4");
56                         Assert.AreEqual (TimeSpan.FromMinutes (1), cb.OpenTimeout, "#5");
57                         Assert.AreEqual (TimeSpan.FromMinutes (1), cb.CloseTimeout, "#6");
58                         Assert.AreEqual (TimeSpan.FromMinutes (1), cb.SendTimeout, "#7");
59                         Assert.AreEqual (TimeSpan.FromMinutes (10), cb.ReceiveTimeout, "#8");
60                         Assert.AreEqual (0, cb.CreateBindingElements ().Count, "#9");
61                 }
62
63                 class MyBinding : Binding
64                 {
65                         public override string Scheme { get { return "hoge"; } }
66
67                         public override BindingElementCollection CreateBindingElements ()
68                         {
69                                 throw new ApplicationException ("HEHE");
70                         }
71                 }
72
73                 [Test]
74                 public void CtorFromAnotherBinding ()
75                 {
76                         CustomBinding cb =
77                                 new CustomBinding (new WSHttpBinding ());
78                         // Its properties become mostly copy of the original one
79                         Assert.AreEqual (4, cb.Elements.Count, "#1");
80                         Assert.AreEqual ("http", cb.Scheme, "#2");
81                         Assert.AreEqual ("WSHttpBinding", cb.Name, "#3");
82                         Assert.AreEqual ("http://tempuri.org/", cb.Namespace, "#4");
83
84                         Assert.AreEqual (4, cb.CreateBindingElements ().Count, "#9");
85                 }
86
87                 class MessageVersionBindingElement : BindingElement {
88                         public MessageVersion Version {
89                                 get;
90                                 private set;
91                         }
92                         
93                         public MessageVersionBindingElement (MessageVersion version)
94                         {
95                                 this.Version = version;
96                         }
97                         
98                         public override BindingElement Clone ()
99                         {
100                                 return new MessageVersionBindingElement (Version);
101                         }
102                         
103                         public override T GetProperty<T> (BindingContext context)
104                         {
105                                 if (typeof (T) == typeof (MessageVersion))
106                                         return (T)(object) Version;
107                                 return null;
108                         }
109                 }
110                 
111                 [Test]
112                 public void MessageVersionProperty ()
113                 {
114                         Assert.IsNull (new CustomBinding ().MessageVersion, "#1");
115                         Assert.AreEqual (MessageVersion.Soap12WSAddressing10, new CustomBinding (new HttpTransportBindingElement ()).MessageVersion, "#2");
116                         Assert.AreEqual (MessageVersion.Soap12WSAddressing10, new CustomBinding (new TextMessageEncodingBindingElement ()).MessageVersion, "#3");
117
118                         var versions = new[] {
119                                 MessageVersion.Soap11, MessageVersion.Soap11WSAddressing10,
120                                 MessageVersion.Soap11WSAddressingAugust2004,
121                                 MessageVersion.Soap12, MessageVersion.Soap12WSAddressing10,
122                                 MessageVersion.Soap12WSAddressingAugust2004
123                         };
124                         
125                         foreach (var version in versions) {
126                                 var binding = new CustomBinding ();
127                                 binding.Elements.Add (new MessageVersionBindingElement (version));
128                                 Assert.AreEqual (version, binding.MessageVersion, "#4:" + version);
129                         }
130                 }
131
132                 [Test]
133                 [ExpectedException (typeof (ApplicationException))]
134                 public void CtorFromAnotherBindingCallsCreateBindingElement ()
135                 {
136                         new CustomBinding (new MyBinding ());
137                 }
138
139                 Message reqmsg, resmsg;
140
141                 [Test]
142                 public void CustomTransportDoesNotRequireMessageEncoding ()
143                 {
144                         ReplyHandler replier = delegate (Message msg) {
145                                 resmsg = msg;
146                         };
147
148                         RequestReceiver receiver = delegate () {
149                                 return reqmsg;
150                         };
151
152                         RequestSender sender = delegate (Message msg) {
153                                 reqmsg = msg;
154
155                                 CustomBinding br = new CustomBinding (
156                                         new HandlerTransportBindingElement (replier, receiver));
157                                 IChannelListener<IReplyChannel> l =
158                                         br.BuildChannelListener<IReplyChannel> (
159                                                 new BindingParameterCollection ());
160                                 l.Open ();
161                                 IReplyChannel rch = l.AcceptChannel ();
162                                 rch.Open ();
163                                 Message res = Message.CreateMessage (MessageVersion.Default, "urn:succeeded");
164                                 rch.ReceiveRequest ().Reply (res);
165                                 rch.Close ();
166                                 l.Close ();
167
168                                 return resmsg;
169                         };
170
171                         CustomBinding bs = new CustomBinding (
172                                 new HandlerTransportBindingElement (sender));
173
174                         IChannelFactory<IRequestChannel> f =
175                                 bs.BuildChannelFactory<IRequestChannel> (
176                                         new BindingParameterCollection ());
177                         f.Open ();
178                         IRequestChannel ch = f.CreateChannel (new EndpointAddress ("urn:dummy"));
179                         ch.Open ();
180                         Message result = ch.Request (Message.CreateMessage (MessageVersion.Default, "urn:request"));
181                 }
182
183                 [Test]
184                 public void TransportBindingElementDefaultMessageVersion ()
185                 {
186                         Assert.AreEqual (MessageVersion.Soap12WSAddressing10, new HandlerTransportBindingElement (null).GetProperty<MessageVersion> (new BindingContext (new CustomBinding (), new BindingParameterCollection ())), "version");
187                 }
188
189                 [Test]
190                 [ExpectedException (typeof (InvalidOperationException))]
191                 //  Envelope Version 'EnvelopeNone (http://schemas.microsoft.com/ws/2005/05/envelope/none)'
192                 // does not support adding Message Headers.
193                 public void MessageSecurityPOX ()
194                 {
195                         SymmetricSecurityBindingElement sbe =
196                                 new SymmetricSecurityBindingElement ();
197                         sbe.ProtectionTokenParameters =
198                                 new X509SecurityTokenParameters ();
199                         RequestSender sender = delegate (Message input) {
200                                 MessageBuffer buf = input.CreateBufferedCopy (0x10000);
201                                 using (XmlWriter w = XmlWriter.Create (Console.Error)) {
202                                         buf.CreateMessage ().WriteMessage (w);
203                                 }
204                                 return buf.CreateMessage ();
205                         };
206
207                         CustomBinding binding = new CustomBinding (
208                                 sbe,
209                                 new TextMessageEncodingBindingElement (
210                                         MessageVersion.None, Encoding.UTF8),
211                                 new HandlerTransportBindingElement (sender));
212
213                         EndpointAddress address = new EndpointAddress (
214                                 new Uri ("http://localhost:37564"),
215                                 new X509CertificateEndpointIdentity (new X509Certificate2 ("Test/Resources/test.pfx", "mono")));
216
217                         ChannelFactory<IRequestChannel> cf =
218                                 new ChannelFactory<IRequestChannel> (binding, address);
219                         IRequestChannel ch = cf.CreateChannel ();
220 /*
221                         // neither of Endpoint, Contract nor its Operation seems
222                         // to have applicable behaviors (except for
223                         // ClientCredentials)
224                         Assert.AreEqual (1, cf.Endpoint.Behaviors.Count, "EndpointBehavior");
225                         Assert.AreEqual (0, cf.Endpoint.Contract.Behaviors.Count, "ContractBehavior");
226                         Assert.AreEqual (1, cf.Endpoint.Contract.Operations.Count, "Operations");
227                         OperationDescription od = cf.Endpoint.Contract.Operations [0];
228                         Assert.AreEqual (0, od.Behaviors.Count, "OperationBehavior");
229 */
230
231                         ch.Open ();
232                         try {
233                                 ch.Request (Message.CreateMessage (MessageVersion.None, "urn:myaction"));
234                         } finally {
235                                 ch.Close ();
236                         }
237                 }
238
239                 [Test]
240                 [Ignore ("it's underway")]
241                 [Category ("NotWorking")]
242                 public void MessageSecurityManualProtection ()
243                 {
244                         SymmetricSecurityBindingElement sbe =
245                                 new SymmetricSecurityBindingElement ();
246                         sbe.ProtectionTokenParameters =
247                                 new X509SecurityTokenParameters ();
248                         RequestSender sender = delegate (Message input) {
249                                 MessageBuffer buf = input.CreateBufferedCopy (0x10000);
250                                 using (XmlWriter w = XmlWriter.Create (Console.Error)) {
251                                         buf.CreateMessage ().WriteMessage (w);
252                                 }
253                                 return buf.CreateMessage ();
254                         };
255
256                         CustomBinding binding = new CustomBinding (
257                                 sbe,
258                                 new TextMessageEncodingBindingElement (),
259                                 new HandlerTransportBindingElement (sender));
260
261                         EndpointAddress address = new EndpointAddress (
262                                 new Uri ("http://localhost:37564"),
263                                 new X509CertificateEndpointIdentity (new X509Certificate2 ("Test/Resources/test.pfx", "mono")));
264
265                         ChannelProtectionRequirements reqs =
266                                 new ChannelProtectionRequirements ();
267                         reqs.OutgoingSignatureParts.AddParts (
268                                 new MessagePartSpecification (new XmlQualifiedName ("SampleValue", "urn:foo")), "urn:myaction");
269                         BindingParameterCollection parameters =
270                                 new BindingParameterCollection ();
271                         parameters.Add (reqs);
272 /*
273                         SymmetricSecurityBindingElement innersbe =
274                                 new SymmetricSecurityBindingElement ();
275                         innersbe.ProtectionTokenParameters =
276                                 new X509SecurityTokenParameters ();
277                         sbe.ProtectionTokenParameters =
278                                 new SecureConversationSecurityTokenParameters (
279                                         innersbe, false, reqs);
280 */
281
282                         IChannelFactory<IRequestChannel> cf =
283                                 binding.BuildChannelFactory<IRequestChannel> (parameters);
284                         cf.Open ();
285                         IRequestChannel ch = cf.CreateChannel (address);
286
287                         ch.Open ();
288                         try {
289                                 ch.Request (Message.CreateMessage (MessageVersion.None, "urn:myaction", new SampleValue ()));
290                         } finally {
291                                 ch.Close ();
292                         }
293                 }
294
295                 [Test]
296                 [ExpectedException (typeof (InvalidOperationException))]
297                 public void CanBuildChannelListenerNoTransport ()
298                 {
299                         CustomBinding cb = new CustomBinding ();
300                         BindingContext ctx = new BindingContext (
301                                 cb, new BindingParameterCollection ());
302                         Assert.IsFalse (new TextMessageEncodingBindingElement ().CanBuildChannelListener<IReplyChannel> (ctx), "#1");
303                 }
304
305                 [Test]
306                 [ExpectedException (typeof (InvalidOperationException))]
307                 public void BuildChannelListenerNoTransport ()
308                 {
309                         CustomBinding cb = new CustomBinding ();
310                         BindingContext ctx = new BindingContext (
311                                 cb, new BindingParameterCollection ());
312                         new TextMessageEncodingBindingElement ().BuildChannelListener<IReplyChannel> (ctx);
313                 }
314
315                 [Test]
316                 [ExpectedException (typeof (ArgumentException))]
317                 [Category ("NotWorking")]
318                 public void BuildChannelListenerWithDuplicateElement ()
319                 {
320                         CustomBinding cb = new CustomBinding (
321                                 new TextMessageEncodingBindingElement (),
322                                 new HttpTransportBindingElement ());
323                         BindingContext ctx = new BindingContext (
324                                 cb, new BindingParameterCollection (),
325                                 new Uri ("http://localhost:37564"), String.Empty, ListenUriMode.Unique);
326                         new TextMessageEncodingBindingElement ().BuildChannelListener<IReplyChannel> (ctx);
327                 }
328
329                 [Test]
330                 [ExpectedException (typeof (InvalidOperationException))]
331                 public void BuildChannelListenerWithNoMessageVersion ()
332                 {
333                         // MyBindingElement overrides GetProperty<T>() without calling GetInnerProperty<T>() and returns null in this case.
334                         // ServiceHost.Open() tries to get MessageVersion and raises an error if it cannot get any.
335                         // HttpTransportBindingElement can actually provide one.
336                         ServiceHost host = new ServiceHost (typeof (FooService));
337                         host.AddServiceEndpoint (typeof (IFooService),
338                                 new CustomBinding (new MyBindingElement (false), new HttpTransportBindingElement ()),
339                                 "http://localhost:37564");
340                         host.Open ();
341                 }
342
343                 [Test]
344                 [ExpectedException (typeof (MyException))]
345                 public void BuildChannelListenerWithMessageVersion ()
346                 {
347                         // MyBindingElement overrides GetProperty<T>() to call GetInnerProperty<T>() (default implementation).
348                         // HttpTransportBindingElement should return Soap11.
349                         ServiceHost host = new ServiceHost (typeof (FooService));
350                         host.AddServiceEndpoint (typeof (IFooService),
351                                 new CustomBinding (new MyBindingElement (true), new HttpTransportBindingElement ()),
352                                 "http://localhost:37564");
353                         host.Open ();
354                         host.Close ();
355                 }
356
357                 [Test]
358                 [ExpectedException (typeof (InvalidOperationException))]
359                 public void RelativeListenUriNoBaseAddress ()
360                 {
361                         // MyBindingElement overrides GetProperty<T>() to call GetInnerProperty<T>() (default implementation).
362                         // HttpTransportBindingElement should return Soap11.
363                         ServiceHost host = new ServiceHost (typeof (FooService));
364                         host.AddServiceEndpoint (typeof (IFooService),
365                                 new CustomBinding (new MyBindingElement (true), new HttpTransportBindingElement ()),
366                                 "http://localhost:37564", new Uri ("foobar", UriKind.Relative));
367                 }
368
369                 [Test]
370                 [ExpectedException (typeof (MyException))]
371                 public void RelativeListenUriWithBaseAddress ()
372                 {
373                         // MyBindingElement overrides GetProperty<T>() to call GetInnerProperty<T>() (default implementation).
374                         // HttpTransportBindingElement should return Soap11.
375                         ServiceHost host = new ServiceHost (typeof (FooService), new Uri ("http://localhost:37564"));
376                         host.AddServiceEndpoint (typeof (IFooService),
377                                 new CustomBinding (new MyBindingElement (true), new HttpTransportBindingElement ()),
378                                 "http://localhost:37564", new Uri ("foobar", UriKind.Relative));
379                         host.Open ();
380                         host.Close ();
381                 }
382                 
383                 [ServiceContract]
384                 public interface IFooService
385                 {
386                         [OperationContract]
387                         string Hello (string msg);
388                 }
389                 public class FooService : IFooService
390                 {
391                         public string Hello (string msg)
392                         {
393                                 return "hello";
394                         }
395                 }
396
397                 class MyBindingElement : BindingElement
398                 {
399                         public MyBindingElement (bool returnProperty)
400                         {
401                                 return_property = returnProperty;
402                         }
403                         
404                         bool return_property;
405
406                         public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (
407                                 BindingContext ctx)
408                         {
409                                 throw new NotImplementedException ();
410                         }
411
412                         public override IChannelListener<TChannel> BuildChannelListener<TChannel> (
413                                 BindingContext ctx)
414                         {
415                                 throw new MyException ();
416                         }
417
418                         public override bool CanBuildChannelListener<TChannel> (BindingContext ctx)
419                         {
420                                 return true;
421                         }
422
423                         public override BindingElement Clone ()
424                         {
425                                 return new MyBindingElement (return_property);
426                         }
427
428                         public override T GetProperty<T> (BindingContext context)
429                         {
430                                 return return_property ? context.GetInnerProperty<T> () : null;
431                         }
432                 }
433                 
434                 public class MyException : Exception
435                 {
436                 }
437         }
438
439         [DataContract (Namespace = "urn:foo")]
440         class SampleValue
441         {
442         }
443 }