/* * Copyright (c) 2007-2008, openmetaverse.org * All rights reserved. * * - 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. * - Neither the name of the openmetaverse.org 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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; using System.Collections.Generic; using System.Text; using NUnit.Framework; using System.Collections; using OpenMetaverse.StructuredData; namespace OpenMetaverse.Tests { /// /// XmlSDTests is a suite of tests for libsl implementation of the SD XML format. /// /// [TestFixture] public class XmlSDTests { /// /// Test that the sample LLSD supplied by Linden Lab is properly deserialized. /// The LLSD string in the test is a pared down version of the sample on the blog. /// http://wiki.secondlife.com/wiki/LLSD /// [Test] public void DeserializeLLSDSample() { OSD theSD = null; OSDMap map = null; OSD tempSD = null; OSDUUID tempUUID = null; OSDString tempStr = null; OSDReal tempReal = null; String testSD = @" region_id 67153d5b-3659-afb4-8510-adda2c034649 scale one minute simulator statistics time dilation 0.9878624 sim fps 44.38898 agent updates per second nan total task count 4 active task count 0 pending uploads 0.0001096525 "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); //Confirm the contents Assert.IsNotNull(theSD); Assert.IsTrue(theSD is OSDMap); Assert.IsTrue(theSD.Type == OSDType.Map); map = (OSDMap)theSD; tempSD = map["region_id"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDUUID); Assert.IsTrue(tempSD.Type == OSDType.UUID); tempUUID = (OSDUUID)tempSD; Assert.AreEqual(new UUID("67153d5b-3659-afb4-8510-adda2c034649"), tempUUID.AsUUID()); tempSD = map["scale"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDString); Assert.IsTrue(tempSD.Type == OSDType.String); tempStr = (OSDString)tempSD; Assert.AreEqual("one minute", tempStr.AsString()); tempSD = map["simulator statistics"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDMap); Assert.IsTrue(tempSD.Type == OSDType.Map); map = (OSDMap)tempSD; tempSD = map["time dilation"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(0.9878624d, tempReal.AsReal()); //TODO - figure out any relevant rounding variability for 64 bit reals tempSD = map["sim fps"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(44.38898d, tempReal.AsReal()); tempSD = map["agent updates per second"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(Double.NaN, tempSD.AsReal()); tempSD = map["total task count"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(4.0d, tempReal.AsReal()); tempSD = map["active task count"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(0.0d, tempReal.AsReal()); tempSD = map["pending uploads"]; Assert.IsNotNull(tempSD); Assert.IsTrue(tempSD is OSDReal); Assert.IsTrue(tempSD.Type == OSDType.Real); tempReal = (OSDReal)tempSD; Assert.AreEqual(0.0001096525d, tempReal.AsReal()); } /// /// Test that various Real representations are parsed correctly. /// [Test] public void DeserializeReals() { OSD theSD = null; OSDArray array = null; OSDReal tempReal = null; String testSD = @" 44.38898 nan 4 -13.333 "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.Real, array[0].Type); tempReal = (OSDReal)array[0]; Assert.AreEqual(44.38898d, tempReal.AsReal()); Assert.AreEqual(OSDType.Real, array[1].Type); tempReal = (OSDReal)array[1]; Assert.AreEqual(Double.NaN, tempReal.AsReal()); Assert.AreEqual(OSDType.Real, array[2].Type); tempReal = (OSDReal)array[2]; Assert.AreEqual(4.0d, tempReal.AsReal()); Assert.AreEqual(OSDType.Real, array[3].Type); tempReal = (OSDReal)array[3]; Assert.AreEqual(-13.333d, tempReal.AsReal()); Assert.AreEqual(OSDType.Real, array[4].Type); tempReal = (OSDReal)array[4]; Assert.AreEqual(0d, tempReal.AsReal()); } /// /// Test that various String representations are parsed correctly. /// [Test] public void DeserializeStrings() { OSD theSD = null; OSDArray array = null; OSDString tempStr = null; String testSD = @" Kissling Attack ships on fire off the shoulder of Orion < > & ' " "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.String, array[0].Type); tempStr = (OSDString)array[0]; Assert.AreEqual("Kissling", tempStr.AsString()); Assert.AreEqual(OSDType.String, array[1].Type); tempStr = (OSDString)array[1]; Assert.AreEqual("Attack ships on fire off the shoulder of Orion", tempStr.AsString()); Assert.AreEqual(OSDType.String, array[2].Type); tempStr = (OSDString)array[2]; Assert.AreEqual("< > & \' \"", tempStr.AsString()); Assert.AreEqual(OSDType.String, array[3].Type); tempStr = (OSDString)array[3]; Assert.AreEqual("", tempStr.AsString()); } /// /// Test that various Integer representations are parsed correctly. /// These tests currently only test for values within the range of a /// 32 bit signed integer, even though the SD specification says /// the type is a 64 bit signed integer, because LLSInteger is currently /// implemented using int, a.k.a. Int32. Not testing Int64 range until /// it's understood if there was a design reason for the Int32. /// [Test] public void DeserializeIntegers() { OSD theSD = null; OSDArray array = null; OSDInteger tempInt = null; String testSD = @" 2147483647 -2147483648 0 013 "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.Integer, array[0].Type); tempInt = (OSDInteger)array[0]; Assert.AreEqual(2147483647, tempInt.AsInteger()); Assert.AreEqual(OSDType.Integer, array[1].Type); tempInt = (OSDInteger)array[1]; Assert.AreEqual(-2147483648, tempInt.AsInteger()); Assert.AreEqual(OSDType.Integer, array[2].Type); tempInt = (OSDInteger)array[2]; Assert.AreEqual(0, tempInt.AsInteger()); Assert.AreEqual(OSDType.Integer, array[3].Type); tempInt = (OSDInteger)array[3]; Assert.AreEqual(13, tempInt.AsInteger()); Assert.AreEqual(OSDType.Integer, array[4].Type); tempInt = (OSDInteger)array[4]; Assert.AreEqual(0, tempInt.AsInteger()); } /// /// Test that various UUID representations are parsed correctly. /// [Test] public void DeserializeUUID() { OSD theSD = null; OSDArray array = null; OSDUUID tempUUID = null; String testSD = @" d7f4aeca-88f1-42a1-b385-b9db18abb255 "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.UUID, array[0].Type); tempUUID = (OSDUUID)array[0]; Assert.AreEqual(new UUID("d7f4aeca-88f1-42a1-b385-b9db18abb255"), tempUUID.AsUUID()); Assert.AreEqual(OSDType.UUID, array[1].Type); tempUUID = (OSDUUID)array[1]; Assert.AreEqual(UUID.Zero, tempUUID.AsUUID()); } /// /// Test that various date representations are parsed correctly. /// [Test] public void DeserializeDates() { OSD theSD = null; OSDArray array = null; OSDDate tempDate = null; DateTime testDate; String testSD = @" 2006-02-01T14:29:53Z 1999-01-01T00:00:00Z "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.Date, array[0].Type); tempDate = (OSDDate)array[0]; DateTime.TryParse("2006-02-01T14:29:53Z", out testDate); Assert.AreEqual(testDate, tempDate.AsDate()); Assert.AreEqual(OSDType.Date, array[1].Type); tempDate = (OSDDate)array[1]; DateTime.TryParse("1999-01-01T00:00:00Z", out testDate); Assert.AreEqual(testDate, tempDate.AsDate()); Assert.AreEqual(OSDType.Date, array[2].Type); tempDate = (OSDDate)array[2]; Assert.AreEqual(Utils.Epoch, tempDate.AsDate()); } /// /// Test that various Boolean representations are parsed correctly. /// [Test] public void DeserializeBoolean() { OSD theSD = null; OSDArray array = null; OSDBoolean tempBool = null; String testSD = @" 1 true 0 false "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.Boolean, array[0].Type); tempBool = (OSDBoolean)array[0]; Assert.AreEqual(true, tempBool.AsBoolean()); Assert.AreEqual(OSDType.Boolean, array[1].Type); tempBool = (OSDBoolean)array[1]; Assert.AreEqual(true, tempBool.AsBoolean()); Assert.AreEqual(OSDType.Boolean, array[2].Type); tempBool = (OSDBoolean)array[2]; Assert.AreEqual(false, tempBool.AsBoolean()); Assert.AreEqual(OSDType.Boolean, array[3].Type); tempBool = (OSDBoolean)array[3]; Assert.AreEqual(false, tempBool.AsBoolean()); Assert.AreEqual(OSDType.Boolean, array[4].Type); tempBool = (OSDBoolean)array[4]; Assert.AreEqual(false, tempBool.AsBoolean()); } /// /// Test that binary elements are parsed correctly. /// [Test] public void DeserializeBinary() { OSD theSD = null; OSDArray array = null; OSDBinary tempBinary = null; String testSD = @" cmFuZG9t dGhlIHF1aWNrIGJyb3duIGZveA== "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.Binary, array[0].Type); tempBinary = (OSDBinary)array[0]; byte[] testData1 = {114, 97, 110, 100, 111, 109}; TestHelper.TestBinary(tempBinary, testData1); Assert.AreEqual(OSDType.Binary, array[1].Type); tempBinary = (OSDBinary)array[1]; byte[] testData2 = {116, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120}; TestHelper.TestBinary(tempBinary, testData2); Assert.AreEqual(OSDType.Binary, array[1].Type); tempBinary = (OSDBinary)array[2]; Assert.AreEqual(0, tempBinary.AsBinary().Length); } /// /// Test that undefened elements are parsed correctly. /// Currently this just checks that there is no error since undefined has no /// value and there is no SD child class for Undefined elements - the /// current implementation generates an instance of SD /// [Test] public void DeserializeUndef() { OSD theSD = null; String testSD = @" "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSD); } /// /// Test that various URI representations are parsed correctly. /// [Test] public void DeserializeURI() { OSD theSD = null; OSDArray array = null; OSDUri tempURI = null; String testSD = @" http://sim956.agni.lindenlab.com:12035/runtime/agents "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(OSDType.URI, array[0].Type); tempURI = (OSDUri)array[0]; Uri testURI = new Uri(@"http://sim956.agni.lindenlab.com:12035/runtime/agents"); Assert.AreEqual(testURI, tempURI.AsUri()); Assert.AreEqual(OSDType.URI, array[1].Type); tempURI = (OSDUri)array[1]; Assert.AreEqual("", tempURI.AsUri().ToString()); } /// /// Test some nested containers. This is not a very deep or complicated SD graph /// but it should reveal basic nesting issues. /// [Test] public void DeserializeNestedContainers() { OSD theSD = null; OSDArray array = null; OSDMap map = null; OSD tempSD = null; String testSD = @" Map One Array One 1 2 A B 1 4 9 "; //Deserialize the string byte[] bytes = Encoding.UTF8.GetBytes(testSD); theSD = OSDParser.DeserializeLLSDXml(bytes); Assert.IsTrue(theSD is OSDArray); array = (OSDArray)theSD; Assert.AreEqual(2, array.Count); //The first element of top level array, a map Assert.AreEqual(OSDType.Map, array[0].Type); map = (OSDMap)array[0]; //First nested map tempSD = map["Map One"]; Assert.IsNotNull(tempSD); Assert.AreEqual(OSDType.Map, tempSD.Type); map = (OSDMap)tempSD; //First nested array tempSD = map["Array One"]; Assert.IsNotNull(tempSD); Assert.AreEqual(OSDType.Array, tempSD.Type); array = (OSDArray)tempSD; Assert.AreEqual(2, array.Count); array = (OSDArray)theSD; //Second element of top level array, an array tempSD = array[1]; Assert.AreEqual(OSDType.Array, tempSD.Type); array = (OSDArray)tempSD; Assert.AreEqual(3, array.Count); //Nested array tempSD = array[2]; Assert.AreEqual(OSDType.Array, tempSD.Type); array = (OSDArray)tempSD; Assert.AreEqual(3, array.Count); } } internal static class TestHelper { /// /// Asserts that the contents of the SDBinary match the values and length /// of the supplied byte array /// /// /// internal static void TestBinary(OSDBinary inBinary, byte[] inExpected) { byte[] binary = inBinary.AsBinary(); Assert.AreEqual(inExpected.Length, binary.Length); for (int i = 0; i < inExpected.Length; i++) { if (inExpected[i] != binary[i]) { Assert.Fail("Expected " + inExpected[i].ToString() + " at position " + i.ToString() + " but saw " + binary[i].ToString()); } } } } }