Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 0b2cc89

Browse files
committed
Merge pull request #2292 from khdang/improve_test_coverage_xmlserializer
Improve test coverage for XmlSerializer
2 parents 256d650 + 645f542 commit 0b2cc89

File tree

3 files changed

+241
-36
lines changed

3 files changed

+241
-36
lines changed

src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,17 @@ public enum ItemChoiceType
16131613
DecimalNumber
16141614
}
16151615

1616+
public class TypeWithAnyAttribute
1617+
{
1618+
public string Name;
1619+
1620+
[XmlAttribute]
1621+
public int IntProperty { get; set; }
1622+
1623+
[XmlAnyAttribute]
1624+
public XmlAttribute[] Attributes { get; set; }
1625+
}
1626+
16161627
public class KnownTypesThroughConstructor
16171628
{
16181629
public object EnumValue;
@@ -2129,3 +2140,11 @@ public class AppEnvironment
21292140
[DataMember(Name = "screen_dpi(x:y)")]
21302141
public int ScreenDpi { get; set; }
21312142
}
2143+
2144+
public class TypeWithBinaryProperty
2145+
{
2146+
[XmlElement(DataType = "hexBinary")]
2147+
public byte[] BinaryHexContent { get; set; }
2148+
[XmlElement(DataType = "base64Binary")]
2149+
public byte[] Base64Content { get; set; }
2150+
}

src/System.Xml.XmlSerializer/src/System/Xml/BinHexEncoder.cs

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,6 @@ internal abstract class BinHexEncoder
1111
private const string s_hexDigits = "0123456789ABCDEF";
1212
private const int CharsChunkSize = 128;
1313

14-
internal static void Encode(byte[] buffer, int index, int count, XmlWriter writer)
15-
{
16-
if (buffer == null)
17-
{
18-
throw new ArgumentNullException("buffer");
19-
}
20-
if (index < 0)
21-
{
22-
throw new ArgumentOutOfRangeException("index");
23-
}
24-
if (count < 0)
25-
{
26-
throw new ArgumentOutOfRangeException("count");
27-
}
28-
if (count > buffer.Length - index)
29-
{
30-
throw new ArgumentOutOfRangeException("count");
31-
}
32-
33-
char[] chars = new char[(count * 2) < CharsChunkSize ? (count * 2) : CharsChunkSize];
34-
int endIndex = index + count;
35-
while (index < endIndex)
36-
{
37-
int cnt = (count < CharsChunkSize / 2) ? count : CharsChunkSize / 2;
38-
int charCount = Encode(buffer, index, cnt, chars);
39-
writer.WriteRaw(chars, 0, charCount);
40-
index += cnt;
41-
count -= cnt;
42-
}
43-
}
44-
4514
internal static string Encode(byte[] inArray, int offsetIn, int count)
4615
{
4716
if (null == inArray)

src/System.Xml.XmlSerializer/tests/XmlSerializerTests.cs

Lines changed: 222 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.IO;
1010
using System.Linq;
1111
using System.Reflection;
12+
using System.Text;
1213
using System.Xml;
1314
using System.Xml.Serialization;
1415
using System.Xml.Linq;
@@ -96,12 +97,17 @@ public static void Xml_FloatAsRoot()
9697
[Fact]
9798
public static void Xml_GuidAsRoot()
9899
{
99-
foreach (Guid value in new Guid[] { Guid.NewGuid(), Guid.Empty })
100-
{
101-
Assert.StrictEqual(SerializeAndDeserialize<Guid>(value, string.Format("<?xml version=\"1.0\"?>" + Environment.NewLine + "<guid>{0}</guid>", value.ToString())), value);
102-
}
100+
Xml_GuidAsRoot(new XmlSerializer(typeof(Guid)));
103101
}
104102

103+
private static void Xml_GuidAsRoot(XmlSerializer serializer)
104+
{
105+
foreach (Guid value in new Guid[] { Guid.NewGuid(), Guid.Empty })
106+
{
107+
Assert.StrictEqual(SerializeAndDeserialize<Guid>(value, string.Format("<?xml version=\"1.0\"?>" + Environment.NewLine + "<guid>{0}</guid>", value.ToString()), () => serializer), value);
108+
}
109+
}
110+
105111
[Fact]
106112
public static void Xml_IntAsRoot()
107113
{
@@ -280,6 +286,11 @@ public static void Xml_ArrayAsGetOnly()
280286

281287
[Fact]
282288
public static void Xml_ListGenericRoot()
289+
{
290+
Xml_ListGenericRoot(new XmlSerializer(typeof(List<string>)));
291+
}
292+
293+
private static void Xml_ListGenericRoot(XmlSerializer serializer)
283294
{
284295
List<string> x = new List<string>();
285296
x.Add("zero");
@@ -290,7 +301,7 @@ public static void Xml_ListGenericRoot()
290301
"<ArrayOfString xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" + Environment.NewLine +
291302
" <string>zero</string>" + Environment.NewLine +
292303
" <string>one</string>" + Environment.NewLine +
293-
"</ArrayOfString>");
304+
"</ArrayOfString>", () => serializer);
294305

295306
Assert.NotNull(y);
296307
Assert.True(y.Count == 2);
@@ -705,6 +716,11 @@ public static void Xml_DefaultNamespaceChangeTest()
705716
SerializeAndDeserialize<string>("Teststring", "<?xml version=\"1.0\"?>" + Environment.NewLine + "<string xmlns=\"MycustomDefaultNamespace\">Teststring</string>",
706717
() => { return new XmlSerializer(typeof(string), "MycustomDefaultNamespace"); }),
707718
"Teststring");
719+
720+
Assert.Throws<ArgumentNullException>(() =>
721+
{
722+
new XmlSerializer(null, "defaultNamespace");
723+
});
708724
}
709725

