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