using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Xml.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Vocaluxe.Base; using VocaluxeLib; using VocaluxeLib.Menu; using VocaluxeLib.Xml; namespace VocaluxeTests { [TestClass] public class CXmlSerializerTest { private const string _Head = "\r\n"; private const string _Empty = _Head + @""; #pragma warning disable 649 #pragma warning disable 169 private struct SBasic { public int I; public string S; public float F; public double D; } [XmlType("Entry")] private struct SEntry { public int I; } private struct SList { [XmlArray] public List Ints; } private struct SArray { [XmlArray] public SEntry[] Ints; } private struct SListEmb { public int I; [XmlElement("Entry")] public List Ints; public int J; } private struct SArrayEmb { public int I; [XmlElement("Entry")] public SEntry[] Ints; public int J; } private struct SProperty { [XmlIgnore] public int Private; // ReSharper disable UnusedMember.Local public int Public { get { return Private - 1; } set { Private = value + 1; } } // ReSharper restore UnusedMember.Local // ReSharper disable UnusedAutoPropertyAccessor.Local public int Auto { get; set; } // ReSharper restore UnusedAutoPropertyAccessor.Local } private struct SBytes { public byte[] B; } private struct SIgnore { [XmlIgnore] public int I; public int J; } private class CIgnore { [XmlIgnore] public int I; public int J; } private struct SDefaultSub { [DefaultValue(111)] public int I; } private struct SDefault { [DefaultValue(1337)] public int I; [DefaultValue("Foo")] public string S; public float? F; [DefaultValue(666.0)] public double D; public SDefaultSub Sub; } #pragma warning restore 169 #pragma warning restore 649 private static void _AssertFail(Action test) where T : Exception { try { test.Invoke(); Assert.Fail("Exception " + typeof(T).Name + " not thrown!"); } catch (Exception e) { Assert.IsInstanceOfType(e, typeof(T)); } } private static void _AssertFail(String xmlString) where T2 : Exception where T : new() { var deserializer = new CXmlDeserializer(); _AssertFail(() => deserializer.DeserializeString(xmlString)); } private static T _AssertSerDeserMatch(string xmlString) where T : new() { var deserializer = new CXmlDeserializer(); var serializer = new CXmlSerializer(); T foo = deserializer.DeserializeString(xmlString); string xmlNew = serializer.Serialize(foo); Assert.AreEqual(xmlString, xmlNew); return foo; } [TestMethod] public void TestBasic() { const string s = @" 1 2 3 4 "; const string sUnordered = @" 4 1 3 2 "; var xml = new CXmlDeserializer(); SBasic foo = xml.DeserializeString(s); Assert.AreEqual(1, foo.I); Assert.AreEqual("2", foo.S); Assert.AreEqual(3, foo.F, 0.0001); Assert.AreEqual(4, foo.D, 0.0001); foo = xml.DeserializeString(sUnordered); Assert.AreEqual(1, foo.I); Assert.AreEqual("2", foo.S); Assert.AreEqual(3, foo.F, 0.0001); Assert.AreEqual(4, foo.D, 0.0001); } [TestMethod] public void TestMissingXmlElement() { string[] s = new string[] {@" 2 3 4 ", @" 1 3 4 ", @" 1 2 3 "}; foreach (string s1 in s) { string sTmp = s1; _AssertFail(sTmp); } } [TestMethod] public void TestMissingStructElement() { string[] s = new string[] {@" 1 1 2 3 4 ", @" 1 1 2 3 4 ", @" 1 2 3 4 1 "}; foreach (string s1 in s) { string sTmp = s1; _AssertFail(sTmp); } } [TestMethod] public void TestBasicSerialization() { const string s = _Head + @" 1 2 3 4 "; _AssertSerDeserMatch(s); } private readonly string[] _XmlList = new string[] { _Head + @" 1 1 ", _Head + @" ", _Head + @" " }; [TestMethod] public void TestList() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); SList foo = xml.DeserializeString(_XmlList[0]); Assert.AreEqual(foo.Ints.Count, 2, "Deserialization failed"); Assert.AreEqual(foo.Ints[0].I, 1, "Deserialization failed"); Assert.AreEqual(foo.Ints[1].I, 1, "Deserialization failed"); string res = ser.Serialize(foo); Assert.AreEqual(_XmlList[0], res, "Serialization failed"); foo = xml.DeserializeString(_XmlList[1]); Assert.AreEqual(foo.Ints.Count, 0, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlList[2], res, "Serialization2 failed"); foo = xml.DeserializeString(_XmlList[2]); Assert.AreEqual(foo.Ints.Count, 0, "Deserialization2 failed"); _AssertSerDeserMatch(_XmlList[2]); res = ser.Serialize(foo); Assert.AreEqual(_XmlList[2], res, "Serialization2 failed"); _AssertFail(_Empty); } [TestMethod] public void TestArray() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); SArray foo = xml.DeserializeString(_XmlList[0]); Assert.AreEqual(foo.Ints.Length, 2, "Deserialization failed"); Assert.AreEqual(foo.Ints[0].I, 1, "Deserialization failed"); Assert.AreEqual(foo.Ints[1].I, 1, "Deserialization failed"); string res = ser.Serialize(foo); Assert.AreEqual(_XmlList[0], res, "Serialization failed"); foo = xml.DeserializeString(_XmlList[1]); Assert.AreEqual(foo.Ints.Length, 0, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlList[2], res, "Serialization2 failed"); foo = xml.DeserializeString(_XmlList[2]); Assert.AreEqual(foo.Ints.Length, 0, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlList[2], res, "Serialization2 failed"); _AssertFail(_Empty); } private const string _XmlListEmb = _Head + @" 2 1 3 "; private const string _XmlListEmb2 = _Head + @" 2 1 2 3 "; private const string _XmlListEmb3 = _Head + @" 2 3 "; [TestMethod] public void TestListEmbedded() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); SListEmb foo = xml.DeserializeString(_XmlListEmb); Assert.AreEqual(foo.Ints.Count, 1, "Deserialization failed"); Assert.AreEqual(foo.Ints[0].I, 1, "Deserialization failed"); string res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb, res, "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb2); Assert.AreEqual(foo.Ints.Count, 2, "Deserialization failed"); Assert.AreEqual(foo.Ints[1].I, 2, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb2, res, "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb3); Assert.AreEqual(foo.Ints.Count, 0, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb3, res, "Serialization failed"); _AssertFail(_Empty); } [TestMethod] public void TestArrayEmbedded() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); SArrayEmb foo = xml.DeserializeString(_XmlListEmb); Assert.AreEqual(foo.Ints.Length, 1, "Deserialization failed"); Assert.AreEqual(foo.Ints[0].I, 1, "Deserialization failed"); string res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb, res, "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb2); Assert.AreEqual(foo.Ints.Length, 2, "Deserialization failed"); Assert.AreEqual(foo.Ints[1].I, 2, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb2, res, "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb3); Assert.AreEqual(foo.Ints.Length, 0, "Deserialization failed"); res = ser.Serialize(foo); Assert.AreEqual(_XmlListEmb3, res, "Serialization failed"); _AssertFail(_Empty); } [TestMethod] public void TestProperty() { const string xmlString = _Head + @" 2 3 "; SProperty foo = _AssertSerDeserMatch(xmlString); Assert.AreEqual(3, foo.Private); Assert.AreEqual(3, foo.Auto); } [TestMethod] public void TestByteArray() { const string xmlString = _Head + @" MTMzNw== "; _AssertSerDeserMatch(xmlString); } private const string _XmlIgnore = _Head + @" 2 "; private const string _XmlIgnore2 = _Head + @" 2 2 "; [TestMethod] public void TestIgnore() { _AssertSerDeserMatch(_XmlIgnore); _AssertFail(_XmlIgnore2); } [TestMethod] public void TestExisting() { var foo = new SIgnore {I = 1}; var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); SIgnore bar = xml.DeserializeString(_XmlIgnore, foo); Assert.AreEqual(1, bar.I); Assert.AreEqual(_XmlIgnore, ser.Serialize(bar)); var foo2 = new CIgnore {I = 1}; CIgnore bar2 = xml.DeserializeString(_XmlIgnore, foo2); Assert.AreEqual(1, bar2.I); Assert.AreEqual(foo2.J, bar2.J, "Original classes should be modified by the deserialization"); Assert.AreEqual(_XmlIgnore, ser.Serialize(bar2)); } [TestMethod] public void TestOnlyList() { const string s = _Head + @" 2 3 "; _AssertSerDeserMatch>(s); } [TestMethod] public void TestOnlyDict() { const string s = _Head + @" 2 3 "; _AssertSerDeserMatch>(s); } [TestMethod] public void TestDefaultValues() { const string s = _Head + @" 1 2 3 4 22 "; _AssertSerDeserMatch(s); var xml = new CXmlDeserializer(new CXmlErrorHandler(exception => { })); SDefault foo = xml.DeserializeString(@""); Assert.AreEqual(foo.I, 1337); Assert.AreEqual(foo.F, null); Assert.AreEqual(foo.S, "Foo"); Assert.AreEqual(foo.D, 666); Assert.AreEqual(foo.Sub.I, 111); string newXml = new CXmlSerializer().Serialize(foo); Assert.AreEqual(_Head +@" ", newXml); } [TestMethod] public void TestRealFiles() { Type[] types = new Type[] {typeof(SThemeCover), typeof(CConfig.SConfig), typeof(SThemeScreen), typeof(SDefaultFonts), typeof(SSkin), typeof(STheme), typeof(Dictionary)}; string filePath = Path.Combine(new string[] {AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "TestXmlFiles"}); foreach (Type type in types) { string xmlPath = Path.Combine(filePath, type.Name + ".xml"); var deser = new CXmlDeserializer(); object foo = null; try { foo = deser.Deserialize(xmlPath, Activator.CreateInstance(type)); } catch (Exception e) { Assert.Fail("Exception with " + type.Name + ": {0}", new object[] {e.Message}); } Assert.IsInstanceOfType(foo, type, "Wrong type with " + type.Name); var ser = new CXmlSerializer(type == typeof(CConfig.SConfig)); string newXml = ser.Serialize(foo, type == typeof(Dictionary) ? "resources" : null); // Typename will be uppercase but input is lowercase newXml = newXml.Replace("