#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
}
}