ServiceHostTest.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // ServiceHostTest.cs
  3. //
  4. // Author:
  5. // Ankit Jain <[email protected]>
  6. // Atsushi Enomoto <[email protected]>
  7. //
  8. // Copyright (C) 2005-2006 Novell, Inc. http://www.novell.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. using System;
  30. using System.Collections.Generic;
  31. using System.ServiceModel;
  32. using System.ServiceModel.Channels;
  33. using System.ServiceModel.Description;
  34. using System.ServiceModel.Dispatcher;
  35. using NUnit.Framework;
  36. namespace MonoTests.System.ServiceModel
  37. {
  38. [TestFixture]
  39. public class ServiceHostTest
  40. {
  41. class MyHost : ServiceHost
  42. {
  43. public MyHost (Type type, Uri uri)
  44. : base (type, uri)
  45. {
  46. }
  47. public IDictionary<string,ContractDescription> ExposedContracts {
  48. get { return ImplementedContracts; }
  49. }
  50. }
  51. [Test]
  52. public void Ctor ()
  53. {
  54. MyHost host = new MyHost (typeof (Foo), new Uri ("http://localhost"));
  55. Assert.IsNotNull (host.Description, "#1");
  56. Assert.AreEqual (typeof (Foo), host.Description.ServiceType, "#1-2");
  57. Assert.IsNotNull (host.BaseAddresses, "#2");
  58. Assert.AreEqual (1, host.BaseAddresses.Count, "#3");
  59. Assert.IsNotNull (host.ChannelDispatchers, "#4");
  60. Assert.AreEqual (0, host.ChannelDispatchers.Count, "#5");
  61. Assert.IsNotNull (host.Authorization, "#6");
  62. Assert.IsNotNull (host.ExposedContracts, "#7");
  63. // Foo is already in the contracts.
  64. Assert.AreEqual (1, host.ExposedContracts.Count, "#8");
  65. // this loop iterates only once.
  66. foreach (KeyValuePair<string,ContractDescription> e in host.ExposedContracts) {
  67. // hmm... so, seems like the key is just the full name of the contract type.
  68. Assert.AreEqual ("MonoTests.System.ServiceModel.ServiceHostTest+Foo", e.Key, "#9");
  69. ContractDescription cd = e.Value;
  70. Assert.AreEqual ("Foo", cd.Name, "#10");
  71. Assert.AreEqual ("http://tempuri.org/", cd.Namespace, "#11");
  72. }
  73. }
  74. [Test]
  75. [ExpectedException (typeof (ArgumentNullException))]
  76. public void CtorNull ()
  77. {
  78. new ServiceHost (typeof (Foo), null);
  79. }
  80. [Test]
  81. [ExpectedException (typeof (ArgumentException))]
  82. public void CtorServiceTypeNotClass ()
  83. {
  84. new ServiceHost (typeof (IBar), new Uri ("http://localhost"));
  85. }
  86. [Test]
  87. [ExpectedException (typeof (ArgumentException))]
  88. public void CtorRelativeBaseAddress ()
  89. {
  90. new ServiceHost (typeof (Foo), new Uri ("test", UriKind.Relative));
  91. }
  92. [Test]
  93. [ExpectedException (typeof (ArgumentException))]
  94. public void CtorMultipleAddressPerScheme ()
  95. {
  96. new ServiceHost ( typeof (Foo),
  97. new Uri ("http://localhost", UriKind.Absolute),
  98. new Uri ("http://someotherhost", UriKind.Absolute));
  99. }
  100. [Test]
  101. [Ignore ("AddServiceEndpoint part does not work")]
  102. public void AddServiceEndpoint ()
  103. {
  104. ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
  105. host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "rel");
  106. host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "svc");
  107. Assert.IsNotNull (host.Description, "#6");
  108. Assert.IsNotNull (host.Description.Endpoints, "#7");
  109. Assert.AreEqual (host.Description.Endpoints.Count, 2, "#8");
  110. Assert.AreEqual ("http://localhost/echo/rel", host.Description.Endpoints [0].Address.Uri.AbsoluteUri, "#9");
  111. }
  112. [Test]
  113. [ExpectedException (typeof (InvalidOperationException))]
  114. public void AddServiceEndpoint1 ()
  115. {
  116. ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("ftp://localhost/echo"));
  117. // ftp does not match BasicHttpBinding
  118. host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "rel");
  119. }
  120. [Test]
  121. [ExpectedException (typeof (InvalidOperationException))]
  122. public void AddServiceEndpoint2 ()
  123. {
  124. // IBar is not part of the contract
  125. ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
  126. host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "rel");
  127. //host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "rel");
  128. }
  129. [Test]
  130. [ExpectedException (typeof (InvalidOperationException))]
  131. public void AddServiceEndpoint3 ()
  132. {
  133. // IBar is not part of the contract
  134. ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
  135. host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "rel");
  136. // host.AddServiceEndpoint ("IBar", new BasicHttpBinding (), "http://localhost/echo/rel");
  137. }
  138. [Test]
  139. public void AddServiceEndpoint4 ()
  140. {
  141. ServiceHost host = new ServiceHost (typeof (Baz), new Uri ("http://localhost/echo"));
  142. host.AddServiceEndpoint ("MonoTests.System.ServiceModel.ServiceHostTest+IBaz", new BasicHttpBinding (), "rel");
  143. }
  144. [Test]
  145. [ExpectedException (typeof (InvalidOperationException))]
  146. public void AddServiceEndpoint5 ()
  147. {
  148. ServiceHost host = new ServiceHost (typeof (Baz), new Uri ("http://localhost/echo"));
  149. // Full type name is expected here (see AddServiceEndpoint4).
  150. host.AddServiceEndpoint ("IBaz", new BasicHttpBinding (), "rel");
  151. }
  152. [Test]
  153. [ExpectedException (typeof (InvalidOperationException))]
  154. public void AddServiceEndpoint6 ()
  155. {
  156. ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
  157. host.AddServiceEndpoint ("ISuchTypeDoesNotExist", new BasicHttpBinding (), "rel");
  158. }
  159. [Test]
  160. [ExpectedException (typeof (InvalidOperationException))]
  161. public void AddServiceEndpointMex ()
  162. {
  163. using (ServiceHost h = new ServiceHost (typeof (Foo), new Uri ("http://localhost:8080"))) {
  164. // it expects ServiceMetadataBehavior
  165. h.AddServiceEndpoint (ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding (), "mex");
  166. }
  167. }
  168. [Test]
  169. public void AddServiceEndpointMetadataExchange ()
  170. {
  171. ServiceHost host = new ServiceHost (typeof (MyMetadataExchange));
  172. // strange, but unlike above, it is accepted. The only difference I can see is the binding name.
  173. host.AddServiceEndpoint ("IMetadataExchange",
  174. new BasicHttpBinding (),
  175. "http://localhost:8080");
  176. }
  177. [Test]
  178. [ExpectedException (typeof (InvalidOperationException))]
  179. public void AddServiceEndpointMetadataExchangeFullNameFails ()
  180. {
  181. ServiceHost host = new ServiceHost (typeof (MyMetadataExchange));
  182. host.AddServiceEndpoint ("System.ServiceModel.Description.IMetadataExchange",
  183. new BasicHttpBinding (),
  184. "http://localhost:8080");
  185. }
  186. [Test]
  187. public void InstanceWithNonSingletonMode ()
  188. {
  189. ServiceHost host = new ServiceHost (
  190. new NonSingletonService ());
  191. Assert.IsNotNull (host.Description.Behaviors.Find<ServiceBehaviorAttribute> ().GetWellKnownSingleton (), "premise1");
  192. host.AddServiceEndpoint (
  193. typeof (NonSingletonService),
  194. new BasicHttpBinding (),
  195. new Uri ("http://localhost:37564/s1"));
  196. // in case Open() didn't fail, we need to close the host.
  197. // And even if Close() caused the expected exception,
  198. // the test should still fail.
  199. try {
  200. host.Open ();
  201. try {
  202. if (host.State == CommunicationState.Opened)
  203. host.Close ();
  204. } catch (InvalidOperationException) {
  205. }
  206. Assert.Fail ("InstanceContextMode was not checked");
  207. } catch (InvalidOperationException) {
  208. }
  209. }
  210. [Test]
  211. public void InstanceWithSingletonMode ()
  212. {
  213. SingletonService instance = new SingletonService ();
  214. ServiceHost host = new ServiceHost (instance);
  215. Assert.IsNotNull (host.Description.Behaviors.Find<ServiceBehaviorAttribute> ().GetWellKnownSingleton (), "#1");
  216. host.AddServiceEndpoint (
  217. typeof (SingletonService),
  218. new BasicHttpBinding (),
  219. new Uri ("http://localhost:37564/s2"));
  220. // in case Open() didn't fail, we need to close the host.
  221. // And even if Close() caused the expected exception,
  222. // the test should still fail.
  223. try {
  224. host.Open ();
  225. ChannelDispatcher cd = (ChannelDispatcher) host.ChannelDispatchers [0];
  226. DispatchRuntime dr = cd.Endpoints [0].DispatchRuntime;
  227. Assert.IsNotNull (dr.InstanceContextProvider, "#2");
  228. InstanceContext ctx = dr.InstanceContextProvider.GetExistingInstanceContext (null, null);
  229. Assert.IsNotNull (ctx, "#3");
  230. Assert.AreEqual (instance, ctx.GetServiceInstance (), "#4");
  231. } finally {
  232. if (host.State == CommunicationState.Opened)
  233. host.Close ();
  234. }
  235. }
  236. [ServiceContract]
  237. interface IBar
  238. {
  239. }
  240. [ServiceContract]
  241. class Foo
  242. {
  243. [OperationContract]
  244. public void SayWhat () { }
  245. }
  246. [ServiceContract]
  247. interface IBaz
  248. {
  249. [OperationContract]
  250. string Echo (string source);
  251. }
  252. class Baz : IBaz
  253. {
  254. public string Echo (string source)
  255. {
  256. return source;
  257. }
  258. }
  259. class MyMetadataExchange : IMetadataExchange
  260. {
  261. public Message Get (Message req)
  262. {
  263. throw new NotImplementedException ();
  264. }
  265. public IAsyncResult BeginGet (Message request, AsyncCallback cb, object state)
  266. {
  267. throw new NotImplementedException ();
  268. }
  269. public Message EndGet (IAsyncResult result)
  270. {
  271. throw new NotImplementedException ();
  272. }
  273. }
  274. [ServiceContract]
  275. public class NonSingletonService
  276. {
  277. [OperationContract]
  278. public void Process (string input)
  279. {
  280. }
  281. }
  282. [ServiceContract]
  283. [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single)]
  284. public class SingletonService
  285. {
  286. [OperationContract]
  287. public void Process (string input)
  288. {
  289. }
  290. }
  291. }
  292. }