Skip to content

Commit 18b32e4

Browse files
committed
Improve System.Security.Cryptography.Xml code coverage
Add tests to fill some coverage gaps
1 parent 82ce59a commit 18b32e4

17 files changed

+2960
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.IO;
5+
using System.Text;
6+
using System.Xml;
7+
using Xunit;
8+
9+
namespace System.Security.Cryptography.Xml.Tests
10+
{
11+
public class CanonicalXmlEntityReferenceTest
12+
{
13+
[Fact]
14+
public void EntityReferenceInCanonicalization()
15+
{
16+
// This test exercises CanonicalXmlEntityReference by using a transform
17+
// that internally creates a CanonicalXmlDocument and loads XML into it.
18+
// When an XmlNodeReader reads from a document containing entity references,
19+
// the target document's CreateEntityReference method is called.
20+
21+
string xml = @"<!DOCTYPE doc [
22+
<!ENTITY test ""TestValue"">
23+
]>
24+
<root>&test;</root>";
25+
26+
XmlDocument doc = new XmlDocument();
27+
doc.PreserveWhitespace = true;
28+
doc.LoadXml(xml);
29+
30+
// Use C14N transform which internally uses CanonicalXmlDocument
31+
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
32+
transform.LoadInput(doc);
33+
34+
Stream output = (Stream)transform.GetOutput();
35+
string result = new StreamReader(output, Encoding.UTF8).ReadToEnd();
36+
37+
// Entity should be expanded in canonical form
38+
Assert.Contains("TestValue", result);
39+
Assert.Contains("<root>", result);
40+
}
41+
42+
[Fact]
43+
public void EntityReferenceWithXmlNodeList()
44+
{
45+
// Test with XmlNodeList input which triggers different code path in CanonicalXml
46+
// When using XmlNodeList, nodes not in the list are not included, which may affect
47+
// entity reference expansion in the canonical output
48+
string xml = @"<!DOCTYPE doc [
49+
<!ENTITY test ""Hello"">
50+
]>
51+
<root><child>&test;</child></root>";
52+
53+
XmlDocument doc = new XmlDocument();
54+
doc.PreserveWhitespace = true;
55+
doc.LoadXml(xml);
56+
57+
XmlNodeList nodeList = doc.SelectNodes("//child")!;
58+
59+
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
60+
transform.LoadInput(nodeList);
61+
62+
Stream output = (Stream)transform.GetOutput();
63+
string result = new StreamReader(output, Encoding.UTF8).ReadToEnd();
64+
65+
// The node should be present in canonical form
66+
Assert.Contains("<child>", result);
67+
Assert.Contains("</child>", result);
68+
}
69+
70+
[Fact]
71+
public void EntityReferenceWithCommentsIncluded()
72+
{
73+
// Test with includeComments = true
74+
string xml = @"<!DOCTYPE doc [
75+
<!ENTITY ent ""EntityContent"">
76+
]>
77+
<root><!--comment-->&ent;</root>";
78+
79+
XmlDocument doc = new XmlDocument();
80+
doc.PreserveWhitespace = true;
81+
doc.LoadXml(xml);
82+
83+
XmlDsigC14NWithCommentsTransform transform = new XmlDsigC14NWithCommentsTransform();
84+
transform.LoadInput(doc);
85+
86+
Stream output = (Stream)transform.GetOutput();
87+
string result = new StreamReader(output, Encoding.UTF8).ReadToEnd();
88+
89+
// Both comment and expanded entity should be in output
90+
Assert.Contains("<!--comment-->", result);
91+
Assert.Contains("EntityContent", result);
92+
}
93+
94+
[Fact]
95+
public void EntityReferenceInExclusiveCanonicalization()
96+
{
97+
// Test with Exclusive C14N transform
98+
string xml = @"<!DOCTYPE doc [
99+
<!ENTITY test ""ExclusiveTest"">
100+
]>
101+
<root xmlns=""http://example.com"">&test;</root>";
102+
103+
XmlDocument doc = new XmlDocument();
104+
doc.PreserveWhitespace = true;
105+
doc.LoadXml(xml);
106+
107+
XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();
108+
transform.LoadInput(doc);
109+
110+
Stream output = (Stream)transform.GetOutput();
111+
string result = new StreamReader(output, Encoding.UTF8).ReadToEnd();
112+
113+
// Entity should be expanded in canonical form
114+
Assert.Contains("ExclusiveTest", result);
115+
Assert.Contains("http://example.com", result);
116+
}
117+
118+
[Fact]
119+
public void EntityReferenceWithHash()
120+
{
121+
// Test the WriteHash code path by using GetDigestedOutput
122+
string xml = @"<!DOCTYPE doc [
123+
<!ENTITY test ""HashTest"">
124+
]>
125+
<root>&test;</root>";
126+
127+
XmlDocument doc = new XmlDocument();
128+
doc.PreserveWhitespace = true;
129+
doc.LoadXml(xml);
130+
131+
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
132+
transform.LoadInput(doc);
133+
134+
using (SHA256 hash = SHA256.Create())
135+
{
136+
byte[] digest = transform.GetDigestedOutput(hash);
137+
138+
// Should produce a valid hash
139+
Assert.NotNull(digest);
140+
Assert.Equal(32, digest.Length); // SHA256 produces 32 bytes
141+
}
142+
}
143+
144+
[Fact]
145+
public void MultipleEntityReferences()
146+
{
147+
// Test with multiple entity references
148+
string xml = @"<!DOCTYPE doc [
149+
<!ENTITY ent1 ""First"">
150+
<!ENTITY ent2 ""Second"">
151+
]>
152+
<root>&ent1; and &ent2;</root>";
153+
154+
XmlDocument doc = new XmlDocument();
155+
doc.PreserveWhitespace = true;
156+
doc.LoadXml(xml);
157+
158+
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
159+
transform.LoadInput(doc);
160+
161+
Stream output = (Stream)transform.GetOutput();
162+
string result = new StreamReader(output, Encoding.UTF8).ReadToEnd();
163+
164+
// Both entities should be expanded
165+
Assert.Contains("First", result);
166+
Assert.Contains("Second", result);
167+
Assert.Contains("and", result);
168+
}
169+
}
170+
}