710726
[Fact]
@@ -840,6 +856,31 @@ public static void Xml_XmlAttributesTest()
840856
Assert.StrictEqual(actual.XmlTextProperty, value.XmlTextProperty);
841857
}
842858

859+
[Fact]
860+
public static void Xml_XmlAnyAttributeTest()
861+
{
862+
var serializer = new XmlSerializer(typeof (TypeWithAnyAttribute));
863+
const string format = @"<?xml version=""1.0"" encoding=""utf-8""?><TypeWithAnyAttribute xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" GroupType = '{0}' IntProperty = '{1}' GroupBase = '{2}'><Name>{3}</Name></TypeWithAnyAttribute>";
864+
const int intProperty = 42;
865+
const string attribute1 = "Technical";
866+
const string attribute2 = "Red";
867+
const string name = "MyGroup";
868+
using (var stream = new MemoryStream())
869+
{
870+
var writer = new StreamWriter(stream);
871+
writer.Write(format, attribute1, intProperty, attribute2, name);
872+
writer.Flush();
873+
stream.Position = 0;
874+
var obj = (TypeWithAnyAttribute)serializer.Deserialize(stream);
875+
Assert.NotNull(obj);
876+
Assert.StrictEqual(intProperty, obj.IntProperty);
877+
Assert.StrictEqual(name, obj.Name);
878+
Assert.StrictEqual(2, obj.Attributes.Length);
879+
Assert.StrictEqual(attribute1, obj.Attributes[0].Value);
880+
Assert.StrictEqual(attribute2, obj.Attributes[1].Value);
881+
}
882+
}
883+
843884
[Fact]
844885
public static void Xml_Struct()
845886
{
@@ -1130,6 +1171,160 @@ public static void Xml_TypeWithNonParameterlessConstructor()
11301171
Assert.Throws<InvalidOperationException>(() => { SerializeAndDeserialize(obj, string.Empty); });
11311172
}
11321173

