Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shoring up XmlSerializer/Schema tests #101621

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

Large diffs are not rendered by default.

Expand Up @@ -3,38 +3,110 @@

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using SerializationTypes;
using Xunit;

public static partial class XmlSerializerTests
{
// Move this test to XmlSerializerTests.cs once #1398 is fixed for the ReflectionOnly serializer.
[Fact]
// XmlTypeMapping is not included in System.Xml.XmlSerializer 4.0.0.0 facade in GAC
public static void Xml_FromMappings()
public static void Xml_CustomDocumentWithXmlAttributesAsNodes()
{
var types = new[] { typeof(Guid), typeof(List<string>) };
XmlReflectionImporter importer = new XmlReflectionImporter();
XmlTypeMapping[] mappings = new XmlTypeMapping[types.Length];
for (int i = 0; i < types.Length; i++)
var customDoc = new CustomDocument();
var customElement = new CustomElement() { Name = "testElement" };
customElement.AddAttribute(customDoc.CreateAttribute("regularAttribute", "regularValue"));
customElement.AddAttribute(customDoc.CreateCustomAttribute("customAttribute", "customValue"));
customDoc.CustomItems.Add(customElement);
var element = customDoc.Document.CreateElement("regularElement");
var innerElement = customDoc.Document.CreateElement("innerElement");
innerElement.InnerXml = "<leafElement>innerText</leafElement>";
element.InnerText = "regularText";
element.AppendChild(innerElement);
element.Attributes.Append(customDoc.CreateAttribute("regularElementAttribute", "regularElementAttributeValue"));
customDoc.AddItem(element);
var actual = SerializeAndDeserialize(customDoc,
WithXmlHeader(@"<customElement name=""testElement"" regularAttribute=""regularValue"" customAttribute=""customValue""/>"), skipStringCompare: true);
Assert.NotNull(actual);
}

// Move this test to XmlSerializerTests.cs once #1401 is fixed for the ReflectionOnly serializer.
[Fact]
public static void Xml_DerivedIXmlSerializable()
{
var dClass = new XmlSerializableDerivedClass() { AttributeString = "derivedIXmlSerTest", DateTimeValue = DateTime.Parse("Dec 31, 1999"), BoolValue = true };

var expectedXml = WithXmlHeader(@$"<BaseIXmlSerializable xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""DerivedIXmlSerializable"" AttributeString=""derivedIXmlSerTest"" DateTimeValue=""12/31/1999 12:00:00 AM"" BoolValue=""True"" xmlns=""{XmlSerializableBaseClass.XmlNamespace}"" />");
var fromBase = SerializeAndDeserialize(dClass, expectedXml, () => new XmlSerializer(typeof(XmlSerializableBaseClass), new Type[] { typeof(XmlSerializableDerivedClass) }));
Assert.Equal(dClass.AttributeString, fromBase.AttributeString);
Assert.StrictEqual(dClass.DateTimeValue, fromBase.DateTimeValue);
Assert.Equal(dClass.BoolValue, fromBase.BoolValue);

// Derived class does not apply XmlRoot attribute to force itself to be emitted with the base class element name, so update expected xml accordingly.
// Since we can't smartly emit xsi:type during serialization though, it is still there even thout it isn't needed.
expectedXml = WithXmlHeader(@"<DerivedIXmlSerializable xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""DerivedIXmlSerializable"" AttributeString=""derivedIXmlSerTest"" DateTimeValue=""12/31/1999 12:00:00 AM"" BoolValue=""True"" />");
var fromDerived = SerializeAndDeserialize(dClass, expectedXml, () => new XmlSerializer(typeof(XmlSerializableDerivedClass)));
Assert.Equal(dClass.AttributeString, fromDerived.AttributeString);
Assert.StrictEqual(dClass.DateTimeValue, fromDerived.DateTimeValue);
Assert.Equal(dClass.BoolValue, fromDerived.BoolValue);
}

// Move this test to XmlSerializerTests.cs once #1402 is fixed for the ReflectionOnly serializer.
// Actually, this test is already there, but it's commented out. Uncomment it once #1402 is fixed.
// BTW, there are multiple (4?) places in the refelction reader where this issue is referenced, although
// one of those places is a potential optimization that is not required to get on par with ILGen afaik.
[Fact]
public static void XML_TypeWithFieldsOrdered()
{
var value = new TypeWithFieldsOrdered()
{
mappings[i] = importer.ImportTypeMapping(types[i]);
}
var serializers = XmlSerializer.FromMappings(mappings, typeof(object));
Xml_GuidAsRoot_Helper(serializers[0]);
Xml_ListGenericRoot_Helper(serializers[1]);
IntField1 = 1,
IntField2 = 2,
StringField1 = "foo1",
StringField2 = "foo2"
};

var actual = SerializeAndDeserialize(value, WithXmlHeader("<TypeWithFieldsOrdered xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <IntField2>2</IntField2>\r\n <IntField1>1</IntField1>\r\n <strfld>foo2</strfld>\r\n <strfld>foo1</strfld>\r\n</TypeWithFieldsOrdered>"));

Assert.NotNull(actual);
Assert.Equal(value.IntField1, actual.IntField1);
Assert.Equal(value.IntField2, actual.IntField2);
Assert.Equal(value.StringField1, actual.StringField1);
Assert.Equal(value.StringField2, actual.StringField2);
}

