/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; using log4net.Config; using NUnit.Framework; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; using OpenMetaverse.StructuredData; namespace OpenSim.Region.CoreModules.World.Serialiser.Tests { [TestFixture] public class SerialiserTests : OpenSimTestCase { private const string ObjectRootPartStubXml = @" false a6dacf01-4636-4bb9-8a97-30609438af9d e6a5a05e-e8cc-4816-8701-04165e335790 1 0 e6a5a05e-e8cc-4816-8701-04165e335790 2698615125 PrimMyRide 0 false 1099511628032000 0 147.2392.69822.78084 000 -4.371139E-08-1-4.371139E-080 000 000 000 000 0 0 1 AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== AA== 0 16 0 0 0 100 100 0 0 0 0 0 0 0 9 0 0 0 10100.5 0 Square Same 00000000-0000-0000-0000-000000000000 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 false false false 10100.5 0 0001 000 000 0001 0 1211330445 0 0 0 0 00000000-0000-0000-0000-000000000000 a6dacf01-4636-4bb9-8a97-30609438af9d a6dacf01-4636-4bb9-8a97-30609438af9d 2147483647 2147483647 0 0 2147483647 None 00000000-0000-0000-0000-000000000000 0 MyNamespace MyStore the answer 42 "; private const string ObjectWithNoOtherPartsXml = ObjectRootPartStubXml + @" "; private const string ObjectWithOtherPartsXml = ObjectRootPartStubXml + @" false a6dacf01-4636-4bb9-8a97-30609438af9d 9958feb1-02a6-49e4-a4ce-eba6f578ee13 3 9958feb1-02a6-49e4-a4ce-eba6f578ee13 1154704500 Alien Head 1 3 false false 21990232560640000 0 125.5655127.34622.48036 -0.21719360.10839840.0009994507 -0.51221060.4851225-0.49574540.5064908 000 000 000 (No Description) 000255 253 0 5 Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA== 0 32 0 0 0 100 100 0 0 0 0 0 0 0 9 0 0 0 9 0 HalfCircle Same 00000000-0000-0000-0000-000000000000 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 false false false 0.11481950.01438910.02768878 0001 000 000 0001 1154704499 1256611042 0 10 0 0 00000000-0000-0000-0000-000000000000 7b2022f0-5f19-488c-b7e5-829d8f96b448 7b2022f0-5f19-488c-b7e5-829d8f96b448 647168 647168 0 0 581632 None 00000000-0000-0000-0000-000000000000 0 000 -2 -2 -2 -2 -2 false a6dacf01-4636-4bb9-8a97-30609438af9d 674b6b86-f5aa-439a-8e00-0d75bc08c80a 3 674b6b86-f5aa-439a-8e00-0d75bc08c80a 1154704501 Alien Head 2 3 false false 21990232560640000 0 125.5655127.34622.48036 -0.24909970.085201260.0009002686 -0.47653680.5194498-0.53013720.4712104 000 000 000 (No Description) 000255 252 0 0 Vw3dpvgTRUOiIUOGsnpWlAB/f38AAAAAgL8AAACAPwAAAAAAAAAF4ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AA== 0 32 0 0 0 100 150 0 0 0 0 0 0 0 9 0 0 0 9 0 Circle Same 00000000-0000-0000-0000-000000000000 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 false false false 0.035743850.059580320.04764182 0001 000 000 0001 1154704499 1256611042 0 10 0 0 00000000-0000-0000-0000-000000000000 7b2022f0-5f19-488c-b7e5-829d8f96b448 7b2022f0-5f19-488c-b7e5-829d8f96b448 647168 647168 0 0 581632 None 00000000-0000-0000-0000-000000000000 0 000 -2 -2 -2 -2 -2 "; private const string ObjectWithBadFloatsXml = @" false a6dacf01-4636-4bb9-8a97-30609438af9d e6a5a05e-e8cc-4816-8701-04165e335790 1 0 e6a5a05e-e8cc-4816-8701-04165e335790 2698615125 NaughtyPrim 0 false 1099511628032000 0 147.2392.69822.78084 000 -4.371139E-08-1-4.371139E-080 000 000 000 000 0 0 1 AAAAAAAAERGZmQAAAAAABQCVlZUAAAAAQEAAAABAQAAAAAAAAAAAAAAAAAAAAA== AA== 0 16 0 0 0 100 100 0 0 0 0 0 0 0 9 0 0 0 10100.5 0 Square Same 00000000-0000-0000-0000-000000000000 0 0 0,5 yo mamma 0 0 0 0 0 0 0 0 1 0 0 0 1 false false false 10100.5 0 0001 000 000 0001 0 1211330445 0 0 0 0 00000000-0000-0000-0000-000000000000 a6dacf01-4636-4bb9-8a97-30609438af9d a6dacf01-4636-4bb9-8a97-30609438af9d 2147483647 2147483647 0 0 2147483647 None 00000000-0000-0000-0000-000000000000 0 "; private const string ObjectWithNoPartsXml2 = @" b46ef588-411e-4a8b-a284-d7dcfe8e74ef 9be68fdd-f740-4a0f-9675-dfbbb536b946 0 0 9be68fdd-f740-4a0f-9675-dfbbb536b946 720005 PrimFun 0 1099511628032000 0 153.9854121.490862.21781 000 0001 000 000 000 000 0 0 0 16 0 0 0 200 200 0 0 0 0 0 0 0 9 0 0 0 1.2831315.9038584.266288 0 Circle Same 0 iVVnRyTLQ+2SC0fK7RVGXwJ6yc/SU4RDA5nhJbLUw3R1AAAAAAAAaOw8QQOhPSRAAKE9JEAAAAAAAAAAAAAAAAAAAAA= AA== 1.2831315.9038584.266288 0 0001 000 000 0010 0 1216066902 0 0 0 0 00000000-0000-0000-0000-000000000000 b46ef588-411e-4a8b-a284-d7dcfe8e74ef b46ef588-411e-4a8b-a284-d7dcfe8e74ef 2147483647 2147483647 0 0 2147483647 None MyNamespace MyStore last words Rosebud 00000000-0000-0000-0000-000000000000 "; protected Scene m_scene; protected SerialiserModule m_serialiserModule; [TestFixtureSetUp] public void Init() { m_serialiserModule = new SerialiserModule(); m_scene = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(m_scene, m_serialiserModule); } [Test] public void TestDeserializeXmlObjectWithNoOtherParts() { TestHelpers.InMethod(); TestHelpers.EnableLogging(); SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithNoOtherPartsXml); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore"); Assert.AreEqual(42, store["the answer"].AsInteger()); // TODO: Check other properties } [Test] public void TestDeserializeXmlObjectWithOtherParts() { TestHelpers.InMethod(); TestHelpers.EnableLogging(); SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithOtherPartsXml); SceneObjectPart[] parts = so.Parts; Assert.AreEqual(3, so.Parts.Length); { SceneObjectPart part = parts[0]; Assert.That(part.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); Assert.That(part.Name, Is.EqualTo("PrimMyRide")); OSDMap store = part.DynAttrs.GetStore("MyNamespace", "MyStore"); Assert.AreEqual(42, store["the answer"].AsInteger()); } { SceneObjectPart part = parts[1]; Assert.That(part.UUID, Is.EqualTo(new UUID("9958feb1-02a6-49e4-a4ce-eba6f578ee13"))); Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); Assert.That(part.Name, Is.EqualTo("Alien Head 1")); } { SceneObjectPart part = parts[2]; Assert.That(part.UUID, Is.EqualTo(new UUID("674b6b86-f5aa-439a-8e00-0d75bc08c80a"))); Assert.That(part.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); Assert.That(part.Name, Is.EqualTo("Alien Head 2")); } // TODO: Check other properties } [Test] public void TestDeserializeBadFloatsXml() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); SceneObjectGroup so = SceneObjectSerializer.FromOriginalXmlFormat(ObjectWithBadFloatsXml); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); Assert.That(rootPart.Name, Is.EqualTo("NaughtyPrim")); // This terminates the deserialization earlier if couldn't be parsed. // TODO: Need to address this Assert.That(rootPart.GroupPosition.X, Is.EqualTo(147.23f)); Assert.That(rootPart.Shape.PathCurve, Is.EqualTo(16)); // Defaults for bad parses Assert.That(rootPart.Shape.FlexiTension, Is.EqualTo(0)); Assert.That(rootPart.Shape.FlexiDrag, Is.EqualTo(0)); // TODO: Check other properties } [Test] public void TestSerializeXml() { TestHelpers.InMethod(); //log4net.Config.XmlConfigurator.Configure(); string rpName = "My Little Donkey"; UUID rpUuid = UUID.Parse("00000000-0000-0000-0000-000000000964"); UUID rpCreatorId = UUID.Parse("00000000-0000-0000-0000-000000000915"); PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); // Vector3 groupPosition = new Vector3(10, 20, 30); // Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); // Vector3 offsetPosition = new Vector3(5, 10, 15); SceneObjectPart rp = new SceneObjectPart(); rp.UUID = rpUuid; rp.Name = rpName; rp.CreatorID = rpCreatorId; rp.Shape = shape; string daNamespace = "MyNamespace"; string daStoreName = "MyStore"; string daKey = "foo"; string daValue = "bar"; OSDMap myStore = new OSDMap(); myStore.Add(daKey, daValue); rp.DynAttrs = new DAMap(); rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore); SceneObjectGroup so = new SceneObjectGroup(rp); // Need to add the object to the scene so that the request to get script state succeeds m_scene.AddSceneObject(so); string xml = SceneObjectSerializer.ToOriginalXmlFormat(so); XmlTextReader xtr = new XmlTextReader(new StringReader(xml)); xtr.ProhibitDtd = true; xtr.XmlResolver = null; xtr.ReadStartElement("SceneObjectGroup"); xtr.ReadStartElement("RootPart"); xtr.ReadStartElement("SceneObjectPart"); UUID uuid = UUID.Zero; string name = null; UUID creatorId = UUID.Zero; DAMap daMap = null; while (xtr.Read() && xtr.Name != "SceneObjectPart") { if (xtr.NodeType != XmlNodeType.Element) continue; switch (xtr.Name) { case "UUID": xtr.ReadStartElement("UUID"); try { uuid = UUID.Parse(xtr.ReadElementString("UUID")); xtr.ReadEndElement(); } catch { } // ignore everything but ... break; case "Name": name = xtr.ReadElementContentAsString(); break; case "CreatorID": xtr.ReadStartElement("CreatorID"); creatorId = UUID.Parse(xtr.ReadElementString("UUID")); xtr.ReadEndElement(); break; case "DynAttrs": daMap = new DAMap(); daMap.ReadXml(xtr); break; } } xtr.ReadEndElement(); xtr.ReadEndElement(); xtr.ReadStartElement("OtherParts"); xtr.ReadEndElement(); xtr.Close(); // TODO: More checks Assert.That(uuid, Is.EqualTo(rpUuid)); Assert.That(name, Is.EqualTo(rpName)); Assert.That(creatorId, Is.EqualTo(rpCreatorId)); Assert.NotNull(daMap); Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString()); } [Test] public void TestDeserializeXml2() { TestHelpers.InMethod(); //log4net.Config.XmlConfigurator.Configure(); SceneObjectGroup so = m_serialiserModule.DeserializeGroupFromXml2(ObjectWithNoPartsXml2); SceneObjectPart rootPart = so.RootPart; Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore"); Assert.AreEqual("Rosebud", store["last words"].AsString()); // TODO: Check other properties } [Test] public void TestSerializeXml2() { TestHelpers.InMethod(); //log4net.Config.XmlConfigurator.Configure(); string rpName = "My Little Pony"; UUID rpUuid = UUID.Parse("00000000-0000-0000-0000-000000000064"); UUID rpCreatorId = UUID.Parse("00000000-0000-0000-0000-000000000015"); PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); // Vector3 groupPosition = new Vector3(10, 20, 30); // Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); // Vector3 offsetPosition = new Vector3(5, 10, 15); SceneObjectPart rp = new SceneObjectPart(); rp.UUID = rpUuid; rp.Name = rpName; rp.CreatorID = rpCreatorId; rp.Shape = shape; string daNamespace = "MyNamespace"; string daStoreName = "MyStore"; string daKey = "foo"; string daValue = "bar"; OSDMap myStore = new OSDMap(); myStore.Add(daKey, daValue); rp.DynAttrs = new DAMap(); rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore); SceneObjectGroup so = new SceneObjectGroup(rp); // Need to add the object to the scene so that the request to get script state succeeds m_scene.AddSceneObject(so); Dictionary options = new Dictionary(); options["old-guids"] = true; string xml2 = m_serialiserModule.SerializeGroupToXml2(so, options); XmlTextReader xtr = new XmlTextReader(new StringReader(xml2)); xtr.ProhibitDtd = true; xtr.XmlResolver = null; xtr.ReadStartElement("SceneObjectGroup"); xtr.ReadStartElement("SceneObjectPart"); UUID uuid = UUID.Zero; string name = null; UUID creatorId = UUID.Zero; DAMap daMap = null; while (xtr.Read() && xtr.Name != "SceneObjectPart") { if (xtr.NodeType != XmlNodeType.Element) continue; switch (xtr.Name) { case "UUID": xtr.ReadStartElement("UUID"); uuid = UUID.Parse(xtr.ReadElementString("Guid")); xtr.ReadEndElement(); break; case "Name": name = xtr.ReadElementContentAsString(); break; case "CreatorID": xtr.ReadStartElement("CreatorID"); creatorId = UUID.Parse(xtr.ReadElementString("Guid")); xtr.ReadEndElement(); break; case "DynAttrs": daMap = new DAMap(); daMap.ReadXml(xtr); break; } } xtr.ReadEndElement(); xtr.ReadStartElement("OtherParts"); xtr.ReadEndElement(); xtr.Close(); // TODO: More checks Assert.That(uuid, Is.EqualTo(rpUuid)); Assert.That(name, Is.EqualTo(rpName)); Assert.That(creatorId, Is.EqualTo(rpCreatorId)); Assert.NotNull(daMap); Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString()); } } }