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