src/libraries/System.Security.Cryptography.Xml/tests/DataObjectTests.cs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,5 +161,143 @@ private static XmlElement CreateTestElement(string name, string idValue, string
161161

162162
return element;
163163
}
164+
165+
[Fact]
166+
public void LoadXml_InvalidElement()
167+
{
168+
XmlDocument doc = new XmlDocument();
169+
doc.LoadXml("<WrongElement />");
170+
171+
DataObject dataObject = new DataObject();
172+
// Actually doesn't throw - just loads it anyway
173+
dataObject.LoadXml(doc.DocumentElement);
174+
Assert.NotNull(dataObject.Data);
175+
}
176+
177+
[Fact]
178+
public void GetXml_WithData()
179+
{
180+
DataObject dataObject = new DataObject();
181+
XmlDocument doc = new XmlDocument();
182+
XmlElement elem = doc.CreateElement("TestData");
183+
elem.InnerText = "test content";
184+
dataObject.Data = new XmlNodeList[] { elem.ChildNodes }[0];
185+
186+
XmlElement xml = dataObject.GetXml();
187+
Assert.NotNull(xml);
188+
Assert.Equal("Object", xml.LocalName);
189+
}
190+
191+
[Fact]
192+
public void Properties_SetAndGet()
193+
{
194+
DataObject dataObject = new DataObject();
195+
196+
dataObject.Id = "obj-1";
197+
Assert.Equal("obj-1", dataObject.Id);
198+
199+
dataObject.MimeType = "text/xml";
200+
Assert.Equal("text/xml", dataObject.MimeType);
201+
202+
dataObject.Encoding = "UTF-8";
203+
Assert.Equal("UTF-8", dataObject.Encoding);
204+
205+
Assert.NotNull(dataObject.Data);
206+
}
207+
208+
[Fact]
209+
public void LoadXml_WithData()
210+
{
211+
string xml = @"<Object Id=""obj1"" xmlns=""http://www.w3.org/2000/09/xmldsig#"">
212+
<test>data</test>
213+
</Object>";
214+
XmlDocument doc = new XmlDocument();
215+
doc.LoadXml(xml);
216+
217+
DataObject dataObject = new DataObject();
218+
dataObject.LoadXml(doc.DocumentElement);
219+
Assert.Equal("obj1", dataObject.Id);
220+
Assert.Equal(1, dataObject.Data.Count);
221+
}
222+
223+
[Fact]
224+
public void LoadXml_NoId()
225+
{
226+
string xml = @"<Object xmlns=""http://www.w3.org/2000/09/xmldsig#"">
227+
<test>data</test>
228+
</Object>";
229+
XmlDocument doc = new XmlDocument();
230+
doc.LoadXml(xml);
231+
232+
DataObject dataObject = new DataObject();
233+
dataObject.LoadXml(doc.DocumentElement);
234+
Assert.Null(dataObject.Id);
235+
}
236+
237+
[Fact]
238+
public void LoadXml_NoMimeType()
239+
{
240+
string xml = @"<Object Id=""obj1"" xmlns=""http://www.w3.org/2000/09/xmldsig#"">
241+
<test>data</test>
242+
</Object>";
243+
XmlDocument doc = new XmlDocument();
244+
doc.LoadXml(xml);
245+
246+
DataObject dataObject = new DataObject();
247+
dataObject.LoadXml(doc.DocumentElement);
248+
Assert.Null(dataObject.MimeType);
249+
}
250+
251+
[Fact]
252+
public void LoadXml_NoEncoding()
253+
{
254+
string xml = @"<Object Id=""obj1"" xmlns=""http://www.w3.org/2000/09/xmldsig#"">
255+
<test>data</test>
256+
</Object>";
257+
XmlDocument doc = new XmlDocument();
258+
doc.LoadXml(xml);
259+
260+
DataObject dataObject = new DataObject();
261+
dataObject.LoadXml(doc.DocumentElement);
262+
Assert.Null(dataObject.Encoding);
263+
}
264+
265+
[Fact]
266+
public void GetXml_NoData()
267+
{
268+
DataObject dataObject = new DataObject();
269+
dataObject.Id = "obj1";
270+
271+
XmlElement xml = dataObject.GetXml();
272+
Assert.NotNull(xml);
273+
Assert.Equal("Object", xml.LocalName);
274+
Assert.Equal("obj1", xml.GetAttribute("Id"));
275+
}
276+
277+
[Fact]
278+
public void GetXml_EmptyStrings()
279+
{
280+
DataObject dataObject = new DataObject();
281+
dataObject.Id = "";
282+
dataObject.MimeType = "";
283+
dataObject.Encoding = "";
284+
285+
XmlElement xml = dataObject.GetXml();
286+
Assert.NotNull(xml);
287+
Assert.Equal("Object", xml.LocalName);
288+
}
289+
290+
[Fact]
291+
public void Constructor_NullArguments()
292+
{
293+
XmlDocument doc = new XmlDocument();
294+
XmlElement elem = doc.CreateElement("test");
295+
296+
DataObject dataObject = new DataObject(null, null, null, elem);
297+
Assert.Null(dataObject.Id);
298+
Assert.Null(dataObject.MimeType);
299+
Assert.Null(dataObject.Encoding);
300+
Assert.NotNull(dataObject.Data);
301+
}
164302
}
165303
}

