ChannelDispatcherTest.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Text;
  7. using NUnit.Framework;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Channels;
  10. using System.ServiceModel.Description;
  11. using System.ServiceModel.Dispatcher;
  12. using MonoTests.Helpers;
  13. namespace MonoTests.System.ServiceModel.Dispatcher
  14. {
  15. [TestFixture]
  16. public class ChannelDispatcherTest
  17. {
  18. Uri CreateAvailableUri (string uriString)
  19. {
  20. var uri = new Uri (uriString);
  21. try {
  22. var t = new TcpListener (uri.Port);
  23. t.Start ();
  24. t.Stop ();
  25. } catch (Exception ex) {
  26. Assert.Fail (String.Format ("Port {0} is not open. It is likely previous tests have failed and the port is kept opened", uri.Port));
  27. }
  28. return uri;
  29. }
  30. [Test]
  31. public void ConstructorNullBindingName ()
  32. {
  33. new ChannelDispatcher (new MyChannelListener (new Uri ("urn:foo")), null);
  34. new ChannelDispatcher (new MyChannelListener (new Uri ("urn:foo")), null, null);
  35. }
  36. [Test]
  37. public void ServiceThrottle ()
  38. {
  39. var cd = new ChannelDispatcher (new MyChannelListener<IReplyChannel> (new Uri ("urn:foo")));
  40. var st = cd.ServiceThrottle;
  41. Assert.IsNull (st, "#0");
  42. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  43. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  44. h.AddServiceEndpoint (typeof (TestContract).FullName, new BasicHttpBinding (), "address");
  45. h.ChannelDispatchers.Add (cd);
  46. Assert.IsNull (st, "#1");
  47. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  48. Assert.IsNull (ed.ChannelDispatcher, "#1-2");
  49. ed.DispatchRuntime.Type = typeof (TestContract);
  50. cd.Endpoints.Add (ed);
  51. Assert.AreEqual (cd, ed.ChannelDispatcher, "#1-3");
  52. cd.MessageVersion = MessageVersion.Default;
  53. {
  54. cd.Open (TimeSpan.FromSeconds (10));
  55. try {
  56. Assert.IsNull (st, "#2");
  57. // so, can't really test actual slot values as it is null.
  58. } finally {
  59. cd.Close (TimeSpan.FromSeconds (10));
  60. }
  61. return;
  62. }
  63. }
  64. [Test]
  65. public void Collection_Add_Remove () {
  66. Console.WriteLine ("STart test Collection_Add_Remove");
  67. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  68. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  69. h.AddServiceEndpoint (typeof (TestContract).FullName, new BasicHttpBinding (), "address");
  70. MyChannelDispatcher d = new MyChannelDispatcher (new MyChannelListener (uri));
  71. h.ChannelDispatchers.Add (d);
  72. Assert.IsTrue (d.Attached, "#1");
  73. h.ChannelDispatchers.Remove (d);
  74. Assert.IsFalse (d.Attached, "#2");
  75. h.ChannelDispatchers.Insert (0, d);
  76. Assert.IsTrue (d.Attached, "#3");
  77. h.ChannelDispatchers.Add (new MyChannelDispatcher (new MyChannelListener (uri)));
  78. h.ChannelDispatchers.Clear ();
  79. Assert.IsFalse (d.Attached, "#4");
  80. }
  81. [Test]
  82. public void EndpointDispatcherAddTest ()
  83. {
  84. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  85. MyChannelDispatcher d = new MyChannelDispatcher (new MyChannelListener (uri));
  86. d.Endpoints.Add (new EndpointDispatcher (new EndpointAddress (uri), "", ""));
  87. }
  88. [Test]
  89. [ExpectedException (typeof (InvalidOperationException))]
  90. public void EndpointDispatcherAddTest2 () {
  91. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  92. MyChannelDispatcher d = new MyChannelDispatcher (new MyChannelListener (uri));
  93. d.Endpoints.Add (new EndpointDispatcher (new EndpointAddress (uri), "", ""));
  94. d.Open (); // the dispatcher must be attached.
  95. }
  96. [Test]
  97. [ExpectedException (typeof (InvalidOperationException))]
  98. public void EndpointDispatcherAddTest3 ()
  99. {
  100. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  101. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  102. MyChannelDispatcher d = new MyChannelDispatcher (new MyChannelListener (uri));
  103. d.Endpoints.Add (new EndpointDispatcher (new EndpointAddress (uri), "", ""));
  104. h.ChannelDispatchers.Add (d);
  105. d.Open (); // missing MessageVersion
  106. }
  107. [Test]
  108. [ExpectedException (typeof (InvalidOperationException))] // i.e. it is thrown synchronously in current thread.
  109. public void EndpointDispatcherAddTest4 ()
  110. {
  111. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  112. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  113. var listener = new MyChannelListener (uri);
  114. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  115. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  116. Assert.IsNotNull (ed.DispatchRuntime, "#1");
  117. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#2");
  118. Assert.IsNull (ed.DispatchRuntime.InstanceContextProvider, "#3");
  119. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#3.2");
  120. Assert.IsNull (ed.DispatchRuntime.SingletonInstanceContext, "#4");
  121. d.Endpoints.Add (ed);
  122. d.MessageVersion = MessageVersion.Default;
  123. h.ChannelDispatchers.Add (d);
  124. // it misses DispatchRuntime.Type, which seems set
  125. // automatically when the dispatcher is created in
  126. // ordinal process but need to be set manually in this case.
  127. try {
  128. d.Open ();
  129. try {
  130. // should not reach here, but in case it didn't, it must be closed.
  131. d.Close (TimeSpan.FromSeconds (10));
  132. } catch {
  133. }
  134. } finally {
  135. Assert.AreEqual (CommunicationState.Opened, listener.State, "#5");
  136. }
  137. }
  138. [Test]
  139. [ExpectedException (typeof (InvalidOperationException))] // i.e. it is thrown synchronously in current thread.
  140. public void EndpointDispatcherAddTest5 ()
  141. {
  142. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  143. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  144. var binding = new BasicHttpBinding ();
  145. var listener = new MyChannelListener (uri);
  146. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  147. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  148. d.Endpoints.Add (ed);
  149. ed.DispatchRuntime.Type = typeof (TestContract); // different from Test4
  150. d.MessageVersion = MessageVersion.Default;
  151. h.ChannelDispatchers.Add (d);
  152. // It rejects "unrecognized type" of the channel listener.
  153. // Test6 uses IChannelListener<IReplyChannel> and works.
  154. d.Open ();
  155. // should not reach here, but in case it didn't, it must be closed.
  156. d.Close (TimeSpan.FromSeconds (10));
  157. }
  158. [Test]
  159. public void EndpointDispatcherAddTest6 ()
  160. {
  161. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  162. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  163. var binding = new BasicHttpBinding ();
  164. var listener = new MyChannelListener<IReplyChannel> (uri);
  165. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  166. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  167. d.Endpoints.Add (ed);
  168. Assert.IsFalse (d.Attached, "#x1");
  169. ed.DispatchRuntime.Type = typeof (TestContract);
  170. d.MessageVersion = MessageVersion.Default;
  171. h.ChannelDispatchers.Add (d);
  172. Assert.IsTrue (d.Attached, "#x2");
  173. d.Open (); // At this state, it does *not* call AcceptChannel() yet.
  174. Assert.IsFalse (listener.AcceptChannelTried, "#1");
  175. Assert.IsFalse (listener.WaitForChannelTried, "#2");
  176. Assert.IsNotNull (ed.DispatchRuntime, "#3");
  177. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#4");
  178. Assert.IsNull (ed.DispatchRuntime.InstanceContextProvider, "#5"); // it is not still set after ChannelDispatcher.Open().
  179. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#5.2");
  180. Assert.IsNull (ed.DispatchRuntime.SingletonInstanceContext, "#6");
  181. d.Close (); // we don't have to even close it.
  182. }
  183. [Test]
  184. [ExpectedException (typeof (InvalidOperationException))]
  185. public void EndpointDispatcherAddTest7 ()
  186. {
  187. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  188. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  189. var binding = new BasicHttpBinding ();
  190. var listener = new MyChannelListener<IReplyChannel> (uri);
  191. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  192. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  193. d.Endpoints.Add (ed);
  194. ed.DispatchRuntime.Type = typeof (TestContract);
  195. d.MessageVersion = MessageVersion.Default;
  196. // add service endpoint to open the host (unlike all tests above).
  197. h.AddServiceEndpoint (typeof (TestContract),
  198. new BasicHttpBinding (), uri.ToString ());
  199. h.ChannelDispatchers.Clear ();
  200. h.ChannelDispatchers.Add (d);
  201. d.Open (); // At this state, it does *not* call AcceptChannel() yet.
  202. // This rejects already-opened ChannelDispatcher.
  203. h.Open (TimeSpan.FromSeconds (10));
  204. // should not reach here, but in case it didn't, it must be closed.
  205. h.Close (TimeSpan.FromSeconds (10));
  206. }
  207. [Test]
  208. [Category ("NotWorking")]
  209. // Validating duplicate listen URI causes this regression.
  210. // Since it is niche, I rather fixed ServiceHostBase to introduce validation.
  211. // It is probably because this code doesn't use ServiceEndpoint to build IChannelListener i.e. built without Binding.
  212. // We can add an extra field to ChannelDispatcher to indicate that it is from ServiceEndpoint (i.e. with Binding),
  213. // but it makes little sense especially for checking duplicate listen URIs. Duplicate listen URIs should be rejected anyways.
  214. public void EndpointDispatcherAddTest8 ()
  215. {
  216. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  217. ServiceHost h = new ServiceHost (typeof (TestContract), uri);
  218. var listener = new MyChannelListener<IReplyChannel> (uri);
  219. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  220. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  221. d.Endpoints.Add (ed);
  222. ed.DispatchRuntime.Type = typeof (TestContract);
  223. d.MessageVersion = MessageVersion.Default;
  224. // add service endpoint to open the host (unlike all tests above).
  225. h.AddServiceEndpoint (typeof (TestContract),
  226. new BasicHttpBinding (), uri.ToString ());
  227. h.ChannelDispatchers.Clear ();
  228. h.ChannelDispatchers.Add (d);
  229. Assert.AreEqual (h, d.Host, "#0");
  230. try {
  231. h.Open (TimeSpan.FromSeconds (10));
  232. Assert.AreEqual (3, h.ChannelDispatchers.Count, "#0"); // TestContract, d, mex
  233. Assert.IsTrue (listener.BeginAcceptChannelTried, "#1"); // while it throws NIE ...
  234. Assert.IsFalse (listener.WaitForChannelTried, "#2");
  235. Assert.IsNotNull (ed.DispatchRuntime, "#3");
  236. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#4");
  237. Assert.IsNotNull (ed.DispatchRuntime.InstanceContextProvider, "#5"); // it was set after ServiceHost.Open().
  238. Assert.IsNull (ed.DispatchRuntime.SingletonInstanceContext, "#6");
  239. /*
  240. var l = new HttpListener ();
  241. l.Prefixes.Add (uri.ToString ());
  242. l.Start ();
  243. l.Stop ();
  244. */
  245. } finally {
  246. h.Close (TimeSpan.FromSeconds (10));
  247. h.Abort ();
  248. }
  249. }
  250. // FIXME: this test itself indeed passes, but some weird conflict that blocks correspoding port happens between this and somewhere (probably above)
  251. // [Test]
  252. public void EndpointDispatcherAddTest9 () // test singleton service
  253. {
  254. var uri = CreateAvailableUri ("http://localhost:" + NetworkHelpers.FindFreePort ());
  255. ServiceHost h = new ServiceHost (new TestContract (), uri);
  256. h.Description.Behaviors.Find<ServiceBehaviorAttribute> ().InstanceContextMode = InstanceContextMode.Single;
  257. var listener = new MyChannelListener<IReplyChannel> (uri);
  258. MyChannelDispatcher d = new MyChannelDispatcher (listener);
  259. var ed = new EndpointDispatcher (new EndpointAddress (uri), "", "");
  260. d.Endpoints.Add (ed);
  261. ed.DispatchRuntime.Type = typeof (TestContract);
  262. d.MessageVersion = MessageVersion.Default;
  263. h.AddServiceEndpoint (typeof (TestContract), new BasicHttpBinding (), uri.ToString ());
  264. h.ChannelDispatchers.Clear ();
  265. Assert.IsNull (ed.DispatchRuntime.SingletonInstanceContext, "#1");
  266. h.ChannelDispatchers.Add (d);
  267. Assert.IsNull (ed.DispatchRuntime.SingletonInstanceContext, "#2");
  268. try {
  269. h.Open (TimeSpan.FromSeconds (10));
  270. Assert.IsNull (ed.DispatchRuntime.InstanceProvider, "#4");
  271. Assert.IsNotNull (ed.DispatchRuntime.InstanceContextProvider, "#5"); // it was set after ServiceHost.Open().
  272. Assert.IsNotNull (ed.DispatchRuntime.SingletonInstanceContext, "#6");
  273. } finally {
  274. h.Close (TimeSpan.FromSeconds (10));
  275. h.Abort ();
  276. }
  277. }
  278. [ServiceContract]
  279. public class TestContract
  280. {
  281. [OperationContract]
  282. public void Process (string input) {
  283. }
  284. }
  285. class MyChannelDispatcher : ChannelDispatcher
  286. {
  287. public bool Attached = false;
  288. public MyChannelDispatcher (IChannelListener l) : base (l) { }
  289. protected override void Attach (ServiceHostBase host) {
  290. base.Attach (host);
  291. Attached = true;
  292. }
  293. protected override void Detach (ServiceHostBase host) {
  294. base.Detach (host);
  295. Attached = false;
  296. }
  297. }
  298. class MyChannelListener<TChannel> : MyChannelListener, IChannelListener<TChannel> where TChannel : class, IChannel
  299. {
  300. public MyChannelListener (Uri uri)
  301. : base (uri)
  302. {
  303. }
  304. public bool AcceptChannelTried { get; set; }
  305. public bool BeginAcceptChannelTried { get; set; }
  306. public TChannel AcceptChannel ()
  307. {
  308. AcceptChannelTried = true;
  309. throw new NotImplementedException ();
  310. }
  311. public TChannel AcceptChannel (TimeSpan timeout)
  312. {
  313. AcceptChannelTried = true;
  314. throw new NotImplementedException ();
  315. }
  316. public IAsyncResult BeginAcceptChannel (AsyncCallback callback, object state)
  317. {
  318. BeginAcceptChannelTried = true;
  319. throw new NotImplementedException ();
  320. }
  321. public IAsyncResult BeginAcceptChannel (TimeSpan timeout, AsyncCallback callback, object state)
  322. {
  323. BeginAcceptChannelTried = true;
  324. throw new NotImplementedException ();
  325. }
  326. public TChannel EndAcceptChannel (IAsyncResult result)
  327. {
  328. throw new NotImplementedException ();
  329. }
  330. }
  331. class MyChannelListener : IChannelListener
  332. {
  333. public MyChannelListener (Uri uri)
  334. {
  335. Uri = uri;
  336. }
  337. public bool WaitForChannelTried { get; set; }
  338. public CommunicationState State { get; set; }
  339. #region IChannelListener Members
  340. public IAsyncResult BeginWaitForChannel (TimeSpan timeout, AsyncCallback callback, object state)
  341. {
  342. WaitForChannelTried = true;
  343. throw new NotImplementedException ();
  344. }
  345. public bool EndWaitForChannel (IAsyncResult result)
  346. {
  347. throw new NotImplementedException ();
  348. }
  349. public T GetProperty<T> () where T : class
  350. {
  351. throw new NotImplementedException ();
  352. }
  353. public Uri Uri { get; set; }
  354. public bool WaitForChannel (TimeSpan timeout)
  355. {
  356. WaitForChannelTried = true;
  357. throw new NotImplementedException ();
  358. }
  359. #endregion
  360. #region ICommunicationObject Members
  361. public void Abort ()
  362. {
  363. State = CommunicationState.Closed;
  364. }
  365. public IAsyncResult BeginClose (TimeSpan timeout, AsyncCallback callback, object state) {
  366. throw new NotImplementedException ();
  367. }
  368. public IAsyncResult BeginClose (AsyncCallback callback, object state) {
  369. throw new NotImplementedException ();
  370. }
  371. public IAsyncResult BeginOpen (TimeSpan timeout, AsyncCallback callback, object state) {
  372. throw new NotImplementedException ();
  373. }
  374. public IAsyncResult BeginOpen (AsyncCallback callback, object state) {
  375. throw new NotImplementedException ();
  376. }
  377. public void Close (TimeSpan timeout)
  378. {
  379. State = CommunicationState.Closed;
  380. }
  381. public void Close ()
  382. {
  383. State = CommunicationState.Closed;
  384. }
  385. public event EventHandler Closed;
  386. public event EventHandler Closing;
  387. public void EndClose (IAsyncResult result) {
  388. throw new NotImplementedException ();
  389. }
  390. public void EndOpen (IAsyncResult result) {
  391. throw new NotImplementedException ();
  392. }
  393. public event EventHandler Faulted;
  394. public void Open (TimeSpan timeout)
  395. {
  396. State = CommunicationState.Opened;
  397. }
  398. public void Open ()
  399. {
  400. State = CommunicationState.Opened;
  401. }
  402. public event EventHandler Opened;
  403. public event EventHandler Opening;
  404. #endregion
  405. }
  406. }
  407. }