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

Xml serializer test updates prep for reflection work #104173

Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ private static bool CompareXElements(XElement baselineXElement, XElement actualX
{
// Check whether the XName is the same, this can be done by comparing the two XNames.

if (!baselineXElement.Name.Equals(actualXElement.Name))
if (!(baselineXElement?.Name.Equals(actualXElement?.Name) ?? false))
{
// Two nodes could be same even if their localName is not the same.
// For example-
Expand Down Expand Up @@ -257,6 +257,13 @@ private static bool CompareXElements(XElement baselineXElement, XElement actualX
// Check if they both have the same namespace.
XNamespace deskns = baselineXElement.GetNamespaceOfPrefix(deskPrefix);
XNamespace coreclrns = actualXElement.GetNamespaceOfPrefix(coreCLRPrefix);
// If here, then both elements are prefixed. They should both have a namespace that corresponds to their prefix.
// Either NS being null here would have failed the next check anyway, whether gracefully or not.
if ((deskns == null) || (coreclrns == null))
{
Debug.WriteLine("Either expected {0} or actual {1} attribute value doesn't have namespace :", deskAtrs[i].Value, coreCLRAtrs[i].Value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that they might both not have a namespace. Is this a scenario we care about differentiating in the debug output?

return false;
}
if (!deskns.Equals(coreclrns))
{
Debug.WriteLine("XML namespace of attribute is different. Expected is {0} but actual is {1}", deskns.NamespaceName, coreclrns.NamespaceName);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
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) }));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is failing on Alpine Linux:

/root/helix/work/workitem/e /root/helix/work/workitem/e
  Discovering: System.Private.Xml.Tests (method display = ClassAndMethod, method display options = None)
  Discovered:  System.Private.Xml.Tests (found 4735 of 4792 test cases)
  Starting:    System.Private.Xml.Tests (parallel test collections = on [2 threads], stop on fail = off)
    XmlSerializerTests.Xml_DerivedIXmlSerializable [FAIL]
      XML comparison is also failing
      Test failed for input: XmlSerializableDerivedClass
      Expected: <?xml version="1.0" encoding="utf-8"?>
      <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="http://example.com/serializer-test-namespace" />
      Actual: <?xml version="1.0" encoding="utf-8"?>
      <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="http://example.com/serializer-test-namespace" />
      Stack Trace:
        /_/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs(2336,0): at XmlSerializerTests.SerializeAndDeserialize[T](T value, String baseline, Func`1 serializerFactory, Boolean skipStringCompare, XmlSerializerNamespaces xns)
        /_/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.Internal.cs(42,0): at XmlSerializerTests.Xml_DerivedIXmlSerializable()
           at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
        /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(57,0): at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
  Finished:    System.Private.Xml.Tests

In the actual value 12:00:00 AM, it is getting E2 80 AF character before AM, instead of regular space 20.

https://helixre8s23ayyeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-80154-merge-8c0184342ee64857b4/System.Private.Xml.Tests/1/console.67912d47.log?helixlogtype=result

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 though 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);
}

// TODO - 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);
}

}
Original file line number Diff line number Diff line change
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
Loading
Loading