ChannelDispatcherTest.cs 16 KB

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