ContractDescriptionTest.cs 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. //
  2. // ContractDescriptionTest.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. // Copyright (C) 2005 Novell, Inc. http://www.novell.com
  8. // Copyright (C) 2011 Xamarin, Inc. http://xamarin.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.ObjectModel;
  31. using System.Linq;
  32. using System.Net.Security;
  33. using System.Reflection;
  34. using System.ServiceModel;
  35. using System.ServiceModel.Channels;
  36. using System.ServiceModel.Description;
  37. using System.ServiceModel.Dispatcher;
  38. using NUnit.Framework;
  39. namespace MonoTests.System.ServiceModel.Description
  40. {
  41. [TestFixture]
  42. public class ContractDescriptionTest
  43. {
  44. [Test]
  45. [ExpectedException (typeof (InvalidOperationException))]
  46. public void GetNonContract ()
  47. {
  48. ContractDescription cd = ContractDescription.GetContract (
  49. typeof (object));
  50. }
  51. [Test]
  52. public void GetContract ()
  53. {
  54. InternalTestGetContract (
  55. ContractDescription.GetContract (typeof (IFoo)));
  56. }
  57. [Test]
  58. public void GetContractParamRenamed ()
  59. {
  60. ContractDescription cd = ContractDescription.GetContract (typeof (IFooMsgParams));
  61. Assert.AreEqual (1, cd.Operations.Count, "Operation count");
  62. // Operation #1
  63. OperationDescription od = cd.Operations [0];
  64. ServiceAssert.AssertOperationDescription (
  65. "MyFoo", null, null,
  66. typeof (IFooMsgParams).GetMethod ("Foo"),
  67. true, false, false,
  68. od, "MyFoo");
  69. // Operation #1 -> Message #1
  70. MessageDescription md = od.Messages [0];
  71. ServiceAssert.AssertMessageAndBodyDescription (
  72. "http://tempuri.org/IFooMsgParams/MyFoo",
  73. MessageDirection.Input,
  74. null, "MyFoo", "http://tempuri.org/", false,
  75. md, "MyFoo");
  76. ServiceAssert.AssertMessagePartDescription (
  77. "MyParam", "http://tempuri.org/", 0, false,
  78. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "MyFoo.msg");
  79. md = od.Messages [1];
  80. ServiceAssert.AssertMessageAndBodyDescription (
  81. "http://tempuri.org/IFooMsgParams/MyFooResponse",
  82. MessageDirection.Output,
  83. null, "MyFooResponse",
  84. "http://tempuri.org/", true,
  85. md, "MyFoo");
  86. ServiceAssert.AssertMessagePartDescription (
  87. "MyResult", "http://tempuri.org/", 0, false,
  88. ProtectionLevel.None, typeof (string), md.Body.ReturnValue, "MyResult ReturnValue");
  89. }
  90. [Test]
  91. public void GetContractConfigName ()
  92. {
  93. ContractDescription cd = ContractDescription.GetContract (typeof (ICtorUseCase2));
  94. Assert.AreEqual("CtorUseCase2", cd.ConfigurationName);
  95. Assert.AreEqual("ICtorUseCase2", cd.Name);
  96. cd = ContractDescription.GetContract (typeof (ICtorUseCase1));
  97. Assert.AreEqual("MonoTests.System.ServiceModel.ICtorUseCase1", cd.ConfigurationName);
  98. Assert.AreEqual("ICtorUseCase1", cd.Name);
  99. }
  100. [Test]
  101. public void GetContract2 ()
  102. {
  103. InternalTestGetContract (
  104. ContractDescription.GetContract (typeof (Foo)));
  105. }
  106. public void InternalTestGetContract (ContractDescription cd)
  107. {
  108. ServiceAssert.AssertContractDescription (
  109. "IFoo", "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null,
  110. cd, "contract");
  111. Assert.AreEqual (2, cd.Operations.Count, "Operation count");
  112. // Operation #1
  113. OperationDescription od = cd.Operations [0];
  114. ServiceAssert.AssertOperationDescription (
  115. "HeyDude", null, null,
  116. typeof (IFoo).GetMethod ("HeyDude"),
  117. true, false, false,
  118. od, "HeyDude");
  119. // Operation #1 -> Message #1
  120. MessageDescription md = od.Messages [0];
  121. ServiceAssert.AssertMessageAndBodyDescription (
  122. "http://tempuri.org/IFoo/HeyDude",
  123. MessageDirection.Input,
  124. null, "HeyDude", "http://tempuri.org/", false,
  125. md, "HeyDude");
  126. ServiceAssert.AssertMessagePartDescription (
  127. "msg", "http://tempuri.org/", 0, false,
  128. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyDude.msg");
  129. ServiceAssert.AssertMessagePartDescription (
  130. "msg2", "http://tempuri.org/", 1, false,
  131. ProtectionLevel.None, typeof (string), md.Body.Parts [1], "HeyDude.msg");
  132. // Operation #1 -> Message #2
  133. md = od.Messages [1];
  134. ServiceAssert.AssertMessageAndBodyDescription (
  135. "http://tempuri.org/IFoo/HeyDudeResponse",
  136. MessageDirection.Output,
  137. null, "HeyDudeResponse",
  138. "http://tempuri.org/", true,
  139. md, "HeyDude");
  140. ServiceAssert.AssertMessagePartDescription (
  141. "HeyDudeResult", "http://tempuri.org/", 0, false,
  142. ProtectionLevel.None, typeof (string), md.Body.ReturnValue, "HeyDudeResponse ReturnValue");
  143. // Operation #2
  144. od = cd.Operations [1];
  145. ServiceAssert.AssertOperationDescription (
  146. "HeyHey", null, null,
  147. typeof (IFoo).GetMethod ("HeyHey"),
  148. true, false, false,
  149. od, "HeyHey");
  150. // Operation #2 -> Message #1
  151. md = od.Messages [0];
  152. ServiceAssert.AssertMessageAndBodyDescription (
  153. "http://tempuri.org/IFoo/HeyHey",
  154. MessageDirection.Input,
  155. null, "HeyHey", "http://tempuri.org/", false,
  156. md, "HeyHey");
  157. ServiceAssert.AssertMessagePartDescription (
  158. "ref1", "http://tempuri.org/", 0, false,
  159. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyHey.ref1");
  160. // Operation #2 -> Message #2
  161. md = od.Messages [1];
  162. ServiceAssert.AssertMessageAndBodyDescription (
  163. "http://tempuri.org/IFoo/HeyHeyResponse",
  164. MessageDirection.Output,
  165. null, "HeyHeyResponse",
  166. "http://tempuri.org/", true,
  167. md, "HeyHey");
  168. ServiceAssert.AssertMessagePartDescription (
  169. "HeyHeyResult", "http://tempuri.org/", 0, false,
  170. ProtectionLevel.None, typeof (void), md.Body.ReturnValue, "HeyHeyResponse ReturnValue");
  171. ServiceAssert.AssertMessagePartDescription (
  172. "out1", "http://tempuri.org/", 0, false,
  173. ProtectionLevel.None, typeof (string), md.Body.Parts [0], "HeyHey.out1");
  174. ServiceAssert.AssertMessagePartDescription (
  175. "ref1", "http://tempuri.org/", 1, false,
  176. ProtectionLevel.None, typeof (string), md.Body.Parts [1], "HeyHey.ref1");
  177. }
  178. [Test]
  179. public void GetContractInherit ()
  180. {
  181. ContractDescription.GetContract (typeof (Foo));
  182. }
  183. [Test]
  184. [ExpectedException (typeof (InvalidOperationException))]
  185. public void GetMultipleServiceContract ()
  186. {
  187. ContractDescription.GetContract (typeof (FooBar));
  188. }
  189. [Test]
  190. // [ExpectedException (typeof (InvalidOperationException))]
  191. public void GetContractNoOperation ()
  192. {
  193. ContractDescription.GetContract (typeof (INoOperation));
  194. }
  195. [Test]
  196. [Category ("NotWorking")]
  197. public void GetContractMessageParameter ()
  198. {
  199. ContractDescription cd = ContractDescription.GetContract (typeof (IMessageParameter));
  200. ServiceAssert.AssertContractDescription (
  201. "IMessageParameter", "http://tempuri.org/",
  202. SessionMode.Allowed, typeof (IMessageParameter), null,
  203. cd, "contract");
  204. OperationDescription od = cd.Operations [0];
  205. ServiceAssert.AssertOperationDescription (
  206. "ReturnMessage", null, null,
  207. typeof (IMessageParameter).GetMethod ("ReturnMessage"),
  208. true, false, false,
  209. od, "operation");
  210. MessageDescription md = od.Messages [0];
  211. ServiceAssert.AssertMessageAndBodyDescription (
  212. "http://tempuri.org/IMessageParameter/ReturnMessage",
  213. MessageDirection.Input,
  214. // Body.WrapperName is null
  215. null, null, null, false,
  216. md, "ReturnMessage");
  217. ServiceAssert.AssertMessagePartDescription (
  218. "arg", "http://tempuri.org/", 0, false,
  219. ProtectionLevel.None, typeof (Message), md.Body.Parts [0], "ReturnMessage input");
  220. }
  221. [Test]
  222. [ExpectedException (typeof (InvalidOperationException))]
  223. public void GetContractInvalidAsync ()
  224. {
  225. ContractDescription.GetContract (typeof (IInvalidAsync));
  226. }
  227. [Test]
  228. // IMetadataExchange contains async patterns.
  229. public void GetContractIMetadataExchange ()
  230. {
  231. ContractDescription cd = ContractDescription.GetContract (typeof (IMetadataExchange));
  232. OperationDescription od = cd.Operations [0];
  233. Assert.AreEqual (2, od.Messages.Count, "premise: message count");
  234. foreach (MessageDescription md in od.Messages) {
  235. if (md.Direction == MessageDirection.Input) {
  236. Assert.AreEqual ("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get", md.Action, "#1-1");
  237. Assert.AreEqual (1, md.Body.Parts.Count, "#1-2");
  238. Assert.IsNull (md.Body.ReturnValue, "#1-3");
  239. Assert.AreEqual (typeof (Message), md.Body.Parts [0].Type, "#1-4");
  240. } else {
  241. Assert.AreEqual ("http://schemas.xmlsoap.org/ws/2004/09/transfer/GetResponse", md.Action, "#2-1");
  242. Assert.AreEqual (0, md.Body.Parts.Count, "#2-2");
  243. Assert.IsNotNull (md.Body.ReturnValue, "#2-3");
  244. Assert.AreEqual (typeof (Message), md.Body.ReturnValue.Type, "#2-4");
  245. }
  246. }
  247. }
  248. [Test]
  249. // enable it if we want to become a compatibility kid. It has
  250. // no ServiceContract, thus it should not be accepted. But
  251. // there is an abuse of ChannelFactory<IRequestChannel> in
  252. // MSDN documentations and probably examples.
  253. [Category ("NotWorking")]
  254. public void GetContractIRequestChannel ()
  255. {
  256. ContractDescription cd = ContractDescription.GetContract (typeof (IRequestChannel));
  257. Assert.AreEqual (typeof (IRequestChannel), cd.ContractType, "#_1");
  258. Assert.AreEqual ("IRequestChannel", cd.Name, "#_2");
  259. Assert.AreEqual ("http://schemas.microsoft.com/2005/07/ServiceModel", cd.Namespace, "#_3");
  260. Assert.AreEqual (false, cd.HasProtectionLevel, "#_4");
  261. Assert.AreEqual (SessionMode.NotAllowed, cd.SessionMode, "#_5");
  262. Assert.AreEqual (0, cd.Behaviors.Count, "#_6");
  263. Assert.AreEqual (1, cd.Operations.Count, "#_7");
  264. OperationDescription od = cd.Operations [0];
  265. Assert.IsNull (od.SyncMethod, "#_8");
  266. Assert.IsNull (od.BeginMethod, "#_9");
  267. Assert.IsNull (od.EndMethod, "#_10");
  268. Assert.AreEqual (false, od.IsOneWay, "#_11");
  269. Assert.AreEqual (false, od.HasProtectionLevel, "#_12");
  270. Assert.AreEqual ("Request", od.Name, "#_13");
  271. Assert.AreEqual (true, od.IsInitiating, "#_14");
  272. Assert.AreEqual (0, od.Behaviors.Count, "#_15");
  273. Assert.AreEqual (2, od.Messages.Count, "#_16");
  274. foreach (MessageDescription md in od.Messages) {
  275. if (md.Direction == MessageDirection.Output) {
  276. Assert.AreEqual ("*", md.Action, "#_17");
  277. Assert.AreEqual (false, md.HasProtectionLevel, "#_18");
  278. Assert.AreEqual (0, md.Headers.Count, "#_19");
  279. Assert.AreEqual (0, md.Properties.Count, "#_20");
  280. Assert.IsNull (md.MessageType, "#_21");
  281. MessageBodyDescription mb = md.Body;
  282. Assert.AreEqual (null, mb.WrapperName, "#_22");
  283. Assert.AreEqual (null, mb.WrapperNamespace, "#_23");
  284. Assert.IsNull (mb.ReturnValue, "#_24");
  285. Assert.AreEqual (0, mb.Parts.Count, "#_25");
  286. } else {
  287. Assert.AreEqual ("*", md.Action, "#_17_");
  288. Assert.AreEqual (false, md.HasProtectionLevel, "#_18_");
  289. Assert.AreEqual (0, md.Headers.Count, "#_19_");
  290. Assert.AreEqual (0, md.Properties.Count, "#_20_");
  291. Assert.IsNull (md.MessageType, "#_21_");
  292. MessageBodyDescription mb = md.Body;
  293. Assert.AreEqual (null, mb.WrapperName, "#_22_");
  294. Assert.AreEqual (null, mb.WrapperNamespace, "#_23_");
  295. Assert.IsNull (mb.ReturnValue, "#_24_");
  296. Assert.AreEqual (0, mb.Parts.Count, "#_25_");
  297. }
  298. }
  299. }
  300. [Test]
  301. [ExpectedException (typeof (InvalidOperationException))]
  302. public void WrongAsyncEndContract ()
  303. {
  304. ContractDescription.GetContract (typeof (IWrongAsyncEndContract));
  305. }
  306. [Test]
  307. public void AsyncContract1 ()
  308. {
  309. ContractDescription cd =
  310. ContractDescription.GetContract (typeof (IAsyncContract1));
  311. Assert.AreEqual (1, cd.Operations.Count);
  312. OperationDescription od = cd.Operations [0];
  313. Assert.AreEqual ("Sum", od.Name, "#1");
  314. Assert.IsNotNull (od.BeginMethod, "#2");
  315. Assert.IsNotNull (od.EndMethod, "#3");
  316. }
  317. [Test]
  318. [ExpectedException (typeof (InvalidOperationException))]
  319. public void DuplicateOperationNames ()
  320. {
  321. ContractDescription.GetContract (typeof (IDuplicateOperationNames));
  322. }
  323. [Test]
  324. [ExpectedException (typeof (InvalidOperationException))]
  325. public void AsyncMethodNameDoesNotStartWithBegin ()
  326. {
  327. ContractDescription.GetContract (typeof (IAsyncMethodNameDoesNotStartWithBegin));
  328. }
  329. [Test]
  330. [ExpectedException (typeof (InvalidOperationException))]
  331. public void AsyncNameDoesNotStartWithBeginButExplicitName ()
  332. {
  333. // it is still invalid ...
  334. ContractDescription.GetContract (typeof (IAsyncNameDoesNotStartWithBeginButExplicitName));
  335. }
  336. [Test]
  337. public void MessageBodyMemberIsNotInferred ()
  338. {
  339. ContractDescription cd = ContractDescription.GetContract (typeof (MessageBodyMemberIsNotInferredService));
  340. OperationDescription od = cd.Operations [0];
  341. MessageDescription md = od.Messages [0];
  342. Assert.AreEqual (0, md.Body.Parts.Count);
  343. }
  344. [Test]
  345. public void TestContractFromObject () {
  346. ContractDescription cd = ContractDescription.GetContract (typeof (Foo));
  347. ServiceAssert.AssertContractDescription (typeof (IFoo).Name, "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null, cd, "#1");
  348. Assert.AreEqual (cd.Operations.Count, 2);
  349. OperationBehaviorAttribute op = cd.Operations.Find ("HeyHey").Behaviors.Find<OperationBehaviorAttribute> ();
  350. Assert.IsNotNull (op);
  351. Assert.AreEqual (
  352. op.ReleaseInstanceMode,
  353. ReleaseInstanceMode.None, "#2");
  354. cd = ContractDescription.GetContract (typeof (IFoo), typeof (Foo));
  355. ServiceAssert.AssertContractDescription (typeof (IFoo).Name, "http://tempuri.org/", SessionMode.Allowed, typeof (IFoo), null, cd, "#3");
  356. Assert.AreEqual (cd.Operations.Count, 2, "#4");
  357. Assert.AreEqual (
  358. cd.Operations.Find ("HeyHey").Behaviors.Find<OperationBehaviorAttribute> ().ReleaseInstanceMode,
  359. ReleaseInstanceMode.AfterCall, "#5");
  360. }
  361. [Test]
  362. public void GetDerivedContract ()
  363. {
  364. var cd = ContractDescription.GetContract (typeof (IFoo3));
  365. Assert.AreEqual (typeof (IFoo3), cd.ContractType, "#1");
  366. Assert.AreEqual (3, cd.Operations.Count, "#2");
  367. cd = ContractDescription.GetContract (typeof (Foo3));
  368. Assert.AreEqual (typeof (IFoo3), cd.ContractType, "#3");
  369. Assert.AreEqual (3, cd.Operations.Count, "#4");
  370. }
  371. [Test]
  372. public void MultipleContractsInTypeHierarchy ()
  373. {
  374. ContractDescription.GetContract (typeof (DuplicateCheckClassWrapper.ServiceInterface));
  375. var host = new ServiceHost (typeof (DuplicateCheckClassWrapper.DummyService)); // fine in MS, fails in Mono with "A contract cannot have two operations that have the identical names and different set of parameters"
  376. }
  377. [Test]
  378. public void GetInheritedContracts ()
  379. {
  380. var cd = ContractDescription.GetContract (typeof (IService));
  381. var ccd = cd.GetInheritedContracts ();
  382. Assert.AreEqual (1, ccd.Count, "#1");
  383. Assert.AreEqual (typeof (IServiceBase), ccd [0].ContractType, "#2");
  384. }
  385. [Test]
  386. public void InheritedContractAndNamespaces ()
  387. {
  388. var cd = ContractDescription.GetContract (typeof (IService));
  389. Assert.IsTrue (cd.Operations.Any (od => od.Messages.Any (md => md.Action == "http://tempuri.org/IServiceBase/Say")), "#1"); // inherited
  390. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IService).GetMethod ("Join") && od.Messages.Any (md => md.Action == "http://tempuri.org/IService/Join")), "#2"); // self
  391. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IService2).GetMethod ("Join") && od.Messages.Any (md => md.Action == "http://tempuri.org/IService/Join")), "#3"); // callback
  392. }
  393. [Test]
  394. public void AsyncContractWithSymmetricCallbackContract ()
  395. {
  396. var cd = ContractDescription.GetContract (typeof(IAsyncContractWithSymmetricCallbackContract));
  397. Assert.AreEqual (2, cd.Operations.Count, "#1");
  398. Assert.AreSame (typeof (IAsyncContractWithSymmetricCallbackContract), cd.ContractType, "#2");
  399. Assert.AreSame (typeof (IAsyncContractWithSymmetricCallbackContract), cd.CallbackContractType, "#3");
  400. }
  401. [Test]
  402. public void InheritingDuplexContract ()
  403. {
  404. var cd = ContractDescription.GetContract (typeof (IDerivedDuplexContract));
  405. Assert.AreEqual (4, cd.Operations.Count, "#1");
  406. Assert.AreSame (typeof (IDerivedDuplexContract), cd.ContractType, "#2");
  407. Assert.AreSame (typeof (IDerivedDuplexCallback), cd.CallbackContractType, "#3");
  408. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IBaseDuplexCallback).GetMethod ("CallbackMethod")), "#4");
  409. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IDerivedDuplexCallback).GetMethod ("CallbackSomething")), "#5");
  410. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IBaseDuplexContract).GetMethod ("ContractMethod")), "#6");
  411. Assert.IsTrue (cd.Operations.Any (od => od.SyncMethod == typeof (IDerivedDuplexContract).GetMethod ("Something")), "#7");
  412. }
  413. [Test]
  414. public void SymmetricInheritingContract ()
  415. {
  416. var cd = ContractDescription.GetContract (typeof(ISymmetricInheritance));
  417. Assert.AreEqual (4, cd.Operations.Count, "#1");
  418. Assert.AreSame (typeof (ISymmetricInheritance), cd.ContractType, "#2");
  419. Assert.AreSame (typeof (ISymmetricInheritance), cd.CallbackContractType, "#3");
  420. Assert.AreEqual (2, cd.Operations.Count(od => od.SyncMethod == typeof (IAsyncContractWithSymmetricCallbackContract).GetMethod ("Foo")), "#4");
  421. Assert.AreEqual (2, cd.Operations.Count(od => od.SyncMethod == typeof (ISymmetricInheritance).GetMethod ("Bar")), "#5");
  422. }
  423. [Test]
  424. public void DeepContractHierarchyTest ()
  425. {
  426. var cd = ContractDescription.GetContract (typeof(IDeepContractHierarchy));
  427. Assert.AreEqual (6, cd.Operations.Count, "#1");
  428. Assert.AreSame (typeof (IDeepContractHierarchy), cd.ContractType, "#2");
  429. Assert.AreSame (typeof (IDeepContractHierarchy), cd.CallbackContractType, "#3");
  430. }
  431. [Test]
  432. public void MessageContractAttributes ()
  433. {
  434. var cd = ContractDescription.GetContract (typeof (IFoo2));
  435. var od = cd.Operations.First (o => o.Name == "Nanoda");
  436. var md = od.Messages.First (m => m.Direction == MessageDirection.Input);
  437. Assert.AreEqual (typeof (OregoMessage), md.MessageType, "message type");
  438. Assert.AreEqual ("http://tempuri.org/IFoo2/Nanoda", md.Action, "action");
  439. Assert.AreEqual (1, md.Headers.Count, "headers");
  440. Assert.AreEqual (3, md.Body.Parts.Count, "body parts");
  441. Assert.AreEqual (0, md.Properties.Count, "properties");
  442. }
  443. // .NET complains: The operation Nanoda2 either has a parameter or a return type that is attributed with MessageContractAttribute. In order to represent the request message using a Message Contract, the operation must have a single parameter attributed with MessageContractAttribute. In order to represent the response message using a Message Contract, the operation's return value must be a type that is attributed with MessageContractAttribute and the operation may not have any out or ref parameters.
  444. [Test]
  445. [ExpectedException (typeof (InvalidOperationException))]
  446. public void MessageContractAttributes2 ()
  447. {
  448. ContractDescription.GetContract (typeof (IFoo2_2));
  449. }
  450. [Test]
  451. public void MessageContractAttributes3 ()
  452. {
  453. ContractDescription.GetContract (typeof (IFoo2_3));
  454. }
  455. [Test]
  456. public void MessageContractAttributes4 ()
  457. {
  458. ContractDescription.GetContract (typeof (IFoo2_4));
  459. }
  460. [Test]
  461. public void MessageContractAttributes5 ()
  462. {
  463. ContractDescription.GetContract (typeof (IFoo2_5));
  464. }
  465. [Test]
  466. public void MessageContractAttributes6 ()
  467. {
  468. ContractDescription.GetContract (typeof (IFoo2_6));
  469. }
  470. [Test]
  471. public void XmlSerializedOperation ()
  472. {
  473. var cd = ContractDescription.GetContract (typeof (XmlSerializedService));
  474. var od = cd.Operations.First ();
  475. var xb = od.Behaviors.Find<XmlSerializerOperationBehavior> ();
  476. Assert.IsNotNull (xb, "#1");
  477. }
  478. [Test]
  479. public void MessageParameterDescriptionInUse ()
  480. {
  481. // bug #41
  482. var cd = ContractDescription.GetContract (typeof (Dealerinfo.wsvDealerinfo.WSVDealerInfoServices));
  483. foreach (var od in cd.Operations)
  484. foreach (var md in od.Messages)
  485. if (md.Action == "*") // return
  486. Assert.IsNotNull (md.Body.ReturnValue, od.Name);
  487. }
  488. [Test]
  489. public void BugX206Contract ()
  490. {
  491. var cd = ContractDescription.GetContract (typeof (BugX206Service));
  492. bool examined = false;
  493. foreach (var md in cd.Operations.First ().Messages) {
  494. if (md.Direction == MessageDirection.Input)
  495. continue;
  496. var pd = md.Body.ReturnValue;
  497. Assert.IsNotNull (pd, "#1");
  498. Assert.AreEqual ("DoWorkResult", pd.Name, "#2");
  499. Assert.IsNull (pd.MemberInfo, "#3");
  500. Assert.AreEqual (typeof (void), pd.Type, "#4");
  501. examined = true;
  502. }
  503. Assert.IsTrue (examined, "end");
  504. }
  505. // It is for testing attribute search in interfaces.
  506. public class Foo : IFoo
  507. {
  508. public string HeyDude (string msg, string msg2)
  509. {
  510. return null;
  511. }
  512. [OperationBehavior (ReleaseInstanceMode = ReleaseInstanceMode.AfterCall)]
  513. public void HeyHey (out string out1, ref string ref1)
  514. {
  515. out1 = null;
  516. }
  517. }
  518. // It inherits both IFoo and IBar, thus cannot be a contract.
  519. public class FooBar : IFoo, IBar
  520. {
  521. public string HeyDude (string msg, string msg2)
  522. {
  523. return null;
  524. }
  525. public void HeyHey (out string out1, ref string ref1)
  526. {
  527. out1 = null;
  528. }
  529. public void OpenBar () {}
  530. }
  531. [ServiceContract]
  532. public interface IFoo
  533. {
  534. [OperationContract]
  535. string HeyDude (string msg, string msg2);
  536. [OperationContract]
  537. void HeyHey (out string out1, ref string ref1);
  538. }
  539. [ServiceContract]
  540. public interface IFoo2
  541. {
  542. // FIXME: it does not pass yet
  543. [OperationContract]
  544. OregoMessage Nanoda (OregoMessage msg);
  545. // FIXME: it does not pass yet
  546. [OperationContract]
  547. Mona NewMona (Mona source);
  548. }
  549. [ServiceContract]
  550. public interface IFoo2_2
  551. {
  552. [OperationContract] // wrong operation contract, must have only one parameter with MessageContractAttribute
  553. OregoMessage Nanoda2 (OregoMessage msg1, OregoMessage msg2);
  554. }
  555. [ServiceContract]
  556. public interface IFoo2_3
  557. {
  558. [OperationContract]
  559. string Nanoda2 (OregoMessage msg1);
  560. }
  561. [ServiceContract]
  562. public interface IFoo2_4
  563. {
  564. [OperationContract]
  565. OregoMessage Nanoda2 (string s, string s2);
  566. }
  567. [ServiceContract]
  568. public interface IFoo2_5
  569. {
  570. [OperationContract]
  571. Message Nanoda2 (OregoMessage msg1);
  572. }
  573. [ServiceContract]
  574. public interface IFoo2_6
  575. {
  576. [OperationContract]
  577. OregoMessage Nanoda2 (Message msg1);
  578. }
  579. [ServiceContract]
  580. public interface IFoo3 : IFoo
  581. {
  582. [OperationContract]
  583. string HeyMan (string msg, string msg2);
  584. }
  585. public class Foo3 : Foo, IFoo3
  586. {
  587. public string HeyMan (string msg, string msg2)
  588. {
  589. return msg + msg2;
  590. }
  591. }
  592. [ServiceContract]
  593. public interface IBar
  594. {
  595. [OperationContract]
  596. void OpenBar ();
  597. }
  598. [MessageContract]
  599. public class OregoMessage
  600. {
  601. [MessageHeader]
  602. public string Head;
  603. [MessageBodyMember]
  604. public string Neutral;
  605. [MessageBodyMember]
  606. public Assembly Huh;
  607. [MessageBodyMember] // it should be ignored ...
  608. public string Setter { set { } }
  609. public string NonMember;
  610. }
  611. public class Mona
  612. {
  613. public string OmaeMona;
  614. public string OreMona;
  615. }
  616. [ServiceContract]
  617. public interface INoOperation
  618. {
  619. }
  620. [ServiceContract]
  621. public interface IMessageParameter
  622. {
  623. [OperationContract]
  624. Message ReturnMessage (Message arg);
  625. }
  626. [ServiceContract]
  627. public interface IInvalidAsync
  628. {
  629. [OperationContract]
  630. Message ReturnMessage (Message arg);
  631. [OperationContract (AsyncPattern = true)]
  632. IAsyncResult BeginReturnMessage (Message arg, AsyncCallback callback, object state);
  633. // and no EndReturnMessage().
  634. }
  635. [ServiceContract]
  636. public interface IWrongAsyncEndContract
  637. {
  638. [OperationContract]
  639. int Sum (int a, int b);
  640. [OperationContract (AsyncPattern = true)]
  641. IAsyncResult BeginSum (int a, int b, AsyncCallback cb, object state);
  642. // this OperationContractAttribute is not allowed.
  643. [OperationContract (AsyncPattern = true)]
  644. int EndSum (IAsyncResult result);
  645. }
  646. [ServiceContract]
  647. public interface IAsyncContract1
  648. {
  649. [OperationContract]
  650. int Sum (int a, int b);
  651. [OperationContract (AsyncPattern = true)]
  652. IAsyncResult BeginSum (int a, int b, AsyncCallback cb, object state);
  653. int EndSum (IAsyncResult result);
  654. }
  655. [ServiceContract]
  656. public interface IAsyncMethodNameDoesNotStartWithBegin
  657. {
  658. [OperationContract]
  659. int Sum (int a, int b);
  660. [OperationContract (AsyncPattern = true)]
  661. IAsyncResult StartSum (int a, int b, AsyncCallback cb, object state);
  662. int EndSum (IAsyncResult result);
  663. }
  664. [ServiceContract]
  665. public interface IAsyncNameDoesNotStartWithBeginButExplicitName
  666. {
  667. [OperationContract]
  668. int Sum (int a, int b);
  669. [OperationContract (Name = "Sum", AsyncPattern = true)]
  670. IAsyncResult StartSum (int a, int b, AsyncCallback cb, object state);
  671. int EndSum (IAsyncResult result);
  672. }
  673. [ServiceContract]
  674. public interface IDuplicateOperationNames
  675. {
  676. [OperationContract]
  677. string Echo (string s);
  678. [OperationContract]
  679. string Echo (string s1, string s2);
  680. }
  681. [ServiceContract]
  682. public interface IFooMsgParams
  683. {
  684. [OperationContract (Name = "MyFoo")]
  685. [return: MessageParameter (Name = "MyResult")]
  686. string Foo ([MessageParameter (Name = "MyParam")] string param);
  687. }
  688. [ServiceContract]
  689. public class MessageBodyMemberIsNotInferredService
  690. {
  691. [OperationContract]
  692. public void Echo (MessageBodyMemberIsNotInferredContract msg)
  693. {
  694. }
  695. }
  696. [MessageContract]
  697. public class MessageBodyMemberIsNotInferredContract
  698. {
  699. string foo = "foo";
  700. public string Foo {
  701. get { return foo; }
  702. set { foo = value; }
  703. }
  704. }
  705. public class DuplicateCheckClassWrapper
  706. {
  707. [ServiceContract]
  708. internal interface ServiceInterface : Foo
  709. {
  710. }
  711. [ServiceContract]
  712. internal interface Foo : Bar
  713. {
  714. [OperationContract] void Foo();
  715. }
  716. [ServiceContract]
  717. internal interface Bar
  718. {
  719. [OperationContract] void FooBar();
  720. }
  721. internal class DummyService : ServiceInterface
  722. {
  723. public void FooBar() { }
  724. public void Foo() { }
  725. }
  726. }
  727. [ServiceContract]
  728. public interface IServiceBase
  729. {
  730. [OperationContract (IsOneWay = true)]
  731. void Say (string word);
  732. }
  733. [ServiceContract (CallbackContract = typeof (IService2))]
  734. public interface IService : IServiceBase
  735. {
  736. [OperationContract]
  737. void Join ();
  738. }
  739. [ServiceContract]
  740. public interface IServiceBase2
  741. {
  742. [OperationContract (IsOneWay = true)]
  743. void Say (string word);
  744. }
  745. [ServiceContract]
  746. public interface IService2 : IServiceBase2
  747. {
  748. [OperationContract]
  749. void Join ();
  750. }
  751. [ServiceContract (CallbackContract = typeof (IAsyncContractWithSymmetricCallbackContract))]
  752. public interface IAsyncContractWithSymmetricCallbackContract
  753. {
  754. [OperationContract]
  755. void Foo();
  756. [OperationContract (AsyncPattern = true)]
  757. IAsyncResult BeginFoo (AsyncCallback callback, object asyncState);
  758. void EndFoo (IAsyncResult result);
  759. }
  760. [ServiceContract (CallbackContract = typeof (ISymmetricInheritance))]
  761. public interface ISymmetricInheritance : IAsyncContractWithSymmetricCallbackContract
  762. {
  763. [OperationContract]
  764. void Bar ();
  765. [OperationContract (AsyncPattern = true)]
  766. IAsyncResult BeginBar (AsyncCallback callback, object asyncState);
  767. void EndBar (IAsyncResult result);
  768. }
  769. [ServiceContract (CallbackContract = typeof (IDeepContractHierarchy))]
  770. public interface IDeepContractHierarchy : ISymmetricInheritance
  771. {
  772. [OperationContract]
  773. void Foobar();
  774. }
  775. public interface IBaseDuplexCallback
  776. {
  777. [OperationContract]
  778. void CallbackMethod ();
  779. }
  780. [ServiceContract (CallbackContract = typeof (IBaseDuplexCallback))]
  781. public interface IBaseDuplexContract
  782. {
  783. [OperationContract]
  784. void ContractMethod ();
  785. }
  786. public interface IDerivedDuplexCallback : IBaseDuplexCallback
  787. {
  788. [OperationContract]
  789. void CallbackSomething ();
  790. }
  791. [ServiceContract (CallbackContract = typeof(IDerivedDuplexCallback))]
  792. public interface IDerivedDuplexContract : IBaseDuplexContract
  793. {
  794. [OperationContract]
  795. void Something ();
  796. }
  797. [ServiceContract]
  798. public interface XmlSerializedService
  799. {
  800. [OperationContract]
  801. [XmlSerializerFormat]
  802. string Echo (string input);
  803. }
  804. [ServiceContract]
  805. public interface BugX206Service
  806. {
  807. [OperationContract]
  808. BugX206Response DoWork ();
  809. }
  810. [MessageContract (IsWrapped = true)]
  811. public partial class BugX206Response
  812. {
  813. }
  814. [Test]
  815. public void TestInterfaceInheritance ()
  816. {
  817. var cd = ContractDescription.GetContract (typeof (InterfaceInheritance));
  818. var inherited = cd.GetInheritedContracts ();
  819. Assert.AreEqual (1, inherited.Count, "#1");
  820. }
  821. public class MyWebGetAttribute : Attribute, IOperationBehavior
  822. {
  823. void IOperationBehavior.AddBindingParameters (OperationDescription operation, BindingParameterCollection parameters)
  824. {
  825. ;
  826. }
  827. void IOperationBehavior.ApplyClientBehavior (OperationDescription operation, ClientOperation client)
  828. {
  829. ;
  830. }
  831. void IOperationBehavior.ApplyDispatchBehavior (OperationDescription operation, DispatchOperation service)
  832. {
  833. ;
  834. }
  835. void IOperationBehavior.Validate (OperationDescription operation)
  836. {
  837. ;
  838. }
  839. }
  840. [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
  841. public class InterfaceInheritance : IInterfaceInheritance
  842. {
  843. public string Get ()
  844. {
  845. throw new NotImplementedException ();
  846. }
  847. public string Test ()
  848. {
  849. throw new NotImplementedException ();
  850. }
  851. }
  852. [ServiceContract]
  853. public interface IInterfaceInheritance: IBaseInterface
  854. {
  855. [OperationContract]
  856. [MyWebGet]
  857. string Test ();
  858. }
  859. [ServiceContract]
  860. public interface IBaseInterface
  861. {
  862. [OperationContract]
  863. [MyWebGet]
  864. string Get ();
  865. }
  866. }
  867. }