#region Apache License 2.0 /* Nuclex .NET Framework Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #endregion // Apache License 2.0 using System; using System.IO; using System.Text; using System.Xml; #if !USE_XMLDOCUMENT using System.Xml.Linq; #endif using System.Xml.Schema; using NUnit.Framework; namespace Nuclex.Support { /// Unit Test for the XML helper class [TestFixture] internal class XmlHelperTest { /// A broken XML schema private const string brokenSchemaXml = "This is not a valid schema"; /// An XML schema with a syntax error private const string syntaxErrorSchemaXml = "" + "" + " " + " " + ""; /// A valid XML schema for a list of 2D points private const string pointsSchemaXml = "" + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; /// A broken XML document private const string brokenXml = "This is not a valid XML file"; /// /// Well-formed XML document that is not conformant to the schema above /// private const string unconformantXml = "" + "" + " " + " " + ""; /// Well-formed XML document that is conformant to the schema private const string conformantXml = "" + "" + " " + " " + ""; #region TempFileKeeper /// /// Creates a temporary file and automatically deletes it on dispose /// private class TempFileKeeper : IDisposable { /// /// Creates a temporary file with the specified contents using the UTF8 encoding /// /// /// Contents that will be written into the temporary file /// public TempFileKeeper(string fileContents) : this(fileContents, Encoding.UTF8) { } /// Creates a temporary file with the specified contents /// /// Contents that will be written into the temporary file /// /// /// Encoding to use for writing the contents into the file /// public TempFileKeeper(string fileContents, Encoding encoding) { string tempFile = Path.GetTempFileName(); try { using( FileStream tempFileStream = new FileStream( tempFile, FileMode.Truncate, FileAccess.Write, FileShare.None ) ) { StreamWriter writer = new StreamWriter(tempFileStream, encoding); writer.Write(fileContents); writer.Flush(); } } catch(Exception) { File.Delete(tempFile); throw; } this.tempFilePath = tempFile; } /// Called when the instance is collected by the GC ~TempFileKeeper() { Dispose(); } /// Immediately releases all resources used by the instance public void Dispose() { if(this.tempFilePath != null) { File.Delete(this.tempFilePath); this.tempFilePath = null; GC.SuppressFinalize(this); } } /// Implicitely converts a TempFileKeeper into a file path /// TempFileKeeper that will be converted /// The path to the temporary file managed by the TempFileKeeper public static implicit operator string(TempFileKeeper tempFileKeeper) { return tempFileKeeper.tempFilePath; } /// Path to the temporary file the TempFileKeeper is managing private string tempFilePath; } #endregion // class TempFileKeeper /// /// Verifies that an exception is thrown when a schema fails to load /// [Test] public void LoadSchemaThrowsOnInvalidSchema() { using( TempFileKeeper tempFile = new TempFileKeeper(brokenSchemaXml) ) { Assert.Throws(delegate() { XmlHelper.LoadSchema(tempFile); }); } } /// /// Verifies that an exception is thrown when a schema contains a syntax error /// [Test] public void LoadSchemaThrowsOnSyntaxErrors() { using( TempFileKeeper tempFile = new TempFileKeeper(syntaxErrorSchemaXml) ) { Assert.Throws(delegate() { XmlHelper.LoadSchema(tempFile); }); } } /// /// Verfifies that TryLoadSchema() can fail without throwing an exception /// when the schema is not a valid XML document /// [Test] public void TryLoadSchemaHandlesMissingFiles() { XmlSchema schema; Assert.IsFalse(XmlHelper.TryLoadSchema("-- hello world --", out schema)); Assert.IsNull(schema); } /// /// Verfifies that TryLoadSchema() can fail without throwing an exception /// when the schema is not a valid XML document /// [Test] public void TryLoadSchemaHandlesBrokenSchemas() { using( TempFileKeeper tempFile = new TempFileKeeper(brokenSchemaXml) ) { XmlSchema schema; Assert.IsFalse(XmlHelper.TryLoadSchema(tempFile, out schema)); Assert.IsNull(schema); } } /// /// Verfifies that TryLoadSchema() can fail without throwing an exception /// when the schema contains a syntax error /// [Test] public void TryLoadSchemaHandlesSyntaxErrors() { using( TempFileKeeper tempFile = new TempFileKeeper(syntaxErrorSchemaXml) ) { XmlSchema schema; Assert.IsFalse(XmlHelper.TryLoadSchema(tempFile, out schema)); Assert.IsNull(schema); } } /// Tests whether a normal, valid schema can be loaded successfully [Test] public void SchemasCanBeLoadedFromFiles() { using( TempFileKeeper tempFile = new TempFileKeeper(pointsSchemaXml) ) { XmlHelper.LoadSchema(tempFile); } } /// Tests whether a normal, valid schema can be loaded successfully [Test] public void TryLoadSchemaCanLoadSchemas() { using( TempFileKeeper tempFile = new TempFileKeeper(pointsSchemaXml) ) { XmlSchema schema; Assert.IsTrue(XmlHelper.TryLoadSchema(tempFile, out schema)); Assert.NotNull(schema); } } /// /// Verifies that an exception is thrown when an invalid XML document is loaded /// [Test] public void LoadingInvalidDocumentThrows() { using(TextReader schemaReader = new StringReader(pointsSchemaXml)) { XmlSchema schema = XmlHelper.LoadSchema(schemaReader); using( TempFileKeeper tempFile = new TempFileKeeper(brokenXml) ) { Assert.Throws( delegate() { XmlHelper.LoadDocument(schema, tempFile); } ); } } } /// /// Verifies that an exception is thrown when a nonconformant XML document is loaded /// [Test] public void SchemaValidationFailureCausesException() { using(TextReader schemaReader = new StringReader(pointsSchemaXml)) { XmlSchema schema = XmlHelper.LoadSchema(schemaReader); using( TempFileKeeper tempFile = new TempFileKeeper(unconformantXml) ) { Assert.Throws( delegate() { XmlHelper.LoadDocument(schema, tempFile); } ); } } } /// /// Tests whether a normal, conformant XML document can be loaded successfully /// [Test] public void LoadedDocumentIsValidatedAgainstSchema() { using(TextReader schemaReader = new StringReader(pointsSchemaXml)) { XmlSchema schema = XmlHelper.LoadSchema(schemaReader); using( TempFileKeeper tempFile = new TempFileKeeper(conformantXml) ) { #if USE_XMLDOCUMENT XmlDocument document = XmlHelper.LoadDocument(schema, tempFile); #else XDocument document = XmlHelper.LoadDocument(schema, tempFile); #endif } } } } } // namespace Nuclex.Support