[bcl] Remove more NET_2_0 checks from class libs
[mono.git] / mcs / class / System.Xml.Linq / Test / System.Xml.XPath / ExtensionsTest.cs
1 //
2 // Author:
3 //      Atsushi Enomoto <atsushi@ximian.com>
4 //
5 // Copyright (C) 2010 Novell, Inc.
6 // (C) 2003 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 // 
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 // 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27
28 //
29 // (based on XPathNavigatorCommonTests)
30 //
31
32 using System;
33 using System.Collections;
34 using System.IO;
35 using System.Linq;
36 using System.Xml;
37 using System.Xml.Linq;
38 using System.Xml.XPath;
39 using NUnit.Framework;
40 using System.Collections.Generic;
41
42 namespace MonoTests.System.Xml
43 {
44         public static class Helpers
45         {
46                 public static string NormalizeNewline(this string str)
47                 {
48                         return str.Replace("\r\n", "\n");
49                 }
50         }
51
52         [TestFixture]
53         public class ExtensionsTest
54         {
55                 XPathNavigator nav;
56
57                 private void AssertNavigator (string label, XPathNavigator nav, XPathNodeType type, string prefix, string localName, string ns, string name, string value, bool hasAttributes, bool hasChildren, bool isEmptyElement)
58                 {
59                         label += nav.GetType ();
60                         Assert.AreEqual (type, nav.NodeType, label + "NodeType");
61                         Assert.AreEqual (prefix, nav.Prefix, label + "Prefix");
62                         Assert.AreEqual (localName, nav.LocalName, label + "LocalName");
63                         Assert.AreEqual (ns, nav.NamespaceURI, label + "Namespace");
64                         Assert.AreEqual (name, nav.Name, label + "Name");
65                         Assert.AreEqual (value, nav.Value, label + "Value");
66                         Assert.AreEqual (hasAttributes, nav.HasAttributes, label + "HasAttributes");
67                         Assert.AreEqual (hasChildren, nav.HasChildren, label + "HasChildren");
68                         Assert.AreEqual (isEmptyElement, nav.IsEmptyElement, label + "IsEmptyElement");
69                 }
70
71                 [Test]
72                 public void DocumentWithXmlDeclaration ()
73                 {
74                         string xml = "<?xml version=\"1.0\" standalone=\"yes\"?><foo>bar</foo>";
75
76                         nav = XDocument.Parse (xml).CreateNavigator ();
77                         DocumentWithXmlDeclaration (nav);
78                 }
79
80                 public void DocumentWithXmlDeclaration (XPathNavigator nav)
81                 {
82                         nav.MoveToFirstChild ();
83                         AssertNavigator ("#1", nav, XPathNodeType.Element, "", "foo", "", "foo", "bar", false, true, false);
84                 }
85
86                 [Test]
87                 public void DocumentWithProcessingInstruction ()
88                 {
89                         string xml = "<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />";
90
91                         nav = XDocument.Parse (xml).CreateNavigator ();
92                         DocumentWithProcessingInstruction (nav);
93                 }
94
95                 public void DocumentWithProcessingInstruction (XPathNavigator nav)
96                 {
97                         Assert.IsTrue (nav.MoveToFirstChild ());
98                         AssertNavigator ("#1", nav, XPathNodeType.ProcessingInstruction, "", "xml-stylesheet", "", "xml-stylesheet", "href='foo.xsl' type='text/xsl' ", false, false, false);
99                         Assert.IsTrue (!nav.MoveToFirstChild ());
100                 }
101
102                 [Test]
103                 public void XmlRootElementOnly ()
104                 {
105                         string xml = "<foo />";
106
107                         nav = XDocument.Parse (xml).CreateNavigator ();
108                         XmlRootElementOnly (nav);
109                 }
110
111                 private void XmlRootElementOnly (XPathNavigator nav)
112                 {
113                         AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
114                         Assert.IsTrue (nav.MoveToFirstChild ());
115                         AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, false, true);
116                         Assert.IsTrue (!nav.MoveToFirstChild ());
117                         Assert.IsTrue (!nav.MoveToNext ());
118                         Assert.IsTrue (!nav.MoveToPrevious ());
119                         nav.MoveToRoot ();
120                         AssertNavigator ("#3", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
121                         Assert.IsTrue (!nav.MoveToNext ());
122                 }
123
124                 [Test]
125                 public void XmlSimpleTextContent ()
126                 {
127                         string xml = "<foo>Test.</foo>";
128
129                         nav = XDocument.Parse (xml).CreateNavigator ();
130                         XmlSimpleTextContent (nav);
131                 }
132
133                 private void XmlSimpleTextContent (XPathNavigator nav)
134                 {
135                         AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
136                         Assert.IsTrue (nav.MoveToFirstChild (), "#x1");
137                         AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "Test.", false, true, false);
138                         Assert.IsTrue (!nav.MoveToNext (), "#x2");
139                         Assert.IsTrue (!nav.MoveToPrevious (), "#x3");
140                         Assert.IsTrue (nav.MoveToFirstChild (), "#x4");
141                         AssertNavigator ("#3", nav, XPathNodeType.Text, "", "", "", "", "Test.", false, false, false);
142
143                         Assert.IsTrue (nav.MoveToParent (), "#x5");
144                         AssertNavigator ("#4", nav, XPathNodeType.Element, "", "foo", "", "foo", "Test.", false, true, false);
145
146                         Assert.IsTrue (nav.MoveToParent (), "#x6");
147                         AssertNavigator ("#5", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
148
149                         nav.MoveToFirstChild ();
150                         nav.MoveToFirstChild ();
151                         nav.MoveToRoot ();
152                         AssertNavigator ("#6", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
153                         Assert.IsTrue (!nav.MoveToNext (), "#x7");
154                 }
155
156                 [Test]
157                 public void XmlSimpleElementContent ()
158                 {
159                         string xml = "<foo><bar /></foo>";
160
161                         nav = XDocument.Parse (xml).CreateNavigator ();
162                         XmlSimpleElementContent (nav);
163                 }
164
165                 private void XmlSimpleElementContent (XPathNavigator nav)
166                 {
167                         AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
168                         Assert.IsTrue (nav.MoveToFirstChild ());
169                         AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
170                         Assert.IsTrue (!nav.MoveToNext ());
171                         Assert.IsTrue (!nav.MoveToPrevious ());
172
173                         Assert.IsTrue (nav.MoveToFirstChild ());
174                         AssertNavigator ("#3", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
175
176                         Assert.IsTrue (nav.MoveToParent ());
177                         AssertNavigator ("#4", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
178
179                         nav.MoveToRoot ();
180                         AssertNavigator ("#5", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
181                         Assert.IsTrue (!nav.MoveToNext ());
182                 }
183
184                 [Test]
185                 public void XmlTwoElementsContent ()
186                 {
187                         string xml = "<foo><bar /><baz /></foo>";
188
189                         nav = XDocument.Parse (xml).CreateNavigator ();
190                         XmlTwoElementsContent (nav);
191                 }
192
193                 private void XmlTwoElementsContent (XPathNavigator nav)
194                 {
195                         AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
196
197                         Assert.IsTrue (nav.MoveToFirstChild ());
198                         AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
199                         Assert.IsTrue (!nav.MoveToNext ());
200                         Assert.IsTrue (!nav.MoveToPrevious ());
201
202                         Assert.IsTrue (nav.MoveToFirstChild ());
203                         AssertNavigator ("#3", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
204                         Assert.IsTrue (!nav.MoveToFirstChild ());
205
206                         Assert.IsTrue (nav.MoveToNext ());
207                         AssertNavigator ("#4", nav, XPathNodeType.Element, "", "baz", "", "baz", "", false, false, true);
208                         Assert.IsTrue (!nav.MoveToFirstChild ());
209
210                         Assert.IsTrue (nav.MoveToPrevious ());
211                         AssertNavigator ("#5", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
212
213                         nav.MoveToRoot ();
214                         AssertNavigator ("#6", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
215                         Assert.IsTrue (!nav.MoveToNext ());
216                 }
217
218                 [Test]
219                 public void XmlElementWithAttributes ()
220                 {
221                         string xml = "<img src='foo.png' alt='image Fooooooo!' />";
222
223                         nav = XDocument.Parse (xml).CreateNavigator ();
224                         XmlElementWithAttributes (nav);
225                 }
226
227                 private void XmlElementWithAttributes (XPathNavigator nav)
228                 {
229                         nav.MoveToFirstChild ();
230                         AssertNavigator ("#1", nav, XPathNodeType.Element, "", "img", "", "img", "", true, false, true);
231                         Assert.IsTrue (!nav.MoveToNext (), "#x1");
232                         Assert.IsTrue (!nav.MoveToPrevious (), "#x2");
233
234                         Assert.IsTrue (nav.MoveToFirstAttribute (), "#x3");
235                         AssertNavigator ("#2", nav, XPathNodeType.Attribute, "", "src", "", "src", "foo.png", false, false, false);
236                         Assert.IsTrue (!nav.MoveToFirstAttribute (), "#x4");    // On attributes, it fails.
237
238                         Assert.IsTrue (nav.MoveToNextAttribute (), "#x5");
239                         AssertNavigator ("#3", nav, XPathNodeType.Attribute, "", "alt", "", "alt", "image Fooooooo!", false, false, false);
240                         Assert.IsTrue (!nav.MoveToNextAttribute (), "#x6");
241
242                         Assert.IsTrue (nav.MoveToParent (), "#x7");
243                         AssertNavigator ("#4", nav, XPathNodeType.Element, "", "img", "", "img", "", true, false, true);
244
245                         Assert.IsTrue (nav.MoveToAttribute ("alt", ""), "#x8");
246                         AssertNavigator ("#5", nav, XPathNodeType.Attribute, "", "alt", "", "alt", "image Fooooooo!", false, false, false);
247                         Assert.IsTrue (!nav.MoveToAttribute ("src", ""), "#x9");        // On attributes, it fails.
248                         Assert.IsTrue (nav.MoveToParent (), "#x10");
249                         Assert.IsTrue (nav.MoveToAttribute ("src", ""), "#x11");
250                         AssertNavigator ("#6", nav, XPathNodeType.Attribute, "", "src", "", "src", "foo.png", false, false, false);
251
252                         nav.MoveToRoot ();
253                         AssertNavigator ("#7", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
254                 }
255
256                 [Test]
257                 // seems like MS does not want to fix their long-time-known
258                 // XPathNavigator bug, so just set it as NotDotNet.
259                 // We are better.
260                 [Category ("NotDotNet")]
261                 public void XmlNamespaceNode ()
262                 {
263                         string xml = "<html xmlns='http://www.w3.org/1999/xhtml'><body>test.</body></html>";
264
265                         nav = XDocument.Parse (xml).CreateNavigator ();
266                         XmlNamespaceNode (nav);
267                 }
268
269                 private void XmlNamespaceNode (XPathNavigator nav)
270                 {
271                         string xhtml = "http://www.w3.org/1999/xhtml";
272                         string xmlNS = "http://www.w3.org/XML/1998/namespace";
273                         nav.MoveToFirstChild ();
274                         AssertNavigator ("#1", nav, XPathNodeType.Element,
275                                 "", "html", xhtml, "html", "test.", false, true, false);
276                         Assert.IsTrue (nav.MoveToFirstNamespace (XPathNamespaceScope.Local));
277                         AssertNavigator ("#2", nav, XPathNodeType.Namespace,
278                                 "", "", "", "", xhtml, false, false, false);
279
280                         // Test difference between Local, ExcludeXml and All.
281                         Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.Local));
282                         Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.ExcludeXml));
283                         // LAMESPEC: MS.NET 1.0 XmlDocument seems to have some bugs around here.
284                         // see http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q316808
285 #if true
286                         Assert.IsTrue (nav.MoveToNextNamespace (XPathNamespaceScope.All));
287                         AssertNavigator ("#3", nav, XPathNodeType.Namespace,
288                                 "", "xml", "", "xml", xmlNS, false, false, false);
289                         Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.All));
290 #endif
291                         // Test to check if MoveToRoot() resets Namespace node status.
292                         nav.MoveToRoot ();
293                         AssertNavigator ("#4", nav, XPathNodeType.Root, "", "", "", "", "test.", false, true, false);
294                         nav.MoveToFirstChild ();
295
296                         // Test without XPathNamespaceScope argument.
297                         Assert.IsTrue (nav.MoveToFirstNamespace ());
298                         Assert.IsTrue (nav.MoveToNextNamespace ());
299                         AssertNavigator ("#5", nav, XPathNodeType.Namespace,
300                                 "", "xml", "", "xml", xmlNS, false, false, false);
301
302                         // Test MoveToParent()
303                         Assert.IsTrue (nav.MoveToParent ());
304                         AssertNavigator ("#6", nav, XPathNodeType.Element,
305                                 "", "html", xhtml, "html", "test.", false, true, false);
306
307                         nav.MoveToFirstChild ();        // body
308                         // Test difference between Local and ExcludeXml
309                         Assert.IsTrue (!nav.MoveToFirstNamespace (XPathNamespaceScope.Local), "Local should fail");
310                         Assert.IsTrue (nav.MoveToFirstNamespace (XPathNamespaceScope.ExcludeXml), "ExcludeXml should succeed");
311                         AssertNavigator ("#7", nav, XPathNodeType.Namespace,
312                                 "", "", "", "", xhtml, false, false, false);
313
314                         Assert.IsTrue (nav.MoveToNextNamespace (XPathNamespaceScope.All));
315                         AssertNavigator ("#8", nav, XPathNodeType.Namespace,
316                                 "", "xml", "", "xml", xmlNS, false, false, false);
317                         Assert.IsTrue (nav.MoveToParent ());
318                         AssertNavigator ("#9", nav, XPathNodeType.Element,
319                                 "", "body", xhtml, "body", "test.", false, true, false);
320
321                         nav.MoveToRoot ();
322                         AssertNavigator ("#10", nav, XPathNodeType.Root, "", "", "", "", "test.", false, true, false);
323                 }
324
325                 [Test]
326                 public void MoveToNamespaces ()
327                 {
328                         string xml = "<a xmlns:x='urn:x'><b xmlns:y='urn:y'/><c/><d><e attr='a'/></d></a>";
329
330                         nav = XDocument.Parse (xml).CreateNavigator ();
331                         MoveToNamespaces (nav);
332                 }
333
334                 private void MoveToNamespaces (XPathNavigator nav)
335                 {
336                         XPathNodeIterator iter = nav.Select ("//e");
337                         iter.MoveNext ();
338                         nav.MoveTo (iter.Current);
339                         Assert.AreEqual ("e", nav.Name, "#1");
340                         nav.MoveToFirstNamespace ();
341                         Assert.AreEqual ("x", nav.Name, "#2");
342                         nav.MoveToNextNamespace ();
343                         Assert.AreEqual ("xml", nav.Name, "#3");
344                 }
345
346                 [Test]
347                 public void IsDescendant ()
348                 {
349                         string xml = "<a><b/><c/><d><e attr='a'/></d></a>";
350
351                         nav = XDocument.Parse (xml).CreateNavigator ();
352                         IsDescendant (nav);
353                 }
354
355                 private void IsDescendant (XPathNavigator nav)
356                 {
357                         XPathNavigator tmp = nav.Clone ();
358                         XPathNodeIterator iter = nav.Select ("//e");
359                         iter.MoveNext ();
360                         Assert.IsTrue (nav.MoveTo (iter.Current), "#1");
361                         Assert.IsTrue (nav.MoveToFirstAttribute (), "#2");
362                         Assert.AreEqual ("attr", nav.Name, "#3");
363                         Assert.AreEqual ("", tmp.Name, "#4");
364                         Assert.IsTrue (tmp.IsDescendant (nav), "#5");
365                         Assert.IsTrue (!nav.IsDescendant (tmp), "#6");
366                         tmp.MoveToFirstChild ();
367                         Assert.AreEqual ("a", tmp.Name, "#7");
368                         Assert.IsTrue (tmp.IsDescendant (nav), "#8");
369                         Assert.IsTrue (!nav.IsDescendant (tmp), "#9");
370                         tmp.MoveTo (iter.Current);
371                         Assert.AreEqual ("e", tmp.Name, "#10");
372                         Assert.IsTrue (tmp.IsDescendant (nav), "#11");
373                         Assert.IsTrue (!nav.IsDescendant (tmp), "#12");
374                 }
375
376                 [Test]
377                 public void LiterallySplitText ()
378                 {
379                         string xml = "<root><![CDATA[test]]> string</root>";
380
381                         nav = XDocument.Parse (xml).CreateNavigator ();
382                         LiterallySplitText (nav);
383                 }
384
385                 private void LiterallySplitText (XPathNavigator nav)
386                 {
387                         nav.MoveToFirstChild ();
388                         nav.MoveToFirstChild ();
389                         Assert.AreEqual (XPathNodeType.Text, nav.NodeType, "#1");
390                         Assert.AreEqual ("test string", nav.Value, "#2");
391                 }
392
393                 // bug #75609
394                 [Test]
395                 public void SelectChildren ()
396                 {
397                         string xml = "<root><foo xmlns='urn:foo' /><ns:foo xmlns:ns='urn:foo' /></root>";
398
399                         nav = XDocument.Parse (xml).CreateNavigator ();
400                         SelectChildrenNS (nav);
401                 }
402
403                 private void SelectChildrenNS (XPathNavigator nav)
404                 {
405                         nav.MoveToFirstChild (); // root
406                         XPathNodeIterator iter = nav.SelectChildren ("foo", "urn:foo");
407                         Assert.AreEqual (2, iter.Count, "#1");
408                 }
409
410
411                 [Test]
412                 // bug #78067
413                 public void OuterXml ()
414                 {
415                         string xml = @"<?xml version=""1.0""?>
416 <one>
417         <two>Some data.</two>
418 </one>";
419
420                         nav = XDocument.Parse (xml).CreateNavigator ();
421                         OuterXml (nav);
422                 }
423
424                 private void OuterXml (XPathNavigator nav)
425                 {
426                         string ret = @"<one>
427   <two>Some data.</two>
428 </one>";
429                         Assert.AreEqual (ret.NormalizeNewline (), nav.OuterXml.NormalizeNewline (), "#1");
430                 }
431
432                 [Test]
433                 public void ReadSubtreeLookupNamespace ()
434                 {
435                         string xml = "<x:foo xmlns:x='urn:x'><bar>x:val</bar></x:foo>";
436                         var doc = new XmlDocument ();
437                         doc.LoadXml (xml);
438                         XPathNavigator nav = doc.LastChild.LastChild.CreateNavigator ();
439                         var xr = nav.ReadSubtree ();
440                         xr.MoveToContent ();
441                         xr.Read (); // should be at x:val
442                         Assert.AreEqual ("urn:x", xr.LookupNamespace ("x"), "#1");
443                 }
444
445                 [Test]
446                 public void GetNamespaceConsistentTree ()
447                 {
448                         string xml = "<x:root xmlns:x='urn:x'>  <x:foo xmlns='ns1'> <x:bar /> </x:foo>  <x:foo xmlns:y='ns2'> <x:bar /> </x:foo></x:root>";
449                         nav = XDocument.Parse (xml).CreateNavigator ();
450                         GetNamespaceConsistentTree (nav);
451                 }
452
453                 private void GetNamespaceConsistentTree (XPathNavigator nav)
454                 {
455                         nav.MoveToFirstChild ();
456                         nav.MoveToFirstChild ();
457                         nav.MoveToNext ();
458                         Assert.AreEqual (String.Empty, nav.GetNamespace (""), "#1." + nav.GetType ());
459                         nav.MoveToNext ();
460                         nav.MoveToNext ();
461                         Assert.AreEqual ("", nav.GetNamespace (""), "#2." + nav.GetType ());
462                 }
463
464                 [Test] // bug #2383
465                 public void EvaluateNodeSetAsEnumerable ()
466                 {
467                         String xml = "<root a='value'/>";
468                         XDocument d = XDocument.Parse (xml);
469                         IEnumerable att = (IEnumerable) d.XPathEvaluate ("/root/@a");
470                         att.Cast<XAttribute> ().FirstOrDefault ();
471                 }
472
473                 [Test] // bug #5902
474                 public void EvaluateNodeSetAsEnumerableOfObject ()
475                 {
476                         var root = XDocument.Parse("<config><item name=\"A\" /></config>");
477                         Assert.IsTrue (root.XPathSelectElements ("config/*").First ().XPathEvaluate (".") is IEnumerable<object>);
478                 }
479
480                 [Test] // bug #2146
481                 public void RemoveDoesSnapshotCopy ()
482                 {
483                         var xml = XElement.Parse ("<p><n>one</n><n>two</n><n>three</n></p>");
484                         xml.Elements ().Last ().NodesBeforeSelf ().Remove ();
485                 }
486
487                 [Test] // bug #2146
488                 public void RemoveDoesSnapshotCopy2 ()
489                 {
490                         var xml = XElement.Parse ("<p><n>one</n><n>two</n><n>three</n></p>");
491                         xml.Elements ().First ().NodesAfterSelf ().Remove ();
492                         Assert.IsTrue (!xml.ToString ().Contains ("three"), "#1");
493                 }
494         }
495 }