2 // ChannelFactory_1Test.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2006 Novell, Inc. http://www.novell.com
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System.Collections.ObjectModel;
31 using System.Runtime.Serialization;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.ServiceModel.Description;
35 using System.Threading;
37 using System.Xml.Serialization;
38 using MonoTests.System.ServiceModel.Channels;
39 using NUnit.Framework;
41 namespace MonoTests.System.ServiceModel
44 public class ChannelFactory_1Test
46 class MyChannelFactory<T> : ChannelFactory<T>
48 public MyChannelFactory (Binding b, EndpointAddress a)
53 public void OpenAnyways ()
60 [ExpectedException (typeof (InvalidOperationException))]
61 public void CreateChannelForClass ()
63 //ChannelFactory<TestService> f =
64 new ChannelFactory<TestService> (
65 new BasicHttpBinding (),
66 new EndpointAddress ("http://localhost:37564"));
70 public void EndpointAddressAfterCreateChannel ()
72 var f = new ChannelFactory<ITestService> (new BasicHttpBinding ());
73 f.CreateChannel (new EndpointAddress ("http://localhost:37564"), null);
74 Assert.IsNull (f.Endpoint.Address, "#1");
78 [Ignore ("fails under .NET; I never bothered to fix the test")]
79 public void CtorNullArgsAllowed ()
81 ChannelFactory<ICtorUseCase1> f1;
82 f1 = new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_1", null);
83 Assert.AreEqual (new EndpointAddress ("http://test1_1"), f1.Endpoint.Address, "#01");
84 f1 = new ChannelFactory<ICtorUseCase1> (new BasicHttpBinding (), (EndpointAddress)null);
85 Assert.AreEqual (null, f1.Endpoint.Address, "#01");
89 [ExpectedException (typeof (InvalidOperationException))]
90 public void CreateChannelFromDefaultConfigWithTwoConfigs ()
92 new ChannelFactory<ICtorUseCase2> ("*");
96 [ExpectedException (typeof (InvalidOperationException))]
97 public void CreateChannelFromDefaultConfigWithNoConfigs ()
99 new ChannelFactory<ICtorUseCase3> ("*");
103 [ExpectedException (typeof (ArgumentNullException))]
104 public void CtorArgsTest1 ()
106 new ChannelFactory<ICtorUseCase1> (new BasicHttpBinding (), (string)null);
110 [ExpectedException (typeof (InvalidOperationException))]
111 public void CtorArgsTest2 ()
113 new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_Incorrect");
117 [ExpectedException (typeof (ArgumentNullException))]
118 public void CtorArgsTest3 ()
120 new ChannelFactory<ICtorUseCase1> ((string)null, new EndpointAddress ("http://test"));
124 [ExpectedException (typeof (ArgumentNullException))]
125 public void ConstructorNullServiceEndpoint ()
127 new ChannelFactory<IFoo> ((ServiceEndpoint) null);
131 [ExpectedException (typeof (ArgumentNullException))]
132 public void ConstructorNullBinding ()
134 new ChannelFactory<IFoo> ((Binding) null);
138 public void ConfigEmptyCtor ()
140 // It has no valid configuration, but goes on.
141 new ChannelFactory<ICtorUseCase1> ();
145 [ExpectedException (typeof (InvalidOperationException))]
146 public void ConfigEmptyCtor2 ()
148 var cf = new ChannelFactory<ICtorUseCase1> ();
149 // It cannot go on further.
154 [Ignore ("fails under .NET; I never bothered to fix the test")]
155 public void ConfigCtor ()
157 new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_1");
161 public void EnsureOpened ()
163 MyChannelFactory<ITestService> f =
164 new MyChannelFactory<ITestService> (
165 new BasicHttpBinding (),
166 new EndpointAddress ("http://localhost:37564"));
167 Assert.AreEqual (CommunicationState.Created,
170 Assert.AreEqual (CommunicationState.Opened,
175 // I was deceived by MSDN and currently ChannelFactory<T>
176 // only accepts IChannel as T. It will be fixed. -> done.
177 public void CreateChannel ()
179 ChannelFactory<ITestService> f =
180 new ChannelFactory<ITestService> (
181 new BasicHttpBinding (),
182 new EndpointAddress ("http://localhost:37564"));
186 private T CreateChannel<T> (RequestSender handler)
188 CustomBinding b = new CustomBinding (new HandlerTransportBindingElement (handler));
189 ChannelFactory<T> f = new ChannelFactory<T> ( b, new EndpointAddress ("urn:dummy"));
190 return f.CreateChannel ();
194 public void InvokeFoo ()
196 ITestService ts = CreateChannel<ITestService> (
197 delegate (Message input) {
198 BodyWriter bw = new HandlerBodyWriter (
199 delegate (XmlDictionaryWriter writer) {
200 writer.WriteStartElement ("FooResponse", "http://tempuri.org/");
201 writer.WriteElementString ("FooResult", "http://tempuri.org/", "cecil");
202 writer.WriteEndElement ();
205 return Message.CreateMessage (input.Version, input.Headers.Action + "Response", bw);
208 Assert.AreEqual ("cecil", ts.Foo ("il offre sa confiance et son amour"));
212 public void InvokeBar ()
214 ITestService ts = CreateChannel<ITestService> (
215 delegate (Message input) {
216 BodyWriter bw = new HandlerBodyWriter (
217 delegate (XmlDictionaryWriter writer) {
218 writer.WriteStartElement ("BarResponse", "http://tempuri.org/");
219 writer.WriteElementString ("DummyBarResponse", "http://tempuri.org/", "cecil");
220 writer.WriteEndElement ();
223 return Message.CreateMessage (input.Version, input.Headers.Action + "Response", bw);
226 ts.Bar ("il offre sa confiance et son amour");
229 Message ToMessage<T> (Message input, bool isXml, T val)
231 TypedMessageConverter tm;
233 tm = TypedMessageConverter.Create (typeof (T),
234 input.Headers.Action + "Response", new XmlSerializerFormatAttribute ());
236 tm = TypedMessageConverter.Create (typeof (T),
237 input.Headers.Action + "Response");
238 return tm.ToMessage (val, input.Version);
241 T FromMessage<T> (Message input, bool isXml)
243 TypedMessageConverter tm;
245 tm = TypedMessageConverter.Create (typeof (T), input.Headers.Action,
246 new XmlSerializerFormatAttribute ());
248 tm = TypedMessageConverter.Create (typeof (T), input.Headers.Action);
249 return (T)tm.FromMessage (input);
253 public void InvokeFooOutEnumParam ()
255 ITestService ts = CreateChannel<ITestService> (
256 delegate (Message input) {
257 // Test input for in and out Enum args.
258 XmlDocument doc = new XmlDocument ();
259 doc.LoadXml (input.ToString ());
261 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
262 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
263 nss.AddNamespace ("t", "http://tempuri.org/");
264 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooOutEnumParam", nss) as XmlElement;
265 Assert.IsNotNull (el, "I#0");
266 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
267 Assert.IsNotNull (arg1, "I#2");
268 Assert.AreEqual ("Blue", arg1.InnerText, "I#3");
270 return ToMessage (input, false,
271 new FooOutEnumParamResponse (FooColor.Green, FooColor.Red));
276 FooColor res = ts.FooOutEnumParam (FooColor.Blue, out argOut);
277 Assert.AreEqual (FooColor.Green, res, "#1");
278 Assert.AreEqual (FooColor.Red, argOut, "#2");
281 public T CreateVoidFooOutParamChannel<T> (bool isXml)
283 return CreateChannel<T> (
284 delegate (Message input) {
285 // Test input for in and ref args.
286 XmlDocument doc = new XmlDocument ();
287 doc.LoadXml (input.ToString ());
289 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
290 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
291 nss.AddNamespace ("t", "http://tempuri.org/");
292 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:VoidFooOutParam", nss) as XmlElement;
293 Assert.IsNotNull (el, "I#0");
294 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
295 Assert.IsNotNull (arg1, "I#2");
296 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
297 XmlNode arg2 = el.SelectSingleNode ("t:arg2", nss);
298 Assert.IsNotNull (arg2, "I#4");
299 Assert.AreEqual ("testRef", arg2.InnerText, "I#4");
301 return ToMessage (input, isXml,
302 new VoidFooOutParamResponse ("refArg", "outArg"));
308 public void InvokeVoidFooOutParam ()
310 ITestService ts = CreateVoidFooOutParamChannel<ITestService> (false);
311 string argRef = "testRef";
313 ts.VoidFooOutParam ("testIt", ref argRef, out argOut);
314 Assert.AreEqual ("refArg", argRef, "#1");
315 Assert.AreEqual ("outArg", argOut, "#2");
319 public void XmlInvokeVoidFooOutParam ()
321 ITestServiceXml ts = CreateVoidFooOutParamChannel<ITestServiceXml> (true);
322 string argRef = "testRef";
324 ts.VoidFooOutParam ("testIt", ref argRef, out argOut);
325 Assert.AreEqual ("refArg", argRef, "#1");
326 Assert.AreEqual ("outArg", argOut, "#2");
329 public T CreateFooOutParamChannel<T> (bool isXml)
331 return CreateChannel<T> (
332 delegate (Message input) {
333 // Test input for in and ref args.
334 XmlDocument doc = new XmlDocument ();
335 doc.LoadXml (input.ToString ());
337 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
338 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
339 nss.AddNamespace ("t", "http://tempuri.org/");
340 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooOutParam", nss) as XmlElement;
341 Assert.IsNotNull (el, "I#0");
342 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
343 Assert.IsNotNull (arg1, "I#2");
344 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
345 XmlNode arg2 = el.SelectSingleNode ("t:arg2", nss);
346 Assert.IsNotNull (arg2, "I#4");
347 Assert.AreEqual ("testRef", arg2.InnerText, "I#4");
349 return ToMessage (input, isXml,
350 new FooOutParamResponse ("callResult", "refArg", "outArg"));
356 public void InvokeFooOutParam ()
358 ITestService ts = CreateFooOutParamChannel<ITestService> (false);
359 string argRef = "testRef";
361 string res = ts.FooOutParam ("testIt", ref argRef, out argOut);
362 Assert.AreEqual ("callResult", res, "#1");
363 Assert.AreEqual ("refArg", argRef, "#2");
364 Assert.AreEqual ("outArg", argOut, "#3");
368 public void XmlInvokeFooOutParam ()
370 ITestServiceXml ts = CreateFooOutParamChannel<ITestServiceXml> (true);
371 string argRef = "testRef";
373 string res = ts.FooOutParam ("testIt", ref argRef, out argOut);
374 Assert.AreEqual ("callResult", res, "#1");
375 Assert.AreEqual ("refArg", argRef, "#2");
376 Assert.AreEqual ("outArg", argOut, "#3");
380 public void InvokeFooComplex ()
382 ITestService ts = CreateChannel<ITestService> (
383 delegate (Message input) {
384 // Test input for in and ref args.
385 XmlDocument doc = new XmlDocument ();
386 doc.LoadXml (input.ToString ());
388 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
389 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
390 nss.AddNamespace ("t", "http://tempuri.org/");
391 nss.AddNamespace ("v", "http://schemas.datacontract.org/2004/07/MonoTests.System.ServiceModel");
392 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooComplex", nss) as XmlElement;
393 Assert.IsNotNull (el, "I#0");
394 XmlNode arg1 = el.SelectSingleNode ("t:arg1/v:val", nss);
395 Assert.IsNotNull (arg1, "I#2");
396 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
398 return ToMessage (input, false, new FooComplexResponse ("callResult"));
402 TestData res = ts.FooComplex (new TestData ("testIt"));
403 Assert.IsNotNull (res, "#1");
404 Assert.AreEqual ("callResult", res.val, "#2");
408 [Ignore ("This somehow results in an infinite loop")]
409 public void XmlInvokeFooComplex ()
411 ITestServiceXml ts = CreateChannel<ITestServiceXml> (
412 delegate (Message input) {
413 // Test input for in and ref args.
414 XmlDocument doc = new XmlDocument ();
415 doc.LoadXml (input.ToString ());
417 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
418 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
419 nss.AddNamespace ("t", "http://tempuri.org/");
420 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooComplex", nss) as XmlElement;
421 Assert.IsNotNull (el, "I#0");
422 XmlElement arg1 = el.SelectSingleNode ("t:arg1", nss) as XmlElement;
423 Assert.IsNotNull (arg1, "I#2");
424 Assert.AreEqual ("testIt", arg1.GetAttribute ("val"), "I#3");
426 return ToMessage (input, true, new FooComplexResponse ("callResult"));
430 TestData res = ts.FooComplex (new TestData ("testIt"));
431 Assert.IsNotNull (res, "#1");
432 Assert.AreEqual ("callResult", res.val, "#2");
437 public void ConstructorServiceEndpoint ()
439 // It is okay to pass ServiceEndpoint that does not have Binding or EndpointAddress.
440 new ChannelFactory<IRequestChannel> (new ServiceEndpoint (ContractDescription.GetContract (typeof (IMetadataExchange)), null, null));
444 public T CreateFooComplexMC_Channel<T> (bool isXml)
446 return CreateChannel<T> (
447 delegate (Message input) {
448 TestMessage arg = FromMessage<TestMessage> (input, isXml);
449 Assert.IsNotNull (arg.data, "I#0");
450 Assert.AreEqual (arg.data.val, "testIt", "I#1");
451 Assert.IsNotNull (arg.msg, "I#2");
452 Assert.AreEqual (arg.msg.val, "testMsg", "I#3");
454 return ToMessage (input, isXml, new TestResult ("callResult", "callArg"));
460 public void InvokeFooComplexMC ()
462 ITestService ts = CreateFooComplexMC_Channel<ITestService> (false);
463 TestResult res = ts.FooComplexMC (new TestMessage ("testIt", "testMsg"));
464 Assert.IsNotNull (res, "#1");
465 Assert.AreEqual ("callResult", res.resData.val, "#2");
466 Assert.AreEqual ("callArg", res.resMsg.val, "#3");
470 [Ignore ("This somehow results in an infinite loop")]
471 public void XmlInvokeFooComplexMC ()
473 ITestServiceXml ts = CreateFooComplexMC_Channel<ITestServiceXml> (true);
474 TestResult res = ts.FooComplexMC (new TestMessage ("testIt", "testMsg"));
475 Assert.IsNotNull (res, "#1");
476 Assert.AreEqual ("callResult", res.resData.val, "#2");
477 Assert.AreEqual ("callArg", res.resMsg.val, "#3");
481 public void OneWayOperationWithRequestReplyChannel ()
483 var host = new ServiceHost (typeof (OneWayService));
484 host.AddServiceEndpoint (typeof (IOneWayService),
485 new BasicHttpBinding (),
486 new Uri ("http://localhost:30158"));
489 var cf = new ChannelFactory<IOneWayService> (
490 new BasicHttpBinding (),
491 new EndpointAddress ("http://localhost:30158"));
492 var ch = cf.CreateChannel ();
493 ch.GiveMessage ("test");
495 Assert.IsTrue (OneWayService.WaitHandle.WaitOne (TimeSpan.FromSeconds (5)), "#1");
502 public interface ITestService
505 string Foo (string arg);
508 void Bar (string arg);
511 void Foo1 (string arg1, string arg2);
514 FooColor FooOutEnumParam (FooColor arg1, out FooColor arg2);
517 string FooOutParam (string arg1, ref string arg2, out string arg3);
520 void VoidFooOutParam (string arg1, ref string arg2, out string arg3);
523 TestData FooComplex (TestData arg1);
526 TestResult FooComplexMC (TestMessage arg1);
530 public interface ITestServiceXml
533 string FooOutParam (string arg1, ref string arg2, out string arg3);
536 void VoidFooOutParam (string arg1, ref string arg2, out string arg3);
539 [XmlSerializerFormat]
540 TestData FooComplex (TestData arg1);
543 [XmlSerializerFormat]
544 TestResult FooComplexMC (TestMessage arg1);
548 public interface IOneWayService
550 [OperationContract (IsOneWay = true)]
551 void GiveMessage (string input);
554 public class OneWayService : IOneWayService
556 public static ManualResetEvent WaitHandle = new ManualResetEvent (false);
558 public void GiveMessage (string input)
564 public enum FooColor { Red = 1, Green, Blue }
567 public class TestData
570 public TestData (string val) { this.val = val; }
578 public class TestMessage
581 public TestMessage (string a, string b) { data = new TestData (a); msg = new TestData (b); }
584 public TestData data;
591 public class TestResult
594 public TestResult (string a, string b) { resData = new TestData (a); resMsg = new TestData (b); }
597 public TestData resData;
600 public TestData resMsg;
603 [MessageContract (WrapperNamespace = "http://tempuri.org/")]
604 class FooOutParamResponse
606 FooOutParamResponse () {}
607 public FooOutParamResponse (string ret, string refArg, string outArg) { FooOutParamResult = ret; this.arg2 = refArg; this.arg3 = outArg; }
610 public string FooOutParamResult;
619 [MessageContract (WrapperNamespace = "http://tempuri.org/")]
620 class FooOutEnumParamResponse
622 FooOutEnumParamResponse () {}
623 public FooOutEnumParamResponse (FooColor ret, FooColor outArg) { FooOutEnumParamResult = ret; this.arg2 = outArg; }
626 public FooColor FooOutEnumParamResult;
629 public FooColor arg2;
632 [MessageContract (WrapperNamespace = "http://tempuri.org/")]
633 class VoidFooOutParamResponse
635 VoidFooOutParamResponse () {}
636 public VoidFooOutParamResponse (string refArg, string outArg) { this.arg2 = refArg; this.arg3 = outArg; }
645 [MessageContract (WrapperNamespace = "http://tempuri.org/")]
646 class FooComplexResponse
648 FooComplexResponse () {}
649 public FooComplexResponse (string val) { FooComplexResult = new TestData (val); }
652 public TestData FooComplexResult;
657 public string Foo (string arg)