ContractDescriptionTest.cs 27 KB

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