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