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 using MonoTests.Helpers;
43 namespace MonoTests.System.ServiceModel
46 public class ChannelFactory_1Test
48 class MyChannelFactory<T> : ChannelFactory<T>
50 public MyChannelFactory (Binding b, EndpointAddress a)
55 public void OpenAnyways ()
62 [ExpectedException (typeof (InvalidOperationException))]
63 public void CreateChannelForClass ()
65 //ChannelFactory<TestService> f =
66 new ChannelFactory<TestService> (
67 new BasicHttpBinding (),
68 new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()));
72 public void EndpointAddressAfterCreateChannel ()
74 var f = new ChannelFactory<ITestService> (new BasicHttpBinding ());
75 f.CreateChannel (new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()), null);
76 Assert.IsNull (f.Endpoint.Address, "#1");
80 [Ignore ("fails under .NET; I never bothered to fix the test")]
81 public void CtorNullArgsAllowed ()
83 ChannelFactory<ICtorUseCase1> f1;
84 f1 = new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_1", null);
85 Assert.AreEqual (new EndpointAddress ("http://test1_1"), f1.Endpoint.Address, "#01");
86 f1 = new ChannelFactory<ICtorUseCase1> (new BasicHttpBinding (), (EndpointAddress)null);
87 Assert.AreEqual (null, f1.Endpoint.Address, "#01");
91 [ExpectedException (typeof (InvalidOperationException))]
92 public void CreateChannelFromDefaultConfigWithTwoConfigs ()
94 new ChannelFactory<ICtorUseCase2> ("*");
98 [ExpectedException (typeof (InvalidOperationException))]
99 public void CreateChannelFromDefaultConfigWithNoConfigs ()
101 new ChannelFactory<ICtorUseCase3> ("*");
105 [ExpectedException (typeof (ArgumentNullException))]
106 public void CtorArgsTest1 ()
108 new ChannelFactory<ICtorUseCase1> (new BasicHttpBinding (), (string)null);
112 [ExpectedException (typeof (InvalidOperationException))]
113 public void CtorArgsTest2 ()
115 new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_Incorrect");
119 [ExpectedException (typeof (ArgumentNullException))]
120 public void CtorArgsTest3 ()
122 new ChannelFactory<ICtorUseCase1> ((string)null, new EndpointAddress ("http://test"));
126 [ExpectedException (typeof (ArgumentNullException))]
127 public void ConstructorNullServiceEndpoint ()
129 new ChannelFactory<IFoo> ((ServiceEndpoint) null);
133 [ExpectedException (typeof (ArgumentNullException))]
134 public void ConstructorNullBinding ()
136 new ChannelFactory<IFoo> ((Binding) null);
140 public void ConfigEmptyCtor ()
142 // It has no valid configuration, but goes on.
143 new ChannelFactory<ICtorUseCase1> ();
147 [ExpectedException (typeof (InvalidOperationException))]
148 public void ConfigEmptyCtor2 ()
150 var cf = new ChannelFactory<ICtorUseCase1> ();
151 // It cannot go on further.
156 [Ignore ("fails under .NET; I never bothered to fix the test")]
157 public void ConfigCtor ()
159 new ChannelFactory<ICtorUseCase1> ("CtorUseCase1_1");
163 public void EnsureOpened ()
165 MyChannelFactory<ITestService> f =
166 new MyChannelFactory<ITestService> (
167 new BasicHttpBinding (),
168 new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()));
169 Assert.AreEqual (CommunicationState.Created,
172 Assert.AreEqual (CommunicationState.Opened,
177 // I was deceived by MSDN and currently ChannelFactory<T>
178 // only accepts IChannel as T. It will be fixed. -> done.
179 public void CreateChannel ()
181 ChannelFactory<ITestService> f =
182 new ChannelFactory<ITestService> (
183 new BasicHttpBinding (),
184 new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()));
188 private T CreateChannel<T> (RequestSender handler)
190 CustomBinding b = new CustomBinding (new HandlerTransportBindingElement (handler));
191 ChannelFactory<T> f = new ChannelFactory<T> ( b, new EndpointAddress ("urn:dummy"));
192 return f.CreateChannel ();
196 public void InvokeFoo ()
198 ITestService ts = CreateChannel<ITestService> (
199 delegate (Message input) {
200 BodyWriter bw = new HandlerBodyWriter (
201 delegate (XmlDictionaryWriter writer) {
202 writer.WriteStartElement ("FooResponse", "http://tempuri.org/");
203 writer.WriteElementString ("FooResult", "http://tempuri.org/", "cecil");
204 writer.WriteEndElement ();
207 return Message.CreateMessage (input.Version, input.Headers.Action + "Response", bw);
210 Assert.AreEqual ("cecil", ts.Foo ("il offre sa confiance et son amour"));
214 public void InvokeBar ()
216 ITestService ts = CreateChannel<ITestService> (
217 delegate (Message input) {
218 BodyWriter bw = new HandlerBodyWriter (
219 delegate (XmlDictionaryWriter writer) {
220 writer.WriteStartElement ("BarResponse", "http://tempuri.org/");
221 writer.WriteElementString ("DummyBarResponse", "http://tempuri.org/", "cecil");
222 writer.WriteEndElement ();
225 return Message.CreateMessage (input.Version, input.Headers.Action + "Response", bw);
228 ts.Bar ("il offre sa confiance et son amour");
231 Message ToMessage<T> (Message input, bool isXml, T val)
233 TypedMessageConverter tm;
235 tm = TypedMessageConverter.Create (typeof (T),
236 input.Headers.Action + "Response", new XmlSerializerFormatAttribute ());
238 tm = TypedMessageConverter.Create (typeof (T),
239 input.Headers.Action + "Response");
240 return tm.ToMessage (val, input.Version);
243 T FromMessage<T> (Message input, bool isXml)
245 TypedMessageConverter tm;
247 tm = TypedMessageConverter.Create (typeof (T), input.Headers.Action,
248 new XmlSerializerFormatAttribute ());
250 tm = TypedMessageConverter.Create (typeof (T), input.Headers.Action);
251 return (T)tm.FromMessage (input);
255 public void InvokeFooOutEnumParam ()
257 ITestService ts = CreateChannel<ITestService> (
258 delegate (Message input) {
259 // Test input for in and out Enum args.
260 XmlDocument doc = new XmlDocument ();
261 doc.LoadXml (input.ToString ());
263 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
264 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
265 nss.AddNamespace ("t", "http://tempuri.org/");
266 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooOutEnumParam", nss) as XmlElement;
267 Assert.IsNotNull (el, "I#0");
268 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
269 Assert.IsNotNull (arg1, "I#2");
270 Assert.AreEqual ("Blue", arg1.InnerText, "I#3");
272 return ToMessage (input, false,
273 new FooOutEnumParamResponse (FooColor.Green, FooColor.Red));
278 FooColor res = ts.FooOutEnumParam (FooColor.Blue, out argOut);
279 Assert.AreEqual (FooColor.Green, res, "#1");
280 Assert.AreEqual (FooColor.Red, argOut, "#2");
283 public T CreateVoidFooOutParamChannel<T> (bool isXml)
285 return CreateChannel<T> (
286 delegate (Message input) {
287 // Test input for in and ref args.
288 XmlDocument doc = new XmlDocument ();
289 doc.LoadXml (input.ToString ());
291 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
292 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
293 nss.AddNamespace ("t", "http://tempuri.org/");
294 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:VoidFooOutParam", nss) as XmlElement;
295 Assert.IsNotNull (el, "I#0");
296 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
297 Assert.IsNotNull (arg1, "I#2");
298 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
299 XmlNode arg2 = el.SelectSingleNode ("t:arg2", nss);
300 Assert.IsNotNull (arg2, "I#4");
301 Assert.AreEqual ("testRef", arg2.InnerText, "I#4");
303 return ToMessage (input, isXml,
304 new VoidFooOutParamResponse ("refArg", "outArg"));
310 public void InvokeVoidFooOutParam ()
312 ITestService ts = CreateVoidFooOutParamChannel<ITestService> (false);
313 string argRef = "testRef";
315 ts.VoidFooOutParam ("testIt", ref argRef, out argOut);
316 Assert.AreEqual ("refArg", argRef, "#1");
317 Assert.AreEqual ("outArg", argOut, "#2");
321 public void XmlInvokeVoidFooOutParam ()
323 ITestServiceXml ts = CreateVoidFooOutParamChannel<ITestServiceXml> (true);
324 string argRef = "testRef";
326 ts.VoidFooOutParam ("testIt", ref argRef, out argOut);
327 Assert.AreEqual ("refArg", argRef, "#1");
328 Assert.AreEqual ("outArg", argOut, "#2");
331 public T CreateFooOutParamChannel<T> (bool isXml)
333 return CreateChannel<T> (
334 delegate (Message input) {
335 // Test input for in and ref args.
336 XmlDocument doc = new XmlDocument ();
337 doc.LoadXml (input.ToString ());
339 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
340 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
341 nss.AddNamespace ("t", "http://tempuri.org/");
342 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooOutParam", nss) as XmlElement;
343 Assert.IsNotNull (el, "I#0");
344 XmlNode arg1 = el.SelectSingleNode ("t:arg1", nss);
345 Assert.IsNotNull (arg1, "I#2");
346 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
347 XmlNode arg2 = el.SelectSingleNode ("t:arg2", nss);
348 Assert.IsNotNull (arg2, "I#4");
349 Assert.AreEqual ("testRef", arg2.InnerText, "I#4");
351 return ToMessage (input, isXml,
352 new FooOutParamResponse ("callResult", "refArg", "outArg"));
358 public void InvokeFooOutParam ()
360 ITestService ts = CreateFooOutParamChannel<ITestService> (false);
361 string argRef = "testRef";
363 string res = ts.FooOutParam ("testIt", ref argRef, out argOut);
364 Assert.AreEqual ("callResult", res, "#1");
365 Assert.AreEqual ("refArg", argRef, "#2");
366 Assert.AreEqual ("outArg", argOut, "#3");
370 public void XmlInvokeFooOutParam ()
372 ITestServiceXml ts = CreateFooOutParamChannel<ITestServiceXml> (true);
373 string argRef = "testRef";
375 string res = ts.FooOutParam ("testIt", ref argRef, out argOut);
376 Assert.AreEqual ("callResult", res, "#1");
377 Assert.AreEqual ("refArg", argRef, "#2");
378 Assert.AreEqual ("outArg", argOut, "#3");
382 public void InvokeFooComplex ()
384 ITestService ts = CreateChannel<ITestService> (
385 delegate (Message input) {
386 // Test input for in and ref args.
387 XmlDocument doc = new XmlDocument ();
388 doc.LoadXml (input.ToString ());
390 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
391 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
392 nss.AddNamespace ("t", "http://tempuri.org/");
393 nss.AddNamespace ("v", "http://schemas.datacontract.org/2004/07/MonoTests.System.ServiceModel");
394 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooComplex", nss) as XmlElement;
395 Assert.IsNotNull (el, "I#0");
396 XmlNode arg1 = el.SelectSingleNode ("t:arg1/v:val", nss);
397 Assert.IsNotNull (arg1, "I#2");
398 Assert.AreEqual ("testIt", arg1.InnerText, "I#3");
400 return ToMessage (input, false, new FooComplexResponse ("callResult"));
404 TestData res = ts.FooComplex (new TestData ("testIt"));
405 Assert.IsNotNull (res, "#1");
406 Assert.AreEqual ("callResult", res.val, "#2");
410 [Ignore ("This somehow results in an infinite loop")]
411 public void XmlInvokeFooComplex ()
413 ITestServiceXml ts = CreateChannel<ITestServiceXml> (
414 delegate (Message input) {
415 // Test input for in and ref args.
416 XmlDocument doc = new XmlDocument ();
417 doc.LoadXml (input.ToString ());
419 XmlNamespaceManager nss = new XmlNamespaceManager (doc.NameTable);
420 nss.AddNamespace ("s", "http://www.w3.org/2003/05/soap-envelope");
421 nss.AddNamespace ("t", "http://tempuri.org/");
422 XmlElement el = doc.SelectSingleNode ("/s:Envelope/s:Body/t:FooComplex", nss) as XmlElement;
423 Assert.IsNotNull (el, "I#0");
424 XmlElement arg1 = el.SelectSingleNode ("t:arg1", nss) as XmlElement;
425 Assert.IsNotNull (arg1, "I#2");
426 Assert.AreEqual ("testIt", arg1.GetAttribute ("val"), "I#3");
428 return ToMessage (input, true, new FooComplexResponse ("callResult"));
432 TestData res = ts.FooComplex (new TestData ("testIt"));
433 Assert.IsNotNull (res, "#1");
434 Assert.AreEqual ("callResult", res.val, "#2");
438 public void ConstructorServiceEndpoint ()
440 // It is okay to pass ServiceEndpoint that does not have Binding or EndpointAddress.
441 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)