src/libraries/System.Security.Cryptography.Xml/tests/DataReferenceTest.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,74 @@ public void LoadXml()
2525
EncryptedKey ek = new EncryptedKey();
2626
ek.LoadXml(doc.DocumentElement);
2727
}
28+
29+
[Fact]
30+
public void Constructor_Empty()
31+
{
32+
DataReference dataRef = new DataReference();
33+
Assert.Equal(string.Empty, dataRef.Uri);
34+
}
35+
36+
[Fact]
37+
public void Constructor_WithUri()
38+
{
39+
string uri = "#data1";
40+
DataReference dataRef = new DataReference(uri);
41+
Assert.Equal(uri, dataRef.Uri);
42+
}
43+
44+
[Fact]
45+
public void Constructor_WithUriAndTransformChain()
46+
{
47+
string uri = "#data1";
48+
TransformChain tc = new TransformChain();
49+
tc.Add(new XmlDsigBase64Transform());
50+
51+
DataReference dataRef = new DataReference(uri, tc);
52+
Assert.Equal(uri, dataRef.Uri);
53+
Assert.NotNull(dataRef.TransformChain);
54+
Assert.Equal(1, dataRef.TransformChain.Count);
55+
}
56+
57+
[Fact]
58+
public void GetXml_SimpleDataReference()
59+
{
60+
DataReference dataRef = new DataReference("#encrypted-data-1");
61+
XmlElement xml = dataRef.GetXml();
62+
Assert.Equal("DataReference", xml.LocalName);
63+
Assert.Equal(EncryptedXml.XmlEncNamespaceUrl, xml.NamespaceURI);
64+
Assert.Equal("#encrypted-data-1", xml.GetAttribute("URI"));
65+
}
66+
67+
[Fact]
68+
public void GetXml_WithTransforms()
69+
{
70+
DataReference dataRef = new DataReference("#data1");
71+
dataRef.TransformChain.Add(new XmlDsigC14NTransform());
72+
73+
XmlElement xml = dataRef.GetXml();
74+
Assert.Equal("DataReference", xml.LocalName);
75+
Assert.NotNull(xml.SelectSingleNode("//*[local-name()='Transforms']"));
76+
}
77+
78+
[Fact]
79+
public void LoadXml_SimpleDataReference()
80+
{
81+
string xml = @"<DataReference URI=""#encrypted-element"" xmlns=""http://www.w3.org/2001/04/xmlenc#"" />";
82+
XmlDocument doc = new XmlDocument();
83+
doc.LoadXml(xml);
84+
85+
DataReference dataRef = new DataReference();
86+
dataRef.LoadXml(doc.DocumentElement);
87+
Assert.Equal("#encrypted-element", dataRef.Uri);
88+
}
89+
90+
[Fact]
91+
public void ReferenceType_IsDataReference()
92+
{
93+
DataReference dataRef = new DataReference();
94+
XmlElement xml = dataRef.GetXml();
95+
Assert.Equal("DataReference", xml.LocalName);
96+
}
2897
}
2998
}

0 commit comments

Comments
 (0)