// // MonoTests.System.Xml.XmlValidatingReaderTests.cs // // Author: // Atsushi Enomoto // // (C)2003 Atsushi Enomoto // using System; using System.Xml; using System.Xml.Schema; using NUnit.Framework; namespace MonoTests.System.Xml { [TestFixture] public class XmlValidatingReaderTests : Assertion { public XmlValidatingReaderTests () { } XmlValidatingReader dvr; private XmlValidatingReader PrepareXmlReader (string xml) { XmlReader reader = new XmlTextReader (xml, XmlNodeType.Document, null); // XmlDocument doc = new XmlDocument (); // doc.LoadXml (xml); // XmlReader reader = new XmlNodeReader (doc); return new XmlValidatingReader (reader); } [Test] public void TestSingleElement () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD try { dvr.Read (); // invalid element. Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + "invalid PCDATA."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // invalid text Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // invalid child Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestElementContent () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD try { dvr.Read (); // root: invalid end Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + "Test."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // invalid end Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // invalid element Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestMixedContent () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // end xml = dtd + "Test."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // valid PCDATA dvr.Read (); // endelement root xml = dtd + "Test."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // valid foo dvr.Read (); // valid #PCDATA dvr.Read (); // valid foo dvr.Read (); // valid endElement foo dvr.Read (); // valid endElement root xml = dtd + "Test."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // valid #PCDATA try { dvr.Read (); // invalid element Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestSequence () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // bar dvr.Read (); // end root xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo try { dvr.Read (); // invalid end root Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // invalid element bar Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestChoice () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo try { dvr.Read (); // invalid element bar Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // end root xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // bar dvr.Read (); // end root xml = dtd + "text."; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo try { dvr.Read (); // invalid text Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestAny () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // empty root. dvr.Read (); // end of document. xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // end root xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // foo dvr.Read (); // foo dvr.Read (); // end root xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root try { dvr.Read (); // bar: invalid (undeclared) element Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] [Category ("NotDotNet")] // MS fails to validate nondeterministic content validation. public void TestNonDeterministicContent () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // bar dvr.Read (); // end root xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // foo dvr.Read (); // end root } [Test] [Category ("NotDotNet")] public void TestAttributes () { // simple content and attributes are required string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.DTD; dvr.Read (); // DTD try { dvr.Read (); // missing attributes Fail ("should be failed."); // MS.NET fails to fail this test. } catch (XmlSchemaException) { } // empty element but attributes are required intSubset = ""; dtd = ""; xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.DTD; dvr.Read (); // DTD try { dvr.Read (); // missing attributes Fail ("should be failed."); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // end of document xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // end of document xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD try { dvr.Read (); // undeclared attribute baz Fail ("should be failed."); } catch (XmlSchemaException) { } } [Test] public void TestAttributeDefaultContribution () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.DTD; this.TestAttributeDefaultContributionInternal (dvr); dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.None; this.TestAttributeDefaultContributionInternal (dvr); } private void TestAttributeDefaultContributionInternal (XmlReader dvr) { dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); AssertEquals (2, dvr.AttributeCount); // foo Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("foo-def", dvr ["foo"]); AssertNotNull (dvr ["bar"]); AssertEquals ("foo-def", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("foo-def", dvr.Value); // bar Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("foo-def", dvr ["foo"]); AssertNotNull (dvr ["bar"]); AssertEquals ("bar-def", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("bar-def", dvr.Value); } [Test] public void TestExpandEntity () { string intSubset = ""; string dtd = ""; string xml = dtd + "&ent;"; dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandEntities; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("entity string", dvr.Value); Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("internal entity string value", dvr.Value); AssertEquals ("entity string", dvr.ReadString ()); // ValidationType = None dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandEntities; dvr.ValidationType = ValidationType.None; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("entity string", dvr.Value); Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("internal entity string value", dvr.Value); AssertEquals ("entity string", dvr.ReadString ()); } [Test] public void TestPreserveEntity () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); // MS BUG: it returns "entity string", however, entity should not be exanded. // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (!dvr.ReadAttributeValue ()); // bar Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("internal ", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals (" value", dvr.Value); // ValidationType = None dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.ValidationType = ValidationType.None; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); // foo Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (!dvr.ReadAttributeValue ()); // bar Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("internal ", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals (" value", dvr.Value); } [Test] // it used to be regarded as MS bug but it was not really. public void TestPreserveEntityNotOnDotNet () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("entity string", dvr.Value); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (!dvr.ReadAttributeValue ()); // bar Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("internal entity string value", dvr.Value); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("internal ", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals (" value", dvr.Value); // ValidationType = None dvr = PrepareXmlReader (xml); dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.ValidationType = ValidationType.None; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); // foo Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("entity string", dvr.Value); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (!dvr.ReadAttributeValue ()); // bar Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("internal entity string value", dvr.Value); // ReadAttributeValue() Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals ("internal ", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals ("ent", dvr.Name); AssertEquals ("", dvr.Value); Assert (dvr.ReadAttributeValue ()); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals ("", dvr.Name); AssertEquals (" value", dvr.Value); } [Test] public void TestNormalization () { string intSubset = "" + ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); ((XmlTextReader) dvr.Reader).Normalization = true; dvr.EntityHandling = EntityHandling.ExpandEntities; dvr.Read (); // DTD dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals ("root", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); AssertEquals ("foo", dvr.Name); AssertEquals ("id1", dvr.Value); Assert (dvr.MoveToNextAttribute ()); AssertEquals ("bar", dvr.Name); AssertEquals ("nameToken", dvr.Value); Assert (dvr.MoveToNextAttribute ()); AssertEquals ("baz", dvr.Name); AssertEquals ("list of name token", dvr.Value); Assert (dvr.MoveToNextAttribute ()); AssertEquals ("quux", dvr.Name); AssertEquals (" quuux quuux ", dvr.Value); } [Test] public void TestValidationEvent () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; eventFired = false; dvr = PrepareXmlReader (xml); dvr.ValidationEventHandler += new ValidationEventHandler (OnInvalidityFound); dvr.ValidationType = ValidationType.DTD; dvr.Read (); // DTD Assert (dvr.Read ()); // invalid foo Assert (eventFired); AssertEquals ("foo", dvr.Name); Assert (dvr.Read ()); // invalid bar AssertEquals ("bar", dvr.Name); Assert (dvr.MoveToFirstAttribute ()); // att AssertEquals ("att", dvr.Name); Assert (dvr.Read ()); // invalid end foo AssertEquals ("foo", dvr.Name); AssertEquals (XmlNodeType.EndElement, dvr.NodeType); Assert (!dvr.Read ()); // When ValidationType is None, event should not be fired, eventFired = false; dvr = PrepareXmlReader (xml); dvr.ValidationEventHandler += new ValidationEventHandler (OnInvalidityFound); dvr.ValidationType = ValidationType.None; dvr.Read (); // DTD Assert (dvr.Read ()); // invalid foo Assert (!eventFired); } private bool eventFired; private void OnInvalidityFound (object o, ValidationEventArgs e) { eventFired = true; } [Test] public void TestIdentityConstraints () { string intSubset = ""; string dtd = ""; string xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.DTD; dvr.Read (); // DTD try { dvr.Read (); // root misses attribute foo Fail (); } catch (XmlSchemaException) { } intSubset = ""; dtd = ""; xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.ValidationType = ValidationType.DTD; dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // c[1] try { dvr.Read (); // c[2] Fail (); } catch (XmlSchemaException) { } xml = dtd + ""; dvr = PrepareXmlReader (xml); dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // c[1] try { dvr.Read (); // c[2] Fail (); } catch (XmlSchemaException) { } } // Entity tests are almost copied from XmlNodeReaderTests. [Test] public void ResolveEntity () { string ent1 = ""; string ent2 = "'>]>"; string dtd = "" + ent1 + ent2; string xml = dtd + "&ent;&ent2;"; dvr = new XmlValidatingReader (xml, XmlNodeType.Document, null); dvr.ValidationType = ValidationType.None; dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // &ent; AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals (1, dvr.Depth); dvr.ResolveEntity (); // It is still entity reference. AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); dvr.Read (); AssertEquals (XmlNodeType.Text, dvr.NodeType); AssertEquals (2, dvr.Depth); AssertEquals ("entity string", dvr.Value); dvr.Read (); AssertEquals (XmlNodeType.EndEntity, dvr.NodeType); AssertEquals (1, dvr.Depth); AssertEquals ("", dvr.Value); dvr.Read (); // &ent2; AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); AssertEquals (1, dvr.Depth); dvr.ResolveEntity (); // It is still entity reference. AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); // It now became element node. dvr.Read (); AssertEquals (XmlNodeType.Element, dvr.NodeType); AssertEquals (2, dvr.Depth); } [Test] public void ResolveEntity2 () { string ent1 = ""; string ent2 = "'>]>"; string dtd = "" + ent1 + ent2; string xml = dtd + "&ent3;&ent2;"; dvr = new XmlValidatingReader (xml, XmlNodeType.Document, null); dvr.ValidationType = ValidationType.None; dvr.EntityHandling = EntityHandling.ExpandCharEntities; dvr.Read (); // DTD dvr.Read (); // root dvr.Read (); // &ent3; AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); #if NET_2_0 // under .NET 2.0, an error is raised here. // under .NET 1.1, the error is thrown on the next read. try { dvr.ResolveEntity (); Fail ("Attempt to resolve undeclared entity should fail."); } catch (XmlException) { } #else // ent3 does not exist in this dtd. dvr.ResolveEntity (); AssertEquals (XmlNodeType.EntityReference, dvr.NodeType); try { dvr.Read (); Fail ("Attempt to resolve undeclared entity should fail."); } catch (XmlException) { } #endif } [Test] [ExpectedException (typeof (XmlException))] public void ResolveEntityWithoutDTD () { string xml = "&ent;&ent2;"; dvr = new XmlValidatingReader (xml, XmlNodeType.Document, null); dvr.Read (); // root dvr.Read (); // &ent; } [Test] public void ResolveEntityReadAttributeValue () { string dtd = "]>"; string xml = dtd + "&ent;"; dvr = new XmlValidatingReader (xml, XmlNodeType.Document, null); dvr.Read (); // doctype dvr.Read (); // root dvr.MoveToAttribute (0); // attr Assert (dvr.ReadAttributeValue ()); // Should read expanded text AssertEquals (XmlNodeType.Text, dvr.NodeType); // not EntityReference AssertEquals ("entity string text", dvr.Value); Assert (!dvr.ReadAttributeValue ()); } [Test] public void ResolveEntitySequentialText () { string xml = @" test'> ]> &ref1; test "; string refOut = "test test "; XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null); XmlValidatingReader r = new XmlValidatingReader (xtr); r.Read (); r.Read (); r.Read (); AssertEquals (refOut, r.ReadOuterXml ()); } } }