#region license // This file is part of Vocaluxe. // // Vocaluxe is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Vocaluxe is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Vocaluxe. If not, see . #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Xml.Serialization; using NUnit.Framework; using Vocaluxe.Base; using VocaluxeLib; using VocaluxeLib.Xml; namespace Tests.VocaluxeLib.XML { [TestFixture] public class CXmlSerializerTest { private const string _Head = "\r\n"; private const string _Empty = _Head + @""; #region Tests [Test] public void TestBasic() { const string s = @" 1 2 3 4 "; const string sUnordered = @" 4 1 3 2 "; var xml = new CXmlDeserializer(); var foo = xml.DeserializeString(s); Assert.That(foo.I, Is.EqualTo(1)); Assert.That(foo.S, Is.EqualTo("2")); Assert.That(foo.F, Is.EqualTo(3).Within(0.0001)); Assert.That(foo.D, Is.EqualTo(4).Within(0.0001)); foo = xml.DeserializeString(sUnordered); Assert.That(foo.I, Is.EqualTo(1)); Assert.That(foo.S, Is.EqualTo("2")); Assert.That(foo.F, Is.EqualTo(3).Within(0.0001)); Assert.That(foo.D, Is.EqualTo(4).Within(0.0001)); } [Test] public void TestMissingXmlElement() { var s = new string[] { @" 2 3 4 ", @" 1 3 4 ", @" 1 2 3 " }; foreach (var s1 in s) { _AssertXmlSerializeFailWithMissingElement(s1); } } [Test] public void TestMissingStructElement() { var s = new string[] { @" 1 1 2 3 4 ", @" 1 1 2 3 4 ", @" 1 2 3 4 1 " }; foreach (var s1 in s) { var sTmp = s1; _AssertXmlSerializeFailWithMissingElement(sTmp); } } [Test] public void TestBasicSerialization() { const string s = _Head + @" 1 2 3 4 "; _AssertSerDeserMatch(s); } private readonly string[] _XmlList = { _Head + @" 1 1 ", _Head + @" ", _Head + @" " }; [Test] public void TestList() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); var foo = xml.DeserializeString(_XmlList[0]); Assert.That(foo.Ints, Has.Count.EqualTo(2), "Deserialization failed"); Assert.That(foo.Ints[0].I, Is.EqualTo(1), "Deserialization failed"); Assert.That(foo.Ints[1].I, Is.EqualTo(1), "Deserialization failed"); var res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlList[0]), "Serialization failed"); foo = xml.DeserializeString(_XmlList[1]); Assert.That(foo.Ints, Is.Empty, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.That(_XmlList[2], Is.EqualTo(res), "Serialization2 failed"); foo = xml.DeserializeString(_XmlList[2]); Assert.That(foo.Ints, Is.Empty, "Deserialization2 failed"); _AssertSerDeserMatch(_XmlList[2]); res = ser.Serialize(foo); Assert.That(_XmlList[2], Is.EqualTo(res), "Serialization2 failed"); _AssertXmlSerializeFailWithMissingElement(_Empty); } [Test] public void TestArray() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); var foo = xml.DeserializeString(_XmlList[0]); Assert.That(foo.Ints, Has.Length.EqualTo(2), "Deserialization failed"); Assert.That(foo.Ints[0].I, Is.EqualTo(1), "Deserialization failed"); Assert.That(foo.Ints[1].I, Is.EqualTo(1), "Deserialization failed"); var res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlList[0]), "Serialization failed"); foo = xml.DeserializeString(_XmlList[1]); Assert.That(foo.Ints, Is.Empty, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.That(_XmlList[2], Is.EqualTo(res), "Serialization2 failed"); foo = xml.DeserializeString(_XmlList[2]); Assert.That(foo.Ints, Is.Empty, "Deserialization2 failed"); res = ser.Serialize(foo); Assert.That(_XmlList[2], Is.EqualTo(res), "Serialization2 failed"); _AssertXmlSerializeFailWithMissingElement(_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 "; private const string _XmlListEmb4 = _Head + @" 2 3 "; [Test] public void TestListEmbedded() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); var foo = xml.DeserializeString(_XmlListEmb); Assert.That(foo.Ints, Has.Count.EqualTo(1), "Deserialization failed"); Assert.That(foo.Ints[0].I, Is.EqualTo(1), "Deserialization failed"); var res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb), "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb2); Assert.That(foo.Ints, Has.Count.EqualTo(2), "Deserialization failed"); Assert.That(foo.Ints[1].I, Is.EqualTo(2) , "Deserialization failed"); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb2), "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb3); Assert.That(foo.Ints, Is.Empty, "Deserialization failed"); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb3), "Serialization failed"); ser = new CXmlSerializer(true); foo.Ints.Clear(); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb4), "Serialization failed"); _AssertXmlSerializeFailWithMissingElement(_Empty); } [Test] public void TestArrayEmbedded() { var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); var foo = xml.DeserializeString(_XmlListEmb); Assert.That(foo.Ints, Has.Length.EqualTo(1), "Deserialization failed"); Assert.That(foo.Ints[0].I, Is.EqualTo(1), "Deserialization failed"); var res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb), "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb2); Assert.That(foo.Ints, Has.Length.EqualTo(2), "Deserialization failed"); Assert.That(foo.Ints[1].I, Is.EqualTo(2), "Deserialization failed"); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb2), "Serialization failed"); foo = xml.DeserializeString(_XmlListEmb3); Assert.That(foo.Ints, Is.Empty, "Deserialization failed"); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb3), "Serialization failed"); ser = new CXmlSerializer(true); foo.Ints = Array.Empty(); res = ser.Serialize(foo); Assert.That(res, Is.EqualTo(_XmlListEmb4), "Serialization failed"); _AssertXmlSerializeFailWithMissingElement(_Empty); } [Test] public void TestProperty() { const string xmlString = _Head + @" 2 3 "; var foo = _AssertSerDeserMatch(xmlString); Assert.That(foo.Private, Is.EqualTo(3)); Assert.That(foo.Auto, Is.EqualTo(3)); } [Test] public void TestByteArray() { const string xmlString = _Head + @" MTMzNw== "; _AssertSerDeserMatch(xmlString); } private const string _XmlIgnore = _Head + @" 2 "; private const string _XmlIgnore2 = _Head + @" 2 2 "; [Test] public void TestIgnore() { _AssertSerDeserMatch(_XmlIgnore); _AssertXmlSerializeFailWithMissingElement(_XmlIgnore2); } [Test] public void TestExisting() { var foo = new SIgnore { I = 1 }; var xml = new CXmlDeserializer(); var ser = new CXmlSerializer(); var bar = xml.DeserializeString(_XmlIgnore, foo); Assert.That(bar.I, Is.EqualTo(1)); Assert.That(ser.Serialize(bar), Is.EqualTo(_XmlIgnore)); var foo2 = new CIgnore { I = 1 }; var bar2 = xml.DeserializeString(_XmlIgnore, foo2); Assert.That(bar2.I, Is.EqualTo(1)); Assert.That(bar2.J, Is.EqualTo(foo2.J), "Original classes should be modified by the deserialization"); Assert.That(ser.Serialize(bar2), Is.EqualTo(_XmlIgnore)); } [Test] public void TestOnlyList() { const string s = _Head + @" 2 3 "; _AssertSerDeserMatch>(s); } [Test] public void TestOnlyDict() { const string s = _Head + @" 2 3 "; _AssertSerDeserMatch>(s); } [Test] public void TestDefaultValues() { const string s = _Head + @" 1 2 3 4 22 "; _AssertSerDeserMatch(s); var xml = new CXmlDeserializer(new CXmlErrorHandler(exception => { })); var foo = xml.DeserializeString(@""); Assert.That(foo.I, Is.EqualTo(1337)); Assert.That(foo.F, Is.Null); Assert.That(foo.S, Is.EqualTo("Foo")); Assert.That(foo.D, Is.EqualTo(666)); Assert.That(foo.Sub.I, Is.EqualTo(111)); var newXml = new CXmlSerializer().Serialize(foo); Assert.That(newXml, Is.EqualTo(_Head + @" ")); } [Test] public void TestEscapedValues() { const string s = _Head + @" Foo\'Bar Foo\'Bar "; _AssertSerDeserMatch(s); var xml = new CXmlDeserializer(new CXmlErrorHandler(exception => { })); var foo = xml.DeserializeString(@""); Assert.That(foo.S, Is.EqualTo("Foo\'Bar")); Assert.That(foo.Sub.S, Is.EqualTo("Foo\'Bar")); } [Test] public void TestUnescapedValues() { const string s = _Head + @" Foo\'Bar Foo\'Bar "; _AssertSerDeserMatch(s); var xml = new CXmlDeserializer(new CXmlErrorHandler(exception => { }), true); var foo = xml.DeserializeString(@""); Assert.That(foo.S, Is.EqualTo("Foo'Bar")); Assert.That(foo.Sub.S, Is.EqualTo("Foo'Bar")); } [Test] public void TestRealFiles( [Values(typeof(SThemeCover), typeof(CConfig.SConfig), /*typeof(SThemeScreen),*/ typeof(SDefaultFonts), typeof(SSkin), typeof(STheme), typeof(Dictionary))] Type type) { var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "VocaluxeLib", "XML", "TestFiles"); var xmlPath = Path.Combine(filePath, type.Name + ".xml"); var deser = new CXmlDeserializer(); var foo = deser.Deserialize(xmlPath, Activator.CreateInstance(type)); Assert.That(foo, Is.InstanceOf(type), "Wrong type with " + type.Name); var ser = new CXmlSerializer(type == typeof(CConfig.SConfig)); var newXml = ser.Serialize(foo, type == typeof(Dictionary) ? "resources" : null); // Typename will be uppercase but input is lowercase newXml = newXml.Replace(" 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; } private struct SUnescaping { [DefaultValue("Foo\'Bar")] public string S; public SUnescapingSub Sub; } private struct SUnescapingSub { [DefaultValue("Foo\'Bar")] public string S; } #pragma warning restore 169 #pragma warning restore 649 private static void _AssertXmlSerializeFailWithMissingElement(string xmlString) where TSerializeType : new() where TXmlException : CXmlException { var deserializer = new CXmlDeserializer(); Assert.Throws(new Action(() => deserializer.DeserializeString(xmlString))); } private static T _AssertSerDeserMatch(string xmlString) where T : new() { var deserializer = new CXmlDeserializer(); var serializer = new CXmlSerializer(); var foo = deserializer.DeserializeString(xmlString); var xmlNew = serializer.Serialize(foo); Assert.That(xmlString, Is.EqualTo(xmlNew)); return foo; } #endregion } }