1174+
[Fact]
1175+
public static void Xml_TypeWithBinaryProperty()
1176+
{
1177+
var obj = new TypeWithBinaryProperty();
1178+
var str = "The quick brown fox jumps over the lazy dog.";
1179+
obj.Base64Content = Encoding.Unicode.GetBytes(str);
1180+
obj.BinaryHexContent = Encoding.Unicode.GetBytes(str);
1181+
var actual = SerializeAndDeserialize(obj, @"<?xml version=""1.0"" encoding=""utf-8""?><TypeWithBinaryProperty xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""><BinaryHexContent>540068006500200071007500690063006B002000620072006F0077006E00200066006F00780020006A0075006D007000730020006F00760065007200200074006800650020006C0061007A007900200064006F0067002E00</BinaryHexContent><Base64Content>VABoAGUAIABxAHUAaQBjAGsAIABiAHIAbwB3AG4AIABmAG8AeAAgAGoAdQBtAHAAcwAgAG8AdgBlAHIAIAB0AGgAZQAgAGwAYQB6AHkAIABkAG8AZwAuAA==</Base64Content></TypeWithBinaryProperty>");
1182+
Assert.StrictEqual(str, Encoding.Unicode.GetString(actual.Base64Content));
1183+
Assert.StrictEqual(str, Encoding.Unicode.GetString(actual.BinaryHexContent));
1184+
}
1185+
1186+
[Fact]
1187+
public static void Xml_FromTypes()
1188+
{
1189+
var serializers = XmlSerializer.FromTypes(new Type[] { typeof(Guid), typeof(List<string>) });
1190+
Xml_GuidAsRoot(serializers[0]);
1191+
Xml_ListGenericRoot(serializers[1]);
1192+
1193+
serializers = XmlSerializer.FromTypes(null);
1194+
Assert.Equal(0, serializers.Length);
1195+
}
1196+
1197+
[Fact]
1198+
public static void Xml_FromMappings()
1199+
{
1200+
var types = new[] {typeof (Guid), typeof (List<string>)};
1201+
XmlReflectionImporter importer = new XmlReflectionImporter();
1202+
XmlTypeMapping[] mappings = new XmlTypeMapping[types.Length];
1203+
for (int i = 0; i < types.Length; i++)
1204+
{
1205+
mappings[i] = importer.ImportTypeMapping(types[i]);
1206+
}
1207+
var serializers = XmlSerializer.FromMappings(mappings, typeof(object));
1208+
Xml_GuidAsRoot(serializers[0]);
1209+
Xml_ListGenericRoot(serializers[1]);
1210+
}
1211+
1212+
[Fact]
1213+
public static void Xml_ConstructorWithXmlRootAttr()
1214+
{
1215+
var serializer = new XmlSerializer(typeof (List<string>), new XmlRootAttribute()
1216+
{
1217+
ElementName = "Places",
1218+
Namespace = "http://www.microsoft.com",
1219+
});
1220+
var expected = new List<string>() { "Madison", "Rochester", null, "Arlington" };
1221+
var actual = SerializeAndDeserialize(expected,
1222+
@"<?xml version=""1.0"" encoding=""utf-8""?><Places xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""http://www.microsoft.com""><string>Madison</string><string>Rochester</string><string xsi:nil=""true"" /><string>Arlington</string></Places>",
1223+
() => serializer);
1224+
Assert.True(expected.SequenceEqual(actual));
1225+
}
1226+
1227+
[Fact]
1228+
public static void Xml_ConstructorWithXmlAttributeOverrides()
1229+
{
1230+
var expected = new Music.Orchestra()
1231+
{
1232+
Instruments = new Music.Instrument[]
1233+
{
1234+
new Music.Brass() { Name = "Trumpet", IsValved = true },
1235+
new Music.Brass() { Name = "Cornet", IsValved = true }
1236+
}
1237+
};
1238+
var overrides = new XmlAttributeOverrides();
1239+
overrides.Add(typeof (Music.Orchestra), "Instruments", new XmlAttributes()
1240+
{
1241+
XmlElements = {new XmlElementAttribute("Brass", typeof (Music.Brass))}
1242+
});
1243+
1244+
// XmlSerializer(Type, XmlAttributeOverrides)
1245+
var serializer = new XmlSerializer(typeof (Music.Orchestra), overrides);
1246+
var actual = SerializeAndDeserialize(expected,
1247+
@"<?xml version=""1.0"" encoding=""utf-8""?><Orchestra xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""><Brass><Name>Trumpet</Name><IsValved>true</IsValved></Brass><Brass><Name>Cornet</Name><IsValved>true</IsValved></Brass></Orchestra>",
1248+
() => serializer);
1249+
Assert.StrictEqual(expected.Instruments[0].Name, actual.Instruments[0].Name);
1250+
1251+
// XmlSerializer(Type, XmlAttributeOverrides, Type[], XmlRootAttribute, String)
1252+
var root = new XmlRootAttribute("Collection");
1253+
serializer = new XmlSerializer(typeof(Music.Orchestra), overrides, Array.Empty<Type>(), root, "defaultNamespace");
1254+
actual = SerializeAndDeserialize(expected,
1255+
@"<?xml version=""1.0"" encoding=""utf-8""?><Collection xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns=""defaultNamespace""><Brass><Name>Trumpet</Name><IsValved>true</IsValved></Brass><Brass><Name>Cornet</Name><IsValved>true</IsValved></Brass></Collection>",
1256+
() => serializer);
1257+
Assert.StrictEqual(expected.Instruments[0].Name, actual.Instruments[0].Name);
1258+
1259+
Assert.Throws<ArgumentNullException>(() =>
1260+
{
1261+
new XmlSerializer(null, overrides);
1262+
});
1263+
}
1264+
1265+
[Fact]
1266+
public static void Xml_ConstructorWithTypeMapping()
1267+
{
1268+
XmlTypeMapping mapping = null;
1269+
XmlSerializer serializer = null;
1270+
Assert.Throws<ArgumentNullException>(() => { new XmlSerializer(mapping); });
1271+
1272+
mapping = new XmlReflectionImporter(null, null).ImportTypeMapping(typeof(List<string>));
1273+
serializer = new XmlSerializer(mapping);
1274+
Xml_ListGenericRoot(serializer);
1275+
}
1276+
1277+
[Fact]
1278+
public static void Xml_DifferentSerializeDeserializeOverloads()
1279+
{
1280+
var expected = new SimpleType() { P1 = "p1 value", P2 = 123 };
1281+
var serializer = new XmlSerializer(typeof (SimpleType));
1282+
var writerTypes = new Type[] { typeof(TextWriter), typeof(XmlWriter) };
1283+
Assert.Throws<InvalidOperationException>(() =>
1284+
{
1285+
XmlWriter writer = null;
1286+
serializer.Serialize(writer, expected);
1287+
});
1288+
Assert.Throws<InvalidOperationException>(() =>
1289+
{
1290+
XmlReader reader = null;
1291+
serializer.Deserialize(reader);
1292+
});
1293+
foreach (var writerType in writerTypes)
1294+
{
1295+
var stream = new MemoryStream();
1296+
1297+
if (writerType == typeof(TextWriter))
1298+
{
1299+
var writer = new StreamWriter(stream);
1300+
serializer.Serialize(writer, expected);
1301+
}
1302+
else
1303+
{
1304+
var writer = XmlWriter.Create(stream);
1305+
serializer.Serialize(writer, expected);
1306+
}
1307+
stream.Position = 0;
1308+
var actualOutput = new StreamReader(stream).ReadToEnd();
1309+
const string baseline =
1310+
@"<?xml version=""1.0"" encoding=""utf-8""?><SimpleType xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema""><P1>p1 value</P1><P2>123</P2></SimpleType>";
1311+
var result = Utils.Compare(baseline, actualOutput);
1312+
Assert.True(result.Equal, string.Format("{1}{0}Test failed for input: {2}{0}Expected: {3}{0}Actual: {4}", Environment.NewLine, result.ErrorMessage, expected, baseline, actualOutput));
1313+
stream.Position = 0;
1314+
1315+
// XmlSerializer.CanSerialize(XmlReader)
1316+
XmlReader reader = XmlReader.Create(stream);
1317+
Assert.True(serializer.CanDeserialize(reader));
1318+
1319+
// XmlSerializer.Deserialize(XmlReader)
1320+
var actual = (SimpleType) serializer.Deserialize(reader);
1321+
Assert.StrictEqual(expected.P1, actual.P1);
1322+
Assert.StrictEqual(expected.P2, actual.P2);
1323+
1324+
stream.Dispose();
1325+
}
1326+
}
1327+
11331328
private static T SerializeAndDeserialize<T>(T value, string baseline, Func<XmlSerializer> serializerFactory = null)
11341329
{
11351330
XmlSerializer serializer = new XmlSerializer(typeof(T));
@@ -1155,3 +1350,25 @@ private static T SerializeAndDeserialize<T>(T value, string baseline, Func<XmlSe
11551350
}
11561351
}
11571352
}
1353+
1354+
#region Type for Xml_ConstructorWithXmlAttributeOverrides
1355+
1356+
namespace Music
1357+
{
1358+
public class Orchestra
1359+
{
1360+
public Instrument[] Instruments;
1361+
}
1362+
1363+
public class Instrument
1364+
{
1365+
public string Name;
1366+
}
1367+
1368+
public class Brass : Instrument
1369+
{
1370+
public bool IsValved;
1371+
}
1372+
}
1373+
1374+
#endregion

0 commit comments

Comments
 (0)