Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.ServiceModel / Test / MetadataTests / BindingTestAssertions.cs
1 //
2 // BindingTestAssertions.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26
27 using System;
28 using System.Net;
29 using System.Net.Security;
30 using System.Xml;
31 using System.Text;
32 using System.Collections.Generic;
33 using System.ServiceModel;
34 using System.ServiceModel.Security;
35 using System.ServiceModel.Channels;
36 using System.ServiceModel.Description;
37 using NUnit.Framework;
38 using NUnit.Framework.Constraints;
39 using NUnit.Framework.SyntaxHelpers;
40
41 using QName = System.Xml.XmlQualifiedName;
42 using WS = System.Web.Services.Description;
43
44 namespace MonoTests.System.ServiceModel.MetadataTests {
45
46         public static class BindingTestAssertions {
47
48                 const string WspNamespace = "http://schemas.xmlsoap.org/ws/2004/09/policy";
49                 const string WsuNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
50                 const string MsbNamespace = "http://schemas.microsoft.com/ws/06/2004/mspolicy/netbinary1";
51                 const string WsawNamespace = "http://www.w3.org/2006/05/addressing/wsdl";
52                 const string MsfNamespace = "http://schemas.microsoft.com/ws/2006/05/framing/policy";
53                 const string SpNamespace = "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy";
54                 const string WsrmNamespace = "http://schemas.xmlsoap.org/ws/2005/02/rm/policy";
55                 const string HttpNamespace = "http://schemas.microsoft.com/ws/06/2004/policy/http";
56                 const string WsomaNamespace = "http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization";
57                 const string Wsa10Namespace = "http://www.w3.org/2005/08/addressing";
58
59                 static readonly QName BinaryEncodingQName = new QName ("BinaryEncoding", MsbNamespace);
60                 static readonly QName UsingAddressingQName = new QName ("UsingAddressing", WsawNamespace);
61                 static readonly QName StreamedTransferQName = new QName ("Streamed", MsfNamespace);
62                 static readonly QName ReliableSessionQName = new QName ("RMAssertion", WsrmNamespace);
63                 static readonly QName TransportBindingQName = new QName ("TransportBinding", SpNamespace);
64                 static readonly QName AsymmetricBindingQName = new QName ("AsymmetricBinding", SpNamespace);
65                 static readonly QName SymmetricBindingQName = new QName ("SymmetricBinding", SpNamespace);
66                 static readonly QName EndorsingSupportingQName = new QName ("EndorsingSupportingTokens", SpNamespace);
67                 static readonly QName SignedSupportingQName = new QName ("SignedSupportingTokens", SpNamespace);
68                 static readonly QName Wss10QName = new QName ("Wss10", SpNamespace);
69                 static readonly QName Wss11QName = new QName ("Wss11", SpNamespace);
70                 static readonly QName Trust10QName = new QName ("Trust10", SpNamespace);
71                 static readonly QName NtlmAuthenticationQName = new QName ("NtlmAuthentication", HttpNamespace);
72                 static readonly QName MtomEncodingQName = new QName ("OptimizedMimeSerialization", WsomaNamespace);
73
74                 public static void CheckImportErrors (WsdlImporter importer, TestLabel label)
75                 {
76                         bool foundErrors = false;
77                         foreach (var error in importer.Errors) {
78                                 if (error.IsWarning)
79                                         Console.WriteLine ("WARNING ({0}): {1}", label, error.Message);
80                                 else {
81                                         Console.WriteLine ("ERROR ({0}): {1}", label, error.Message);
82                                         foundErrors = true;
83                                 }
84                         }
85
86                         if (foundErrors)
87                                 Assert.Fail ("Found import errors", label);
88                 }
89
90                 static void CheckSoapBinding (object extension, string transport, TestLabel label)
91                 {
92                         label.EnterScope ("soap");
93                         Assert.That (extension, Is.InstanceOfType (typeof (WS.SoapBinding)), label.Get ());
94                         var soap = (WS.SoapBinding)extension;
95                         Assert.That (soap.Style, Is.EqualTo (WS.SoapBindingStyle.Document), label.Get ());
96                         Assert.That (soap.Transport, Is.EqualTo (transport), label.Get ());
97                         Assert.That (soap.Required, Is.False, label.Get ());
98                         label.LeaveScope ();
99                 }
100
101                 public static void CheckBasicHttpBinding (
102                         Binding binding, string scheme, BasicHttpSecurityMode security,
103                         WSMessageEncoding encoding, HttpClientCredentialType clientCred,
104                         AuthenticationSchemes authScheme, TestLabel label)
105                 {
106                         label.EnterScope ("http");
107
108                         if (security == BasicHttpSecurityMode.Message) {
109                                 Assert.That (binding, Is.InstanceOfType (typeof(CustomBinding)), label.Get ());
110                         } else {
111                                 Assert.That (binding, Is.InstanceOfType (typeof(BasicHttpBinding)), label.Get ());
112                                 var basicHttp = (BasicHttpBinding)binding;
113                                 Assert.That (basicHttp.EnvelopeVersion, Is.EqualTo (EnvelopeVersion.Soap11), label.Get ());
114                                 Assert.That (basicHttp.MessageVersion, Is.EqualTo (MessageVersion.Soap11), label.Get ());
115                                 Assert.That (basicHttp.Scheme, Is.EqualTo (scheme), label.Get ());
116                                 Assert.That (basicHttp.TransferMode, Is.EqualTo (TransferMode.Buffered), label.Get ());
117                                 Assert.That (basicHttp.MessageEncoding, Is.EqualTo (encoding), label.Get ());
118                                 Assert.That (basicHttp.Security, Is.Not.Null, label.Get ());
119                                 Assert.That (basicHttp.Security.Mode, Is.EqualTo (security), label.Get ());
120                                 Assert.That (basicHttp.Security.Transport.ClientCredentialType, Is.EqualTo (clientCred), label.Get ());
121                                 Assert.That (basicHttp.Security.Message.AlgorithmSuite, Is.EqualTo (SecurityAlgorithmSuite.Basic256), label.Get ());
122                         }
123
124                         label.EnterScope ("elements");
125
126                         var elements = binding.CreateBindingElements ();
127                         Assert.That (elements, Is.Not.Null, label.Get ());
128                         if ((security == BasicHttpSecurityMode.Message) ||
129                                 (security == BasicHttpSecurityMode.TransportWithMessageCredential))
130                                 Assert.That (elements.Count, Is.EqualTo (3), label.Get ());
131                         else
132                                 Assert.That (elements.Count, Is.EqualTo (2), label.Get ());
133                         
134                         TextMessageEncodingBindingElement textElement = null;
135                         TransportSecurityBindingElement securityElement = null;
136                         HttpTransportBindingElement transportElement = null;
137                         AsymmetricSecurityBindingElement asymmSecurityElement = null;
138                         MtomMessageEncodingBindingElement mtomElement = null;
139                         
140                         foreach (var element in elements) {
141                                 if (element is TextMessageEncodingBindingElement)
142                                         textElement = (TextMessageEncodingBindingElement)element;
143                                 else if (element is HttpTransportBindingElement)
144                                         transportElement = (HttpTransportBindingElement)element;
145                                 else if (element is TransportSecurityBindingElement)
146                                         securityElement = (TransportSecurityBindingElement)element;
147                                 else if (element is AsymmetricSecurityBindingElement)
148                                         asymmSecurityElement = (AsymmetricSecurityBindingElement)element;
149                                 else if (element is MtomMessageEncodingBindingElement)
150                                         mtomElement = (MtomMessageEncodingBindingElement)element;
151                                 else
152                                         Assert.Fail (string.Format (
153                                                 "Unknown element: {0}", element.GetType ()), label.Get ());
154                         }
155
156                         label.EnterScope ("text");
157                         if (encoding == WSMessageEncoding.Text) {
158                                 Assert.That (textElement, Is.Not.Null, label.Get ());
159                                 Assert.That (textElement.WriteEncoding, Is.InstanceOfType (typeof(UTF8Encoding)), label.Get ());
160                         } else {
161                                 Assert.That (textElement, Is.Null, label.Get ());
162                         }
163                         label.LeaveScope ();
164
165                         label.EnterScope ("mtom");
166                         if (encoding == WSMessageEncoding.Mtom) {
167                                 Assert.That (mtomElement, Is.Not.Null, label.Get ());
168                         } else {
169                                 Assert.That (mtomElement, Is.Null, label.Get ());
170                         }
171                         label.LeaveScope ();
172
173                         label.EnterScope ("security");
174                         if (security == BasicHttpSecurityMode.TransportWithMessageCredential) {
175                                 Assert.That (securityElement, Is.Not.Null, label.Get ());
176                                 Assert.That (securityElement.SecurityHeaderLayout,
177                                              Is.EqualTo (SecurityHeaderLayout.Lax), label.Get ());
178                         } else {
179                                 Assert.That (securityElement, Is.Null, label.Get ());
180                         }
181                         label.LeaveScope ();
182
183                         label.EnterScope ("asymmetric");
184                         if (security == BasicHttpSecurityMode.Message) {
185                                 Assert.That (asymmSecurityElement, Is.Not.Null, label.Get ());
186                         } else {
187                                 Assert.That (asymmSecurityElement, Is.Null, label.Get ());
188                         }
189                         label.LeaveScope ();
190
191                         label.EnterScope ("transport");
192                         Assert.That (transportElement, Is.Not.Null, label.Get ());
193                         
194                         Assert.That (transportElement.Realm, Is.Empty, label.Get ());
195                         Assert.That (transportElement.Scheme, Is.EqualTo (scheme), label.Get ());
196                         Assert.That (transportElement.TransferMode, Is.EqualTo (TransferMode.Buffered), label.Get ());
197
198                         label.EnterScope ("auth");
199                         Assert.That (transportElement.AuthenticationScheme, Is.EqualTo (authScheme), label.Get ());
200                         label.LeaveScope (); // auth
201                         label.LeaveScope (); // transport
202                         label.LeaveScope (); // elements
203                         label.LeaveScope (); // http
204                 }
205
206                 static void CheckEndpoint (ServiceEndpoint endpoint, string uri, TestLabel label)
207                 {
208                         label.EnterScope ("endpoint");
209                         Assert.That (endpoint.ListenUri, Is.EqualTo (new Uri (uri)), label.Get ());
210                         Assert.That (endpoint.ListenUriMode, Is.EqualTo (ListenUriMode.Explicit), label.Get ());
211                         Assert.That (endpoint.Contract, Is.Not.Null, label.Get ());
212                         Assert.That (endpoint.Contract.Name, Is.EqualTo ("MyContract"), label.Get ());
213                         Assert.That (endpoint.Address, Is.Not.Null, label.Get ());
214                         Assert.That (endpoint.Address.Uri, Is.EqualTo (new Uri (uri)), label.Get ());
215                         Assert.That (endpoint.Address.Identity, Is.Null, label.Get ());
216                         Assert.That (endpoint.Address.Headers, Is.Not.Null, label.Get ());
217                         Assert.That (endpoint.Address.Headers.Count, Is.EqualTo (0), label.Get ());
218                         label.LeaveScope ();
219                 }
220
221                 public static void BasicHttpBinding (
222                         TestContext context, MetadataSet doc, WSMessageEncoding encoding, TestLabel label)
223                 {
224                         BasicHttpBinding (
225                                 context, doc, BasicHttpSecurityMode.None, encoding,
226                                 HttpClientCredentialType.None, AuthenticationSchemes.Anonymous,
227                                 label);
228                 }
229
230                 public static void BasicHttpBinding (
231                         TestContext context, MetadataSet doc, BasicHttpSecurityMode security, TestLabel label)
232                 {
233                         BasicHttpBinding (
234                                 context, doc, security, WSMessageEncoding.Text,
235                                 HttpClientCredentialType.None, AuthenticationSchemes.Anonymous,
236                                 label);
237                 }
238                 
239                 public static void BasicHttpBinding (
240                         TestContext context, MetadataSet doc, BasicHttpSecurityMode security,
241                         WSMessageEncoding encoding, HttpClientCredentialType clientCred,
242                         AuthenticationSchemes authScheme, TestLabel label)
243                 {
244                         label.EnterScope ("basicHttpBinding");
245                         BasicHttpBinding_inner (
246                                 context, doc, security, encoding, clientCred,
247                                 authScheme, false, label);
248                         label.LeaveScope ();
249                 }
250
251                 public static void BasicHttpsBinding (
252                         TestContext context, MetadataSet doc, BasicHttpSecurityMode security,
253                         WSMessageEncoding encoding, HttpClientCredentialType clientCred,
254                         AuthenticationSchemes authScheme, TestLabel label)
255                 {
256                         label.EnterScope ("basicHttpsBinding");
257                         BasicHttpBinding_inner (
258                                 context, doc, security, encoding, clientCred,
259                                 authScheme, true, label);
260                         label.LeaveScope ();
261                 }
262                 
263                 static void BasicHttpBinding_inner (
264                         TestContext context, MetadataSet doc, BasicHttpSecurityMode security,
265                         WSMessageEncoding encoding, HttpClientCredentialType clientCred,
266                         AuthenticationSchemes authScheme, bool isHttps, TestLabel label)
267                 {
268                         var sd = (WS.ServiceDescription)doc.MetadataSections [0].Metadata;
269
270                         label.EnterScope ("wsdl");
271                         label.EnterScope ("bindings");
272                         Assert.That (sd.Bindings.Count, Is.EqualTo (1), label.Get ());
273
274                         var binding = sd.Bindings [0];
275                         Assert.That (binding.ExtensibleAttributes, Is.Null, label.Get ());
276                         Assert.That (binding.Extensions, Is.Not.Null, label.Get ());
277
278                         bool hasPolicyXml;
279
280                         switch (security) {
281                         case BasicHttpSecurityMode.None:
282                                 if (isHttps)
283                                         throw new InvalidOperationException ();
284                                 hasPolicyXml = encoding == WSMessageEncoding.Mtom;
285                                 break;
286                         case BasicHttpSecurityMode.Message:
287                         case BasicHttpSecurityMode.Transport:
288                         case BasicHttpSecurityMode.TransportWithMessageCredential:
289                                 if (encoding == WSMessageEncoding.Mtom)
290                                         throw new InvalidOperationException ();
291                                 hasPolicyXml = true;
292                                 break;
293                         case BasicHttpSecurityMode.TransportCredentialOnly:
294                                 if (isHttps)
295                                         throw new InvalidOperationException ();
296                                 hasPolicyXml = true;
297                                 break;
298                         default:
299                                 throw new InvalidOperationException ();
300                         }
301                         label.LeaveScope ();
302
303                         WS.SoapBinding soap = null;
304                         XmlElement xml = null;
305
306                         foreach (var ext in binding.Extensions) {
307                                 if (ext is WS.SoapBinding)
308                                         soap = (WS.SoapBinding)ext;
309                                 else if (ext is XmlElement)
310                                         xml = (XmlElement)ext;
311                         }
312
313                         CheckSoapBinding (soap, WS.SoapBinding.HttpTransport, label);
314                         label.LeaveScope ();
315
316                         label.EnterScope ("policy-xml");
317                         if (!hasPolicyXml)
318                                 Assert.That (xml, Is.Null, label.Get ());
319                         else {
320                                 Assert.That (xml, Is.Not.Null, label.Get ());
321                                 var assertions = AssertPolicy (sd, xml, label);
322                                 Assert.That (assertions, Is.Not.Null, label.Get ());
323                                 if (clientCred == HttpClientCredentialType.Ntlm)
324                                         AssertPolicy (assertions, NtlmAuthenticationQName, label);
325                                 if (encoding == WSMessageEncoding.Mtom)
326                                         AssertPolicy (assertions, MtomEncodingQName, label);
327                                 switch (security) {
328                                 case BasicHttpSecurityMode.Message:
329                                         AssertPolicy (assertions, AsymmetricBindingQName, label);
330                                         AssertPolicy (assertions, Wss10QName, label);
331                                         break;
332                                 case BasicHttpSecurityMode.Transport:
333                                         AssertPolicy (assertions, TransportBindingQName, label);
334                                         break;
335                                 case BasicHttpSecurityMode.TransportWithMessageCredential:
336                                         AssertPolicy (assertions, SignedSupportingQName, label);
337                                         AssertPolicy (assertions, TransportBindingQName, label);
338                                         AssertPolicy (assertions, Wss10QName, label);
339                                         break;
340                                 default:
341                                         break;
342                                 }
343                                 Assert.That (assertions.Count, Is.EqualTo (0), label.Get ());
344                         }
345                         label.LeaveScope ();
346
347                         label.EnterScope ("services");
348                         Assert.That (sd.Services, Is.Not.Null, label.Get ());
349                         Assert.That (sd.Services.Count, Is.EqualTo (1), label.Get ());
350                         var service = sd.Services [0];
351                         Assert.That (service.Ports, Is.Not.Null, label.Get ());
352                         Assert.That (service.Ports.Count, Is.EqualTo (1), label.Get ());
353                         var port = service.Ports [0];
354                         
355                         label.EnterScope ("port");
356                         Assert.That (port.Extensions, Is.Not.Null, label.Get ());
357                         Assert.That (port.Extensions.Count, Is.EqualTo (1), label.Get ());
358                         
359                         WS.SoapAddressBinding soap_addr_binding = null;
360                         foreach (var extension in port.Extensions) {
361                                 if (extension is WS.SoapAddressBinding)
362                                         soap_addr_binding = (WS.SoapAddressBinding)extension;
363                                 else
364                                         Assert.Fail (label.Get ());
365                         }
366                         Assert.That (soap_addr_binding, Is.Not.Null, label.Get ());
367                         label.LeaveScope ();
368
369                         label.LeaveScope (); // wsdl
370
371                         var importer = new WsdlImporter (doc);
372
373                         label.EnterScope ("bindings");
374                         var bindings = importer.ImportAllBindings ();
375                         CheckImportErrors (importer, label);
376
377                         Assert.That (bindings, Is.Not.Null, label.Get ());
378                         Assert.That (bindings.Count, Is.EqualTo (1), label.Get ());
379
380                         string scheme;
381                         if ((security == BasicHttpSecurityMode.Transport) ||
382                             (security == BasicHttpSecurityMode.TransportWithMessageCredential))
383                                 scheme = "https";
384                         else
385                                 scheme = "http";
386
387                         CheckBasicHttpBinding (
388                                 bindings [0], scheme, security, encoding, clientCred,
389                                 authScheme, label);
390                         label.LeaveScope ();
391
392                         label.EnterScope ("endpoints");
393                         var endpoints = importer.ImportAllEndpoints ();
394                         CheckImportErrors (importer, label);
395
396                         Assert.That (endpoints, Is.Not.Null, label.Get ());
397                         Assert.That (endpoints.Count, Is.EqualTo (1), label.Get ());
398
399                         var uri = isHttps ? MetadataSamples.HttpsUri : MetadataSamples.HttpUri;
400
401                         CheckEndpoint (endpoints [0], uri, label);
402                         label.LeaveScope ();
403                 }
404
405                 public static void CheckNetTcpBinding (
406                         Binding binding, SecurityMode security, bool reliableSession,
407                         TransferMode transferMode, TestLabel label)
408                 {
409                         label.EnterScope ("net-tcp");
410                         if (security == SecurityMode.Message) {
411                                 Assert.That (binding, Is.InstanceOfType (typeof(CustomBinding)), label.Get ());
412                         } else {
413                                 Assert.That (binding, Is.InstanceOfType (typeof(NetTcpBinding)), label.Get ());
414                                 var netTcp = (NetTcpBinding)binding;
415                                 Assert.That (netTcp.EnvelopeVersion, Is.EqualTo (EnvelopeVersion.Soap12), label.Get ());
416                                 Assert.That (netTcp.MessageVersion, Is.EqualTo (MessageVersion.Soap12WSAddressing10), label.Get ());
417                                 Assert.That (netTcp.Scheme, Is.EqualTo ("net.tcp"), label.Get ());
418                                 Assert.That (netTcp.TransferMode, Is.EqualTo (transferMode), label.Get ());
419
420                                 label.EnterScope ("security");
421                                 Assert.That (netTcp.Security, Is.Not.Null, label.Get ());
422                                 Assert.That (netTcp.Security.Mode, Is.EqualTo (security), label.Get ());
423
424                                 Assert.That (netTcp.Security.Transport, Is.Not.Null, label.Get ());
425                                 Assert.That (netTcp.Security.Transport.ProtectionLevel, Is.EqualTo (ProtectionLevel.EncryptAndSign), label.Get ());
426                                 Assert.That (netTcp.Security.Transport.ClientCredentialType, Is.EqualTo (TcpClientCredentialType.Windows), label.Get ());
427                                 label.LeaveScope ();
428                         }
429
430                         label.EnterScope ("elements");
431                         
432                         var elements = binding.CreateBindingElements ();
433                         Assert.That (elements, Is.Not.Null, label.Get ());
434
435                         TcpTransportBindingElement transportElement = null;
436                         TransactionFlowBindingElement transactionFlowElement = null;
437                         BinaryMessageEncodingBindingElement encodingElement = null;
438                         WindowsStreamSecurityBindingElement windowsStreamElement = null;
439                         ReliableSessionBindingElement reliableSessionElement = null;
440                         TransportSecurityBindingElement transportSecurityElement = null;
441                         SslStreamSecurityBindingElement sslStreamElement = null;
442                         SymmetricSecurityBindingElement symmSecurityElement = null;
443                         
444                         foreach (var element in elements) {
445                                 if (element is TcpTransportBindingElement)
446                                         transportElement = (TcpTransportBindingElement)element;
447                                 else if (element is TransactionFlowBindingElement)
448                                         transactionFlowElement = (TransactionFlowBindingElement)element;
449                                 else if (element is BinaryMessageEncodingBindingElement)
450                                         encodingElement = (BinaryMessageEncodingBindingElement)element;
451                                 else if (element is WindowsStreamSecurityBindingElement)
452                                         windowsStreamElement = (WindowsStreamSecurityBindingElement)element;
453                                 else if (element is ReliableSessionBindingElement)
454                                         reliableSessionElement = (ReliableSessionBindingElement)element;
455                                 else if (element is TransportSecurityBindingElement)
456                                         transportSecurityElement = (TransportSecurityBindingElement)element;
457                                 else if (element is SslStreamSecurityBindingElement)
458                                         sslStreamElement = (SslStreamSecurityBindingElement)element;
459                                 else if (element is SymmetricSecurityBindingElement)
460                                         symmSecurityElement = (SymmetricSecurityBindingElement)element;
461                                 else
462                                         Assert.Fail (string.Format (
463                                                 "Unknown element `{0}'.", element.GetType ()), label.Get ());
464                         }
465
466                         label.EnterScope ("windows-stream");
467                         if (security == SecurityMode.Transport) {
468                                 Assert.That (windowsStreamElement, Is.Not.Null, label.Get ());
469                                 Assert.That (windowsStreamElement.ProtectionLevel, Is.EqualTo (ProtectionLevel.EncryptAndSign), label.Get ());
470                         } else {
471                                 Assert.That (windowsStreamElement, Is.Null, label.Get ());
472                         }
473                         label.LeaveScope ();
474
475                         label.EnterScope ("reliable-session");
476                         if (reliableSession) {
477                                 Assert.That (reliableSessionElement, Is.Not.Null, label.Get ());
478                         } else {
479                                 Assert.That (reliableSessionElement, Is.Null, label.Get ());
480                         }
481                         label.LeaveScope ();
482
483                         label.EnterScope ("encoding");
484                         Assert.That (encodingElement, Is.Not.Null, label.Get ());
485                         label.LeaveScope ();
486
487                         label.EnterScope ("transaction");
488                         if (security == SecurityMode.Message) {
489                                 Assert.That (transactionFlowElement, Is.Null, label.Get ());
490                         } else {
491                                 Assert.That (transactionFlowElement, Is.Not.Null, label.Get ());
492                         }
493                         label.LeaveScope ();
494
495                         label.EnterScope ("transport");
496                         Assert.That (transportElement, Is.Not.Null, label.Get ());
497
498                         Assert.That (transportElement.Scheme, Is.EqualTo ("net.tcp"), label.Get ());
499                         Assert.That (transportElement.TransferMode, Is.EqualTo (transferMode), label.Get ());
500                         label.LeaveScope (); // transport
501
502                         label.EnterScope ("security");
503                         switch (security) {
504                         case SecurityMode.None:
505                         case SecurityMode.Transport:
506                                 Assert.That (transportSecurityElement, Is.Null, label.Get ());
507                                 Assert.That (sslStreamElement, Is.Null, label.Get ());
508                                 Assert.That (symmSecurityElement, Is.Null, label.Get ());
509                                 break;
510                         case SecurityMode.TransportWithMessageCredential:
511                                 Assert.That (transportSecurityElement, Is.Not.Null, label.Get ());
512                                 Assert.That (sslStreamElement, Is.Not.Null, label.Get ());
513                                 Assert.That (symmSecurityElement, Is.Null, label.Get ());
514                                 break;
515                         case SecurityMode.Message:
516                                 Assert.That (transportSecurityElement, Is.Null, label.Get ());
517                                 Assert.That (sslStreamElement, Is.Null, label.Get ());
518                                 Assert.That (symmSecurityElement, Is.Not.Null, label.Get ());
519                                 break;
520                         default:
521                                 throw new InvalidOperationException ();
522                         }
523                         label.LeaveScope ();
524
525                         label.LeaveScope (); // elements
526                         label.LeaveScope (); // net-tcp
527                 }
528
529                 public static void NetTcpBinding (
530                         TestContext context, MetadataSet doc, SecurityMode security,
531                         bool reliableSession, TransferMode transferMode, TestLabel label)
532                 {
533                         label.EnterScope ("netTcpBinding");
534
535                         var sd = (WS.ServiceDescription)doc.MetadataSections [0].Metadata;
536
537                         label.EnterScope ("wsdl");
538
539                         label.EnterScope ("bindings");
540                         Assert.That (sd.Bindings.Count, Is.EqualTo (1), label.Get ());
541                         var binding = sd.Bindings [0];
542                         Assert.That (binding.ExtensibleAttributes, Is.Null, label.Get ());
543                         Assert.That (binding.Extensions, Is.Not.Null, label.Get ());
544
545                         WS.Soap12Binding soap = null;
546                         XmlElement xml = null;
547                         
548                         foreach (var ext in binding.Extensions) {
549                                 if (ext is WS.Soap12Binding)
550                                         soap = (WS.Soap12Binding)ext;
551                                 else if (ext is XmlElement)
552                                         xml = (XmlElement)ext;
553                         }
554                         
555                         CheckSoapBinding (soap, "http://schemas.microsoft.com/soap/tcp", label);
556
557                         label.EnterScope ("policy-xml");
558                         Assert.That (xml, Is.Not.Null, label.Get ());
559                         var assertions = AssertPolicy (sd, xml, label);
560                         Assert.That (assertions, Is.Not.Null, label.Get ());
561                         AssertPolicy (assertions, BinaryEncodingQName, label);
562                         AssertPolicy (assertions, UsingAddressingQName, label);
563                         if (transferMode == TransferMode.Streamed)
564                                 AssertPolicy (assertions, StreamedTransferQName, label);
565                         switch (security) {
566                         case SecurityMode.Message:
567                                 AssertPolicy (assertions, SymmetricBindingQName, label);
568                                 AssertPolicy (assertions, Wss11QName, label);
569                                 AssertPolicy (assertions, Trust10QName, label);
570                                 break;
571                         case SecurityMode.Transport:
572                                 AssertPolicy (assertions, TransportBindingQName, label);
573                                 break;
574                         case SecurityMode.TransportWithMessageCredential:
575                                 AssertPolicy (assertions, TransportBindingQName, label);
576                                 AssertPolicy (assertions, EndorsingSupportingQName, label);
577                                 AssertPolicy (assertions, Wss11QName, label);
578                                 AssertPolicy (assertions, Trust10QName, label);
579                                 break;
580                         default:
581                                 break;
582                         }
583                         if (reliableSession)
584                                 AssertPolicy (assertions, ReliableSessionQName, label);
585                         Assert.That (assertions.Count, Is.EqualTo (0), label.Get ());
586                         label.LeaveScope ();
587
588                         label.EnterScope ("services");
589                         Assert.That (sd.Services, Is.Not.Null, label.Get ());
590                         Assert.That (sd.Services.Count, Is.EqualTo (1), label.Get ());
591                         var service = sd.Services [0];
592                         Assert.That (service.Ports, Is.Not.Null, label.Get ());
593                         Assert.That (service.Ports.Count, Is.EqualTo (1), label.Get ());
594                         var port = service.Ports [0];
595
596                         label.EnterScope ("port");
597                         Assert.That (port.Extensions, Is.Not.Null, label.Get ());
598                         Assert.That (port.Extensions.Count, Is.EqualTo (2), label.Get ());
599
600                         WS.Soap12AddressBinding soap_addr_binding = null;
601                         XmlElement port_xml = null;
602                         foreach (var extension in port.Extensions) {
603                                 if (extension is WS.Soap12AddressBinding)
604                                         soap_addr_binding = (WS.Soap12AddressBinding)extension;
605                                 else if (extension is XmlElement)
606                                         port_xml = (XmlElement)extension;
607                                 else
608                                         Assert.Fail (label.Get ());
609                         }
610                         Assert.That (soap_addr_binding, Is.Not.Null, label.Get ());
611                         Assert.That (port_xml, Is.Not.Null, label.Get ());
612                         Assert.That (port_xml.NamespaceURI, Is.EqualTo (Wsa10Namespace), label.Get ());
613                         Assert.That (port_xml.LocalName, Is.EqualTo ("EndpointReference"), label.Get ());
614                         label.LeaveScope ();
615                         label.LeaveScope ();
616
617                         label.LeaveScope (); // wsdl
618
619                         var importer = new WsdlImporter (doc);
620
621                         label.EnterScope ("bindings");
622                         var bindings = importer.ImportAllBindings ();
623                         CheckImportErrors (importer, label);
624                         Assert.That (bindings, Is.Not.Null, label.Get ());
625                         Assert.That (bindings.Count, Is.EqualTo (1), label.Get ());
626                         
627                         CheckNetTcpBinding (
628                                 bindings [0], security, reliableSession,
629                                 transferMode, label);
630                         label.LeaveScope ();
631
632                         label.EnterScope ("endpoints");
633                         var endpoints = importer.ImportAllEndpoints ();
634                         CheckImportErrors (importer, label);
635                         Assert.That (endpoints, Is.Not.Null, label.Get ());
636                         Assert.That (endpoints.Count, Is.EqualTo (1), label.Get ());
637                         
638                         CheckEndpoint (endpoints [0], MetadataSamples.NetTcpUri, label);
639                         label.LeaveScope ();
640
641                         label.LeaveScope ();
642                 }
643
644                 public static void Dump (PolicyAssertionCollection assertions)
645                 {
646                         foreach (var assertion in assertions)
647                                 Console.WriteLine ("ASSERTION: {0}", assertion.OuterXml);
648                 }
649
650                 public static void AssertPolicy (
651                         PolicyAssertionCollection assertions, QName qname, TestLabel label)
652                 {
653                         var assertion = assertions.Find (qname.Name, qname.Namespace);
654                         label.EnterScope (qname.Name);
655                         Assert.That (assertion, Is.Not.Null, label.ToString ());
656                         assertions.Remove (assertion);
657                         label.LeaveScope ();
658                 }
659
660                 static XmlElement ResolvePolicy (WS.ServiceDescription sd, XmlElement policy)
661                 {
662                         if (policy.LocalName.Equals ("Policy"))
663                                 return policy;
664
665                         var uri = policy.GetAttribute ("URI");
666                         if (!uri.StartsWith ("#"))
667                                 return null;
668                         
669                         foreach (var sext in sd.Extensions) {
670                                 var sxml = sext as XmlElement;
671                                 if (sxml == null)
672                                         continue;
673                                 if (!sxml.NamespaceURI.Equals (WspNamespace))
674                                         continue;
675                                 if (!sxml.LocalName.Equals ("Policy"))
676                                         continue;
677                                 var id = sxml.GetAttribute ("Id", WsuNamespace);
678                                 if (uri.Substring (1).Equals (id))
679                                         return sxml;
680                         }
681
682                         return null;
683                 }
684
685                 public static PolicyAssertionCollection AssertPolicy (
686                         WS.Binding binding, TestLabel label)
687                 {
688                         label.EnterScope ("FindPolicy");
689                         XmlElement policy = null;
690                 
691                         foreach (var extension in binding.Extensions) {
692                                 var xml = extension as XmlElement;
693                                 if (xml == null)
694                                         continue;
695                                 Assert.That (policy, Is.Null, label.Get ());
696                                 policy = xml;
697                         }
698                         Assert.That (policy, Is.Not.Null, label.Get ());
699                         try {
700                                 return AssertPolicy (binding.ServiceDescription, policy, label);
701                         } finally {
702                                 label.LeaveScope ();
703                         }
704                 }
705
706                 static XmlElement AssertExactlyOneChildElement (XmlElement element)
707                 {
708                         XmlElement found = null;
709                         foreach (var node in element.ChildNodes) {
710                                 if (node is XmlWhitespace)
711                                         continue;
712                                 var e = node as XmlElement;
713                                 if (e == null)
714                                         return null;
715                                 if (found != null)
716                                         return null;
717                                 found = e;
718                         }
719
720                         return found;
721                 }
722                 
723                 public static PolicyAssertionCollection AssertPolicy (
724                         WS.ServiceDescription sd, XmlElement element, TestLabel label)
725                 {
726                         label.EnterScope ("wsp:Policy");
727                         Assert.That (element.NamespaceURI, Is.EqualTo (WspNamespace), label.Get ());
728                         Assert.That (element.LocalName, Is.EqualTo ("Policy") | Is.EqualTo ("PolicyReference"), label.Get ());
729
730                         var policy = ResolvePolicy (sd, element);
731                         Assert.That (policy, Is.Not.Null, label.Get ());
732
733                         label.EnterScope ("wsp:ExactlyOne");
734                         var exactlyOne = AssertExactlyOneChildElement (policy);
735                         Assert.That (exactlyOne, Is.Not.Null, label.Get ());
736                         Assert.That (exactlyOne.NamespaceURI, Is.EqualTo (WspNamespace), label.Get ());
737                         Assert.That (exactlyOne.LocalName, Is.EqualTo ("ExactlyOne"), label.Get ());
738                         label.LeaveScope ();
739
740                         label.EnterScope ("wsp:Any");
741                         var all = AssertExactlyOneChildElement (exactlyOne);
742                         Assert.That (all, Is.Not.Null, label.Get ());
743                         Assert.That (all.NamespaceURI, Is.EqualTo (WspNamespace), label.Get ());
744                         Assert.That (all.LocalName, Is.EqualTo ("All"), label.Get ());
745                         label.LeaveScope ();
746
747                         var collection = new PolicyAssertionCollection ();
748
749                         label.EnterScope ("assertions");
750                         foreach (var node in all.ChildNodes) {
751                                 if (node is XmlWhitespace)
752                                         continue;
753                                 Assert.That (node, Is.InstanceOfType (typeof (XmlElement)), label.ToString ());
754                                 collection.Add ((XmlElement)node);
755                         }
756                         label.LeaveScope ();
757
758                         label.LeaveScope ();
759
760                         return collection;
761                 }
762
763                 public static void TestOperation (MetadataSet metadata, bool soap12, TestLabel label)
764                 {
765                         label.EnterScope ("TestOperation");
766
767                         label.EnterScope ("metadata");
768                         WS.ServiceDescription sd = null;
769                         foreach (var ms in metadata.MetadataSections) {
770                                 if (!ms.Dialect.Equals ("http://schemas.xmlsoap.org/wsdl/"))
771                                         continue;
772                                 sd = ms.Metadata as WS.ServiceDescription;
773                         }
774                         Assert.That (sd, Is.Not.Null, label.Get ());
775                         Assert.That (sd.Bindings, Is.Not.Null, label.Get ());
776                         Assert.That (sd.Bindings.Count, Is.EqualTo (1), label.Get ());
777                         var binding = sd.Bindings [0];
778                         label.LeaveScope ();
779
780                         label.EnterScope ("operation");
781                         Assert.That (binding.Operations, Is.Not.Null, label.Get ());
782                         Assert.That (binding.Operations.Count, Is.EqualTo (1), label.Get ());
783                         var op = binding.Operations [0];
784
785                         Assert.That (op.Name, Is.EqualTo ("Hello"), label.Get ());
786                         Assert.That (op.ExtensibleAttributes, Is.Null, label.Get ());
787
788                         label.EnterScope ("extensions");
789                         Assert.That (op.Extensions, Is.Not.Null, label.Get ());
790                         Assert.That (op.Extensions.Count, Is.EqualTo (1), label.Get ());
791                         Assert.That (op.Extensions [0], Is.InstanceOfType (typeof (WS.SoapOperationBinding)), label.Get ());
792                         var soap = (WS.SoapOperationBinding)op.Extensions [0];
793                         TestSoap (soap, soap12, label);
794                         label.LeaveScope ();
795
796                         TestSoapMessage (op.Input, soap12, label);
797                         TestSoapMessage (op.Output, soap12, label);
798                         label.LeaveScope (); // operation
799
800                         label.LeaveScope ();
801                 }
802
803                 static void TestSoap (WS.SoapOperationBinding soap, bool soap12, TestLabel label)
804                 {
805                         label.EnterScope ("soap");
806                         var type = soap12 ? typeof (WS.Soap12OperationBinding) : typeof (WS.SoapOperationBinding);
807                         Assert.That (soap.GetType (), Is.EqualTo (type), label.Get ());
808                         Assert.That (soap.Style, Is.EqualTo (WS.SoapBindingStyle.Document), label.Get ());
809                         Assert.That (soap.SoapAction, Is.EqualTo ("http://tempuri.org/IMyContract/Hello"), label.Get ());
810                         Assert.That (soap.Required, Is.False, label.Get ());
811                         label.LeaveScope ();
812                 }
813
814                 static void TestSoapMessage (WS.MessageBinding binding, bool soap12, TestLabel label)
815                 {
816                         label.EnterScope (binding is WS.InputBinding ? "input" : "output");
817
818                         Assert.That (binding, Is.Not.Null, label.Get ());
819                         Assert.That (binding.Name, Is.Null, label.Get ());
820                         Assert.That (binding.ExtensibleAttributes, Is.Null, label.Get ());
821                         Assert.That (binding.Extensions, Is.Not.Null, label.Get ());
822                         Assert.That (binding.Extensions.Count, Is.EqualTo (1), label.Get ());
823                         Assert.That (binding.Extensions [0], Is.InstanceOfType (typeof (WS.SoapBodyBinding)), label.Get ());
824                         var body = (WS.SoapBodyBinding)binding.Extensions [0];
825                         TestSoapBody (body, soap12, label);
826                         label.LeaveScope ();
827                 }
828
829                 static void TestSoapBody (WS.SoapBodyBinding soap, bool soap12, TestLabel label)
830                 {
831                         label.EnterScope ("soap-body");
832                         var type = soap12 ? typeof (WS.Soap12BodyBinding) : typeof (WS.SoapBodyBinding);
833                         Assert.That (soap.GetType (), Is.EqualTo (type), label.Get ());
834                         Assert.That (soap.Encoding, Is.Empty, label.Get ());
835                         Assert.That (soap.Namespace, Is.Empty, label.Get ());
836                         Assert.That (soap.Parts, Is.Null, label.Get ());
837                         Assert.That (soap.Use, Is.EqualTo (WS.SoapBindingUse.Literal), label.Get ());
838                         label.LeaveScope ();
839                 }
840         }
841 }