1 //
2 // XmlDsigXPathTransformTest.cs - Test Cases for XmlDsigXPathTransform
3 //
4 // Author:
5 //	Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Licensed to the .NET Foundation under one or more agreements.
11 // See the LICENSE file in the project root for more information.
12 
13 using System.IO;
14 using System.Xml;
15 using Xunit;
16 
17 namespace System.Security.Cryptography.Xml.Tests
18 {
19 
20     // Note: GetInnerXml is protected in XmlDsigXPathTransform making it
21     // difficult to test properly. This class "open it up" :-)
22     public class UnprotectedXmlDsigXPathTransform : XmlDsigXPathTransform
23     {
24 
UnprotectedGetInnerXml()25         public XmlNodeList UnprotectedGetInnerXml()
26         {
27             return base.GetInnerXml();
28         }
29     }
30 
31     public class XmlDsigXPathTransformTest
32     {
33 
34         protected UnprotectedXmlDsigXPathTransform transform;
35 
XmlDsigXPathTransformTest()36         public XmlDsigXPathTransformTest()
37         {
38             transform = new UnprotectedXmlDsigXPathTransform();
39         }
40 
41         [Fact]
Properties()42         public void Properties()
43         {
44             Assert.Equal("http://www.w3.org/TR/1999/REC-xpath-19991116", transform.Algorithm);
45 
46             Type[] input = transform.InputTypes;
47             Assert.True((input.Length == 3), "Input #");
48             // check presence of every supported input types
49             bool istream = false;
50             bool ixmldoc = false;
51             bool ixmlnl = false;
52             foreach (Type t in input)
53             {
54                 if (t.ToString() == "System.IO.Stream")
55                     istream = true;
56                 if (t.ToString() == "System.Xml.XmlDocument")
57                     ixmldoc = true;
58                 if (t.ToString() == "System.Xml.XmlNodeList")
59                     ixmlnl = true;
60             }
61             Assert.True(istream, "Input Stream");
62             Assert.True(ixmldoc, "Input XmlDocument");
63             Assert.True(ixmlnl, "Input XmlNodeList");
64 
65             Type[] output = transform.OutputTypes;
66             Assert.True((output.Length == 1), "Output #");
67             // check presence of every supported output types
68             bool oxmlnl = false;
69             foreach (Type t in output)
70             {
71                 if (t.ToString() == "System.Xml.XmlNodeList")
72                     oxmlnl = true;
73             }
74             Assert.True(oxmlnl, "Output XmlNodeList");
75         }
76 
AreEqual(string msg, XmlNodeList expected, XmlNodeList actual)77         protected void AreEqual(string msg, XmlNodeList expected, XmlNodeList actual)
78         {
79             for (int i = 0; i < expected.Count; i++)
80             {
81                 Assert.Equal(expected[i].OuterXml, actual[i].OuterXml);
82             }
83             Assert.Equal(expected.Count, actual.Count);
84         }
85 
86         [Fact]
GetInnerXml()87         public void GetInnerXml()
88         {
89             XmlNodeList xnl = transform.UnprotectedGetInnerXml();
90             Assert.Equal(1, xnl.Count);
91             Assert.Equal("<XPath xmlns=\"http://www.w3.org/2000/09/xmldsig#\" />", xnl[0].OuterXml);
92         }
93 
94         [Fact]
OnlyInner()95         public void OnlyInner()
96         {
97             XmlNodeList inner = InnerXml(""); // empty
98             transform.LoadInnerXml(inner);
99             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
100             Assert.Equal(0, xnl.Count);
101         }
102 
GetDoc()103         private XmlDocument GetDoc()
104         {
105             string test = "<catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan</artist><price>10.90</price>";
106             test += "<year>1985</year></cd><cd><title>Hide your heart</title><artist>Bonnie Tyler</artist><price>9.90</price>";
107             test += "<year>1988</year></cd><cd><title>Greatest Hits</title><artist>Dolly Parton</artist><price>9.90</price>";
108             test += "<year>1982</year></cd><cd><title>Still got the blues</title><artist>Gary Moore</artist><price>10.20</price>";
109             test += "<year>1990</year></cd><cd><title>Eros</title><artist>Eros Ramazzotti</artist><price>9.90</price>";
110             test += "<year>1997</year></cd></catalog>";
111             XmlDocument doc = new XmlDocument();
112             doc.LoadXml(test);
113             return doc;
114         }
115 
InnerXml(string xpathExpr)116         private XmlNodeList InnerXml(string xpathExpr)
117         {
118             string xpath = "<XPath xmlns=\"http://www.w3.org/2000/09/xmldsig#\">" + xpathExpr + "</XPath>";
119             XmlDocument doc = new XmlDocument();
120             doc.LoadXml(xpath);
121             return doc.ChildNodes;
122         }
123 
124         [Fact]
LoadInputAsXmlDocument()125         public void LoadInputAsXmlDocument()
126         {
127             XmlDocument doc = GetDoc();
128             transform.LoadInput(doc);
129             XmlNodeList inner = InnerXml("//*/title");
130             transform.LoadInnerXml(inner);
131             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
132             Assert.Equal(73, xnl.Count);
133         }
134 
135         [Fact]
LoadInputAsXmlDocument_EmptyXPath()136         public void LoadInputAsXmlDocument_EmptyXPath()
137         {
138             XmlDocument doc = GetDoc();
139             transform.LoadInput(doc);
140             // empty means no LoadInnerXml
141             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
142             Assert.Equal(0, xnl.Count);
143         }
144 
145         [Fact]
LoadInputAsXmlNodeList()146         public void LoadInputAsXmlNodeList()
147         {
148             XmlDocument doc = GetDoc();
149             transform.LoadInput(doc.ChildNodes);
150             XmlNodeList inner = InnerXml("//*/title");
151             transform.LoadInnerXml(inner);
152             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
153             Assert.Equal(1, xnl.Count);
154         }
155 
156         [Fact]
LoadInputAsXmlNodeList_EmptyXPath()157         public void LoadInputAsXmlNodeList_EmptyXPath()
158         {
159             XmlDocument doc = GetDoc();
160             transform.LoadInput(doc.ChildNodes);
161             // empty means no LoadInnerXml
162             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
163             Assert.Equal(0, xnl.Count);
164         }
165 
166         [Fact]
LoadInputAsStream()167         public void LoadInputAsStream()
168         {
169             XmlDocument doc = GetDoc();
170             doc.PreserveWhitespace = true;
171             MemoryStream ms = new MemoryStream();
172             doc.Save(ms);
173             ms.Position = 0;
174             transform.LoadInput(ms);
175             XmlNodeList inner = InnerXml("//*/title");
176             transform.LoadInnerXml(inner);
177             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
178             Assert.Equal(73, xnl.Count);
179         }
180 
181         [Fact]
LoadInputAsStream_EmptyXPath()182         public void LoadInputAsStream_EmptyXPath()
183         {
184             XmlDocument doc = GetDoc();
185             MemoryStream ms = new MemoryStream();
186             doc.Save(ms);
187             ms.Position = 0;
188             transform.LoadInput(ms);
189             // empty means no LoadInnerXml
190             XmlNodeList xnl = (XmlNodeList)transform.GetOutput();
191             Assert.Equal(0, xnl.Count);
192         }
193 
194         [Fact]
LoadInnerXml()195         public void LoadInnerXml()
196         {
197             XmlNodeList inner = InnerXml("//*");
198             transform.LoadInnerXml(inner);
199             XmlNodeList xnl = transform.UnprotectedGetInnerXml();
200             Assert.Equal(inner, xnl);
201         }
202 
203         [Fact]
UnsupportedInput()204         public void UnsupportedInput()
205         {
206             byte[] bad = { 0xBA, 0xD };
207             // LAMESPEC: input MUST be one of InputType - but no exception is thrown (not documented)
208             transform.LoadInput(bad);
209         }
210 
211         [Fact]
UnsupportedOutput()212         public void UnsupportedOutput()
213         {
214             XmlDocument doc = new XmlDocument();
215             AssertExtensions.Throws<ArgumentException>("type", () => transform.GetOutput(doc.GetType()));
216         }
217 
218         [Fact]
TransformSimple()219         public void TransformSimple()
220         {
221             XmlDsigXPathTransform t = new XmlDsigXPathTransform();
222             XmlDocument xpdoc = new XmlDocument();
223             string ns = "http://www.w3.org/2000/09/xmldsig#";
224             string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'>*|@*|namespace::*</XPath>"; // not absolute path.. so @* and namespace::* does not make sense.
225             xpdoc.LoadXml(xpath);
226             t.LoadInnerXml(xpdoc.ChildNodes);
227             XmlDocument doc = new XmlDocument();
228             doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
229             t.LoadInput(doc);
230             XmlNodeList nl = (XmlNodeList)t.GetOutput();
231             Assert.Equal(XmlNodeType.Document, nl[0].NodeType);
232             Assert.Equal(XmlNodeType.Element, nl[1].NodeType);
233             Assert.Equal("element", nl[1].LocalName);
234             Assert.Equal(XmlNodeType.Element, nl[2].NodeType);
235             Assert.Equal("foo", nl[2].LocalName);
236             Assert.Equal(XmlNodeType.Element, nl[3].NodeType);
237             Assert.Equal("bar", nl[3].LocalName);
238             // MS.NET bug - ms.net returns ns node even when the
239             // current node is ns node (it is like returning
240             // attribute from attribute nodes).
241             //			Assert.Equal (XmlNodeType.Attribute, nl [4].NodeType);
242             //			Assert.Equal ("xmlns", nl [4].LocalName);
243         }
244 
245         [Fact]
246         // MS.NET looks incorrect, or something incorrect in this test code; It turned out nothing to do with function here()
FunctionHereObsolete()247         public void FunctionHereObsolete()
248         {
249             XmlDsigXPathTransform t = new XmlDsigXPathTransform();
250             XmlDocument xpdoc = new XmlDocument();
251             string ns = "http://www.w3.org/2000/09/xmldsig#";
252             //			string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'>here()</XPath>";
253             string xpath = "<XPath xmlns='" + ns + "' xmlns:x='urn:foo'></XPath>";
254             xpdoc.LoadXml(xpath);
255             t.LoadInnerXml(xpdoc.ChildNodes);
256             XmlDocument doc = new XmlDocument();
257 
258             doc.LoadXml("<element a='b'><foo><bar>test</bar></foo></element>");
259             t.LoadInput(doc);
260 
261             XmlNodeList nl = (XmlNodeList)t.GetOutput();
262             Assert.Equal(0, nl.Count);
263 
264             doc.LoadXml("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
265             t.LoadInput(doc);
266             nl = (XmlNodeList)t.GetOutput();
267             Assert.Equal(0, nl.Count);
268 
269             doc.LoadXml("<element xmlns='urn:foo'><foo xmlns='urn:bar'><bar>test</bar></foo></element>");
270             t.LoadInput(doc);
271             nl = (XmlNodeList)t.GetOutput();
272             Assert.Equal(0, nl.Count);
273 
274             doc.LoadXml("<element xmlns='urn:foo' xmlns:x='urn:x'><foo xmlns='urn:bar'><bar>test</bar></foo></element>");
275             t.LoadInput(doc);
276             nl = (XmlNodeList)t.GetOutput();
277             Assert.Equal(0, nl.Count);
278 
279             doc.LoadXml("<envelope><Signature xmlns='http://www.w3.org/2000/09/xmldsig#'><XPath>blah</XPath></Signature></envelope>");
280             t.LoadInput(doc);
281             nl = (XmlNodeList)t.GetOutput();
282             Assert.Equal(0, nl.Count);
283         }
284     }
285 }
286