// Move this test to XmlSerializerTests.RuntimeOnly.cs once #1399 is fixed for the ReflectionOnly serializer.
[Fact]
// XmlTypeMapping is not included in System.Xml.XmlSerializer 4.0.0.0 facade in GAC
public static void Xml_ConstructorWithTypeMapping()
public static void Xml_XmlSchema()
{
XmlTypeMapping mapping = null;
XmlSerializer serializer = null;
Assert.Throws<ArgumentNullException>(() => { new XmlSerializer(mapping); });
var expectedXml = WithXmlHeader("<xsd:schema xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" elementFormDefault=\"qualified\" targetNamespace=\"http://example.com/my-schema\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <xsd:element name=\"MyElement\" type=\"xsd:string\" />\r\n <xsd:group name=\"MyGroup\">\r\n <xsd:sequence>\r\n <xsd:element name=\"Item1\" />\r\n <xsd:element name=\"Item2\" />\r\n </xsd:sequence>\r\n </xsd:group>\r\n</xsd:schema>");

XmlSchema schema = new XmlSchema
{
TargetNamespace = "http://example.com/my-schema",
ElementFormDefault = XmlSchemaForm.Qualified
};
schema.Items.Add(new XmlSchemaElement
{
Name = "MyElement",
SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema")
});
schema.Items.Add(new XmlSchemaGroup
{
Name = "MyGroup",
Particle = new XmlSchemaSequence
{
Items = { new XmlSchemaElement { Name = "Item1" }, new XmlSchemaElement { Name = "Item2" } }
}
});
schema.Namespaces.Add("xsd", "http://www.w3.org/2001/XMLSchema");
schema.Namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

var actual = SerializeAndDeserialize(schema, expectedXml, () => new XmlSerializer(typeof(XmlSchema)));

mapping = new XmlReflectionImporter(null, null).ImportTypeMapping(typeof(List<string>));
serializer = new XmlSerializer(mapping);
Xml_ListGenericRoot_Helper(serializer);
Assert.Equivalent(schema, actual);
}

}
Expand Up @@ -2143,6 +2143,35 @@ public static void XmlSerializationGeneratedCodeTest()
Assert.NotNull(cg);
}

[Fact]
// XmlTypeMapping is not included in System.Xml.XmlSerializer 4.0.0.0 facade in GAC
public static void Xml_FromMappings()
{
var types = new[] { typeof(Guid), typeof(List<string>) };
XmlReflectionImporter importer = new XmlReflectionImporter();
XmlTypeMapping[] mappings = new XmlTypeMapping[types.Length];
for (int i = 0; i < types.Length; i++)
{
mappings[i] = importer.ImportTypeMapping(types[i]);
}
var serializers = XmlSerializer.FromMappings(mappings, typeof(object));
Xml_GuidAsRoot_Helper(serializers[0]);
Xml_ListGenericRoot_Helper(serializers[1]);
}

[Fact]
// XmlTypeMapping is not included in System.Xml.XmlSerializer 4.0.0.0 facade in GAC
public static void Xml_ConstructorWithTypeMapping()
{
XmlTypeMapping mapping = null;
XmlSerializer serializer = null;
Assert.Throws<ArgumentNullException>(() => { new XmlSerializer(mapping); });

mapping = new XmlReflectionImporter(null, null).ImportTypeMapping(typeof(List<string>));
serializer = new XmlSerializer(mapping);
Xml_ListGenericRoot_Helper(serializer);
}

[Fact]
public static void XmlMembersMapping_PrimitiveValue()
{
Expand Down