// // XmlDsigExcC14NTransformTest.cs - NUnit Test Cases for XmlDsigExcC14NTransform // // Author: // original: // Sebastien Pouliot // Aleksey Sanin (aleksey@aleksey.com) // this file: // Atsushi Enomoto // // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com) // (C) 2003 Aleksey Sanin (aleksey@aleksey.com) // (C) 2004 Novell (http://www.novell.com) // // // WARNING!! // This file is simply replaced C14N->ExcC14N, and then replaced expected // output XML. So, they are *not* from c14n specification. // using System; using System.IO; using System.Security.Cryptography.Xml; using System.Text; using System.Xml; using NUnit.Framework; namespace MonoTests.System.Security.Cryptography.Xml { // Note: GetInnerXml is protected in XmlDsigExcC14NTransform making it // difficult to test properly. This class "open it up" :-) public class UnprotectedXmlDsigExcC14NTransform : XmlDsigExcC14NTransform { public UnprotectedXmlDsigExcC14NTransform () { } public UnprotectedXmlDsigExcC14NTransform (bool includeComments) : base (includeComments) { } public UnprotectedXmlDsigExcC14NTransform (string inclusiveNamespacesPrefixList) : base (inclusiveNamespacesPrefixList) { } public UnprotectedXmlDsigExcC14NTransform (bool includeComments, string inclusiveNamespacesPrefixList) : base (includeComments, inclusiveNamespacesPrefixList) { } public XmlNodeList UnprotectedGetInnerXml () { return base.GetInnerXml (); } } [TestFixture] public class XmlDsigExcC14NTransformTest { protected UnprotectedXmlDsigExcC14NTransform transform; [SetUp] protected void SetUp () { transform = new UnprotectedXmlDsigExcC14NTransform (); } [TearDown] protected void CleanUp () { try { if (File.Exists ("doc.dtd")) File.Delete ("doc.dtd"); if (File.Exists ("world.txt")) File.Delete ("world.txt"); } catch {} } [Test] // ctor () public void Constructor1 () { Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); } [Test] // ctor (Boolean) public void Constructor2 () { transform = new UnprotectedXmlDsigExcC14NTransform (true); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (false); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); } [Test] // ctor (String) public void Constructor3 () { transform = new UnprotectedXmlDsigExcC14NTransform (null); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (string.Empty); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.AreEqual (string.Empty, transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform ("#default xsd"); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.AreEqual ("#default xsd", transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); } [Test] // ctor (Boolean, String) public void Constructor4 () { transform = new UnprotectedXmlDsigExcC14NTransform (true, null); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (true, string.Empty); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm, "Algorithm"); Assert.AreEqual (string.Empty, transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (true, "#default xsd"); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments", transform.Algorithm, "Algorithm"); Assert.AreEqual ("#default xsd", transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (false, null); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.IsNull (transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (false, string.Empty); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.AreEqual (string.Empty, transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); transform = new UnprotectedXmlDsigExcC14NTransform (false, "#default xsd"); Assert.AreEqual ("http://www.w3.org/2001/10/xml-exc-c14n#", transform.Algorithm, "Algorithm"); Assert.AreEqual ("#default xsd", transform.InclusiveNamespacesPrefixList, "InclusiveNamespacesPrefixList"); CheckProperties (transform); } void CheckProperties (XmlDsigExcC14NTransform transform) { Type[] input = transform.InputTypes; Assert.IsTrue ((input.Length == 3), "Input #"); // check presence of every supported input types bool istream = false; bool ixmldoc = false; bool ixmlnl = false; foreach (Type t in input) { if (t.ToString () == "System.IO.Stream") istream = true; if (t.ToString () == "System.Xml.XmlDocument") ixmldoc = true; if (t.ToString () == "System.Xml.XmlNodeList") ixmlnl = true; } Assert.IsTrue (istream, "Input Stream"); Assert.IsTrue (ixmldoc, "Input XmlDocument"); Assert.IsTrue (ixmlnl, "Input XmlNodeList"); Type[] output = transform.OutputTypes; Assert.IsTrue ((output.Length == 1), "Output #"); // check presence of every supported output types bool ostream = false; foreach (Type t in output) { if (t.ToString () == "System.IO.Stream") ostream = true; } Assert.IsTrue (ostream, "Output Stream"); } [Test] public void Types () { Type [] input = transform.InputTypes; input [0] = null; input [1] = null; input [2] = null; // property does not return a clone foreach (Type t in transform.InputTypes) { Assert.IsNull (t); } // it's not a static array XmlDsigExcC14NTransform t2 = new XmlDsigExcC14NTransform (); foreach (Type t in t2.InputTypes) { Assert.IsNotNull (t); } } [Test] public void GetInnerXml () { XmlNodeList xnl = transform.UnprotectedGetInnerXml (); Assert.IsNull (xnl, "Default InnerXml"); } private string Stream2String (Stream s) { StringBuilder sb = new StringBuilder (); int b = s.ReadByte (); while (b != -1) { sb.Append (Convert.ToChar (b)); b = s.ReadByte (); } return sb.ToString (); } static string xml = " \r\n text & "; // BAD for XmlDocument input (framework 1.0 result) static string c14xml1 = " \r\n \r text & "; // GOOD for Stream input static string c14xml2 = " \n text & "; // GOOD for XmlDocument input. The difference is because once // xml string is loaded to XmlDocument, there is no difference // between \r and , so every \r must be handled as . static string c14xml3 = " \n text & "; private XmlDocument GetDoc () { XmlDocument doc = new XmlDocument (); doc.PreserveWhitespace = true; doc.LoadXml (xml); return doc; } [Test] public void LoadInputAsXmlDocument () { XmlDocument doc = GetDoc (); transform.LoadInput (doc); Stream s = (Stream) transform.GetOutput (); string output = Stream2String (s); Assert.AreEqual (c14xml3, output, "XmlDocument"); } [Test] // see LoadInputAsXmlNodeList2 description public void LoadInputAsXmlNodeList () { XmlDocument doc = GetDoc (); // Argument list just contains element Test. transform.LoadInput (doc.ChildNodes); Stream s = (Stream) transform.GetOutput (); string output = Stream2String (s); Assert.AreEqual ("", output, "XmlChildNodes"); } [Test] // MS has a bug that those namespace declaration nodes in // the node-set are written to output. Related spec section is: // http://www.w3.org/TR/2001/REC-xml-c14n-20010315#ProcessingModel public void LoadInputAsXmlNodeList2 () { XmlDocument doc = GetDoc (); transform.LoadInput (doc.SelectNodes ("//*")); Stream s = (Stream) transform.GetOutput (); string output = Stream2String (s); string expected = ""; Assert.AreEqual (expected, output, "XmlChildNodes"); } [Test] public void LoadInputAsStream () { MemoryStream ms = new MemoryStream (); byte[] x = Encoding.ASCII.GetBytes (xml); ms.Write (x, 0, x.Length); ms.Position = 0; transform.LoadInput (ms); Stream s = (Stream) transform.GetOutput (); string output = Stream2String (s); Assert.AreEqual (c14xml2, output, "MemoryStream"); } [Test] [Ignore ("LAMESPEC: input MUST be one of InputType - but no exception is thrown (not documented)")] public void LoadInputWithUnsupportedType () { byte[] bad = { 0xBA, 0xD }; transform.LoadInput (bad); } [Test] [ExpectedException (typeof (ArgumentException))] public void UnsupportedOutput () { XmlDocument doc = new XmlDocument(); object o = transform.GetOutput (doc.GetType ()); } [Test] public void ExcC14NSpecExample1 () { using (StreamWriter sw = new StreamWriter ("doc.dtd", false, Encoding.ASCII)) { sw.Write (""); sw.Close (); } string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample1Input); Assert.AreEqual (ExcC14NSpecExample1Output, res, "Example 1 from c14n spec - PIs, Comments, and Outside of Document Element (without comments)"); } [Test] public void ExcC14NSpecExample2 () { string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample2Input); Assert.AreEqual (ExcC14NSpecExample2Output, res, "Example 2 from c14n spec - Whitespace in Document Content (without comments)"); } [Test] public void ExcC14NSpecExample3 () { string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample3Input); Assert.AreEqual (ExcC14NSpecExample3Output, res, "Example 3 from c14n spec - Start and End Tags (without comments)"); } [Test] // [Ignore ("This test should be fine, but it does not pass under MS.NET")] public void ExcC14NSpecExample4 () { string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample4Input); Assert.AreEqual (ExcC14NSpecExample4Output, res, "Example 4 from c14n spec - Character Modifications and Character References (without comments)"); } [Test] public void ExcC14NSpecExample5 () { using (StreamWriter sw = new StreamWriter ("world.txt", false, Encoding.ASCII)) { sw.Write ("world"); sw.Close (); } string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample5Input); Assert.AreEqual (ExcC14NSpecExample5Output, res, "Example 5 from c14n spec - Entity References (without comments)"); } [Test] public void ExcC14NSpecExample6 () { string res = ExecuteXmlDSigExcC14NTransform (ExcC14NSpecExample6Input); Assert.AreEqual (ExcC14NSpecExample6Output, res, "Example 6 from c14n spec - UTF-8 Encoding (without comments)"); } private string ExecuteXmlDSigExcC14NTransform (string InputXml) { XmlDocument doc = new XmlDocument (); doc.PreserveWhitespace = true; doc.LoadXml (InputXml); // Testing default attribute support with // vreader.ValidationType = ValidationType.None. // UTF8Encoding utf8 = new UTF8Encoding (); byte[] data = utf8.GetBytes (InputXml.ToString ()); Stream stream = new MemoryStream (data); XmlTextReader reader = new XmlTextReader (stream); XmlValidatingReader vreader = new XmlValidatingReader (reader); vreader.ValidationType = ValidationType.None; vreader.EntityHandling = EntityHandling.ExpandCharEntities; doc.Load (vreader); transform.LoadInput (doc); return Stream2String ((Stream)transform.GetOutput ()); } // // Example 1 from ExcC14N spec - PIs, Comments, and Outside of Document Element: // http://www.w3.org/TR/xml-c14n#Example-OutsideDoc // // Aleksey: // removed reference to an empty external DTD // static string ExcC14NSpecExample1Input = "\n" + "\n" + "\n" + "\n" + // "\n" + "\n" + "Hello, world!\n" + "\n" + "\n\n" + "\n\n" + "\n"; static string ExcC14NSpecExample1Output = "\n" + "Hello, world!\n" + ""; // // Example 2 from ExcC14N spec - Whitespace in Document Content: // http://www.w3.org/TR/xml-c14n#Example-WhitespaceInContent // static string ExcC14NSpecExample2Input = "\n" + " \n" + " A B \n" + " \n" + " A\n" + " \n" + " B\n" + " A B \n" + " C\n" + " \n" + "\n"; static string ExcC14NSpecExample2Output = "\n" + " \n" + " A B \n" + " \n" + " A\n" + " \n" + " B\n" + " A B \n" + " C\n" + " \n" + ""; // // Example 3 from ExcC14N spec - Start and End Tags: // http://www.w3.org/TR/xml-c14n#Example-SETags // static string ExcC14NSpecExample3Input = "]>\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; static string ExcC14NSpecExample3Output = "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + // " \n" + " \n" + " \n" + " \n" + ""; // // Example 4 from ExcC14N spec - Character Modifications and Character References: // http://www.w3.org/TR/xml-c14n#Example-Chars // // Aleksey: // This test does not include "normId" element // because it has an invalid ID attribute "id" which // should be normalized by XML parser. Currently Mono // does not support this (see comment after this example // in the spec). static string ExcC14NSpecExample4Input = "]>\n" + "\n" + " First line Second line\n" + " 2\n" + " \"0\" && value<\"10\" ?\"valid\":\"error\"]]>\n" + " \"0\" && value<\"10\" ?\"valid\":\"error\"\'>valid\n" + " \n" + // " \n" + "\n"; static string ExcC14NSpecExample4Output = "\n" + " First line \n" + "Second line\n" + " 2\n" + " value>\"0\" && value<\"10\" ?\"valid\":\"error\"\n" + " "0" && value<"10" ?"valid":"error"\">valid\n" + " \n" + // " \n" + ""; // // Example 5 from ExcC14N spec - Entity References: // http://www.w3.org/TR/xml-c14n#Example-Entities // static string ExcC14NSpecExample5Input = "\n" + "\n" + "\n" + "\n" + "\n" + "]>\n" + "\n" + " &ent1;, &ent2;!\n" + "\n" + "\n" + "\n"; static string ExcC14NSpecExample5Output = "\n" + " Hello, world!\n" + ""; // // Example 6 from ExcC14N spec - UTF-8 Encoding: // http://www.w3.org/TR/xml-c14n#Example-UTF8 // static string ExcC14NSpecExample6Input = "\n" + "©\n"; static string ExcC14NSpecExample6Output = "\xC2\xA9"; // // Example 7 from ExcC14N spec - Document Subsets: // http://www.w3.org/TR/xml-c14n#Example-DocSubsets // // Aleksey: // Well, XPath support in Mono is far from complete.... // I was not able to simplify the xpath expression from this test // so it runs on Mono and still makes sense for testing this feature. // Thus this test is not included in the suite now. static string ExcC14NSpecExample7Input = "\n" + "\n" + "]>\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; static string ExcC14NSpecExample7Xpath = "(//.|//@*|//namespace::*)\n" + "[\n" + "self::ietf:e1\n" + " or\n" + "(parent::ietf:e1 and not(self::text() or self::e2))\n" + " or\n" + "count(id(\"E3\")|ancestor-or-self::node()) = count(ancestor-or-self::node())\n" + "]"; static string ExcC14NSpecExample7Output = ""; [Test] public void SimpleNamespacePrefixes () { string input = "http://tempuri.org/IFoo/Echo"; string expected = @"http://tempuri.org/IFoo/Echo"; XmlDocument doc = new XmlDocument (); doc.LoadXml (input); XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform (); t.LoadInput (doc); Stream s = t.GetOutput () as Stream; Assert.AreEqual (new StreamReader (s, Encoding.UTF8).ReadToEnd (), expected); } [Test] [ExpectedException (typeof (NullReferenceException))] public void GetDigestedOutput_Null () { new XmlDsigExcC14NTransform ().GetDigestedOutput (null); } } }