diff options
author | JimboWei <v-wjiang@microsoft.com> | 2017-04-19 08:50:38 +0300 |
---|---|---|
committer | Shin Mao <shmao@microsoft.com> | 2017-04-19 08:50:38 +0300 |
commit | 70e1f494e0d47f440bdb6a1bf871859af9fa10dc (patch) | |
tree | cd4d271a5a7e8cf9735852b86d256d55c6f7eda7 /src | |
parent | fb74c60aa5c70ad38303986b71d994127c03deb8 (diff) |
Add two desktop test cases and some reference files for DataContractSerializer test (#18259)
* Add test case and reference files for DataContractSerializer
* Format and remove useless code for new DataContractSerializer cases
* Set expected value to test baseline and remove repeat code to similar scenarios for DataContractSerializer test
* Update the code and remove unnecessary code in these cases
* Rename the namespace to SerializationTestTypes and format the code
Diffstat (limited to 'src')
10 files changed, 1150 insertions, 125 deletions
diff --git a/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs b/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs index be6219caae..3719eeb8c0 100644 --- a/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs +++ b/src/System.Runtime.Serialization.Xml/tests/DataContractSerializer.cs @@ -2775,21 +2775,23 @@ public static partial class DataContractSerializerTests Assert.Equal(value.IntProperty, actual.IntProperty); } + #region DesktopTest + [Fact] public static void DCS_ResolveNameReturnsEmptyNamespace() { - EmptyNsContainer instance = new EmptyNsContainer(new EmptyNSAddress()); + SerializationTestTypes.EmptyNsContainer instance = new SerializationTestTypes.EmptyNsContainer(new SerializationTestTypes.EmptyNSAddress()); var settings = new DataContractSerializerSettings() { MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = false }; - string baseline1 = @"<EmptyNsContainer xmlns=""http://schemas.datacontract.org/2004/07/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><Name>P1</Name><address i:type=""EmptyNSAddress"" xmlns=""""><street>downing street</street></address></EmptyNsContainer>"; - EmptyNsContainer result = SerializeAndDeserialize(instance, baseline1, settings); + string baseline1 = @"<EmptyNsContainer xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><Name>P1</Name><address i:type=""EmptyNSAddress"" xmlns=""""><street>downing street</street></address></EmptyNsContainer>"; + var result = SerializeAndDeserialize(instance, baseline1, settings); Assert.True(result.address == null, "Address not null"); - settings = new DataContractSerializerSettings() { DataContractResolver = new EmptyNamespaceResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = false }; + settings = new DataContractSerializerSettings() { DataContractResolver = new SerializationTestTypes.EmptyNamespaceResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = false }; result = SerializeAndDeserialize(instance, baseline1, settings); Assert.True(result.address == null, "Address not null"); - instance = new EmptyNsContainer(new UknownEmptyNSAddress()); - string baseline2 = @"<EmptyNsContainer xmlns=""http://schemas.datacontract.org/2004/07/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><Name>P1</Name><address i:type=""AddressFoo"" xmlns=""""><street>downing street</street></address></EmptyNsContainer>"; + instance = new SerializationTestTypes.EmptyNsContainer(new SerializationTestTypes.UknownEmptyNSAddress()); + string baseline2 = @"<EmptyNsContainer xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><Name>P1</Name><address i:type=""AddressFoo"" xmlns=""""><street>downing street</street></address></EmptyNsContainer>"; result = SerializeAndDeserialize(instance, baseline2, settings); Assert.True(result.address == null, "Address not null"); } @@ -2797,19 +2799,69 @@ public static partial class DataContractSerializerTests [Fact] public static void DCS_ResolveDatacontractBaseType() { - Customer customerInstance = new PreferredCustomerProxy(); + SerializationTestTypes.Customer customerInstance = new SerializationTestTypes.PreferredCustomerProxy(); Type customerBaseType = customerInstance.GetType().BaseType; - var settings = new DataContractSerializerSettings() { DataContractResolver = new ProxyDataContractResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = true }; - string baseline1 = @"<Customer z:Id=""1"" i:type=""PreferredCustomer"" xmlns=""http://schemas.datacontract.org/2004/07/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:z=""http://schemas.microsoft.com/2003/10/Serialization/""><Name i:nil=""true""/><VipInfo i:nil=""true""/></Customer>"; + var settings = new DataContractSerializerSettings() { DataContractResolver = new SerializationTestTypes.ProxyDataContractResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = true }; + string baseline1 = @"<Customer z:Id=""1"" i:type=""PreferredCustomer"" xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:z=""http://schemas.microsoft.com/2003/10/Serialization/""><Name i:nil=""true""/><VipInfo i:nil=""true""/></Customer>"; object result = SerializeAndDeserialize(customerInstance, baseline1, settings); Assert.Equal(customerBaseType, result.GetType()); - settings = new DataContractSerializerSettings() { DataContractResolver = new ProxyDataContractResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = false }; - string baseline2 = @"<Customer z:Id=""i1"" i:type=""PreferredCustomer"" xmlns=""http://schemas.datacontract.org/2004/07/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:z=""http://schemas.microsoft.com/2003/10/Serialization/""><Name i:nil=""true""/><VipInfo i:nil=""true""/></Customer>"; + settings = new DataContractSerializerSettings() { DataContractResolver = new SerializationTestTypes.ProxyDataContractResolver(), MaxItemsInObjectGraph = int.MaxValue, IgnoreExtensionDataObject = false, PreserveObjectReferences = false }; + string baseline2 = @"<Customer z:Id=""i1"" i:type=""PreferredCustomer"" xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:z=""http://schemas.microsoft.com/2003/10/Serialization/""><Name i:nil=""true""/><VipInfo i:nil=""true""/></Customer>"; result = SerializeAndDeserialize(customerInstance, baseline2, settings); Assert.Equal(customerBaseType, result.GetType()); } + /// <summary> + /// Roundtrips a Datacontract type which contains Primitive types assigned to member of type object. + /// Resolver is plugged in and resolves the primitive types. Verify resolver called during ser and deser + /// </summary> + [Fact] + public static void DCS_BasicRoundTripResolvePrimitiveTypes() + { + var dataContractSerializerSettings = new DataContractSerializerSettings() + { + DataContractResolver = new SerializationTestTypes.PrimitiveTypeResolver(), + IgnoreExtensionDataObject = false, + KnownTypes = null, + MaxItemsInObjectGraph = int.MaxValue, + PreserveObjectReferences = false + }; + + string baseline = @"<ObjectContainer xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><_data i:type=""a:PrimitiveContainer_foo"" xmlns:a=""http://www.default.com""><a i:type=""a:Boolean_foo"">false</a><array1><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/></array1><b i:type=""a:Byte_foo"">255</b><c i:type=""a:Byte_foo"">0</c><d i:type=""a:Char_foo"">65535</d><e i:type=""a:Decimal_foo"">79228162514264337593543950335</e><f i:type=""a:Decimal_foo"">-1</f><f5 i:type=""a:DateTime_foo"">9999-12-31T23:59:59.9999999</f5><g i:type=""a:Decimal_foo"">-79228162514264337593543950335</g><guidData i:type=""a:Guid_foo"">4bc848b1-a541-40bf-8aa9-dd6ccb6d0e56</guidData><h i:type=""a:Decimal_foo"">1</h><i i:type=""a:Decimal_foo"">0</i><j i:type=""a:Decimal_foo"">0</j><k i:type=""a:Double_foo"">0</k><l i:type=""a:Double_foo"">4.94065645841247E-324</l><lDTO xmlns:b=""http://schemas.datacontract.org/2004/07/System""/><m i:type=""a:Double_foo"">1.7976931348623157E+308</m><n i:type=""a:Double_foo"">-1.7976931348623157E+308</n><nDTO i:type=""a:DateTimeOffset_foo""><DateTime xmlns=""http://schemas.datacontract.org/2004/07/System"">9999-12-31T23:59:59.9999999Z</DateTime><OffsetMinutes xmlns=""http://schemas.datacontract.org/2004/07/System"">0</OffsetMinutes></nDTO><o i:type=""a:Double_foo"">NaN</o><obj/><p i:type=""a:Double_foo"">-INF</p><q i:type=""a:Double_foo"">INF</q><r i:type=""a:Single_foo"">0</r><s i:type=""a:Single_foo"">1.401298E-45</s><strData i:nil=""true""/><t i:type=""a:Single_foo"">-3.40282347E+38</t><timeSpan i:type=""a:TimeSpan_foo"">P10675199DT2H48M5.4775807S</timeSpan><u i:type=""a:Single_foo"">3.40282347E+38</u><uri>http://www.microsoft.com/</uri><v i:type=""a:Single_foo"">NaN</v><w i:type=""a:Single_foo"">-INF</w><x i:type=""a:Single_foo"">INF</x><xmlQualifiedName i:type=""a:XmlQualifiedName_foo"" xmlns:b=""http://www.microsoft.com"">b:WCF</xmlQualifiedName><y i:type=""a:Int32_foo"">0</y><z i:type=""a:Int32_foo"">2147483647</z><z1 i:type=""a:Int32_foo"">-2147483648</z1><z2 i:type=""a:Int64_foo"">0</z2><z3 i:type=""a:Int64_foo"">9223372036854775807</z3><z4 i:type=""a:Int64_foo"">-9223372036854775808</z4><z5/><z6 i:type=""a:SByte_foo"">0</z6><z7 i:type=""a:SByte_foo"">127</z7><z8 i:type=""a:SByte_foo"">-128</z8><z9 i:type=""a:Int16_foo"">0</z9><z91 i:type=""a:Int16_foo"">32767</z91><z92 i:type=""a:Int16_foo"">-32768</z92><z93 i:type=""a:String_foo"">abc</z93><z94 i:type=""a:UInt16_foo"">0</z94><z95 i:type=""a:UInt16_foo"">65535</z95><z96 i:type=""a:UInt16_foo"">0</z96><z97 i:type=""a:UInt32_foo"">0</z97><z98 i:type=""a:UInt32_foo"">4294967295</z98><z99 i:type=""a:UInt32_foo"">0</z99><z990 i:type=""a:UInt64_foo"">0</z990><z991 i:type=""a:UInt64_foo"">18446744073709551615</z991><z992 i:type=""a:UInt64_foo"">0</z992><z993>AQIDBA==</z993></_data><_data2 i:type=""a:PrimitiveContainer_foo"" xmlns:a=""http://www.default.com""><a i:type=""a:Boolean_foo"">false</a><array1><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/><anyType xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""/></array1><b i:type=""a:Byte_foo"">255</b><c i:type=""a:Byte_foo"">0</c><d i:type=""a:Char_foo"">65535</d><e i:type=""a:Decimal_foo"">79228162514264337593543950335</e><f i:type=""a:Decimal_foo"">-1</f><f5 i:type=""a:DateTime_foo"">9999-12-31T23:59:59.9999999</f5><g i:type=""a:Decimal_foo"">-79228162514264337593543950335</g><guidData i:type=""a:Guid_foo"">4bc848b1-a541-40bf-8aa9-dd6ccb6d0e56</guidData><h i:type=""a:Decimal_foo"">1</h><i i:type=""a:Decimal_foo"">0</i><j i:type=""a:Decimal_foo"">0</j><k i:type=""a:Double_foo"">0</k><l i:type=""a:Double_foo"">4.94065645841247E-324</l><lDTO xmlns:b=""http://schemas.datacontract.org/2004/07/System""/><m i:type=""a:Double_foo"">1.7976931348623157E+308</m><n i:type=""a:Double_foo"">-1.7976931348623157E+308</n><nDTO i:type=""a:DateTimeOffset_foo""><DateTime xmlns=""http://schemas.datacontract.org/2004/07/System"">9999-12-31T23:59:59.9999999Z</DateTime><OffsetMinutes xmlns=""http://schemas.datacontract.org/2004/07/System"">0</OffsetMinutes></nDTO><o i:type=""a:Double_foo"">NaN</o><obj/><p i:type=""a:Double_foo"">-INF</p><q i:type=""a:Double_foo"">INF</q><r i:type=""a:Single_foo"">0</r><s i:type=""a:Single_foo"">1.401298E-45</s><strData i:nil=""true""/><t i:type=""a:Single_foo"">-3.40282347E+38</t><timeSpan i:type=""a:TimeSpan_foo"">P10675199DT2H48M5.4775807S</timeSpan><u i:type=""a:Single_foo"">3.40282347E+38</u><uri>http://www.microsoft.com/</uri><v i:type=""a:Single_foo"">NaN</v><w i:type=""a:Single_foo"">-INF</w><x i:type=""a:Single_foo"">INF</x><xmlQualifiedName i:type=""a:XmlQualifiedName_foo"" xmlns:b=""http://www.microsoft.com"">b:WCF</xmlQualifiedName><y i:type=""a:Int32_foo"">0</y><z i:type=""a:Int32_foo"">2147483647</z><z1 i:type=""a:Int32_foo"">-2147483648</z1><z2 i:type=""a:Int64_foo"">0</z2><z3 i:type=""a:Int64_foo"">9223372036854775807</z3><z4 i:type=""a:Int64_foo"">-9223372036854775808</z4><z5/><z6 i:type=""a:SByte_foo"">0</z6><z7 i:type=""a:SByte_foo"">127</z7><z8 i:type=""a:SByte_foo"">-128</z8><z9 i:type=""a:Int16_foo"">0</z9><z91 i:type=""a:Int16_foo"">32767</z91><z92 i:type=""a:Int16_foo"">-32768</z92><z93 i:type=""a:String_foo"">abc</z93><z94 i:type=""a:UInt16_foo"">0</z94><z95 i:type=""a:UInt16_foo"">65535</z95><z96 i:type=""a:UInt16_foo"">0</z96><z97 i:type=""a:UInt32_foo"">0</z97><z98 i:type=""a:UInt32_foo"">4294967295</z98><z99 i:type=""a:UInt32_foo"">0</z99><z990 i:type=""a:UInt64_foo"">0</z990><z991 i:type=""a:UInt64_foo"">18446744073709551615</z991><z992 i:type=""a:UInt64_foo"">0</z992><z993>AQIDBA==</z993></_data2></ObjectContainer>"; + var value = new SerializationTestTypes.ObjectContainer(new SerializationTestTypes.PrimitiveContainer()); + + var actual = SerializeAndDeserialize(value, baseline, dataContractSerializerSettings); + // Throw Exception when verification failed + SerializationTestTypes.ComparisonHelper.CompareRecursively(value, actual); + } + + /// <summary> + /// Roundtrip Datacontract types which contains members of type enum and struct. + /// Some enums are resolved by Resolver and others by the KT attribute. + /// Enum and struct members are of base enum type and ValueTyperespecitively + /// </summary> + [Fact] + public static void DCS_BasicRoundTripResolveEnumStructTypes() + { + var dataContractSerializerSettings = new DataContractSerializerSettings() + { + DataContractResolver = new SerializationTestTypes.PrimitiveTypeResolver(), + IgnoreExtensionDataObject = false, + KnownTypes = null, + MaxItemsInObjectGraph = int.MaxValue, + PreserveObjectReferences = false + }; + + string baseline = @"<ObjectContainer xmlns=""http://schemas.datacontract.org/2004/07/SerializationTestTypes"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance""><_data i:type=""a:EnumStructContainer"" xmlns:a=""http://www.default.com""><enumArrayData xmlns:b=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""><b:anyType i:type=""a:1munemy"">red</b:anyType><b:anyType i:type=""a:1munemy"">black</b:anyType><b:anyType i:type=""a:1munemy"">blue</b:anyType><b:anyType i:type=""a:1"">Autumn</b:anyType><b:anyType i:type=""a:2"">Spring</b:anyType></enumArrayData><p1 i:type=""a:VT_foo""><b>10</b></p1><p2 i:type=""a:NotSer_foo""><a>0</a></p2><p3 i:type=""a:MyStruct_foo""><globName i:nil=""true""/><value>0</value></p3></_data><_data2 i:type=""a:EnumStructContainer"" xmlns:a=""http://www.default.com""><enumArrayData xmlns:b=""http://schemas.microsoft.com/2003/10/Serialization/Arrays""><b:anyType i:type=""a:1munemy"">red</b:anyType><b:anyType i:type=""a:1munemy"">black</b:anyType><b:anyType i:type=""a:1munemy"">blue</b:anyType><b:anyType i:type=""a:1"">Autumn</b:anyType><b:anyType i:type=""a:2"">Spring</b:anyType></enumArrayData><p1 i:type=""a:VT_foo""><b>10</b></p1><p2 i:type=""a:NotSer_foo""><a>0</a></p2><p3 i:type=""a:MyStruct_foo""><globName i:nil=""true""/><value>0</value></p3></_data2></ObjectContainer>"; + var value = new SerializationTestTypes.ObjectContainer(new SerializationTestTypes.EnumStructContainer()); + + var actual = SerializeAndDeserialize(value, baseline, dataContractSerializerSettings); + SerializationTestTypes.ComparisonHelper.CompareRecursively(value, actual); + } + + #endregion + private static T SerializeAndDeserialize<T>(T value, string baseline, DataContractSerializerSettings settings = null, Func<DataContractSerializer> serializerFactory = null, bool skipStringCompare = false) { DataContractSerializer dcs; diff --git a/src/System.Runtime.Serialization.Xml/tests/MyResolver.cs b/src/System.Runtime.Serialization.Xml/tests/MyResolver.cs index 4267d68809..dcf969f8ac 100644 --- a/src/System.Runtime.Serialization.Xml/tests/MyResolver.cs +++ b/src/System.Runtime.Serialization.Xml/tests/MyResolver.cs @@ -24,60 +24,3 @@ internal class MyResolver : DataContractResolver return knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace); } } - -public class EmptyNamespaceResolver : DataContractResolver -{ - public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) - { - XmlDictionary dic = new XmlDictionary(); - if (dataContractType == typeof(EmptyNsContainer)) - { - typeName = dic.Add("EmptyNsContainer"); - typeNamespace = dic.Add("MyNamespace"); - return true; - } - else if (dataContractType == typeof(UknownEmptyNSAddress)) - { - typeName = dic.Add("AddressFoo"); - typeNamespace = dic.Add(""); - return true; - } - else - { - return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace); - } - } - - public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) - { - if (typeNamespace == "MyNamespace") - { - switch (typeName) - { - case "EmptyNsContainer": - return typeof(EmptyNsContainer); - } - } - else if (typeName.Equals("AddressFoo")) - { - return typeof(UknownEmptyNSAddress); - } - - return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); - } -} - -[Serializable] -public class ProxyDataContractResolver : DataContractResolver -{ - public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) - { - return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); - } - - public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) - { - Type actualDataContractType = dataContractType.Name.EndsWith("Proxy") ? dataContractType.BaseType : dataContractType; - return knownTypeResolver.TryResolveType(actualDataContractType, declaredType, null, out typeName, out typeNamespace); - } -} diff --git a/src/System.Runtime.Serialization.Xml/tests/ReflectionOnly/System.Runtime.Serialization.Xml.ReflectionOnly.Tests.csproj b/src/System.Runtime.Serialization.Xml/tests/ReflectionOnly/System.Runtime.Serialization.Xml.ReflectionOnly.Tests.csproj index 5b5e701af3..42234000bf 100644 --- a/src/System.Runtime.Serialization.Xml/tests/ReflectionOnly/System.Runtime.Serialization.Xml.ReflectionOnly.Tests.csproj +++ b/src/System.Runtime.Serialization.Xml/tests/ReflectionOnly/System.Runtime.Serialization.Xml.ReflectionOnly.Tests.csproj @@ -24,6 +24,11 @@ <Compile Include="$(TestSourceFolder)..\MyResolver.cs" /> <Compile Include="$(TestSourceFolder)..\XmlDictionaryReaderTests.cs" /> <Compile Include="$(TestSourceFolder)..\XmlDictionaryWriterTest.cs" /> + <Compile Include="$(TestSourceFolder)..\SerializationTestTypes\ComparisonHelper.cs" /> + <Compile Include="$(TestSourceFolder)..\SerializationTestTypes\DataContractResolverLibrary.cs" /> + <Compile Include="$(TestSourceFolder)..\SerializationTestTypes\DCRSampleType.cs" /> + <Compile Include="$(TestSourceFolder)..\SerializationTestTypes\DCRTypeLibrary.cs" /> + <Compile Include="$(TestSourceFolder)..\SerializationTestTypes\Primitives.cs" /> <Compile Include="$(CommonTestPath)\System\PlatformDetection.cs"> <Link>CommonTest\System\PlatformDetection.cs</Link> </Compile> diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/ComparisonHelper.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/ComparisonHelper.cs new file mode 100644 index 0000000000..92ef79fdd8 --- /dev/null +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/ComparisonHelper.cs @@ -0,0 +1,579 @@ +using System; +using System.Collections; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.Serialization; +using System.Xml; +using System.Xml.Serialization; + +namespace SerializationTestTypes +{ + public enum ComparisionType + { + DCS, + POCO + } + + #region ComparisionType passed as parameter + + /// <summary> + /// A type which does not have DataContract,MessageContract,Serializable,does not implements ISerializable or does not implement IXmlSerializable is considered a POCO type + /// While comparing POCO types, Non-public, readonly fields, ReadOnly/ WriteOnly properties and Non-public properties are ignored + /// </summary> + public static class ComparisonHelper + { + private const string LogMessage = "Comparing Type = {0} & Value = {1} with Type {2} & Value = {3}"; + + public static void CompareRecursively(object originalData, object deserializedData, bool approxComparisonForFloatingPointAnd64BitValues = false) + { + ComparisionType cmpType = ComparisionType.DCS; + SerializationMechanism att = ComparisonHelper.GetSerializationMechanism(originalData); + if (att.Equals(SerializationMechanism.POCO)) + { + cmpType = ComparisionType.POCO; + } + ComparisonHelper.CompareData(originalData, deserializedData, att, cmpType); + } + + private static SerializationMechanism GetSerializationMechanism(object data) + { + if (data == null) return SerializationMechanism.POCO; + SerializationMechanism att = SerializationMechanism.POCO; + + bool hasDataContractAttribute = data.GetType().GetCustomAttributes(typeof(DataContractAttribute), false).Length > 0; + bool hasSerializableAttribute = data.GetType().IsSerializable; + bool hasISerializable = typeof(ISerializable).IsAssignableFrom(data.GetType()); + bool hasIXmlSerializable = typeof(IXmlSerializable).IsAssignableFrom(data.GetType()); + + if ( + (!hasDataContractAttribute) && + (!hasISerializable) && + (!hasIXmlSerializable) && + (!hasSerializableAttribute) + ) + { + att = SerializationMechanism.POCO; + } + else + { + if (hasDataContractAttribute || hasIXmlSerializable) + { + att = SerializationMechanism.DataContractAttribute; + } + //CollectionDataContract is handled as part of DataContract containerTypeAttribute + if (data.GetType().GetCustomAttributes(typeof(CollectionDataContractAttribute), false).Length > 0) + { + hasDataContractAttribute = true; + } + + //ISerializable interface is handled as part of Serializable containerTypeAttribute + //since if a type implements ISerializable it must be marked with [Serializable] attribute + if (data.GetType().GetInterface("ISerializable") != null) + { + hasSerializableAttribute = true; + } + + if (hasDataContractAttribute && hasISerializable) + { + att = SerializationMechanism.DataContractAttribute; + } + else if (hasDataContractAttribute == true && hasISerializable == false) + { + att = SerializationMechanism.DataContractAttribute; + } + else if (hasDataContractAttribute == false && (hasISerializable == true || hasSerializableAttribute == true)) + { + att = SerializationMechanism.SerializableAttribute; + } + } + + return att; + } + + /// <summary> + /// Throws an exception if mismatch is found + /// </summary> + /// <param name="originalData"></param> + /// <param name="deserializedData"></param> + private static void CompareData(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType) + { + if (originalData == null) // both are null, comparison succeeded + { + return; + } + + if (originalData.GetType().Name.Equals(typeof(System.Runtime.Serialization.ExtensionDataObject).Name)) + { + return; + } + + //Fail if only one of the objects is null + if ((null == originalData) != (null == deserializedData)) + { + String message = String.Format("Comparision failed: Original data is {0}, deserialized data is {1}", + originalData == null ? "null" : "not null", deserializedData == null ? "null" : "not null"); + + if (originalData != null) + { + message += String.Format("Contents of Original data are {0}", originalData.ToString()); + } + if (deserializedData != null) + { + message += String.Format("Contents of Deserialized data are {0}", deserializedData.ToString()); + } + throw new Exception(message); + } + + if (originalData is IObjectReference) + { + //All IObjectReference types implement Equals method which compares the object returned by GetRealObject method + bool result = originalData.Equals(deserializedData); + if (!result) + { + throw new Exception("Comparision failed for type " + originalData.GetType().Name); + } + return; + } + + //Return false if the type of the object is not same + Type originalDataType = originalData.GetType(); + Type deserializedDataType = deserializedData.GetType(); + + if (!originalDataType.Equals(deserializedDataType)) + { + throw new Exception(String.Format("Comparision failed : Original type {0} not same as deserialized type {1}", originalDataType.ToString(), deserializedDataType.ToString())); + } + + object[] dataContractAttributes = originalDataType.GetCustomAttributes(typeof(DataContractAttribute), false); + if (dataContractAttributes != null && dataContractAttributes.Length > 0) + { + DataContractAttribute dataContractAttribute = (DataContractAttribute)dataContractAttributes[0]; + if (dataContractAttribute.IsReference) + { + return; + } + } + + MethodInfo equalsMethod = originalDataType.GetMethod("Equals", new Type[] { typeof(object) }); + + #region "new object()" + if (originalDataType == typeof(object)) + { + return; // deserializedDataType == object as well; objects should be the same + } + #endregion + + #region String type + else if (originalDataType.Equals(typeof(System.String))) + { + if (!originalData.Equals(deserializedData)) + { + throw new Exception(String.Format("Comparision failed: Original string data {0} is not same as deserialized string data {1}", originalData, deserializedData)); + } + } + #endregion + + #region XML types + else if (originalDataType.Equals(typeof(XmlElement)) || + originalDataType.Equals(typeof(XmlNode))) + { + string originalDataXml = ((XmlNode)originalData).InnerXml; + string deserializedDataXml = ((XmlNode)deserializedData).InnerXml; + Trace.WriteLine(String.Format(LogMessage, originalDataType, originalDataXml, deserializedDataType, deserializedDataXml)); + if (!originalDataXml.Equals(deserializedDataXml)) + { + throw new Exception(String.Format("Comparision failed: Original XML data ({0}) is not the same as the deserialized XML data ({1})", + originalDataXml, deserializedDataXml)); + } + } + #endregion + + #region Special types + else if (originalDataType == typeof(DBNull)) + { + // only 1 possible value, DBNull.Value + if ((((DBNull)originalData) == DBNull.Value) != (((DBNull)deserializedData) == DBNull.Value)) + { + throw new Exception(String.Format("Different instances of DBNull: original={0}, deserialized={1}", originalData, deserializedData)); + } + } + else if (originalDataType.Equals(typeof(DateTime))) + { + if (!(((DateTime)originalData).ToUniversalTime().Equals(((DateTime)deserializedData).ToUniversalTime()))) + { + throw new Exception(String.Format("Comparision failed: Original Datetime ticks {0} is not same as deserialized Datetime ticks {1}", ((DateTime)originalData).Ticks.ToString(), ((DateTime)deserializedData).Ticks.ToString())); + } + } + else if ( + (originalDataType.Equals(typeof(TimeSpan))) + || (originalDataType.Equals(typeof(Uri))) + || (originalDataType.Equals(typeof(XmlQualifiedName))) + || (originalDataType.Equals(typeof(Guid))) + || (originalDataType.Equals(typeof(Decimal))) + || (originalDataType.Equals(typeof(DateTimeOffset))) + ) + { + if (!originalData.Equals(deserializedData)) + { + throw new Exception(String.Format("Comparision failed : Original type data {0} is not same as deserialized type data {1}", originalData.ToString(), deserializedData.ToString())); + } + } + + #endregion + + #region Value Types + + else if (originalDataType.IsValueType) + { + //Value types can be Primitive types, Structs, Enums, Bool, User Defined Structs + + #region Primitive Types + //Numeric types, bool + if (originalDataType.IsPrimitive) + { + bool different = !originalData.Equals(deserializedData); + if (different) + { + throw new Exception(String.Format("Comparision failed: Original primitive data {0} is not same as deserialized primitive data {1}", originalData.ToString(), deserializedData.ToString())); + } + } + #endregion + + #region Enum type + else if (originalDataType.IsEnum) + { + SerializationMechanism enumAttribute = GetSerializationMechanism(originalData); + + //Verify member is marked with EnumMember attribute and compare the value with the Value property of the enum + if (enumAttribute.Equals(SerializationMechanism.DataContractAttribute)) + { + if (ComparisonHelper.IsMemberMarkedWithEnumMember(originalData, cmpType)) + { + //Verify this will work for all scenarios + if (!originalData.ToString().Equals(deserializedData.ToString())) + { + throw new Exception(String.Format("Comparision failed: Original enum data {0} is not same as deserialized enum data {1}", originalData.ToString(), deserializedData.ToString())); + } + } + } + } + #endregion + + //If not a Primitive and Enum, it has to be a struct + #region User defined structs + else + { + #region Compare Fields + ComparisonHelper.CompareFields(originalData, deserializedData, containerTypeAttribute, cmpType); + #endregion + + #region Compare properties + ComparisonHelper.CompareProperties(originalData, deserializedData, containerTypeAttribute, cmpType); + #endregion + + } + #endregion + } + #endregion + + #region Types which know how to compare themselves + else if (equalsMethod.DeclaringType == originalData.GetType()) + { + // the type knows how to compare itself, we'll use it + if (!originalData.Equals(deserializedData)) + { + throw new Exception(String.Format("Comparision failed: Original type data {0} is not same as deserialized type data {1}", originalData.ToString(), deserializedData.ToString())); + } + } + #endregion + + #region IDictionary and IDictionary<T> + //Compares generic as well as non-generic dictionary types + //Hashtables + else if (originalData is IDictionary) + { + if (deserializedData is IDictionary) + { + IDictionaryEnumerator originalDataEnum = ((IDictionary)originalData).GetEnumerator(); + IDictionaryEnumerator deserializedDataEnum = ((IDictionary)deserializedData).GetEnumerator(); + while (originalDataEnum.MoveNext()) + { + deserializedDataEnum.MoveNext(); + DictionaryEntry originalEntry = originalDataEnum.Entry; + DictionaryEntry deserializedEntry = deserializedDataEnum.Entry; + //Compare the keys and then the values + CompareData(originalEntry.Key, deserializedEntry.Key, containerTypeAttribute, cmpType); + CompareData(originalEntry.Value, deserializedEntry.Value, containerTypeAttribute, cmpType); + } + } + else + { + throw new Exception(String.Format("Comparision failed: Original IDictionary type {0} and deserialized IDictionary type {1} are not of same", originalDataType.GetType().ToString(), deserializedDataType.GetType().ToString())); + } + } + #endregion + + #region IEnumerable,IList,ICollection,IEnumerable<t>,IList<T>,ICollection<T> + //Array,Lists,Queues,Stacks etc + else if (originalData is IEnumerable) + { + IEnumerator originalDataEnumerator = ((IEnumerable)originalData).GetEnumerator(); + IEnumerator deserializedDataEnumerator = ((IEnumerable)deserializedData).GetEnumerator(); + if (null != originalDataEnumerator && null != deserializedDataEnumerator) + { + while (originalDataEnumerator.MoveNext()) + { + deserializedDataEnumerator.MoveNext(); + CompareData(originalDataEnumerator.Current, deserializedDataEnumerator.Current, containerTypeAttribute, cmpType); + } + } + else + { + throw new Exception(String.Format("Comparision failed: Original type {0} and deserialized type {1} are not IEnumerable", originalDataType.GetType().ToString(), deserializedDataType.GetType().ToString())); + } + } + + #endregion + + #region Class + else if (originalDataType.IsClass) + { + #region Compare Fields + ComparisonHelper.CompareFields(originalData, deserializedData, containerTypeAttribute, cmpType); + #endregion + + #region Compare properties + ComparisonHelper.CompareProperties(originalData, deserializedData, containerTypeAttribute, cmpType); + #endregion + } + #endregion + } + + private static bool IsMemberMarkedWithEnumMember(object data, ComparisionType cmpType) + { + bool isEnumMember = false; + //Non-public members are not serialized for POCO types + BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; + if (cmpType.Equals(ComparisionType.DCS)) + { + flag = flag | BindingFlags.NonPublic; + } + + FieldInfo info = data.GetType().GetField(data.ToString(), flag); + if (null != info) + { + isEnumMember = info.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length > 0; + } + return isEnumMember; + } + + + /// <summary> + /// Iterates through the properties and invokes compare method + /// </summary> + /// <param name="originalData"></param> + /// <param name="deserializedData"></param> + /// <param name="containerTypeAttribute"></param> + private static void CompareProperties(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType) + { + BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; + //Include private fields for DCS types + if (cmpType.Equals(ComparisionType.DCS)) + { + flag = flag | BindingFlags.NonPublic; + } + + foreach (System.Reflection.PropertyInfo property in originalData.GetType().GetProperties(flag)) + { + object newData = property.GetValue(originalData, null); + SerializationMechanism fieldAttribute = ComparisonHelper.GetSerializationMechanism(newData); + if (cmpType.Equals(ComparisionType.DCS)) + { + if (containerTypeAttribute.Equals(SerializationMechanism.DataContractAttribute)) + { + if ( + (property.GetCustomAttributes(typeof(DataMemberAttribute), false).Length > 0) + || + (property.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length > 0) + ) + { + //Pass attribute of the complex type for furthur evaluation + if (IsComplexType(newData)) + { + CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType); + } + else //Is a simple type + { + CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType); + } + } + } + else if (containerTypeAttribute.Equals(SerializationMechanism.SerializableAttribute)) + { + if (property.GetCustomAttributes(typeof(NonSerializedAttribute), false).Length == 0) + { + //Pass attribute of the complex type for furthur evaluation + if (IsComplexType(newData)) + { + CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType); + } + else //Is a simple type, so pass Parents attribute + { + CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType); + } + } + } + } + else if (cmpType.Equals(ComparisionType.POCO)) + { + //Ignore member with [IgnoreDataMember] attribute on a POCO type + if (property.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false).Length == 0) + { + //On POCO types, Properties which have both getter and setter will be serialized otherwise ignored + if (property.CanRead && property.CanWrite) + { + //Pass attribute of the complex type for furthur evaluation + if (IsComplexType(newData)) + { + CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType); + } + else //Is a simple type, so pass Parents attribute + { + CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType); + } + } + else if (property.CanRead && !property.CanWrite) //Get-Only collection + { + //Pass attribute of the complex type for furthur evaluation + if (IsComplexType(newData)) + { + CompareData(newData, property.GetValue(deserializedData, null), fieldAttribute, cmpType); + } + else //Is a simple type, so pass Parents attribute + { + CompareData(newData, property.GetValue(deserializedData, null), containerTypeAttribute, cmpType); + } + } + } + } + } + } + + /// <summary> + /// </summary> + /// <param name="data"></param> + /// <returns></returns> + public static bool IsComplexType(object data) + { + bool complexType = false; + if (data == null) return false; + if ( + ((data.GetType().IsValueType) + && + (!data.GetType().IsPrimitive) + && + (!data.GetType().IsEnum)) + || + ((data.GetType().IsClass) + && + (!(data.GetType().Equals(typeof(System.String))) + )) + ) + { + complexType = true; + } + return complexType; + } + + private static void CompareFields(object originalData, object deserializedData, SerializationMechanism containerTypeAttribute, ComparisionType cmpType) + { + //Compare fields + //Non-public members are not serialized for POCO types + BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; + if (cmpType.Equals(ComparisionType.DCS)) + { + flag = flag | BindingFlags.NonPublic; + } + + foreach (System.Reflection.FieldInfo field in originalData.GetType().GetFields(flag)) + { + object newData = field.GetValue(originalData); + SerializationMechanism fieldAttribute = GetSerializationMechanism(newData); + if (cmpType.Equals(ComparisionType.DCS)) + { + if (containerTypeAttribute.Equals(SerializationMechanism.DataContractAttribute)) + { + if ( + (field.GetCustomAttributes(typeof(DataMemberAttribute), false).Length > 0) + || + (field.GetCustomAttributes(typeof(EnumMemberAttribute), false).Length > 0) + ) + { + //Pass attribute of the complex type for furthur evaluation + if (ComparisonHelper.IsComplexType(newData)) + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType); + } + else //Is a simple type + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType); + } + } + } + else if (containerTypeAttribute.Equals(SerializationMechanism.SerializableAttribute)) + { + //Do not compare [NonSerialized] members + if (!field.IsNotSerialized) + { + if (ComparisonHelper.IsComplexType(newData)) + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType); + } + else //Is a simple type + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType); + } + } + } + } + else if (cmpType.Equals(ComparisionType.POCO)) + { + //ReadOnly fields should be ignored for POCO type + //Ignore member with [IgnoreDataMember] attribute on a POCO type + if ((!field.IsInitOnly) && (field.GetCustomAttributes(typeof(IgnoreDataMemberAttribute), false).Length == 0)) + { + if (ComparisonHelper.IsComplexType(newData)) + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), fieldAttribute, cmpType); + } + else //Is a simple type + { + ComparisonHelper.CompareData(field.GetValue(originalData), field.GetValue(deserializedData), containerTypeAttribute, cmpType); + } + } + } + } + } + + public static bool CompareDoubleApproximately(double d1, double d2) + { + if ((d1 < 0) != (d2 < 0)) return false; + d1 = Math.Abs(d1); + d2 = Math.Abs(d2); + double max = Math.Max(d1, d2); + double min = Math.Min(d1, d2); + if (min == 0) return (max == 0); + double difference = max - min; + double ratio = difference / min; + return (ratio < 0.0000001); + } + } + + public enum SerializationMechanism + { + POCO, + DataContractAttribute, + SerializableAttribute, + } + #endregion +} diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRSampleType.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRSampleType.cs new file mode 100644 index 0000000000..2efa75d709 --- /dev/null +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRSampleType.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Xml; + +namespace SerializationTestTypes +{ + [DataContract] + public class PrimitiveContainer + { + public PrimitiveContainer() + { + a = false; + b = Byte.MaxValue; + c = Byte.MinValue; + + //char + //datetime + e = Decimal.MaxValue; + f = Decimal.MinusOne; + g = Decimal.MinValue; + h = Decimal.One; + i = Decimal.Zero; + j = default(Decimal); + k = default(Double); + l = Double.Epsilon; + m = Double.MaxValue; + n = Double.MinValue; + o = Double.NaN; + p = Double.NegativeInfinity; + q = Double.PositiveInfinity; + r = default(Single); + s = Single.Epsilon; + t = Single.MinValue; + u = Single.MaxValue; + v = Single.NaN; + w = Single.NegativeInfinity; + x = Single.PositiveInfinity; + y = default(Int32); + z = Int32.MaxValue; + z1 = Int32.MinValue; + z2 = default(Int64); + z3 = Int64.MaxValue; + z4 = Int64.MinValue; + z5 = new Object(); + z6 = default(SByte); + z7 = SByte.MaxValue; + z8 = SByte.MinValue; + z9 = default(Int16); + z91 = Int16.MaxValue; + z92 = Int16.MinValue; + z93 = "abc"; + z94 = default(UInt16); + z95 = UInt16.MaxValue; + z96 = UInt16.MinValue; + z97 = default(UInt32); + z98 = UInt32.MaxValue; + z99 = UInt32.MinValue; + z990 = default(UInt64); + z991 = UInt64.MaxValue; + z992 = UInt64.MinValue; + z993 = new Byte[] { 1, 2, 3, 4 }; + } + + [DataMember] + public object a; + + [DataMember] + public object b; + + [DataMember] + public object c; + + [DataMember] + public object d = Char.MaxValue; + + [DataMember] + public object f5 = DateTime.MaxValue; + + [DataMember] + public object guidData = Guid.Parse("4bc848b1-a541-40bf-8aa9-dd6ccb6d0e56"); + + [DataMember] + public object strData; + + [DataMember] + public object e; + + [DataMember] + public object f; + + [DataMember] + public object g; + + [DataMember] + public object h; + + [DataMember] + public object i; + + [DataMember] + public object j; + + [DataMember] + public object k; + + [DataMember] + public object l; + + [DataMember] + public object m; + + [DataMember] + public object n; + + [DataMember] + public object o; + + [DataMember] + public object p; + + [DataMember] + public object q; + + [DataMember] + public object r; + + [DataMember] + public object s; + + [DataMember] + public object t; + + [DataMember] + public object u; + + [DataMember] + public object v; + + [DataMember] + public object w; + + [DataMember] + public object x; + + [DataMember] + public object y; + + [DataMember] + public object z; + + [DataMember] + public object z1; + + [DataMember] + public object z2; + + [DataMember] + public object z3; + + [DataMember] + public object z4; + + [DataMember] + public object z5; + + [DataMember] + public object z6; + + [DataMember] + public object z7; + + [DataMember] + public object z8; + + [DataMember] + public object z9; + + [DataMember] + public object z91; + + [DataMember] + public object z92; + + [DataMember] + public object z93; + + [DataMember] + public object z94; + + [DataMember] + public object z95; + + [DataMember] + public object z96; + + [DataMember] + public object z97; + + [DataMember] + public object z98; + + [DataMember] + public object z99; + + [DataMember] + public object z990; + + [DataMember] + public object z991; + + [DataMember] + public object z992; + + [DataMember] + public Byte[] z993; + + [DataMember] + public object xmlQualifiedName = new XmlQualifiedName("WCF", "http://www.microsoft.com"); + + [DataMember] + public ValueType timeSpan = TimeSpan.MaxValue; + + [DataMember] + public object obj = new object(); + + [DataMember] + public Uri uri = new Uri("http://www.microsoft.com"); + + [DataMember] + public Array array1 = new object[] { new object(), new object(), new object() }; + + [DataMember] + public object nDTO = DateTimeOffset.MaxValue; + + [DataMember] + public List<DateTimeOffset> lDTO = new List<DateTimeOffset>(); + } + + [DataContract] + [KnownType(typeof(EmptyNSAddress))] + public class EmptyNsContainer + { + [DataMember] + public object address; + + [DataMember] + public string Name; + + public EmptyNsContainer(EmptyNSAddress obj) + { + address = obj; + Name = "P1"; + } + } + + [DataContract(Namespace = "")] + public class UknownEmptyNSAddress : EmptyNSAddress + { + public UknownEmptyNSAddress() + { + } + } + + [DataContract(Namespace = "")] + public class EmptyNSAddress + { + [DataMember] + public string street; + + public EmptyNSAddress() + { + street = "downing street"; + } + } + + [DataContract(IsReference = true)] + [KnownType(typeof(PreferredCustomer))] + public class Customer + { + [DataMember] + public string Name { get; set; } + } + + [DataContract(IsReference = true)] + public class PreferredCustomer : Customer + { + [DataMember] + public string VipInfo { get; set; } + } + + [DataContract(IsReference = true)] + public class PreferredCustomerProxy : PreferredCustomer + { + } +} diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRTypeLibrary.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRTypeLibrary.cs new file mode 100644 index 0000000000..7e42b95183 --- /dev/null +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DCRTypeLibrary.cs @@ -0,0 +1,30 @@ +using System.Runtime.Serialization; + +namespace SerializationTestTypes +{ + [DataContract] + public class ObjectContainer + { + [DataMember] + private object _data; + + [DataMember] + private object _data2; + + public ObjectContainer(object input) + { + _data = input; + _data2 = _data; + } + + public object Data + { + get { return _data; } + } + + public object Data2 + { + get { return _data2; } + } + } +} diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DataContractResolverLibrary.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DataContractResolverLibrary.cs new file mode 100644 index 0000000000..0348c2c083 --- /dev/null +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/DataContractResolverLibrary.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Xml; + +namespace SerializationTestTypes +{ + [Serializable] + public class PrimitiveTypeResolver : DataContractResolver + { + private readonly static string s_defaultNS = "http://www.default.com"; + private readonly static Dictionary<string, Type> s_types = new Dictionary<string, Type>(); + + public override bool TryResolveType(Type dcType, Type declaredType, DataContractResolver KTResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) + { + string resolvedTypeName = string.Empty; + string resolvedNamespace = string.Empty; + resolvedNamespace = s_defaultNS; + resolvedTypeName = dcType.Name + "_foo"; + s_types[resolvedTypeName] = dcType; + XmlDictionary dic = new XmlDictionary(); + typeName = dic.Add(resolvedTypeName); + typeNamespace = dic.Add(resolvedNamespace); + return true; + } + + public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver KTResolver) + { + return s_types[typeName]; + } + } + + public class EmptyNamespaceResolver : DataContractResolver + { + public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) + { + XmlDictionary dic = new XmlDictionary(); + if (dataContractType == typeof(EmptyNsContainer)) + { + typeName = dic.Add("EmptyNsContainer"); + typeNamespace = dic.Add("MyNamespace"); + return true; + } + else if (dataContractType == typeof(UknownEmptyNSAddress)) + { + typeName = dic.Add("AddressFoo"); + typeNamespace = dic.Add(""); + return true; + } + else + { + return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace); + } + } + + public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) + { + if (typeNamespace == "MyNamespace") + { + switch (typeName) + { + case "EmptyNsContainer": + return typeof(EmptyNsContainer); + } + } + else if (typeName.Equals("AddressFoo")) + { + return typeof(UknownEmptyNSAddress); + } + + return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); + } + } + + [Serializable] + public class ProxyDataContractResolver : DataContractResolver + { + public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver) + { + return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); + } + + public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) + { + Type actualDataContractType = dataContractType.Name.EndsWith("Proxy") ? dataContractType.BaseType : dataContractType; + return knownTypeResolver.TryResolveType(actualDataContractType, declaredType, null, out typeName, out typeNamespace); + } + } +} diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/Primitives.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/Primitives.cs new file mode 100644 index 0000000000..c1f27fd4c9 --- /dev/null +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTestTypes/Primitives.cs @@ -0,0 +1,83 @@ +using System; +using System.Runtime.Serialization; + +namespace SerializationTestTypes +{ + [DataContract] + public struct VT + { + [DataMember] + public int b; + + public VT(int v) + { + b = v; + } + } + + public struct NotSer + { + public int a; + } + + [DataContract] + public enum MyEnum1 : byte + { + [EnumMember] + red, + [EnumMember] + blue, + [EnumMember] + black + } + + [Flags] + public enum Seasons1 : byte + { + None = 0, + Summer = 1, + Autumn = 2, + Winter = 4, + Spring = 8, + All = Summer | Autumn | Winter | Spring, + } + + [Flags] + public enum Seasons2 : sbyte + { + None = 0, + Summer = 1, + Autumn = 2, + Winter = 4, + Spring = 8, + All = Summer | Autumn | Winter | Spring, + } + + public struct MyStruct + { + public int value; + public string globName; + + public MyStruct(bool init) + { + value = 10; + globName = "\uFEA5\uFEA3\uFEA8\uFEAA\uFEA3\uFEBB\uFEC2\uFEC3"; + } + } + + [DataContract] + public class EnumStructContainer + { + [DataMember] + public object p1 = new VT(10); + + [DataMember] + public object p2 = new NotSer(); + + [DataMember] + public object[] enumArrayData = new object[] { MyEnum1.red, MyEnum1.black, MyEnum1.blue, Seasons1.Autumn, Seasons2.Spring }; + + [DataMember] + public object p3 = new MyStruct(); + } +} diff --git a/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs b/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs index abaf1b33bc..15a5ee83b0 100644 --- a/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs +++ b/src/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs @@ -4378,60 +4378,3 @@ public static class Outer public string LastName { get; set; } } } - -[DataContract] -[KnownType(typeof(EmptyNSAddress))] -public class EmptyNsContainer -{ - [DataMember] - public object address; - - [DataMember] - public string Name; - - public EmptyNsContainer(EmptyNSAddress obj) - { - address = obj; - Name = "P1"; - } -} - -[DataContract(Namespace = "")] -public class UknownEmptyNSAddress : EmptyNSAddress -{ - public UknownEmptyNSAddress() - { - } -} - -[DataContract(Namespace = "")] -public class EmptyNSAddress -{ - [DataMember] - public string street; - - public EmptyNSAddress() - { - street = "downing street"; - } -} - -[DataContract(IsReference = true)] -[KnownType(typeof(PreferredCustomer))] -public class Customer -{ - [DataMember] - public string Name { get; set; } -} - -[DataContract(IsReference = true)] -public class PreferredCustomer : Customer -{ - [DataMember] - public string VipInfo { get; set; } -} - -[DataContract(IsReference = true)] -public class PreferredCustomerProxy : PreferredCustomer -{ -} diff --git a/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.csproj b/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.csproj index af1a0f5632..69e880032c 100644 --- a/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.csproj +++ b/src/System.Runtime.Serialization.Xml/tests/System.Runtime.Serialization.Xml.Tests.csproj @@ -23,6 +23,11 @@ <Compile Include="$(TestSourceFolder)MyResolver.cs" /> <Compile Include="$(TestSourceFolder)XmlDictionaryReaderTests.cs" /> <Compile Include="$(TestSourceFolder)XmlDictionaryWriterTest.cs" /> + <Compile Include="$(TestSourceFolder)SerializationTestTypes\ComparisonHelper.cs" /> + <Compile Include="$(TestSourceFolder)SerializationTestTypes\DataContractResolverLibrary.cs" /> + <Compile Include="$(TestSourceFolder)SerializationTestTypes\DCRSampleType.cs" /> + <Compile Include="$(TestSourceFolder)SerializationTestTypes\DCRTypeLibrary.cs" /> + <Compile Include="$(TestSourceFolder)SerializationTestTypes\Primitives.cs" /> <Compile Include="$(CommonTestPath)\System\PlatformDetection.cs"> <Link>CommonTest\System\PlatformDetection.cs</Link> </Compile> |